blob: ab6606f76fd9374f4c6f70679c020fcf171e71e9 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002 *
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 * evalfunc.c: Builtin functions
12 */
13#define USING_FLOAT_STUFF
14
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020019#ifdef VMS
20# include <float.h>
21#endif
22
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020023static void f_and(typval_T *argvars, typval_T *rettv);
Bram Moolenaar59716a22017-03-01 20:32:44 +010024#ifdef FEAT_BEVAL
Bram Moolenaarbe0a2592019-05-09 13:50:16 +020025static void f_balloon_gettext(typval_T *argvars, typval_T *rettv);
Bram Moolenaar59716a22017-03-01 20:32:44 +010026static void f_balloon_show(typval_T *argvars, typval_T *rettv);
Bram Moolenaar669a8282017-11-19 20:13:05 +010027# if defined(FEAT_BEVAL_TERM)
Bram Moolenaar246fe032017-11-19 19:56:27 +010028static void f_balloon_split(typval_T *argvars, typval_T *rettv);
Bram Moolenaar669a8282017-11-19 20:13:05 +010029# endif
Bram Moolenaar59716a22017-03-01 20:32:44 +010030#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020031static void f_byte2line(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020032static void f_call(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020033static void f_changenr(typval_T *argvars, typval_T *rettv);
34static void f_char2nr(typval_T *argvars, typval_T *rettv);
Bram Moolenaar6f02b002021-01-10 20:22:54 +010035static void f_charcol(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020036static void f_col(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020037static void f_confirm(typval_T *argvars, typval_T *rettv);
38static void f_copy(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020039static void f_cursor(typval_T *argsvars, typval_T *rettv);
Bram Moolenaar4f974752019-02-17 17:44:42 +010040#ifdef MSWIN
Bram Moolenaar4551c0a2018-06-20 22:38:21 +020041static void f_debugbreak(typval_T *argvars, typval_T *rettv);
42#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020043static void f_deepcopy(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020044static void f_did_filetype(typval_T *argvars, typval_T *rettv);
Bram Moolenaar4132eb52020-02-14 16:53:00 +010045static void f_echoraw(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020046static void f_empty(typval_T *argvars, typval_T *rettv);
Bram Moolenaar691ddee2019-05-09 14:52:41 +020047static void f_environ(typval_T *argvars, typval_T *rettv);
Bram Moolenaar80adaa82023-07-07 18:57:40 +010048static void f_err_teapot(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020049static void f_escape(typval_T *argvars, typval_T *rettv);
50static void f_eval(typval_T *argvars, typval_T *rettv);
51static void f_eventhandler(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020052static void f_execute(typval_T *argvars, typval_T *rettv);
Bram Moolenaar26735992021-08-08 14:43:22 +020053static void f_exists_compiled(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020054static void f_expand(typval_T *argvars, typval_T *rettv);
Bram Moolenaar80dad482019-06-09 17:22:31 +020055static void f_expandcmd(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020056static void f_feedkeys(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020057static void f_fnameescape(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020058static void f_foreground(typval_T *argvars, typval_T *rettv);
Bram Moolenaar437bafe2016-08-01 15:40:54 +020059static void f_funcref(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020060static void f_function(typval_T *argvars, typval_T *rettv);
61static void f_garbagecollect(typval_T *argvars, typval_T *rettv);
62static void f_get(typval_T *argvars, typval_T *rettv);
Bram Moolenaar07ad8162018-02-13 13:59:59 +010063static void f_getchangelist(typval_T *argvars, typval_T *rettv);
Bram Moolenaar6f02b002021-01-10 20:22:54 +010064static void f_getcharpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020065static void f_getcharsearch(typval_T *argvars, typval_T *rettv);
Bram Moolenaar691ddee2019-05-09 14:52:41 +020066static void f_getenv(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020067static void f_getfontname(typval_T *argvars, typval_T *rettv);
Bram Moolenaar4f505882018-02-10 21:06:32 +010068static void f_getjumplist(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020069static void f_getpid(typval_T *argvars, typval_T *rettv);
70static void f_getcurpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar6f02b002021-01-10 20:22:54 +010071static void f_getcursorcharpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020072static void f_getpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020073static void f_getreg(typval_T *argvars, typval_T *rettv);
Bram Moolenaarbb861e22020-06-07 18:16:36 +020074static void f_getreginfo(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020075static void f_getregtype(typval_T *argvars, typval_T *rettv);
Bram Moolenaarf49cc602018-11-11 15:21:05 +010076static void f_gettagstack(typval_T *argvars, typval_T *rettv);
Bram Moolenaar0b39c3f2020-08-30 15:52:10 +020077static void f_gettext(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020078static void f_haslocaldir(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020079static void f_hlID(typval_T *argvars, typval_T *rettv);
80static void f_hlexists(typval_T *argvars, typval_T *rettv);
81static void f_hostname(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020082static void f_index(typval_T *argvars, typval_T *rettv);
Yegappan Lakshmananb2186552022-08-13 13:09:20 +010083static void f_indexof(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020084static void f_input(typval_T *argvars, typval_T *rettv);
85static void f_inputdialog(typval_T *argvars, typval_T *rettv);
86static void f_inputlist(typval_T *argvars, typval_T *rettv);
87static void f_inputrestore(typval_T *argvars, typval_T *rettv);
88static void f_inputsave(typval_T *argvars, typval_T *rettv);
89static void f_inputsecret(typval_T *argvars, typval_T *rettv);
Bram Moolenaar67a2deb2019-11-25 00:05:32 +010090static void f_interrupt(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020091static void f_invert(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020092static void f_islocked(typval_T *argvars, typval_T *rettv);
zeertzjqcdc83932022-09-12 13:38:41 +010093static void f_keytrans(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020094static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020095static void f_libcall(typval_T *argvars, typval_T *rettv);
96static void f_libcallnr(typval_T *argvars, typval_T *rettv);
97static void f_line(typval_T *argvars, typval_T *rettv);
98static void f_line2byte(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020099#ifdef FEAT_LUA
100static void f_luaeval(typval_T *argvars, typval_T *rettv);
101#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200102static void f_match(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200103static void f_matchend(typval_T *argvars, typval_T *rettv);
104static void f_matchlist(typval_T *argvars, typval_T *rettv);
105static void f_matchstr(typval_T *argvars, typval_T *rettv);
106static void f_matchstrpos(typval_T *argvars, typval_T *rettv);
107static void f_max(typval_T *argvars, typval_T *rettv);
108static void f_min(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200109#ifdef FEAT_MZSCHEME
110static void f_mzeval(typval_T *argvars, typval_T *rettv);
111#endif
112static void f_nextnonblank(typval_T *argvars, typval_T *rettv);
113static void f_nr2char(typval_T *argvars, typval_T *rettv);
114static void f_or(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200115#ifdef FEAT_PERL
116static void f_perleval(typval_T *argvars, typval_T *rettv);
117#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200118static void f_prevnonblank(typval_T *argvars, typval_T *rettv);
119static void f_printf(typval_T *argvars, typval_T *rettv);
Bram Moolenaare9bd5722019-08-17 19:36:06 +0200120static void f_pum_getpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200121static void f_pumvisible(typval_T *argvars, typval_T *rettv);
122#ifdef FEAT_PYTHON3
123static void f_py3eval(typval_T *argvars, typval_T *rettv);
124#endif
125#ifdef FEAT_PYTHON
126static void f_pyeval(typval_T *argvars, typval_T *rettv);
127#endif
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100128#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
129static void f_pyxeval(typval_T *argvars, typval_T *rettv);
130#endif
Bram Moolenaar4f645c52020-02-08 16:40:39 +0100131static void f_test_srand_seed(typval_T *argvars, typval_T *rettv);
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +0100132static void f_rand(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200133static void f_range(typval_T *argvars, typval_T *rettv);
Bram Moolenaar0b6d9112018-05-22 20:35:17 +0200134static void f_reg_executing(typval_T *argvars, typval_T *rettv);
135static void f_reg_recording(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200136static void f_rename(typval_T *argvars, typval_T *rettv);
137static void f_repeat(typval_T *argvars, typval_T *rettv);
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100138#ifdef FEAT_RUBY
139static void f_rubyeval(typval_T *argvars, typval_T *rettv);
140#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200141static void f_screenattr(typval_T *argvars, typval_T *rettv);
142static void f_screenchar(typval_T *argvars, typval_T *rettv);
Bram Moolenaar2912abb2019-03-29 14:16:42 +0100143static void f_screenchars(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200144static void f_screencol(typval_T *argvars, typval_T *rettv);
145static void f_screenrow(typval_T *argvars, typval_T *rettv);
Bram Moolenaar2912abb2019-03-29 14:16:42 +0100146static void f_screenstring(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200147static void f_search(typval_T *argvars, typval_T *rettv);
148static void f_searchdecl(typval_T *argvars, typval_T *rettv);
149static void f_searchpair(typval_T *argvars, typval_T *rettv);
150static void f_searchpairpos(typval_T *argvars, typval_T *rettv);
151static void f_searchpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar6f02b002021-01-10 20:22:54 +0100152static void f_setcharpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200153static void f_setcharsearch(typval_T *argvars, typval_T *rettv);
Bram Moolenaar6f02b002021-01-10 20:22:54 +0100154static void f_setcursorcharpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar691ddee2019-05-09 14:52:41 +0200155static void f_setenv(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200156static void f_setfperm(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200157static void f_setpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200158static void f_setreg(typval_T *argvars, typval_T *rettv);
Bram Moolenaarf49cc602018-11-11 15:21:05 +0100159static void f_settagstack(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200160#ifdef FEAT_CRYPT
161static void f_sha256(typval_T *argvars, typval_T *rettv);
Bram Moolenaarb005cd82019-09-04 15:54:55 +0200162#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200163static void f_shellescape(typval_T *argvars, typval_T *rettv);
164static void f_shiftwidth(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200165static void f_soundfold(typval_T *argvars, typval_T *rettv);
166static void f_spellbadword(typval_T *argvars, typval_T *rettv);
167static void f_spellsuggest(typval_T *argvars, typval_T *rettv);
168static void f_split(typval_T *argvars, typval_T *rettv);
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +0100169static void f_srand(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200170static void f_submatch(typval_T *argvars, typval_T *rettv);
171static void f_substitute(typval_T *argvars, typval_T *rettv);
Bram Moolenaarc216a7a2022-12-05 13:50:55 +0000172static void f_swapfilelist(typval_T *argvars, typval_T *rettv);
Bram Moolenaar00f123a2018-08-21 20:28:54 +0200173static void f_swapinfo(typval_T *argvars, typval_T *rettv);
Bram Moolenaar110bd602018-09-16 18:46:59 +0200174static void f_swapname(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200175static void f_synID(typval_T *argvars, typval_T *rettv);
176static void f_synIDattr(typval_T *argvars, typval_T *rettv);
177static void f_synIDtrans(typval_T *argvars, typval_T *rettv);
178static void f_synstack(typval_T *argvars, typval_T *rettv);
179static void f_synconcealed(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200180static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200181static void f_taglist(typval_T *argvars, typval_T *rettv);
182static void f_tagfiles(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200183static void f_type(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200184static void f_virtcol(typval_T *argvars, typval_T *rettv);
185static void f_visualmode(typval_T *argvars, typval_T *rettv);
186static void f_wildmenumode(typval_T *argvars, typval_T *rettv);
Bram Moolenaar0c1e3742019-12-27 13:49:24 +0100187static void f_windowsversion(typval_T *argvars, typval_T *rettv);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200188static void f_wordcount(typval_T *argvars, typval_T *rettv);
189static void f_xor(typval_T *argvars, typval_T *rettv);
190
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +0100191
Bram Moolenaar94738d82020-10-21 14:25:07 +0200192/*
193 * Functions that check the argument type of a builtin function.
194 * Each function returns FAIL and gives an error message if the type is wrong.
195 */
196
197// Context passed to an arg_ function.
198typedef struct {
Bram Moolenaarca174532020-10-21 16:42:22 +0200199 int arg_count; // actual argument count
Bram Moolenaar078a4612022-01-04 15:17:03 +0000200 type2_T *arg_types; // list of argument types
Bram Moolenaarca174532020-10-21 16:42:22 +0200201 int arg_idx; // current argument index (first arg is zero)
Bram Moolenaar351ead02021-01-16 16:07:01 +0100202 cctx_T *arg_cctx;
Bram Moolenaar94738d82020-10-21 14:25:07 +0200203} argcontext_T;
204
205// A function to check one argument type. The first argument is the type to
206// check. If needed, other argument types can be obtained with the context.
207// E.g. if "arg_idx" is 1, then (type - 1) is the first argument type.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000208typedef int (*argcheck_T)(type_T *, type_T *, argcontext_T *);
Bram Moolenaar94738d82020-10-21 14:25:07 +0200209
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100210/*
Bram Moolenaar351ead02021-01-16 16:07:01 +0100211 * Call need_type() to check an argument type.
212 */
213 static int
214check_arg_type(
215 type_T *expected,
216 type_T *actual,
217 argcontext_T *context)
218{
Bram Moolenaarc6951a72022-12-29 20:56:24 +0000219 return need_type(actual, expected, FALSE,
Bram Moolenaar351ead02021-01-16 16:07:01 +0100220 context->arg_idx - context->arg_count, context->arg_idx + 1,
221 context->arg_cctx, FALSE, FALSE);
222}
223
224/*
Bram Moolenaara5d1a672022-09-30 17:57:47 +0100225 * Call need_type() to check an argument type and that it is modifiable
226 */
227 static int
228check_arg_type_mod(
229 type_T *expected,
230 type_T *actual,
231 argcontext_T *context)
232{
Bram Moolenaarc6951a72022-12-29 20:56:24 +0000233 if (need_type(actual, expected, FALSE,
Bram Moolenaara5d1a672022-09-30 17:57:47 +0100234 context->arg_idx - context->arg_count, context->arg_idx + 1,
235 context->arg_cctx, FALSE, FALSE) == FAIL)
236 return FAIL;
237 return arg_type_modifiable(actual, context->arg_idx + 1);
238}
239
240/*
Bram Moolenaarfa103972022-09-29 19:14:42 +0100241 * Give an error if "type" is a constant.
242 */
243 int
244arg_type_modifiable(type_T *type, int arg_idx)
245{
246 char *tofree;
247
248 if ((type->tt_flags & TTFLAG_CONST) == 0)
249 return OK;
250 semsg(_(e_argument_nr_trying_to_modify_const_str),
251 arg_idx, type_name(type, &tofree));
252 vim_free(tofree);
253 return FAIL;
254}
255
256/*
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100257 * Check "type" is a float or a number.
258 */
Bram Moolenaar94738d82020-10-21 14:25:07 +0200259 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000260arg_float_or_nr(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaar94738d82020-10-21 14:25:07 +0200261{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100262 if (type->tt_type == VAR_FLOAT
263 || type->tt_type == VAR_NUMBER
264 || type_any_or_unknown(type))
Bram Moolenaar94738d82020-10-21 14:25:07 +0200265 return OK;
266 arg_type_mismatch(&t_number, type, context->arg_idx + 1);
267 return FAIL;
268}
269
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100270/*
271 * Check "type" is a number.
272 */
Bram Moolenaarca174532020-10-21 16:42:22 +0200273 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000274arg_number(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarca174532020-10-21 16:42:22 +0200275{
Bram Moolenaar351ead02021-01-16 16:07:01 +0100276 return check_arg_type(&t_number, type, context);
Bram Moolenaarca174532020-10-21 16:42:22 +0200277}
278
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100279/*
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200280 * Check "type" is a dict of 'any'.
281 */
282 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000283arg_dict_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200284{
285 return check_arg_type(&t_dict_any, type, context);
286}
287
288/*
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200289 * Check "type" is a list of 'any'.
290 */
291 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000292arg_list_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200293{
294 return check_arg_type(&t_list_any, type, context);
295}
296
297/*
Bram Moolenaara5d1a672022-09-30 17:57:47 +0100298 * Check "type" is a list of 'any' and modifiable
299 */
300 static int
301arg_list_any_mod(
302 type_T *type,
303 type_T *decl_type UNUSED,
304 argcontext_T *context)
305{
306 return check_arg_type_mod(&t_list_any, type, context);
307}
308
309/*
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200310 * Check "type" is a list of numbers.
311 */
312 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000313arg_list_number(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200314{
315 return check_arg_type(&t_list_number, type, context);
316}
317
318/*
319 * Check "type" is a list of strings.
320 */
321 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000322arg_list_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200323{
324 return check_arg_type(&t_list_string, type, context);
325}
326
327/*
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100328 * Check "type" is a string.
329 */
330 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000331arg_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100332{
Bram Moolenaar351ead02021-01-16 16:07:01 +0100333 return check_arg_type(&t_string, type, context);
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100334}
335
336/*
Yegappan Lakshmanan5dfe4672021-09-14 17:54:30 +0200337 * Check "type" is a blob
338 */
339 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000340arg_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan5dfe4672021-09-14 17:54:30 +0200341{
342 return check_arg_type(&t_blob, type, context);
343}
344
345/*
Bram Moolenaarf2b26bc2021-01-30 23:05:11 +0100346 * Check "type" is a bool or number 0 or 1.
347 */
348 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000349arg_bool(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarf2b26bc2021-01-30 23:05:11 +0100350{
Bram Moolenaarf2b26bc2021-01-30 23:05:11 +0100351 return check_arg_type(&t_bool, type, context);
352}
353
354/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200355 * Check "type" is a list of 'any' or a blob.
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100356 */
Bram Moolenaarca174532020-10-21 16:42:22 +0200357 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000358arg_list_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarca174532020-10-21 16:42:22 +0200359{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100360 if (type->tt_type == VAR_LIST
361 || type->tt_type == VAR_BLOB
362 || type_any_or_unknown(type))
Bram Moolenaarca174532020-10-21 16:42:22 +0200363 return OK;
364 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
365 return FAIL;
366}
367
368/*
Bram Moolenaarfa103972022-09-29 19:14:42 +0100369 * Check "type" is a modifiable list of 'any' or a blob.
370 */
371 static int
372arg_list_or_blob_mod(
373 type_T *type,
374 type_T *decl_type,
375 argcontext_T *context)
376{
377 if (arg_list_or_blob(type, decl_type, context) == FAIL)
378 return FAIL;
379 return arg_type_modifiable(type, context->arg_idx + 1);
380}
381
382/*
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200383 * Check "type" is a string or a number
384 */
385 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000386arg_string_or_nr(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200387{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100388 if (type->tt_type == VAR_STRING
389 || type->tt_type == VAR_NUMBER
390 || type_any_or_unknown(type))
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200391 return OK;
392 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
393 return FAIL;
394}
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200395
396/*
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200397 * Check "type" is a buffer (string or a number)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200398 */
399 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000400arg_buffer(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200401{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100402 if (type->tt_type == VAR_STRING
403 || type->tt_type == VAR_NUMBER
404 || type_any_or_unknown(type))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200405 return OK;
406 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
407 return FAIL;
408}
409
410/*
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200411 * Check "type" is a buffer or a dict of any
412 */
413 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000414arg_buffer_or_dict_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200415{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100416 if (type->tt_type == VAR_STRING
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200417 || type->tt_type == VAR_NUMBER
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100418 || type->tt_type == VAR_DICT
419 || type_any_or_unknown(type))
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200420 return OK;
421 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
422 return FAIL;
423}
424
425/*
426 * Check "type" is a line (string or a number)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200427 */
428 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000429arg_lnum(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200430{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100431 if (type->tt_type == VAR_STRING
432 || type->tt_type == VAR_NUMBER
433 || type_any_or_unknown(type))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200434 return OK;
435 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
436 return FAIL;
437}
438
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +0200439/*
Bram Moolenaarca81f0e2021-06-20 14:41:01 +0200440 * Check "type" is a string or a list of strings.
441 */
442 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000443arg_string_or_list_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarca81f0e2021-06-20 14:41:01 +0200444{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100445 if (type->tt_type == VAR_STRING
446 || type_any_or_unknown(type))
Bram Moolenaarca81f0e2021-06-20 14:41:01 +0200447 return OK;
448 if (type->tt_type != VAR_LIST)
449 {
450 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
451 return FAIL;
452 }
453 if (type->tt_member->tt_type == VAR_ANY
454 || type->tt_member->tt_type == VAR_STRING)
455 return OK;
456
457 arg_type_mismatch(&t_list_string, type, context->arg_idx + 1);
458 return FAIL;
459}
460
461/*
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +0200462 * Check "type" is a string or a list of 'any'
463 */
464 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000465arg_string_or_list_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +0200466{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100467 if (type->tt_type == VAR_STRING
468 || type->tt_type == VAR_LIST
469 || type_any_or_unknown(type))
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +0200470 return OK;
471 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
472 return FAIL;
473}
474
475/*
Ernie Rael51d04d12022-05-04 15:40:22 +0100476 * Check "type" is a string or a dict of 'any'
477 */
478 static int
479arg_string_or_dict_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
480{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100481 if (type->tt_type == VAR_STRING
482 || type->tt_type == VAR_DICT
483 || type_any_or_unknown(type))
Ernie Rael51d04d12022-05-04 15:40:22 +0100484 return OK;
485 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
486 return FAIL;
487}
488
489/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200490 * Check "type" is a string or a blob
491 */
492 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000493arg_string_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200494{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100495 if (type->tt_type == VAR_STRING
496 || type->tt_type == VAR_BLOB
497 || type_any_or_unknown(type))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200498 return OK;
499 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
500 return FAIL;
501}
502
503/*
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200504 * Check "type" is a list of 'any' or a dict of 'any'.
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100505 */
506 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000507arg_list_or_dict(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100508{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100509 if (type->tt_type == VAR_LIST
510 || type->tt_type == VAR_DICT
511 || type_any_or_unknown(type))
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100512 return OK;
513 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
514 return FAIL;
515}
516
517/*
Bram Moolenaarfa103972022-09-29 19:14:42 +0100518 * Check "type" is a list of 'any' or a dict of 'any'. And modifiable.
519 */
520 static int
521arg_list_or_dict_mod(
522 type_T *type,
523 type_T *decl_type,
524 argcontext_T *context)
525{
526 if (arg_list_or_dict(type, decl_type, context) == FAIL)
527 return FAIL;
528 return arg_type_modifiable(type, context->arg_idx + 1);
529}
530
531/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200532 * Check "type" is a list of 'any' or a dict of 'any' or a blob.
Bram Moolenaara5d1a672022-09-30 17:57:47 +0100533 * Also check if "type" is modifiable.
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200534 */
535 static int
Bram Moolenaara5d1a672022-09-30 17:57:47 +0100536arg_list_or_dict_or_blob_mod(
537 type_T *type,
538 type_T *decl_type UNUSED,
539 argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200540{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100541 if (type->tt_type == VAR_LIST
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000542 || type->tt_type == VAR_DICT
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100543 || type->tt_type == VAR_BLOB
544 || type_any_or_unknown(type))
Bram Moolenaara5d1a672022-09-30 17:57:47 +0100545 return arg_type_modifiable(type, context->arg_idx + 1);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200546 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
547 return FAIL;
548}
549
550/*
Bram Moolenaar2d877592021-12-16 08:21:09 +0000551 * Check "type" is a list of 'any' or a dict of 'any' or a blob or a string.
552 */
553 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000554arg_list_or_dict_or_blob_or_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaar2d877592021-12-16 08:21:09 +0000555{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100556 if (type->tt_type == VAR_LIST
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000557 || type->tt_type == VAR_DICT
558 || type->tt_type == VAR_BLOB
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100559 || type->tt_type == VAR_STRING
560 || type_any_or_unknown(type))
Bram Moolenaar2d877592021-12-16 08:21:09 +0000561 return OK;
562 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
563 return FAIL;
564}
565
566/*
Bram Moolenaara5d1a672022-09-30 17:57:47 +0100567 * Check "type" is a list of 'any' or a dict of 'any' or a blob or a string.
568 * Also check the value is modifiable.
569 */
570 static int
571arg_list_or_dict_or_blob_or_string_mod(
572 type_T *type,
573 type_T *decl_type,
574 argcontext_T *context)
575{
576 if (arg_list_or_dict_or_blob_or_string(type, decl_type, context) == FAIL)
577 return FAIL;
578 return arg_type_modifiable(type, context->arg_idx + 1);
579}
580
581/*
Bram Moolenaar16f6c8a2022-02-22 15:12:14 +0000582 * Check second argument of map() or filter().
583 */
584 static int
585check_map_filter_arg2(type_T *type, argcontext_T *context, int is_map)
586{
587 type_T *expected_member = NULL;
588 type_T *(args[2]);
Bram Moolenaarb1e32ac2023-02-21 12:38:51 +0000589 type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, NULL, args};
Bram Moolenaar16f6c8a2022-02-22 15:12:14 +0000590
591 if (context->arg_types[0].type_curr->tt_type == VAR_LIST
592 || context->arg_types[0].type_curr->tt_type == VAR_DICT)
593 {
594 // Use the declared type if possible, so that an error is given if
595 // a declared list changes type, but not if a constant list changes
596 // type.
597 if (context->arg_types[0].type_decl->tt_type == VAR_LIST
598 || context->arg_types[0].type_decl->tt_type == VAR_DICT)
599 expected_member = context->arg_types[0].type_decl->tt_member;
600 else
601 expected_member = context->arg_types[0].type_curr->tt_member;
602 }
603 else if (context->arg_types[0].type_curr->tt_type == VAR_STRING)
604 expected_member = &t_string;
605 else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB)
606 expected_member = &t_number;
607
608 args[0] = NULL;
609 args[1] = &t_unknown;
610 if (type->tt_argcount != -1)
611 {
612 if (!(type->tt_argcount == 2 || (type->tt_argcount == 1
613 && (type->tt_flags & TTFLAG_VARARGS))))
614 {
615 emsg(_(e_invalid_number_of_arguments));
616 return FAIL;
617 }
618 if (type->tt_flags & TTFLAG_VARARGS)
619 // check the argument types at runtime
620 t_func_exp.tt_argcount = -1;
621 else
622 {
623 if (context->arg_types[0].type_curr->tt_type == VAR_STRING
624 || context->arg_types[0].type_curr->tt_type == VAR_BLOB
625 || context->arg_types[0].type_curr->tt_type == VAR_LIST)
626 args[0] = &t_number;
627 else if (context->arg_types[0].type_decl->tt_type == VAR_DICT)
628 args[0] = &t_string;
629 if (args[0] != NULL)
630 args[1] = expected_member;
631 }
632 }
633
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100634 if (!type_any_or_unknown(type->tt_member) || args[0] != NULL)
Bram Moolenaar16f6c8a2022-02-22 15:12:14 +0000635 {
636 where_T where = WHERE_INIT;
637
638 if (is_map)
639 t_func_exp.tt_member = expected_member == NULL
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100640 || type_any_or_unknown(type->tt_member)
Bram Moolenaar16f6c8a2022-02-22 15:12:14 +0000641 ? &t_any : expected_member;
642 else
643 t_func_exp.tt_member = &t_bool;
644 if (args[0] == NULL)
645 args[0] = &t_unknown;
Bram Moolenaar6e1a3872022-02-23 19:11:49 +0000646 if (type->tt_argcount == -1)
647 t_func_exp.tt_argcount = -1;
Bram Moolenaar16f6c8a2022-02-22 15:12:14 +0000648
649 where.wt_index = 2;
650 return check_type(&t_func_exp, type, TRUE, where);
651 }
652 return OK;
653}
654
655/*
Bram Moolenaar18024052021-12-25 21:43:28 +0000656 * Check second argument of filter(): func must return a bool.
657 */
658 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000659arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaar18024052021-12-25 21:43:28 +0000660{
Bram Moolenaar1080c482022-01-26 18:26:21 +0000661 if (type->tt_type == VAR_STRING
662 || type->tt_type == VAR_PARTIAL
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100663 || type_any_or_unknown(type))
Bram Moolenaar1080c482022-01-26 18:26:21 +0000664 return OK;
665
666 if (type->tt_type == VAR_FUNC)
Bram Moolenaar16f6c8a2022-02-22 15:12:14 +0000667 return check_map_filter_arg2(type, context, FALSE);
668 semsg(_(e_string_or_function_required_for_argument_nr), 2);
669 return FAIL;
Bram Moolenaar18024052021-12-25 21:43:28 +0000670}
671
672/*
Bram Moolenaareddd4fc2022-02-20 15:52:28 +0000673 * Check second argument of map(), the function.
Bram Moolenaar18024052021-12-25 21:43:28 +0000674 */
675 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000676arg_map_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaar18024052021-12-25 21:43:28 +0000677{
Bram Moolenaar1080c482022-01-26 18:26:21 +0000678 if (type->tt_type == VAR_STRING
679 || type->tt_type == VAR_PARTIAL
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100680 || type_any_or_unknown(type))
Bram Moolenaar1080c482022-01-26 18:26:21 +0000681 return OK;
682
683 if (type->tt_type == VAR_FUNC)
Bram Moolenaar16f6c8a2022-02-22 15:12:14 +0000684 return check_map_filter_arg2(type, context, TRUE);
685 semsg(_(e_string_or_function_required_for_argument_nr), 2);
686 return FAIL;
Bram Moolenaar18024052021-12-25 21:43:28 +0000687}
688
689/*
Bram Moolenaare843efc2022-02-22 21:54:44 +0000690 * Check second argument of sort() and uniq(), the "how" argument.
691 */
692 static int
693arg_sort_how(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
694{
695 if (type->tt_type == VAR_STRING
696 || type->tt_type == VAR_PARTIAL
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100697 || type_any_or_unknown(type))
Bram Moolenaare843efc2022-02-22 21:54:44 +0000698 return OK;
699
700 if (type->tt_type == VAR_FUNC)
701 {
702 type_T *(args[2]);
Bram Moolenaarb1e32ac2023-02-21 12:38:51 +0000703 type_T t_func_exp = {VAR_FUNC, 2, 0, 0, &t_number, NULL, args};
Bram Moolenaare843efc2022-02-22 21:54:44 +0000704
705 if (context->arg_types[0].type_curr->tt_type == VAR_LIST)
706 args[0] = context->arg_types[0].type_curr->tt_member;
707 else
708 args[0] = &t_unknown;
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100709 if (!type_any_or_unknown(type->tt_member) || args[0] != &t_unknown)
Bram Moolenaare843efc2022-02-22 21:54:44 +0000710 {
711 where_T where = WHERE_INIT;
712
713 args[1] = args[0];
Bram Moolenaarfa026162022-02-23 21:03:32 +0000714 if (type->tt_argcount == -1)
715 t_func_exp.tt_argcount = -1;
Bram Moolenaare843efc2022-02-22 21:54:44 +0000716 where.wt_index = 2;
717 return check_type(&t_func_exp, type, TRUE, where);
718 }
719
720 return OK;
721 }
722 semsg(_(e_string_or_function_required_for_argument_nr), 2);
723 return FAIL;
724}
725
726/*
Bram Moolenaar73199812021-12-26 17:18:14 +0000727 * Check an expression argument, can be a string, funcref or partial.
728 * Also accept a bool, a constant resulting from compiling a string argument.
729 * Also accept a number, one and zero are accepted.
730 */
731 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000732arg_string_or_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaar73199812021-12-26 17:18:14 +0000733{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100734 if (type->tt_type == VAR_STRING
Bram Moolenaar73199812021-12-26 17:18:14 +0000735 || type->tt_type == VAR_PARTIAL
736 || type->tt_type == VAR_FUNC
737 || type->tt_type == VAR_BOOL
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100738 || type->tt_type == VAR_NUMBER
739 || type_any_or_unknown(type))
Bram Moolenaar73199812021-12-26 17:18:14 +0000740 return OK;
741 arg_type_mismatch(&t_func_any, type, context->arg_idx + 1);
742 return FAIL;
743}
744
745/*
rbtnn0ccb5842021-12-18 18:33:46 +0000746 * Check "type" is a list of 'any' or a blob or a string.
747 */
748 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000749arg_string_list_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
rbtnn0ccb5842021-12-18 18:33:46 +0000750{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100751 if (type->tt_type == VAR_LIST
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000752 || type->tt_type == VAR_BLOB
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100753 || type->tt_type == VAR_STRING
754 || type_any_or_unknown(type))
rbtnn0ccb5842021-12-18 18:33:46 +0000755 return OK;
756 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
757 return FAIL;
758}
759
760/*
Yegappan Lakshmananf9dc2782023-05-11 15:02:56 +0100761 * Check "type" is a modifiable list of 'any' or a blob or a string.
762 */
763 static int
764arg_string_list_or_blob_mod(type_T *type, type_T *decl_type, argcontext_T *context)
765{
766 if (arg_string_list_or_blob(type, decl_type, context) == FAIL)
767 return FAIL;
768 return arg_type_modifiable(type, context->arg_idx + 1);
769}
770
771/*
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200772 * Check "type" is a job.
773 */
774 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000775arg_job(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200776{
777 return check_arg_type(&t_job, type, context);
778}
779
780/*
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +0200781 * Check "type" is a channel or a job.
782 */
783 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000784arg_chan_or_job(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +0200785{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100786 if (type->tt_type == VAR_CHANNEL
787 || type->tt_type == VAR_JOB
788 || type_any_or_unknown(type))
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +0200789 return OK;
790 arg_type_mismatch(&t_channel, type, context->arg_idx + 1);
791 return FAIL;
792}
793
794/*
Bram Moolenaar078a4612022-01-04 15:17:03 +0000795 * Check "type" can be used as the type_decl of the previous argument.
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100796 * Must not be used for the first argcheck_T entry.
797 */
798 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000799arg_same_as_prev(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100800{
Bram Moolenaar078a4612022-01-04 15:17:03 +0000801 type_T *prev_type = context->arg_types[context->arg_idx - 1].type_decl;
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100802
Bram Moolenaar351ead02021-01-16 16:07:01 +0100803 return check_arg_type(prev_type, type, context);
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100804}
805
806/*
Bram Moolenaarb0e6b512021-01-12 20:23:40 +0100807 * Check "type" is the same basic type as the previous argument, checks list or
808 * dict vs other type, but not member type.
809 * Must not be used for the first argcheck_T entry.
810 */
811 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000812arg_same_struct_as_prev(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarb0e6b512021-01-12 20:23:40 +0100813{
Bram Moolenaar078a4612022-01-04 15:17:03 +0000814 type_T *prev_type = context->arg_types[context->arg_idx - 1].type_curr;
Bram Moolenaarb0e6b512021-01-12 20:23:40 +0100815
Bram Moolenaar078a4612022-01-04 15:17:03 +0000816 if (prev_type->tt_type != context->arg_types[context->arg_idx].type_curr->tt_type)
Bram Moolenaar351ead02021-01-16 16:07:01 +0100817 return check_arg_type(prev_type, type, context);
Bram Moolenaarb0e6b512021-01-12 20:23:40 +0100818 return OK;
819}
820
821/*
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100822 * Check "type" is an item of the list or blob of the previous arg.
Bram Moolenaarca174532020-10-21 16:42:22 +0200823 * Must not be used for the first argcheck_T entry.
824 */
825 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000826arg_item_of_prev(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Bram Moolenaarca174532020-10-21 16:42:22 +0200827{
Bram Moolenaar078a4612022-01-04 15:17:03 +0000828 type_T *prev_type = context->arg_types[context->arg_idx - 1].type_curr;
Bram Moolenaarca174532020-10-21 16:42:22 +0200829 type_T *expected;
830
831 if (prev_type->tt_type == VAR_LIST)
832 expected = prev_type->tt_member;
833 else if (prev_type->tt_type == VAR_BLOB)
834 expected = &t_number;
835 else
836 // probably VAR_ANY, can't check
837 return OK;
838
Bram Moolenaar351ead02021-01-16 16:07:01 +0100839 return check_arg_type(expected, type, context);
Bram Moolenaarca174532020-10-21 16:42:22 +0200840}
841
Bram Moolenaar94738d82020-10-21 14:25:07 +0200842/*
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +0200843 * Check "type" is a string or a number or a list
844 */
845 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000846arg_str_or_nr_or_list(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +0200847{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100848 if (type->tt_type == VAR_STRING
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000849 || type->tt_type == VAR_NUMBER
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100850 || type->tt_type == VAR_LIST
851 || type_any_or_unknown(type))
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +0200852 return OK;
853 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
854 return FAIL;
855}
856
857/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200858 * Check "type" is a dict of 'any' or a string
859 */
860 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000861arg_dict_any_or_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200862{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100863 if (type->tt_type == VAR_DICT
864 || type->tt_type == VAR_STRING
865 || type_any_or_unknown(type))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200866 return OK;
867 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
868 return FAIL;
869}
870
871/*
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +0200872 * Check "type" which is the third argument of extend() (number or string or
873 * any)
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100874 */
875 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000876arg_extend3(type_T *type, type_T *decl_type, argcontext_T *context)
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100877{
Bram Moolenaar078a4612022-01-04 15:17:03 +0000878 type_T *first_type = context->arg_types[context->arg_idx - 2].type_curr;
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100879
880 if (first_type->tt_type == VAR_LIST)
Bram Moolenaar078a4612022-01-04 15:17:03 +0000881 return arg_number(type, decl_type, context);
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100882 if (first_type->tt_type == VAR_DICT)
Bram Moolenaar078a4612022-01-04 15:17:03 +0000883 return arg_string(type, decl_type, context);
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +0100884 return OK;
885}
886
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200887/*
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200888 * Check "type" which is the first argument of get() (blob or list or dict or
889 * funcref)
890 */
891 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000892arg_get1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200893{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100894 if (type->tt_type == VAR_BLOB
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200895 || type->tt_type == VAR_LIST
896 || type->tt_type == VAR_DICT
897 || type->tt_type == VAR_FUNC
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100898 || type->tt_type == VAR_PARTIAL
899 || type_any_or_unknown(type))
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200900 return OK;
901
902 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
903 return FAIL;
904}
905
906/*
907 * Check "type" which is the first argument of len() (number or string or
908 * blob or list or dict)
909 */
910 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000911arg_len1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200912{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100913 if (type->tt_type == VAR_STRING
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200914 || type->tt_type == VAR_NUMBER
915 || type->tt_type == VAR_BLOB
916 || type->tt_type == VAR_LIST
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100917 || type->tt_type == VAR_DICT
918 || type_any_or_unknown(type))
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200919 return OK;
920
921 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
922 return FAIL;
923}
924
925/*
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +0200926 * Check "type" which is the second argument of remove() (number or string or
927 * any)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200928 */
929 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000930arg_remove2(type_T *type, type_T *decl_type, argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200931{
Bram Moolenaar078a4612022-01-04 15:17:03 +0000932 type_T *first_type = context->arg_types[context->arg_idx - 1].type_curr;
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200933
934 if (first_type->tt_type == VAR_LIST || first_type->tt_type == VAR_BLOB)
Bram Moolenaar078a4612022-01-04 15:17:03 +0000935 return arg_number(type, decl_type, context);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200936 if (first_type->tt_type == VAR_DICT)
Bram Moolenaar078a4612022-01-04 15:17:03 +0000937 return arg_string_or_nr(type, decl_type, context);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200938 return OK;
939}
940
941/*
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +0200942 * Check "type" which is the first argument of repeat() (string or number or
943 * list or any)
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +0200944 */
945 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000946arg_repeat1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +0200947{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100948 if (type->tt_type == VAR_STRING
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +0200949 || type->tt_type == VAR_NUMBER
Bakudankun375141e2022-09-09 18:46:47 +0100950 || type->tt_type == VAR_BLOB
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100951 || type->tt_type == VAR_LIST
952 || type_any_or_unknown(type))
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +0200953 return OK;
954
955 arg_type_mismatch(&t_string, type, context->arg_idx + 1);
956 return FAIL;
957}
958
959/*
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +0200960 * Check "type" which is the first argument of slice() (list or blob or string
961 * or any)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200962 */
963 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000964arg_slice1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200965{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100966 if (type->tt_type == VAR_LIST
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200967 || type->tt_type == VAR_BLOB
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100968 || type->tt_type == VAR_STRING
969 || type_any_or_unknown(type))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200970 return OK;
971
972 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
973 return FAIL;
974}
975
976/*
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +0200977 * Check "type" which is the first argument of count() (string or list or dict
978 * or any)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200979 */
980 static int
Bram Moolenaar3e518a82022-08-30 17:45:33 +0100981arg_string_or_list_or_dict(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200982{
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100983 if (type->tt_type == VAR_STRING
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200984 || type->tt_type == VAR_LIST
Bram Moolenaar330d64d2022-10-09 12:55:33 +0100985 || type->tt_type == VAR_DICT
986 || type_any_or_unknown(type))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200987 return OK;
988
Bram Moolenaar3e518a82022-08-30 17:45:33 +0100989 semsg(_(e_string_list_or_dict_required_for_argument_nr),
990 context->arg_idx + 1);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200991 return FAIL;
992}
993
994/*
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +0200995 * Check "type" which is the first argument of cursor() (number or string or
996 * list or any)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200997 */
998 static int
Bram Moolenaar078a4612022-01-04 15:17:03 +0000999arg_cursor1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001000{
Bram Moolenaar330d64d2022-10-09 12:55:33 +01001001 if (type->tt_type == VAR_NUMBER
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001002 || type->tt_type == VAR_STRING
Bram Moolenaar330d64d2022-10-09 12:55:33 +01001003 || type->tt_type == VAR_LIST
1004 || type_any_or_unknown(type))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001005 return OK;
1006
1007 arg_type_mismatch(&t_number, type, context->arg_idx + 1);
1008 return FAIL;
1009}
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +01001010
1011/*
Bram Moolenaar94738d82020-10-21 14:25:07 +02001012 * Lists of functions that check the argument types of a builtin function.
1013 */
Yegappan Lakshmanan5dfe4672021-09-14 17:54:30 +02001014static argcheck_T arg1_blob[] = {arg_blob};
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001015static argcheck_T arg1_bool[] = {arg_bool};
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001016static argcheck_T arg1_buffer[] = {arg_buffer};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001017static argcheck_T arg1_buffer_or_dict_any[] = {arg_buffer_or_dict_any};
1018static argcheck_T arg1_chan_or_job[] = {arg_chan_or_job};
1019static argcheck_T arg1_dict_any[] = {arg_dict_any};
1020static argcheck_T arg1_dict_or_string[] = {arg_dict_any_or_string};
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001021static argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001022static argcheck_T arg1_job[] = {arg_job};
1023static argcheck_T arg1_list_any[] = {arg_list_any};
1024static argcheck_T arg1_list_number[] = {arg_list_number};
Yegappan Lakshmananf9dc2782023-05-11 15:02:56 +01001025static argcheck_T arg1_string_or_list_or_blob_mod[] = {arg_string_list_or_blob_mod};
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001026static argcheck_T arg1_list_or_dict[] = {arg_list_or_dict};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001027static argcheck_T arg1_list_string[] = {arg_list_string};
Bram Moolenaar3e518a82022-08-30 17:45:33 +01001028static argcheck_T arg1_string_or_list_or_dict[] = {arg_string_or_list_or_dict};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001029static argcheck_T arg1_lnum[] = {arg_lnum};
1030static argcheck_T arg1_number[] = {arg_number};
1031static argcheck_T arg1_string[] = {arg_string};
1032static argcheck_T arg1_string_or_list_any[] = {arg_string_or_list_any};
1033static argcheck_T arg1_string_or_list_string[] = {arg_string_or_list_string};
1034static argcheck_T arg1_string_or_nr[] = {arg_string_or_nr};
1035static argcheck_T arg2_any_buffer[] = {NULL, arg_buffer};
1036static argcheck_T arg2_buffer_any[] = {arg_buffer, NULL};
1037static argcheck_T arg2_buffer_bool[] = {arg_buffer, arg_bool};
1038static argcheck_T arg2_buffer_list_any[] = {arg_buffer, arg_list_any};
1039static argcheck_T arg2_buffer_lnum[] = {arg_buffer, arg_lnum};
1040static argcheck_T arg2_buffer_number[] = {arg_buffer, arg_number};
1041static argcheck_T arg2_buffer_string[] = {arg_buffer, arg_string};
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001042static argcheck_T arg2_chan_or_job_dict[] = {arg_chan_or_job, arg_dict_any};
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001043static argcheck_T arg2_chan_or_job_string[] = {arg_chan_or_job, arg_string};
Yegappan Lakshmananccfb7c62021-08-16 21:39:09 +02001044static argcheck_T arg2_dict_any_list_any[] = {arg_dict_any, arg_list_any};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001045static argcheck_T arg2_dict_any_string_or_nr[] = {arg_dict_any, arg_string_or_nr};
1046static argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string};
1047static argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr};
1048static argcheck_T arg2_job_dict[] = {arg_job, arg_dict_any};
1049static argcheck_T arg2_job_string_or_number[] = {arg_job, arg_string_or_nr};
1050static argcheck_T arg2_list_any_number[] = {arg_list_any, arg_number};
1051static argcheck_T arg2_list_any_string[] = {arg_list_any, arg_string};
1052static argcheck_T arg2_list_number[] = {arg_list_number, arg_list_number};
1053static argcheck_T arg2_list_number_bool[] = {arg_list_number, arg_bool};
Bram Moolenaarfa103972022-09-29 19:14:42 +01001054static argcheck_T arg2_listblobmod_item[] = {arg_list_or_blob_mod, arg_item_of_prev};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001055static argcheck_T arg2_lnum[] = {arg_lnum, arg_lnum};
1056static argcheck_T arg2_lnum_number[] = {arg_lnum, arg_number};
1057static argcheck_T arg2_number[] = {arg_number, arg_number};
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001058static argcheck_T arg2_number_any[] = {arg_number, NULL};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001059static argcheck_T arg2_number_bool[] = {arg_number, arg_bool};
1060static argcheck_T arg2_number_dict_any[] = {arg_number, arg_dict_any};
1061static argcheck_T arg2_number_list[] = {arg_number, arg_list_any};
1062static argcheck_T arg2_number_string[] = {arg_number, arg_string};
1063static argcheck_T arg2_number_string_or_list[] = {arg_number, arg_string_or_list_any};
1064static argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any};
1065static argcheck_T arg2_string[] = {arg_string, arg_string};
1066static argcheck_T arg2_string_any[] = {arg_string, NULL};
1067static argcheck_T arg2_string_bool[] = {arg_string, arg_bool};
1068static argcheck_T arg2_string_chan_or_job[] = {arg_string, arg_chan_or_job};
1069static argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any};
1070static argcheck_T arg2_string_list_number[] = {arg_string, arg_list_number};
1071static argcheck_T arg2_string_number[] = {arg_string, arg_number};
1072static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any};
LemonBoy0f7a3e12022-05-26 12:10:37 +01001073static argcheck_T arg2_string_or_list_bool[] = {arg_string_or_list_any, arg_bool};
Yegappan Lakshmanan4c8d2f02022-11-12 16:07:47 +00001074static argcheck_T arg2_string_or_list_number[] = {arg_string_or_list_any, arg_number};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001075static argcheck_T arg2_string_string_or_number[] = {arg_string, arg_string_or_nr};
1076static argcheck_T arg3_any_list_dict[] = {NULL, arg_list_any, arg_dict_any};
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001077static argcheck_T arg3_buffer_lnum_lnum[] = {arg_buffer, arg_lnum, arg_lnum};
1078static argcheck_T arg3_buffer_number_number[] = {arg_buffer, arg_number, arg_number};
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02001079static argcheck_T arg3_buffer_string_any[] = {arg_buffer, arg_string, NULL};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001080static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any};
1081static argcheck_T arg3_dict_number_number[] = {arg_dict_any, arg_number, arg_number};
1082static argcheck_T arg3_list_string_dict[] = {arg_list_any, arg_string, arg_dict_any};
1083static argcheck_T arg3_lnum_number_bool[] = {arg_lnum, arg_number, arg_bool};
1084static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
1085static argcheck_T arg3_number_any_dict[] = {arg_number, NULL, arg_dict_any};
1086static argcheck_T arg3_number_number_dict[] = {arg_number, arg_number, arg_dict_any};
1087static argcheck_T arg3_number_string_any[] = {arg_number, arg_string, NULL};
1088static argcheck_T arg3_number_string_buffer[] = {arg_number, arg_string, arg_buffer};
1089static argcheck_T arg3_number_string_string[] = {arg_number, arg_string, arg_string};
1090static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string};
1091static argcheck_T arg3_string_any_dict[] = {arg_string, NULL, arg_dict_any};
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001092static argcheck_T arg3_string_any_string[] = {arg_string, NULL, arg_string};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001093static argcheck_T arg3_string_bool_bool[] = {arg_string, arg_bool, arg_bool};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001094static argcheck_T arg3_string_number_bool[] = {arg_string, arg_number, arg_bool};
K.Takata11df3ae2022-10-19 14:02:40 +01001095static argcheck_T arg3_string_number_number[] = {arg_string, arg_number, arg_number};
Ernie Rael51d04d12022-05-04 15:40:22 +01001096static argcheck_T arg3_string_or_dict_bool_dict[] = {arg_string_or_dict_any, arg_bool, arg_dict_any};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001097static argcheck_T arg3_string_string_bool[] = {arg_string, arg_string, arg_bool};
1098static argcheck_T arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any};
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001099static argcheck_T arg3_string_string_number[] = {arg_string, arg_string, arg_number};
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001100static argcheck_T arg4_number_number_string_any[] = {arg_number, arg_number, arg_string, NULL};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001101static argcheck_T arg4_string_string_any_string[] = {arg_string, arg_string, NULL, arg_string};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001102static argcheck_T arg4_string_string_number_string[] = {arg_string, arg_string, arg_number, arg_string};
Yegappan Lakshmanan577922b2023-06-08 17:09:45 +01001103static argcheck_T arg4_string_number_bool_bool[] = {arg_string, arg_number, arg_bool, arg_bool};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001104/* Function specific argument types (not covered by the above) */
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001105static argcheck_T arg15_assert_fails[] = {arg_string_or_nr, arg_string_or_list_any, NULL, arg_number, arg_string};
1106static argcheck_T arg34_assert_inrange[] = {arg_float_or_nr, arg_float_or_nr, arg_float_or_nr, arg_string};
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001107static argcheck_T arg4_browse[] = {arg_bool, arg_string, arg_string, arg_string};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001108static argcheck_T arg23_chanexpr[] = {arg_chan_or_job, NULL, arg_dict_any};
1109static argcheck_T arg23_chanraw[] = {arg_chan_or_job, arg_string_or_blob, arg_dict_any};
Bram Moolenaar3e518a82022-08-30 17:45:33 +01001110static argcheck_T arg24_count[] = {arg_string_or_list_or_dict, NULL, arg_bool, arg_number};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001111static argcheck_T arg13_cursor[] = {arg_cursor1, arg_number, arg_number};
1112static argcheck_T arg12_deepcopy[] = {NULL, arg_bool};
1113static argcheck_T arg12_execute[] = {arg_string_or_list_string, arg_string};
Bram Moolenaarfa103972022-09-29 19:14:42 +01001114static argcheck_T arg23_extend[] = {arg_list_or_dict_mod, arg_same_as_prev, arg_extend3};
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001115static argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001116static argcheck_T arg23_get[] = {arg_get1, arg_string_or_nr, NULL};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001117static argcheck_T arg14_glob[] = {arg_string, arg_bool, arg_bool, arg_bool};
1118static argcheck_T arg25_globpath[] = {arg_string, arg_string, arg_bool, arg_bool, arg_bool};
1119static argcheck_T arg24_index[] = {arg_list_or_blob, arg_item_of_prev, arg_number, arg_bool};
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01001120static argcheck_T arg23_index[] = {arg_list_or_blob, arg_filter_func, arg_dict_any};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001121static argcheck_T arg23_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001122static argcheck_T arg1_len[] = {arg_len1};
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001123static argcheck_T arg3_libcall[] = {arg_string, arg_string, arg_string_or_nr};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001124static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool};
Bram Moolenaara5d1a672022-09-30 17:57:47 +01001125static argcheck_T arg2_filter[] = {arg_list_or_dict_or_blob_or_string_mod, arg_filter_func};
1126static argcheck_T arg2_map[] = {arg_list_or_dict_or_blob_or_string_mod, arg_map_func};
Bram Moolenaar18024052021-12-25 21:43:28 +00001127static argcheck_T arg2_mapnew[] = {arg_list_or_dict_or_blob_or_string, NULL};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001128static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any};
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02001129static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any, arg_number, arg_number, arg_dict_any};
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001130static argcheck_T arg119_printf[] = {arg_string_or_nr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
rbtnn0ccb5842021-12-18 18:33:46 +00001131static argcheck_T arg23_reduce[] = {arg_string_list_or_blob, NULL, NULL};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001132static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string, arg_number};
Bram Moolenaara5d1a672022-09-30 17:57:47 +01001133static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob_mod, arg_remove2, arg_number};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001134static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number};
Bram Moolenaar73199812021-12-26 17:18:14 +00001135static argcheck_T arg15_search[] = {arg_string, arg_string, arg_number, arg_number, arg_string_or_func};
1136static argcheck_T arg37_searchpair[] = {arg_string, arg_string, arg_string, arg_string, arg_string_or_func, arg_number, arg_number};
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001137static argcheck_T arg3_setbufline[] = {arg_buffer, arg_lnum, arg_str_or_nr_or_list};
1138static argcheck_T arg2_setline[] = {arg_lnum, NULL};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001139static argcheck_T arg24_setloclist[] = {arg_number, arg_list_any, arg_string, arg_dict_any};
1140static argcheck_T arg13_setqflist[] = {arg_list_any, arg_string, arg_dict_any};
1141static argcheck_T arg23_settagstack[] = {arg_number, arg_dict_any, arg_string};
1142static argcheck_T arg02_sign_getplaced[] = {arg_buffer, arg_dict_any};
1143static argcheck_T arg45_sign_place[] = {arg_number, arg_string, arg_string, arg_buffer, arg_dict_any};
1144static argcheck_T arg23_slice[] = {arg_slice1, arg_number, arg_number};
Bram Moolenaara5d1a672022-09-30 17:57:47 +01001145static argcheck_T arg13_sortuniq[] = {arg_list_any_mod, arg_sort_how, arg_dict_any};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001146static argcheck_T arg24_strpart[] = {arg_string, arg_number, arg_number, arg_bool};
1147static argcheck_T arg12_system[] = {arg_string, arg_str_or_nr_or_list};
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02001148static argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string};
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001149static argcheck_T arg23_writefile[] = {arg_list_or_blob, arg_string, arg_string};
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001150static argcheck_T arg24_match_func[] = {arg_string_or_list_any, arg_string, arg_number, arg_number};
Bram Moolenaarcd268012021-07-22 19:11:08 +02001151
Bram Moolenaar32517c42023-01-15 18:17:12 +00001152// Can be used by functions called through "f_retfunc" to create new types.
1153static garray_T *current_type_gap = NULL;
Bram Moolenaar94738d82020-10-21 14:25:07 +02001154
1155/*
1156 * Functions that return the return type of a builtin function.
Bram Moolenaara1224cb2020-10-22 12:31:49 +02001157 * Note that "argtypes" is NULL if "argcount" is zero.
Bram Moolenaar94738d82020-10-21 14:25:07 +02001158 */
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001159 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001160ret_void(int argcount UNUSED,
1161 type2_T *argtypes UNUSED,
1162 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001163{
1164 return &t_void;
1165}
1166 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001167ret_any(int argcount UNUSED,
1168 type2_T *argtypes UNUSED,
1169 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001170{
1171 return &t_any;
1172}
1173 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001174ret_bool(int argcount UNUSED,
1175 type2_T *argtypes UNUSED,
1176 type_T **decl_type UNUSED)
Bram Moolenaar403dc312020-10-17 19:29:51 +02001177{
1178 return &t_bool;
1179}
1180 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001181ret_number_bool(int argcount UNUSED,
1182 type2_T *argtypes UNUSED,
1183 type_T **decl_type UNUSED)
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001184{
1185 return &t_number_bool;
1186}
1187 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001188ret_number(int argcount UNUSED,
1189 type2_T *argtypes UNUSED,
1190 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001191{
1192 return &t_number;
1193}
1194 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001195ret_float(int argcount UNUSED,
1196 type2_T *argtypes UNUSED,
1197 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001198{
1199 return &t_float;
1200}
1201 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001202ret_string(int argcount UNUSED,
1203 type2_T *argtypes UNUSED,
1204 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001205{
1206 return &t_string;
1207}
Bram Moolenaare69f6d02020-04-01 22:11:01 +02001208 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001209ret_list_any(int argcount UNUSED,
1210 type2_T *argtypes UNUSED,
1211 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001212{
1213 return &t_list_any;
1214}
1215 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001216ret_list_number(int argcount UNUSED,
1217 type2_T *argtypes UNUSED,
Bram Moolenaar81330182022-02-01 12:11:58 +00001218 type_T **decl_type)
1219{
Bram Moolenaar81330182022-02-01 12:11:58 +00001220 *decl_type = &t_list_any;
1221 return &t_list_number;
1222}
1223 static type_T *
1224ret_list_string(int argcount UNUSED,
1225 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001226 type_T **decl_type)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001227{
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001228 *decl_type = &t_list_any;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001229 return &t_list_string;
1230}
1231 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001232ret_list_dict_any(int argcount UNUSED,
1233 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001234 type_T **decl_type)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001235{
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001236 *decl_type = &t_list_any;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001237 return &t_list_dict_any;
1238}
1239 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001240ret_list_items(int argcount UNUSED,
1241 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001242 type_T **decl_type)
Bram Moolenaarefc5db52021-07-07 21:21:30 +02001243{
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001244 *decl_type = &t_list_any;
Bram Moolenaarefc5db52021-07-07 21:21:30 +02001245 return &t_list_list_any;
1246}
mityu61065042021-07-19 20:07:21 +02001247
1248 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001249ret_list_string_items(int argcount UNUSED,
1250 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001251 type_T **decl_type)
mityu61065042021-07-19 20:07:21 +02001252{
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001253 *decl_type = &t_list_any;
mityu61065042021-07-19 20:07:21 +02001254 return &t_list_list_string;
1255}
Bram Moolenaarefc5db52021-07-07 21:21:30 +02001256 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001257ret_dict_any(int argcount UNUSED,
1258 type2_T *argtypes UNUSED,
1259 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001260{
1261 return &t_dict_any;
1262}
1263 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001264ret_job_info(int argcount,
1265 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001266 type_T **decl_type)
Bram Moolenaar64ed4d42021-01-12 21:22:31 +01001267{
1268 if (argcount == 0)
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001269 {
1270 *decl_type = &t_list_any;
Bram Moolenaar64ed4d42021-01-12 21:22:31 +01001271 return &t_list_job;
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001272 }
Bram Moolenaar64ed4d42021-01-12 21:22:31 +01001273 return &t_dict_any;
1274}
1275 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001276ret_dict_number(int argcount UNUSED,
1277 type2_T *argtypes UNUSED,
1278 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001279{
1280 return &t_dict_number;
1281}
1282 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001283ret_dict_string(int argcount UNUSED,
1284 type2_T *argtypes UNUSED,
1285 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001286{
1287 return &t_dict_string;
1288}
1289 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001290ret_blob(int argcount UNUSED,
1291 type2_T *argtypes UNUSED,
1292 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001293{
1294 return &t_blob;
1295}
1296 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001297ret_func_any(int argcount UNUSED,
1298 type2_T *argtypes UNUSED,
1299 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001300{
Bram Moolenaare69f6d02020-04-01 22:11:01 +02001301 return &t_func_any;
1302}
1303 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001304ret_func_unknown(int argcount UNUSED,
1305 type2_T *argtypes UNUSED,
1306 type_T **decl_type UNUSED)
Bram Moolenaar2f9f4cc2021-12-20 09:36:27 +00001307{
1308 return &t_func_unknown;
1309}
1310 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001311ret_channel(int argcount UNUSED,
1312 type2_T *argtypes UNUSED,
1313 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001314{
1315 return &t_channel;
1316}
1317 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001318ret_job(int argcount UNUSED,
1319 type2_T *argtypes UNUSED,
1320 type_T **decl_type UNUSED)
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001321{
1322 return &t_job;
1323}
Bram Moolenaar865af6b2020-06-18 18:45:49 +02001324 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001325ret_first_arg(int argcount,
1326 type2_T *argtypes,
1327 type_T **decl_type)
Bram Moolenaar865af6b2020-06-18 18:45:49 +02001328{
1329 if (argcount > 0)
Bram Moolenaar81330182022-02-01 12:11:58 +00001330 {
1331 *decl_type = argtypes[0].type_decl;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001332 return argtypes[0].type_curr;
Bram Moolenaar81330182022-02-01 12:11:58 +00001333 }
Bram Moolenaar865af6b2020-06-18 18:45:49 +02001334 return &t_void;
1335}
Bram Moolenaar1780f082021-07-31 22:03:59 +02001336 static type_T *
Bram Moolenaar00eb9952022-02-05 19:23:18 +00001337ret_slice(int argcount,
1338 type2_T *argtypes,
1339 type_T **decl_type)
1340{
1341 if (argcount > 0)
1342 {
1343 if (argtypes[0].type_decl != NULL)
1344 {
1345 switch (argtypes[0].type_decl->tt_type)
1346 {
1347 case VAR_STRING: *decl_type = &t_string; break;
1348 case VAR_BLOB: *decl_type = &t_blob; break;
1349 case VAR_LIST: *decl_type = &t_list_any; break;
1350 default: break;
1351 }
1352 }
1353 return argtypes[0].type_curr;
1354 }
1355 return &t_void;
1356}
1357 static type_T *
Bram Moolenaar381692b2022-02-02 20:01:27 +00001358ret_copy(int argcount,
1359 type2_T *argtypes,
1360 type_T **decl_type)
1361{
1362 if (argcount > 0)
1363 {
1364 if (argtypes[0].type_decl != NULL)
1365 {
1366 if (argtypes[0].type_decl->tt_type == VAR_LIST)
1367 *decl_type = &t_list_any;
1368 else if (argtypes[0].type_decl->tt_type == VAR_DICT)
1369 *decl_type = &t_dict_any;
1370 else
1371 *decl_type = argtypes[0].type_decl;
1372 }
1373 if (argtypes[0].type_curr != NULL)
1374 {
1375 if (argtypes[0].type_curr->tt_type == VAR_LIST)
1376 return &t_list_any;
1377 else if (argtypes[0].type_curr->tt_type == VAR_DICT)
1378 return &t_dict_any;
1379 }
1380 return argtypes[0].type_curr;
1381 }
1382 return &t_void;
1383}
1384 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001385ret_extend(int argcount,
1386 type2_T *argtypes,
1387 type_T **decl_type)
1388{
1389 if (argcount > 0)
1390 {
1391 *decl_type = argtypes[0].type_decl;
1392 // if the second argument has a different current type then the current
1393 // type is "any"
1394 if (argcount > 1 && !equal_type(argtypes[0].type_curr,
1395 argtypes[1].type_curr, 0))
1396 {
1397 if (argtypes[0].type_curr->tt_type == VAR_LIST)
1398 return &t_list_any;
1399 if (argtypes[0].type_curr->tt_type == VAR_DICT)
1400 return &t_dict_any;
1401 }
1402 return argtypes[0].type_curr;
1403 }
1404 return &t_void;
1405}
1406 static type_T *
1407ret_repeat(int argcount,
1408 type2_T *argtypes,
1409 type_T **decl_type UNUSED)
Bram Moolenaar1780f082021-07-31 22:03:59 +02001410{
Bram Moolenaarf78da4f2021-08-01 15:40:31 +02001411 if (argcount == 0)
1412 return &t_any;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001413 if (argtypes[0].type_curr == &t_number)
Bram Moolenaar1780f082021-07-31 22:03:59 +02001414 return &t_string;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001415 return argtypes[0].type_curr;
Bram Moolenaar1780f082021-07-31 22:03:59 +02001416}
Bram Moolenaarea696852020-11-09 18:31:39 +01001417// for map(): returns first argument but item type may differ
1418 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001419ret_first_cont(int argcount,
1420 type2_T *argtypes,
1421 type_T **decl_type UNUSED)
Bram Moolenaarea696852020-11-09 18:31:39 +01001422{
Bram Moolenaarf78da4f2021-08-01 15:40:31 +02001423 if (argcount > 0)
1424 {
Bram Moolenaar078a4612022-01-04 15:17:03 +00001425 if (argtypes[0].type_curr->tt_type == VAR_LIST)
Bram Moolenaarf78da4f2021-08-01 15:40:31 +02001426 return &t_list_any;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001427 if (argtypes[0].type_curr->tt_type == VAR_DICT)
Bram Moolenaarf78da4f2021-08-01 15:40:31 +02001428 return &t_dict_any;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001429 if (argtypes[0].type_curr->tt_type == VAR_BLOB)
1430 return argtypes[0].type_curr;
Bram Moolenaarf78da4f2021-08-01 15:40:31 +02001431 }
Bram Moolenaarea696852020-11-09 18:31:39 +01001432 return &t_any;
1433}
Bram Moolenaar078a4612022-01-04 15:17:03 +00001434// for getline()
1435 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001436ret_getline(int argcount,
1437 type2_T *argtypes UNUSED,
1438 type_T **decl_type UNUSED)
Bram Moolenaar078a4612022-01-04 15:17:03 +00001439{
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001440 if (argcount == 1)
1441 return &t_string;
1442 *decl_type = &t_list_any;
1443 return &t_list_string;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001444}
Bram Moolenaar08018222021-12-22 18:45:37 +00001445// for finddir()
1446 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001447ret_finddir(int argcount,
1448 type2_T *argtypes UNUSED,
1449 type_T **decl_type UNUSED)
Bram Moolenaar08018222021-12-22 18:45:37 +00001450{
1451 if (argcount < 3)
1452 return &t_string;
1453 // Depending on the count would be a string or a list of strings.
1454 return &t_any;
1455}
Bram Moolenaar32517c42023-01-15 18:17:12 +00001456// for values(): list of member of first argument
1457 static type_T *
1458ret_list_member(int argcount,
1459 type2_T *argtypes,
1460 type_T **decl_type)
1461{
1462 if (argcount > 0)
1463 {
1464 type_T *t = argtypes[0].type_decl;
1465 if (current_type_gap != NULL
1466 && (t->tt_type == VAR_DICT || t->tt_type == VAR_LIST))
1467 t = get_list_type(t->tt_member, current_type_gap);
1468 else
1469 t = &t_list_any;
1470 *decl_type = t;
1471
1472 t = argtypes[0].type_curr;
1473 if (current_type_gap != NULL
1474 && (t->tt_type == VAR_DICT || t->tt_type == VAR_LIST))
1475 return get_list_type(t->tt_member, current_type_gap);
1476 }
1477 return &t_list_any;
1478}
Bram Moolenaar865af6b2020-06-18 18:45:49 +02001479
Bram Moolenaarf151ad12020-06-30 13:38:01 +02001480/*
1481 * Used for getqflist(): returns list if there is no argument, dict if there is
1482 * one.
1483 */
1484 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001485ret_list_or_dict_0(int argcount,
1486 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001487 type_T **decl_type)
Bram Moolenaarf151ad12020-06-30 13:38:01 +02001488{
1489 if (argcount > 0)
1490 return &t_dict_any;
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001491 *decl_type = &t_list_any;
Bram Moolenaarf151ad12020-06-30 13:38:01 +02001492 return &t_list_dict_any;
1493}
1494
1495/*
1496 * Used for getloclist(): returns list if there is one argument, dict if there
1497 * are two.
1498 */
1499 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001500ret_list_or_dict_1(int argcount,
1501 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001502 type_T **decl_type)
Bram Moolenaarf151ad12020-06-30 13:38:01 +02001503{
1504 if (argcount > 1)
1505 return &t_dict_any;
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001506 *decl_type = &t_list_any;
Bram Moolenaarf151ad12020-06-30 13:38:01 +02001507 return &t_list_dict_any;
1508}
1509
Bram Moolenaar846178a2020-07-05 17:04:13 +02001510 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001511ret_argv(int argcount,
1512 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001513 type_T **decl_type)
Bram Moolenaar846178a2020-07-05 17:04:13 +02001514{
1515 // argv() returns list of strings
1516 if (argcount == 0)
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001517 {
1518 *decl_type = &t_list_any;
Bram Moolenaar846178a2020-07-05 17:04:13 +02001519 return &t_list_string;
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001520 }
Bram Moolenaar846178a2020-07-05 17:04:13 +02001521
1522 // argv(0) returns a string, but argv(-1] returns a list
1523 return &t_any;
1524}
1525
Bram Moolenaarad7c2492020-07-05 20:55:29 +02001526 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001527ret_remove(int argcount,
1528 type2_T *argtypes,
Bram Moolenaar2ac037f2022-05-09 14:12:14 +01001529 type_T **decl_type)
Bram Moolenaarad7c2492020-07-05 20:55:29 +02001530{
Bram Moolenaarf78da4f2021-08-01 15:40:31 +02001531 if (argcount > 0)
Bram Moolenaar5e654232020-09-16 15:22:00 +02001532 {
Bram Moolenaar078a4612022-01-04 15:17:03 +00001533 if (argtypes[0].type_curr->tt_type == VAR_LIST
1534 || argtypes[0].type_curr->tt_type == VAR_DICT)
Bram Moolenaar81330182022-02-01 12:11:58 +00001535 {
Bram Moolenaar2ac037f2022-05-09 14:12:14 +01001536 if (argcount == 3)
1537 {
1538 *decl_type = argtypes[0].type_decl;
1539 return argtypes[0].type_curr;
1540 }
Bram Moolenaar81330182022-02-01 12:11:58 +00001541 if (argtypes[0].type_curr->tt_type
1542 == argtypes[0].type_decl->tt_type)
1543 *decl_type = argtypes[0].type_decl->tt_member;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001544 return argtypes[0].type_curr->tt_member;
Bram Moolenaar81330182022-02-01 12:11:58 +00001545 }
Bram Moolenaar078a4612022-01-04 15:17:03 +00001546 if (argtypes[0].type_curr->tt_type == VAR_BLOB)
Bram Moolenaar5e654232020-09-16 15:22:00 +02001547 return &t_number;
1548 }
Bram Moolenaarad7c2492020-07-05 20:55:29 +02001549 return &t_any;
1550}
1551
Bram Moolenaar3d945cc2020-08-06 21:26:59 +02001552 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001553ret_getreg(int argcount,
1554 type2_T *argtypes UNUSED,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001555 type_T **decl_type)
Bram Moolenaar3d945cc2020-08-06 21:26:59 +02001556{
1557 // Assume that if the third argument is passed it's non-zero
1558 if (argcount == 3)
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001559 {
1560 *decl_type = &t_list_any;
Bram Moolenaar3d945cc2020-08-06 21:26:59 +02001561 return &t_list_string;
Bram Moolenaar82e46e52022-02-05 18:12:34 +00001562 }
Bram Moolenaar3d945cc2020-08-06 21:26:59 +02001563 return &t_string;
1564}
1565
Bram Moolenaar4a6d1b62020-08-08 17:55:49 +02001566 static type_T *
LemonBoy0f7a3e12022-05-26 12:10:37 +01001567ret_virtcol(int argcount,
1568 type2_T *argtypes UNUSED,
1569 type_T **decl_type)
1570{
1571 // Assume that if the second argument is passed it's non-zero
1572 if (argcount == 2)
1573 {
1574 *decl_type = &t_list_any;
1575 return &t_list_number;
1576 }
1577 return &t_number;
1578}
1579
1580 static type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00001581ret_maparg(int argcount,
1582 type2_T *argtypes UNUSED,
1583 type_T **decl_type UNUSED)
Bram Moolenaar4a6d1b62020-08-08 17:55:49 +02001584{
1585 // Assume that if the fourth argument is passed it's non-zero
1586 if (argcount == 4)
1587 return &t_dict_any;
1588 return &t_string;
1589}
1590
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02001591/*
1592 * Array with names and number of arguments of all internal functions
1593 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
1594 */
Bram Moolenaarac92e252019-08-03 21:58:38 +02001595typedef struct
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02001596{
Bram Moolenaar25e42232019-08-04 15:04:10 +02001597 char *f_name; // function name
1598 char f_min_argc; // minimal number of arguments
1599 char f_max_argc; // maximal number of arguments
1600 char f_argtype; // for method: FEARG_ values
Bram Moolenaar94738d82020-10-21 14:25:07 +02001601 argcheck_T *f_argcheck; // list of functions to check argument types
Bram Moolenaar81330182022-02-01 12:11:58 +00001602 type_T *(*f_retfunc)(int argcount, type2_T *argtypes,
1603 type_T **decl_type);
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001604 // return type function
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02001605 void (*f_func)(typval_T *args, typval_T *rvar);
Bram Moolenaar25e42232019-08-04 15:04:10 +02001606 // implementation of function
Bram Moolenaarac92e252019-08-03 21:58:38 +02001607} funcentry_T;
1608
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02001609// values for f_argtype; zero means it cannot be used as a method
1610#define FEARG_1 1 // base is the first argument
1611#define FEARG_2 2 // base is the second argument
Bram Moolenaar24278d22019-08-16 21:49:22 +02001612#define FEARG_3 3 // base is the third argument
Bram Moolenaaraad222c2019-09-06 22:46:09 +02001613#define FEARG_4 4 // base is the fourth argument
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02001614
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001615#if defined(HAVE_MATH_H)
Bram Moolenaar15c47602020-03-26 22:16:48 +01001616# define MATH_FUNC(name) name
1617#else
1618# define MATH_FUNC(name) NULL
1619#endif
1620#ifdef FEAT_TIMERS
1621# define TIMER_FUNC(name) name
1622#else
1623# define TIMER_FUNC(name) NULL
1624#endif
1625#ifdef FEAT_JOB_CHANNEL
1626# define JOB_FUNC(name) name
1627#else
1628# define JOB_FUNC(name) NULL
1629#endif
1630#ifdef FEAT_PROP_POPUP
1631# define PROP_FUNC(name) name
1632#else
1633# define PROP_FUNC(name) NULL
1634#endif
1635#ifdef FEAT_SIGNS
1636# define SIGN_FUNC(name) name
1637#else
1638# define SIGN_FUNC(name) NULL
1639#endif
1640#ifdef FEAT_SOUND
1641# define SOUND_FUNC(name) name
1642#else
1643# define SOUND_FUNC(name) NULL
1644#endif
1645#ifdef FEAT_TERMINAL
1646# define TERM_FUNC(name) name
1647#else
1648# define TERM_FUNC(name) NULL
1649#endif
1650
Bram Moolenaarac92e252019-08-03 21:58:38 +02001651static funcentry_T global_functions[] =
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02001652{
Bram Moolenaar94738d82020-10-21 14:25:07 +02001653 {"abs", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001654 ret_any, f_abs},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001655 {"acos", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001656 ret_float, f_acos},
Bram Moolenaarfa103972022-09-29 19:14:42 +01001657 {"add", 2, 2, FEARG_1, arg2_listblobmod_item,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001658 ret_first_arg, f_add},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001659 {"and", 2, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001660 ret_number, f_and},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001661 {"append", 2, 2, FEARG_2, arg2_setline,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001662 ret_number_bool, f_append},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001663 {"appendbufline", 3, 3, FEARG_3, arg3_setbufline,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001664 ret_number_bool, f_appendbufline},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001665 {"argc", 0, 1, 0, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001666 ret_number, f_argc},
1667 {"argidx", 0, 0, 0, NULL,
1668 ret_number, f_argidx},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001669 {"arglistid", 0, 2, 0, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001670 ret_number, f_arglistid},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001671 {"argv", 0, 2, 0, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001672 ret_argv, f_argv},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001673 {"asin", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001674 ret_float, f_asin},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001675 {"assert_beeps", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001676 ret_number_bool, f_assert_beeps},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001677 {"assert_equal", 2, 3, FEARG_2, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001678 ret_number_bool, f_assert_equal},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001679 {"assert_equalfile", 2, 3, FEARG_1, arg3_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001680 ret_number_bool, f_assert_equalfile},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001681 {"assert_exception", 1, 2, 0, arg2_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001682 ret_number_bool, f_assert_exception},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001683 {"assert_fails", 1, 5, FEARG_1, arg15_assert_fails,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001684 ret_number_bool, f_assert_fails},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001685 {"assert_false", 1, 2, FEARG_1, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001686 ret_number_bool, f_assert_false},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001687 {"assert_inrange", 3, 4, FEARG_3, arg34_assert_inrange,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001688 ret_number_bool, f_assert_inrange},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001689 {"assert_match", 2, 3, FEARG_2, arg3_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001690 ret_number_bool, f_assert_match},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001691 {"assert_nobeep", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar5b8cabf2021-04-02 18:55:57 +02001692 ret_number_bool, f_assert_nobeep},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001693 {"assert_notequal", 2, 3, FEARG_2, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001694 ret_number_bool, f_assert_notequal},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001695 {"assert_notmatch", 2, 3, FEARG_2, arg3_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001696 ret_number_bool, f_assert_notmatch},
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02001697 {"assert_report", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001698 ret_number_bool, f_assert_report},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001699 {"assert_true", 1, 2, FEARG_1, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001700 ret_number_bool, f_assert_true},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001701 {"atan", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001702 ret_float, f_atan},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001703 {"atan2", 2, 2, FEARG_1, arg2_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001704 ret_float, f_atan2},
Yegappan Lakshmanan1755a912022-05-19 10:31:47 +01001705 {"autocmd_add", 1, 1, FEARG_1, arg1_list_any,
1706 ret_number_bool, f_autocmd_add},
1707 {"autocmd_delete", 1, 1, FEARG_1, arg1_list_any,
1708 ret_number_bool, f_autocmd_delete},
1709 {"autocmd_get", 0, 1, FEARG_1, arg1_dict_any,
1710 ret_list_dict_any, f_autocmd_get},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001711 {"balloon_gettext", 0, 0, 0, NULL,
1712 ret_string,
Bram Moolenaar59716a22017-03-01 20:32:44 +01001713#ifdef FEAT_BEVAL
Bram Moolenaar15c47602020-03-26 22:16:48 +01001714 f_balloon_gettext
1715#else
1716 NULL
Bram Moolenaar59716a22017-03-01 20:32:44 +01001717#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01001718 },
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02001719 {"balloon_show", 1, 1, FEARG_1, arg1_string_or_list_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001720 ret_void,
Bram Moolenaar15c47602020-03-26 22:16:48 +01001721#ifdef FEAT_BEVAL
1722 f_balloon_show
1723#else
1724 NULL
1725#endif
1726 },
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001727 {"balloon_split", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001728 ret_list_string,
Bram Moolenaar15c47602020-03-26 22:16:48 +01001729#if defined(FEAT_BEVAL_TERM)
1730 f_balloon_split
1731#else
1732 NULL
1733#endif
1734 },
Yegappan Lakshmanan5dfe4672021-09-14 17:54:30 +02001735 {"blob2list", 1, 1, FEARG_1, arg1_blob,
1736 ret_list_number, f_blob2list},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001737 {"browse", 4, 4, 0, arg4_browse,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001738 ret_string, f_browse},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001739 {"browsedir", 2, 2, 0, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001740 ret_string, f_browsedir},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001741 {"bufadd", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001742 ret_number, f_bufadd},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001743 {"bufexists", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001744 ret_number_bool, f_bufexists},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001745 {"buffer_exists", 1, 1, FEARG_1, arg1_buffer, // obsolete
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001746 ret_number_bool, f_bufexists},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001747 {"buffer_name", 0, 1, FEARG_1, arg1_buffer, // obsolete
Bram Moolenaarb8f519e2020-10-21 14:49:08 +02001748 ret_string, f_bufname},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001749 {"buffer_number", 0, 1, FEARG_1, arg1_buffer, // obsolete
Bram Moolenaarb8f519e2020-10-21 14:49:08 +02001750 ret_number, f_bufnr},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001751 {"buflisted", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001752 ret_number_bool, f_buflisted},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001753 {"bufload", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001754 ret_void, f_bufload},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001755 {"bufloaded", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001756 ret_number_bool, f_bufloaded},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001757 {"bufname", 0, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001758 ret_string, f_bufname},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001759 {"bufnr", 0, 2, FEARG_1, arg2_buffer_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001760 ret_number, f_bufnr},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001761 {"bufwinid", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001762 ret_number, f_bufwinid},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001763 {"bufwinnr", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001764 ret_number, f_bufwinnr},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001765 {"byte2line", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001766 ret_number, f_byte2line},
Christian Brabandt67672ef2023-04-24 21:09:54 +01001767 {"byteidx", 2, 3, FEARG_1, arg3_string_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001768 ret_number, f_byteidx},
Christian Brabandt67672ef2023-04-24 21:09:54 +01001769 {"byteidxcomp", 2, 3, FEARG_1, arg3_string_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001770 ret_number, f_byteidxcomp},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001771 {"call", 2, 3, FEARG_1, arg3_any_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001772 ret_any, f_call},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001773 {"ceil", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001774 ret_float, f_ceil},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001775 {"ch_canread", 1, 1, FEARG_1, arg1_chan_or_job,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001776 ret_number_bool, JOB_FUNC(f_ch_canread)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001777 {"ch_close", 1, 1, FEARG_1, arg1_chan_or_job,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001778 ret_void, JOB_FUNC(f_ch_close)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001779 {"ch_close_in", 1, 1, FEARG_1, arg1_chan_or_job,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001780 ret_void, JOB_FUNC(f_ch_close_in)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001781 {"ch_evalexpr", 2, 3, FEARG_1, arg23_chanexpr,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001782 ret_any, JOB_FUNC(f_ch_evalexpr)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001783 {"ch_evalraw", 2, 3, FEARG_1, arg23_chanraw,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001784 ret_any, JOB_FUNC(f_ch_evalraw)},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001785 {"ch_getbufnr", 2, 2, FEARG_1, arg2_chan_or_job_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001786 ret_number, JOB_FUNC(f_ch_getbufnr)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001787 {"ch_getjob", 1, 1, FEARG_1, arg1_chan_or_job,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001788 ret_job, JOB_FUNC(f_ch_getjob)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001789 {"ch_info", 1, 1, FEARG_1, arg1_chan_or_job,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001790 ret_dict_any, JOB_FUNC(f_ch_info)},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02001791 {"ch_log", 1, 2, FEARG_1, arg2_string_chan_or_job,
Bram Moolenaar4c5678f2022-11-30 18:12:19 +00001792 ret_void, f_ch_log},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001793 {"ch_logfile", 1, 2, FEARG_1, arg2_string,
Bram Moolenaar4c5678f2022-11-30 18:12:19 +00001794 ret_void, f_ch_logfile},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001795 {"ch_open", 1, 2, FEARG_1, arg2_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001796 ret_channel, JOB_FUNC(f_ch_open)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001797 {"ch_read", 1, 2, FEARG_1, arg2_chan_or_job_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001798 ret_string, JOB_FUNC(f_ch_read)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001799 {"ch_readblob", 1, 2, FEARG_1, arg2_chan_or_job_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001800 ret_blob, JOB_FUNC(f_ch_readblob)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001801 {"ch_readraw", 1, 2, FEARG_1, arg2_chan_or_job_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001802 ret_string, JOB_FUNC(f_ch_readraw)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001803 {"ch_sendexpr", 2, 3, FEARG_1, arg23_chanexpr,
Yegappan Lakshmanan3b470ae2022-04-16 10:41:27 +01001804 ret_any, JOB_FUNC(f_ch_sendexpr)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001805 {"ch_sendraw", 2, 3, FEARG_1, arg23_chanraw,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001806 ret_void, JOB_FUNC(f_ch_sendraw)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001807 {"ch_setoptions", 2, 2, FEARG_1, arg2_chan_or_job_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001808 ret_void, JOB_FUNC(f_ch_setoptions)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001809 {"ch_status", 1, 2, FEARG_1, arg2_chan_or_job_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001810 ret_string, JOB_FUNC(f_ch_status)},
1811 {"changenr", 0, 0, 0, NULL,
1812 ret_number, f_changenr},
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02001813 {"char2nr", 1, 2, FEARG_1, arg2_string_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001814 ret_number, f_char2nr},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001815 {"charclass", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001816 ret_number, f_charclass},
Yegappan Lakshmanan4c8d2f02022-11-12 16:07:47 +00001817 {"charcol", 1, 2, FEARG_1, arg2_string_or_list_number,
Bram Moolenaar6f02b002021-01-10 20:22:54 +01001818 ret_number, f_charcol},
Yegappan Lakshmanan577922b2023-06-08 17:09:45 +01001819 {"charidx", 2, 4, FEARG_1, arg4_string_number_bool_bool,
Bram Moolenaar17793ef2020-12-28 12:56:58 +01001820 ret_number, f_charidx},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001821 {"chdir", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001822 ret_string, f_chdir},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001823 {"cindent", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001824 ret_number, f_cindent},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001825 {"clearmatches", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001826 ret_void, f_clearmatches},
Yegappan Lakshmanan4c8d2f02022-11-12 16:07:47 +00001827 {"col", 1, 2, FEARG_1, arg2_string_or_list_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001828 ret_number, f_col},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001829 {"complete", 2, 2, FEARG_2, arg2_number_list,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001830 ret_void, f_complete},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001831 {"complete_add", 1, 1, FEARG_1, arg1_dict_or_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001832 ret_number, f_complete_add},
1833 {"complete_check", 0, 0, 0, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001834 ret_number_bool, f_complete_check},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001835 {"complete_info", 0, 1, FEARG_1, arg1_list_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001836 ret_dict_any, f_complete_info},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001837 {"confirm", 1, 4, FEARG_1, arg4_string_string_number_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001838 ret_number, f_confirm},
1839 {"copy", 1, 1, FEARG_1, NULL,
Bram Moolenaar381692b2022-02-02 20:01:27 +00001840 ret_copy, f_copy},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001841 {"cos", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001842 ret_float, f_cos},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001843 {"cosh", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001844 ret_float, f_cosh},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001845 {"count", 2, 4, FEARG_1, arg24_count,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001846 ret_number, f_count},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02001847 {"cscope_connection",0,3, 0, arg3_number_string_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001848 ret_number, f_cscope_connection},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001849 {"cursor", 1, 3, FEARG_1, arg13_cursor,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001850 ret_number, f_cursor},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001851 {"debugbreak", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001852 ret_number,
Bram Moolenaar4f974752019-02-17 17:44:42 +01001853#ifdef MSWIN
Bram Moolenaar15c47602020-03-26 22:16:48 +01001854 f_debugbreak
1855#else
1856 NULL
Bram Moolenaar4551c0a2018-06-20 22:38:21 +02001857#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01001858 },
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001859 {"deepcopy", 1, 2, FEARG_1, arg12_deepcopy,
Bram Moolenaar381692b2022-02-02 20:01:27 +00001860 ret_copy, f_deepcopy},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001861 {"delete", 1, 2, FEARG_1, arg2_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001862 ret_number_bool, f_delete},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001863 {"deletebufline", 2, 3, FEARG_1, arg3_buffer_lnum_lnum,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001864 ret_number_bool, f_deletebufline},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001865 {"did_filetype", 0, 0, 0, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001866 ret_number_bool, f_did_filetype},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001867 {"diff_filler", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001868 ret_number, f_diff_filler},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001869 {"diff_hlID", 2, 2, FEARG_1, arg2_lnum_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001870 ret_number, f_diff_hlID},
h-east29b85712021-07-26 21:54:04 +02001871 {"digraph_get", 1, 1, FEARG_1, arg1_string,
1872 ret_string, f_digraph_get},
Yegappan Lakshmananfc3b7752021-09-08 14:57:42 +02001873 {"digraph_getlist",0, 1, FEARG_1, arg1_bool,
h-east29b85712021-07-26 21:54:04 +02001874 ret_list_string_items, f_digraph_getlist},
Yegappan Lakshmananfc3b7752021-09-08 14:57:42 +02001875 {"digraph_set", 2, 2, FEARG_1, arg2_string,
h-east29b85712021-07-26 21:54:04 +02001876 ret_bool, f_digraph_set},
1877 {"digraph_setlist",1, 1, FEARG_1, arg1_list_string,
1878 ret_bool, f_digraph_setlist},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001879 {"echoraw", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001880 ret_void, f_echoraw},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001881 {"empty", 1, 1, FEARG_1, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001882 ret_number_bool, f_empty},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001883 {"environ", 0, 0, 0, NULL,
1884 ret_dict_string, f_environ},
Bram Moolenaar80adaa82023-07-07 18:57:40 +01001885 {"err_teapot", 0, 1, 0, NULL,
1886 ret_number_bool, f_err_teapot},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001887 {"escape", 2, 2, FEARG_1, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001888 ret_string, f_escape},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001889 {"eval", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001890 ret_any, f_eval},
1891 {"eventhandler", 0, 0, 0, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001892 ret_number_bool, f_eventhandler},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001893 {"executable", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001894 ret_number, f_executable},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001895 {"execute", 1, 2, FEARG_1, arg12_execute,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001896 ret_string, f_execute},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001897 {"exepath", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001898 ret_string, f_exepath},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001899 {"exists", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001900 ret_number_bool, f_exists},
Bram Moolenaar26735992021-08-08 14:43:22 +02001901 {"exists_compiled", 1, 1, FEARG_1, arg1_string,
1902 ret_number_bool, f_exists_compiled},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001903 {"exp", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001904 ret_float, f_exp},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001905 {"expand", 1, 3, FEARG_1, arg3_string_bool_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001906 ret_any, f_expand},
Yegappan Lakshmanan2b74b682022-04-03 21:30:32 +01001907 {"expandcmd", 1, 2, FEARG_1, arg2_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001908 ret_string, f_expandcmd},
Bram Moolenaarfbcbffe2020-10-31 19:33:38 +01001909 {"extend", 2, 3, FEARG_1, arg23_extend,
Bram Moolenaar81330182022-02-01 12:11:58 +00001910 ret_extend, f_extend},
Bram Moolenaarb0e6b512021-01-12 20:23:40 +01001911 {"extendnew", 2, 3, FEARG_1, arg23_extendnew,
1912 ret_first_cont, f_extendnew},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001913 {"feedkeys", 1, 2, FEARG_1, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001914 ret_void, f_feedkeys},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001915 {"file_readable", 1, 1, FEARG_1, arg1_string, // obsolete
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001916 ret_number_bool, f_filereadable},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001917 {"filereadable", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01001918 ret_number_bool, f_filereadable},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001919 {"filewritable", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001920 ret_number, f_filewritable},
Bram Moolenaar18024052021-12-25 21:43:28 +00001921 {"filter", 2, 2, FEARG_1, arg2_filter,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001922 ret_first_arg, f_filter},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001923 {"finddir", 1, 3, FEARG_1, arg3_string_string_number,
Bram Moolenaar08018222021-12-22 18:45:37 +00001924 ret_finddir, f_finddir},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001925 {"findfile", 1, 3, FEARG_1, arg3_string_string_number,
Bram Moolenaar10c83dd2021-09-04 14:49:56 +02001926 ret_any, f_findfile},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001927 {"flatten", 1, 2, FEARG_1, arg2_list_any_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001928 ret_list_any, f_flatten},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001929 {"flattennew", 1, 2, FEARG_1, arg2_list_any_number,
Bram Moolenaar3b690062021-02-01 20:14:51 +01001930 ret_list_any, f_flattennew},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001931 {"float2nr", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001932 ret_number, f_float2nr},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001933 {"floor", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001934 ret_float, f_floor},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001935 {"fmod", 2, 2, FEARG_1, arg2_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001936 ret_float, f_fmod},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001937 {"fnameescape", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001938 ret_string, f_fnameescape},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02001939 {"fnamemodify", 2, 2, FEARG_1, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001940 ret_string, f_fnamemodify},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001941 {"foldclosed", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001942 ret_number, f_foldclosed},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001943 {"foldclosedend", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001944 ret_number, f_foldclosedend},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001945 {"foldlevel", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001946 ret_number, f_foldlevel},
1947 {"foldtext", 0, 0, 0, NULL,
1948 ret_string, f_foldtext},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001949 {"foldtextresult", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001950 ret_string, f_foldtextresult},
1951 {"foreground", 0, 0, 0, NULL,
1952 ret_void, f_foreground},
Bram Moolenaardd44b582022-09-15 22:03:57 +01001953 {"fullcommand", 1, 2, FEARG_1, arg2_string_bool,
Bram Moolenaar038e09e2021-02-06 12:38:51 +01001954 ret_string, f_fullcommand},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001955 {"funcref", 1, 3, FEARG_1, arg3_any_list_dict,
Bram Moolenaar2f9f4cc2021-12-20 09:36:27 +00001956 ret_func_unknown, f_funcref},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001957 {"function", 1, 3, FEARG_1, arg3_any_list_dict,
Bram Moolenaar2f9f4cc2021-12-20 09:36:27 +00001958 ret_func_unknown, f_function},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001959 {"garbagecollect", 0, 1, 0, arg1_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001960 ret_void, f_garbagecollect},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02001961 {"get", 2, 3, FEARG_1, arg23_get,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001962 ret_any, f_get},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001963 {"getbufinfo", 0, 1, FEARG_1, arg1_buffer_or_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001964 ret_list_dict_any, f_getbufinfo},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001965 {"getbufline", 2, 3, FEARG_1, arg3_buffer_lnum_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001966 ret_list_string, f_getbufline},
Bram Moolenaarce30ccc2022-11-21 19:57:04 +00001967 {"getbufoneline", 2, 2, FEARG_1, arg2_buffer_lnum,
1968 ret_string, f_getbufoneline},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02001969 {"getbufvar", 2, 3, FEARG_1, arg3_buffer_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001970 ret_any, f_getbufvar},
Kota Kato66bb9ae2023-01-17 18:31:56 +00001971 {"getcellwidths", 0, 0, 0, NULL,
1972 ret_list_any, f_getcellwidths},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001973 {"getchangelist", 0, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001974 ret_list_any, f_getchangelist},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001975 {"getchar", 0, 1, 0, arg1_bool,
Bram Moolenaar3a7503c2021-06-07 18:29:17 +02001976 ret_any, f_getchar},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001977 {"getcharmod", 0, 0, 0, NULL,
1978 ret_number, f_getcharmod},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001979 {"getcharpos", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar6f02b002021-01-10 20:22:54 +01001980 ret_list_number, f_getcharpos},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001981 {"getcharsearch", 0, 0, 0, NULL,
1982 ret_dict_any, f_getcharsearch},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02001983 {"getcharstr", 0, 1, 0, arg1_bool,
Bram Moolenaar3a7503c2021-06-07 18:29:17 +02001984 ret_string, f_getcharstr},
Shougo Matsushita79d599b2022-05-07 12:48:29 +01001985 {"getcmdcompltype", 0, 0, 0, NULL,
1986 ret_string, f_getcmdcompltype},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001987 {"getcmdline", 0, 0, 0, NULL,
1988 ret_string, f_getcmdline},
1989 {"getcmdpos", 0, 0, 0, NULL,
1990 ret_number, f_getcmdpos},
Shougo Matsushita79d599b2022-05-07 12:48:29 +01001991 {"getcmdscreenpos", 0, 0, 0, NULL,
1992 ret_number, f_getcmdscreenpos},
Bram Moolenaar94738d82020-10-21 14:25:07 +02001993 {"getcmdtype", 0, 0, 0, NULL,
1994 ret_string, f_getcmdtype},
1995 {"getcmdwintype", 0, 0, 0, NULL,
1996 ret_string, f_getcmdwintype},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001997 {"getcompletion", 2, 3, FEARG_1, arg3_string_string_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02001998 ret_list_string, f_getcompletion},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001999 {"getcurpos", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002000 ret_list_number, f_getcurpos},
Bram Moolenaar82e46e52022-02-05 18:12:34 +00002001 {"getcursorcharpos", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar6f02b002021-01-10 20:22:54 +01002002 ret_list_number, f_getcursorcharpos},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002003 {"getcwd", 0, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002004 ret_string, f_getcwd},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002005 {"getenv", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar7ad67d12021-03-10 16:08:26 +01002006 ret_any, f_getenv},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002007 {"getfontname", 0, 1, 0, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002008 ret_string, f_getfontname},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002009 {"getfperm", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002010 ret_string, f_getfperm},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002011 {"getfsize", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002012 ret_number, f_getfsize},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002013 {"getftime", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002014 ret_number, f_getftime},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002015 {"getftype", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002016 ret_string, f_getftype},
2017 {"getimstatus", 0, 0, 0, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002018 ret_number_bool, f_getimstatus},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002019 {"getjumplist", 0, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002020 ret_list_any, f_getjumplist},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002021 {"getline", 1, 2, FEARG_1, arg2_lnum,
Bram Moolenaar078a4612022-01-04 15:17:03 +00002022 ret_getline, f_getline},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002023 {"getloclist", 1, 2, 0, arg2_number_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002024 ret_list_or_dict_1, f_getloclist},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002025 {"getmarklist", 0, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002026 ret_list_dict_any, f_getmarklist},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002027 {"getmatches", 0, 1, 0, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002028 ret_list_dict_any, f_getmatches},
2029 {"getmousepos", 0, 0, 0, NULL,
2030 ret_dict_number, f_getmousepos},
Bram Moolenaar24dc19c2022-11-14 19:49:15 +00002031 {"getmouseshape", 0, 0, 0, NULL,
2032 ret_string, f_getmouseshape},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002033 {"getpid", 0, 0, 0, NULL,
2034 ret_number, f_getpid},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002035 {"getpos", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002036 ret_list_number, f_getpos},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002037 {"getqflist", 0, 1, 0, arg1_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002038 ret_list_or_dict_0, f_getqflist},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002039 {"getreg", 0, 3, FEARG_1, arg3_string_bool_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002040 ret_getreg, f_getreg},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002041 {"getreginfo", 0, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002042 ret_dict_any, f_getreginfo},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002043 {"getregtype", 0, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002044 ret_string, f_getregtype},
Yegappan Lakshmanan520f6ef2022-08-25 17:40:40 +01002045 {"getscriptinfo", 0, 1, 0, arg1_dict_any,
Yegappan Lakshmananf768c3d2022-08-22 13:15:13 +01002046 ret_list_dict_any, f_getscriptinfo},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002047 {"gettabinfo", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002048 ret_list_dict_any, f_gettabinfo},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002049 {"gettabvar", 2, 3, FEARG_1, arg3_number_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002050 ret_any, f_gettabvar},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002051 {"gettabwinvar", 3, 4, FEARG_1, arg4_number_number_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002052 ret_any, f_gettabwinvar},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002053 {"gettagstack", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002054 ret_dict_any, f_gettagstack},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002055 {"gettext", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002056 ret_string, f_gettext},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002057 {"getwininfo", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002058 ret_list_dict_any, f_getwininfo},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002059 {"getwinpos", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002060 ret_list_number, f_getwinpos},
2061 {"getwinposx", 0, 0, 0, NULL,
2062 ret_number, f_getwinposx},
2063 {"getwinposy", 0, 0, 0, NULL,
2064 ret_number, f_getwinposy},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002065 {"getwinvar", 2, 3, FEARG_1, arg3_number_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002066 ret_any, f_getwinvar},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002067 {"glob", 1, 4, FEARG_1, arg14_glob,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002068 ret_any, f_glob},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002069 {"glob2regpat", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002070 ret_string, f_glob2regpat},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002071 {"globpath", 2, 5, FEARG_2, arg25_globpath,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002072 ret_any, f_globpath},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002073 {"has", 1, 2, 0, arg2_string_bool,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002074 ret_number_bool, f_has},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002075 {"has_key", 2, 2, FEARG_1, arg2_dict_any_string_or_nr,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002076 ret_number_bool, f_has_key},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002077 {"haslocaldir", 0, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002078 ret_number, f_haslocaldir},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002079 {"hasmapto", 1, 3, FEARG_1, arg3_string_string_bool,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002080 ret_number_bool, f_hasmapto},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002081 {"highlightID", 1, 1, FEARG_1, arg1_string, // obsolete
Bram Moolenaarb8f519e2020-10-21 14:49:08 +02002082 ret_number, f_hlID},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002083 {"highlight_exists",1, 1, FEARG_1, arg1_string, // obsolete
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002084 ret_number_bool, f_hlexists},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002085 {"histadd", 2, 2, FEARG_2, arg2_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002086 ret_number_bool, f_histadd},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002087 {"histdel", 1, 2, FEARG_1, arg2_string_string_or_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002088 ret_number_bool, f_histdel},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002089 {"histget", 1, 2, FEARG_1, arg2_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002090 ret_string, f_histget},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002091 {"histnr", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002092 ret_number, f_histnr},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002093 {"hlID", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002094 ret_number, f_hlID},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002095 {"hlexists", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002096 ret_number_bool, f_hlexists},
Yegappan Lakshmanand1a8d652021-11-03 21:56:45 +00002097 {"hlget", 0, 2, FEARG_1, arg2_string_bool,
2098 ret_list_dict_any, f_hlget},
2099 {"hlset", 1, 1, FEARG_1, arg1_list_any,
2100 ret_number_bool, f_hlset},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002101 {"hostname", 0, 0, 0, NULL,
2102 ret_string, f_hostname},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002103 {"iconv", 3, 3, FEARG_1, arg3_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002104 ret_string, f_iconv},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002105 {"indent", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002106 ret_number, f_indent},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002107 {"index", 2, 4, FEARG_1, arg24_index,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002108 ret_number, f_index},
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01002109 {"indexof", 2, 3, FEARG_1, arg23_index,
2110 ret_number, f_indexof},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002111 {"input", 1, 3, FEARG_1, arg3_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002112 ret_string, f_input},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002113 {"inputdialog", 1, 3, FEARG_1, arg3_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002114 ret_string, f_inputdialog},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002115 {"inputlist", 1, 1, FEARG_1, arg1_list_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002116 ret_number, f_inputlist},
2117 {"inputrestore", 0, 0, 0, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002118 ret_number_bool, f_inputrestore},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002119 {"inputsave", 0, 0, 0, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002120 ret_number_bool, f_inputsave},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002121 {"inputsecret", 1, 2, FEARG_1, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002122 ret_string, f_inputsecret},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002123 {"insert", 2, 3, FEARG_1, arg23_insert,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002124 ret_first_arg, f_insert},
2125 {"interrupt", 0, 0, 0, NULL,
2126 ret_void, f_interrupt},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002127 {"invert", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002128 ret_number, f_invert},
LemonBoydca1d402022-04-28 15:26:33 +01002129 {"isabsolutepath", 1, 1, FEARG_1, arg1_string,
2130 ret_number_bool, f_isabsolutepath},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002131 {"isdirectory", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002132 ret_number_bool, f_isdirectory},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002133 {"isinf", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002134 ret_number, MATH_FUNC(f_isinf)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002135 {"islocked", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002136 ret_number_bool, f_islocked},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002137 {"isnan", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002138 ret_number_bool, MATH_FUNC(f_isnan)},
Bram Moolenaar3e518a82022-08-30 17:45:33 +01002139 {"items", 1, 1, FEARG_1, arg1_string_or_list_or_dict,
Bram Moolenaarefc5db52021-07-07 21:21:30 +02002140 ret_list_items, f_items},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002141 {"job_getchannel", 1, 1, FEARG_1, arg1_job,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002142 ret_channel, JOB_FUNC(f_job_getchannel)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002143 {"job_info", 0, 1, FEARG_1, arg1_job,
Bram Moolenaar64ed4d42021-01-12 21:22:31 +01002144 ret_job_info, JOB_FUNC(f_job_info)},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002145 {"job_setoptions", 2, 2, FEARG_1, arg2_job_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002146 ret_void, JOB_FUNC(f_job_setoptions)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002147 {"job_start", 1, 2, FEARG_1, arg2_string_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002148 ret_job, JOB_FUNC(f_job_start)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002149 {"job_status", 1, 1, FEARG_1, arg1_job,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002150 ret_string, JOB_FUNC(f_job_status)},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002151 {"job_stop", 1, 2, FEARG_1, arg2_job_string_or_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002152 ret_number_bool, JOB_FUNC(f_job_stop)},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002153 {"join", 1, 2, FEARG_1, arg2_list_any_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002154 ret_string, f_join},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002155 {"js_decode", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002156 ret_any, f_js_decode},
2157 {"js_encode", 1, 1, FEARG_1, NULL,
2158 ret_string, f_js_encode},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002159 {"json_decode", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002160 ret_any, f_json_decode},
2161 {"json_encode", 1, 1, FEARG_1, NULL,
2162 ret_string, f_json_encode},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002163 {"keys", 1, 1, FEARG_1, arg1_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002164 ret_list_string, f_keys},
zeertzjqcdc83932022-09-12 13:38:41 +01002165 {"keytrans", 1, 1, FEARG_1, arg1_string,
2166 ret_string, f_keytrans},
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02002167 {"last_buffer_nr", 0, 0, 0, NULL, // obsolete
Bram Moolenaarb8f519e2020-10-21 14:49:08 +02002168 ret_number, f_last_buffer_nr},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02002169 {"len", 1, 1, FEARG_1, arg1_len,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002170 ret_number, f_len},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002171 {"libcall", 3, 3, FEARG_3, arg3_libcall,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002172 ret_string, f_libcall},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002173 {"libcallnr", 3, 3, FEARG_3, arg3_libcall,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002174 ret_number, f_libcallnr},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002175 {"line", 1, 2, FEARG_1, arg2_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002176 ret_number, f_line},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002177 {"line2byte", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002178 ret_number, f_line2byte},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002179 {"lispindent", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002180 ret_number, f_lispindent},
Yegappan Lakshmanan5dfe4672021-09-14 17:54:30 +02002181 {"list2blob", 1, 1, FEARG_1, arg1_list_number,
2182 ret_blob, f_list2blob},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002183 {"list2str", 1, 2, FEARG_1, arg2_list_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002184 ret_string, f_list2str},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002185 {"listener_add", 1, 2, FEARG_2, arg2_any_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002186 ret_number, f_listener_add},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002187 {"listener_flush", 0, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002188 ret_void, f_listener_flush},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002189 {"listener_remove", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002190 ret_number_bool, f_listener_remove},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002191 {"localtime", 0, 0, 0, NULL,
2192 ret_number, f_localtime},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002193 {"log", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002194 ret_float, f_log},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002195 {"log10", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002196 ret_float, f_log10},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02002197 {"luaeval", 1, 2, FEARG_1, arg2_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002198 ret_any,
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002199#ifdef FEAT_LUA
Bram Moolenaar15c47602020-03-26 22:16:48 +01002200 f_luaeval
2201#else
2202 NULL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002203#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002204 },
Bram Moolenaar18024052021-12-25 21:43:28 +00002205 {"map", 2, 2, FEARG_1, arg2_map,
Bram Moolenaarea696852020-11-09 18:31:39 +01002206 ret_first_cont, f_map},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002207 {"maparg", 1, 4, FEARG_1, arg14_maparg,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002208 ret_maparg, f_maparg},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002209 {"mapcheck", 1, 3, FEARG_1, arg3_string_string_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002210 ret_string, f_mapcheck},
Ernie Rael09661202022-04-25 14:40:44 +01002211 {"maplist", 0, 1, 0, arg1_bool,
2212 ret_list_dict_any, f_maplist},
Bram Moolenaar18024052021-12-25 21:43:28 +00002213 {"mapnew", 2, 2, FEARG_1, arg2_mapnew,
Bram Moolenaarea696852020-11-09 18:31:39 +01002214 ret_first_cont, f_mapnew},
Ernie Rael51d04d12022-05-04 15:40:22 +01002215 {"mapset", 1, 3, FEARG_1, arg3_string_or_dict_bool_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002216 ret_void, f_mapset},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002217 {"match", 2, 4, FEARG_1, arg24_match_func,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002218 ret_any, f_match},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002219 {"matchadd", 2, 5, FEARG_1, arg25_matchadd,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002220 ret_number, f_matchadd},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002221 {"matchaddpos", 2, 5, FEARG_1, arg25_matchaddpos,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002222 ret_number, f_matchaddpos},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002223 {"matcharg", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002224 ret_list_string, f_matcharg},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002225 {"matchdelete", 1, 2, FEARG_1, arg2_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002226 ret_number_bool, f_matchdelete},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002227 {"matchend", 2, 4, FEARG_1, arg24_match_func,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002228 ret_number, f_matchend},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002229 {"matchfuzzy", 2, 3, FEARG_1, arg3_list_string_dict,
Yegappan Lakshmanan2d8e9982023-06-24 16:42:25 +01002230 ret_list_any, f_matchfuzzy},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002231 {"matchfuzzypos", 2, 3, FEARG_1, arg3_list_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002232 ret_list_any, f_matchfuzzypos},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002233 {"matchlist", 2, 4, FEARG_1, arg24_match_func,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002234 ret_list_string, f_matchlist},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002235 {"matchstr", 2, 4, FEARG_1, arg24_match_func,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002236 ret_string, f_matchstr},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002237 {"matchstrpos", 2, 4, FEARG_1, arg24_match_func,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002238 ret_list_any, f_matchstrpos},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002239 {"max", 1, 1, FEARG_1, arg1_list_or_dict,
Bram Moolenaar9ae37052021-01-22 22:31:10 +01002240 ret_number, f_max},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002241 {"menu_info", 1, 2, FEARG_1, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002242 ret_dict_any,
Bram Moolenaara2cbdea2020-03-16 21:08:31 +01002243#ifdef FEAT_MENU
Bram Moolenaar15c47602020-03-26 22:16:48 +01002244 f_menu_info
2245#else
2246 NULL
Bram Moolenaara2cbdea2020-03-16 21:08:31 +01002247#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002248 },
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002249 {"min", 1, 1, FEARG_1, arg1_list_or_dict,
Bram Moolenaar9ae37052021-01-22 22:31:10 +01002250 ret_number, f_min},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002251 {"mkdir", 1, 3, FEARG_1, arg3_string_string_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002252 ret_number_bool, f_mkdir},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002253 {"mode", 0, 1, FEARG_1, arg1_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002254 ret_string, f_mode},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002255 {"mzeval", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002256 ret_any,
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002257#ifdef FEAT_MZSCHEME
Bram Moolenaar15c47602020-03-26 22:16:48 +01002258 f_mzeval
2259#else
2260 NULL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002261#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002262 },
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002263 {"nextnonblank", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002264 ret_number, f_nextnonblank},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002265 {"nr2char", 1, 2, FEARG_1, arg2_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002266 ret_string, f_nr2char},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002267 {"or", 2, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002268 ret_number, f_or},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002269 {"pathshorten", 1, 2, FEARG_1, arg2_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002270 ret_string, f_pathshorten},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002271 {"perleval", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002272 ret_any,
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002273#ifdef FEAT_PERL
Bram Moolenaar15c47602020-03-26 22:16:48 +01002274 f_perleval
2275#else
2276 NULL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002277#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002278 },
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02002279 {"popup_atcursor", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002280 ret_number, PROP_FUNC(f_popup_atcursor)},
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02002281 {"popup_beval", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002282 ret_number, PROP_FUNC(f_popup_beval)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002283 {"popup_clear", 0, 1, 0, arg1_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002284 ret_void, PROP_FUNC(f_popup_clear)},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02002285 {"popup_close", 1, 2, FEARG_1, arg2_number_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002286 ret_void, PROP_FUNC(f_popup_close)},
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02002287 {"popup_create", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002288 ret_number, PROP_FUNC(f_popup_create)},
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02002289 {"popup_dialog", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002290 ret_number, PROP_FUNC(f_popup_dialog)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002291 {"popup_filter_menu", 2, 2, 0, arg2_number_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002292 ret_bool, PROP_FUNC(f_popup_filter_menu)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002293 {"popup_filter_yesno", 2, 2, 0, arg2_number_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002294 ret_bool, PROP_FUNC(f_popup_filter_yesno)},
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002295 {"popup_findecho", 0, 0, 0, NULL,
2296 ret_number, PROP_FUNC(f_popup_findecho)},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002297 {"popup_findinfo", 0, 0, 0, NULL,
2298 ret_number, PROP_FUNC(f_popup_findinfo)},
2299 {"popup_findpreview", 0, 0, 0, NULL,
2300 ret_number, PROP_FUNC(f_popup_findpreview)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002301 {"popup_getoptions", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002302 ret_dict_any, PROP_FUNC(f_popup_getoptions)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002303 {"popup_getpos", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002304 ret_dict_any, PROP_FUNC(f_popup_getpos)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002305 {"popup_hide", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002306 ret_void, PROP_FUNC(f_popup_hide)},
2307 {"popup_list", 0, 0, 0, NULL,
2308 ret_list_number, PROP_FUNC(f_popup_list)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002309 {"popup_locate", 2, 2, 0, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002310 ret_number, PROP_FUNC(f_popup_locate)},
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02002311 {"popup_menu", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002312 ret_number, PROP_FUNC(f_popup_menu)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002313 {"popup_move", 2, 2, FEARG_1, arg2_number_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002314 ret_void, PROP_FUNC(f_popup_move)},
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02002315 {"popup_notification", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002316 ret_number, PROP_FUNC(f_popup_notification)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002317 {"popup_setoptions", 2, 2, FEARG_1, arg2_number_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002318 ret_void, PROP_FUNC(f_popup_setoptions)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002319 {"popup_settext", 2, 2, FEARG_1, arg2_number_string_or_list,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002320 ret_void, PROP_FUNC(f_popup_settext)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002321 {"popup_show", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002322 ret_void, PROP_FUNC(f_popup_show)},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002323 {"pow", 2, 2, FEARG_1, arg2_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002324 ret_float, f_pow},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002325 {"prevnonblank", 1, 1, FEARG_1, arg1_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002326 ret_number, f_prevnonblank},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02002327 {"printf", 1, 19, FEARG_2, arg119_printf,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002328 ret_string, f_printf},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002329 {"prompt_getprompt", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002330 ret_string, JOB_FUNC(f_prompt_getprompt)},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02002331 {"prompt_setcallback", 2, 2, FEARG_1, arg2_buffer_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002332 ret_void, JOB_FUNC(f_prompt_setcallback)},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02002333 {"prompt_setinterrupt", 2, 2, FEARG_1, arg2_buffer_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002334 ret_void, JOB_FUNC(f_prompt_setinterrupt)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002335 {"prompt_setprompt", 2, 2, FEARG_1, arg2_buffer_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002336 ret_void, JOB_FUNC(f_prompt_setprompt)},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002337 {"prop_add", 3, 3, FEARG_1, arg3_number_number_dict,
Bram Moolenaar7f9969c2022-07-25 18:13:54 +01002338 ret_number, PROP_FUNC(f_prop_add)},
Yegappan Lakshmananccfb7c62021-08-16 21:39:09 +02002339 {"prop_add_list", 2, 2, FEARG_1, arg2_dict_any_list_any,
2340 ret_void, PROP_FUNC(f_prop_add_list)},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002341 {"prop_clear", 1, 3, FEARG_1, arg3_number_number_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002342 ret_void, PROP_FUNC(f_prop_clear)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002343 {"prop_find", 1, 2, FEARG_1, arg2_dict_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002344 ret_dict_any, PROP_FUNC(f_prop_find)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002345 {"prop_list", 1, 2, FEARG_1, arg2_number_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002346 ret_list_dict_any, PROP_FUNC(f_prop_list)},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002347 {"prop_remove", 1, 3, FEARG_1, arg3_dict_number_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002348 ret_number, PROP_FUNC(f_prop_remove)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002349 {"prop_type_add", 2, 2, FEARG_1, arg2_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002350 ret_void, PROP_FUNC(f_prop_type_add)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002351 {"prop_type_change", 2, 2, FEARG_1, arg2_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002352 ret_void, PROP_FUNC(f_prop_type_change)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002353 {"prop_type_delete", 1, 2, FEARG_1, arg2_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002354 ret_void, PROP_FUNC(f_prop_type_delete)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002355 {"prop_type_get", 1, 2, FEARG_1, arg2_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002356 ret_dict_any, PROP_FUNC(f_prop_type_get)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002357 {"prop_type_list", 0, 1, FEARG_1, arg1_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002358 ret_list_string, PROP_FUNC(f_prop_type_list)},
2359 {"pum_getpos", 0, 0, 0, NULL,
2360 ret_dict_number, f_pum_getpos},
2361 {"pumvisible", 0, 0, 0, NULL,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002362 ret_number_bool, f_pumvisible},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002363 {"py3eval", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002364 ret_any,
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002365#ifdef FEAT_PYTHON3
Bram Moolenaar15c47602020-03-26 22:16:48 +01002366 f_py3eval
2367#else
2368 NULL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002369#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002370 },
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002371 {"pyeval", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002372 ret_any,
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002373#ifdef FEAT_PYTHON
Bram Moolenaar15c47602020-03-26 22:16:48 +01002374 f_pyeval
2375#else
2376 NULL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002377#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002378 },
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002379 {"pyxeval", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002380 ret_any,
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01002381#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
Bram Moolenaar15c47602020-03-26 22:16:48 +01002382 f_pyxeval
2383#else
2384 NULL
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01002385#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002386 },
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002387 {"rand", 0, 1, FEARG_1, arg1_list_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002388 ret_number, f_rand},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002389 {"range", 1, 3, FEARG_1, arg3_number,
Bram Moolenaar82e46e52022-02-05 18:12:34 +00002390 ret_list_number, f_range},
K.Takata11df3ae2022-10-19 14:02:40 +01002391 {"readblob", 1, 3, FEARG_1, arg3_string_number_number,
Bram Moolenaarc423ad72021-01-13 20:38:03 +01002392 ret_blob, f_readblob},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002393 {"readdir", 1, 3, FEARG_1, arg3_string_any_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002394 ret_list_string, f_readdir},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002395 {"readdirex", 1, 3, FEARG_1, arg3_string_any_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002396 ret_list_dict_any, f_readdirex},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002397 {"readfile", 1, 3, FEARG_1, arg3_string_string_number,
Bram Moolenaarc423ad72021-01-13 20:38:03 +01002398 ret_list_string, f_readfile},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002399 {"reduce", 2, 3, FEARG_1, arg23_reduce,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002400 ret_any, f_reduce},
2401 {"reg_executing", 0, 0, 0, NULL,
2402 ret_string, f_reg_executing},
2403 {"reg_recording", 0, 0, 0, NULL,
2404 ret_string, f_reg_recording},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002405 {"reltime", 0, 2, FEARG_1, arg2_list_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002406 ret_list_any, f_reltime},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002407 {"reltimefloat", 1, 1, FEARG_1, arg1_list_number,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002408 ret_float, f_reltimefloat},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002409 {"reltimestr", 1, 1, FEARG_1, arg1_list_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002410 ret_string, f_reltimestr},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002411 {"remote_expr", 2, 4, FEARG_1, arg24_remote_expr,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002412 ret_string, f_remote_expr},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002413 {"remote_foreground", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002414 ret_string, f_remote_foreground},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002415 {"remote_peek", 1, 2, FEARG_1, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002416 ret_number, f_remote_peek},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002417 {"remote_read", 1, 2, FEARG_1, arg2_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002418 ret_string, f_remote_read},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002419 {"remote_send", 2, 3, FEARG_1, arg3_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002420 ret_string, f_remote_send},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002421 {"remote_startserver", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002422 ret_void, f_remote_startserver},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002423 {"remove", 2, 3, FEARG_1, arg23_remove,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002424 ret_remove, f_remove},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002425 {"rename", 2, 2, FEARG_1, arg2_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002426 ret_number_bool, f_rename},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002427 {"repeat", 2, 2, FEARG_1, arg2_repeat,
Bram Moolenaar1780f082021-07-31 22:03:59 +02002428 ret_repeat, f_repeat},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002429 {"resolve", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002430 ret_string, f_resolve},
Yegappan Lakshmananf9dc2782023-05-11 15:02:56 +01002431 {"reverse", 1, 1, FEARG_1, arg1_string_or_list_or_blob_mod,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002432 ret_first_arg, f_reverse},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002433 {"round", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002434 ret_float, f_round},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002435 {"rubyeval", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002436 ret_any,
Bram Moolenaare99be0e2019-03-26 22:51:09 +01002437#ifdef FEAT_RUBY
Bram Moolenaar15c47602020-03-26 22:16:48 +01002438 f_rubyeval
2439#else
2440 NULL
Bram Moolenaare99be0e2019-03-26 22:51:09 +01002441#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002442 },
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002443 {"screenattr", 2, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002444 ret_number, f_screenattr},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002445 {"screenchar", 2, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002446 ret_number, f_screenchar},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002447 {"screenchars", 2, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002448 ret_list_number, f_screenchars},
2449 {"screencol", 0, 0, 0, NULL,
2450 ret_number, f_screencol},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002451 {"screenpos", 3, 3, FEARG_1, arg3_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002452 ret_dict_number, f_screenpos},
2453 {"screenrow", 0, 0, 0, NULL,
2454 ret_number, f_screenrow},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002455 {"screenstring", 2, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002456 ret_string, f_screenstring},
Bram Moolenaarcd268012021-07-22 19:11:08 +02002457 {"search", 1, 5, FEARG_1, arg15_search,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002458 ret_number, f_search},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002459 {"searchcount", 0, 1, FEARG_1, arg1_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002460 ret_dict_any, f_searchcount},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002461 {"searchdecl", 1, 3, FEARG_1, arg3_string_bool_bool,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002462 ret_number_bool, f_searchdecl},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02002463 {"searchpair", 3, 7, 0, arg37_searchpair,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002464 ret_number, f_searchpair},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02002465 {"searchpairpos", 3, 7, 0, arg37_searchpair,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002466 ret_list_number, f_searchpairpos},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002467 {"searchpos", 1, 5, FEARG_1, arg15_search,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002468 ret_list_number, f_searchpos},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002469 {"server2client", 2, 2, FEARG_1, arg2_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002470 ret_number_bool, f_server2client},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002471 {"serverlist", 0, 0, 0, NULL,
2472 ret_string, f_serverlist},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002473 {"setbufline", 3, 3, FEARG_3, arg3_setbufline,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002474 ret_number_bool, f_setbufline},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02002475 {"setbufvar", 3, 3, FEARG_3, arg3_buffer_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002476 ret_void, f_setbufvar},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002477 {"setcellwidths", 1, 1, FEARG_1, arg1_list_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002478 ret_void, f_setcellwidths},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002479 {"setcharpos", 2, 2, FEARG_2, arg2_string_list_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002480 ret_number_bool, f_setcharpos},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002481 {"setcharsearch", 1, 1, FEARG_1, arg1_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002482 ret_void, f_setcharsearch},
Shougo Matsushita07ea5f12022-08-27 12:22:25 +01002483 {"setcmdline", 1, 2, FEARG_1, arg2_string_number,
2484 ret_number_bool, f_setcmdline},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002485 {"setcmdpos", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002486 ret_number_bool, f_setcmdpos},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002487 {"setcursorcharpos", 1, 3, FEARG_1, arg13_cursor,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002488 ret_number_bool, f_setcursorcharpos},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02002489 {"setenv", 2, 2, FEARG_2, arg2_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002490 ret_void, f_setenv},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002491 {"setfperm", 2, 2, FEARG_1, arg2_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002492 ret_number_bool, f_setfperm},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002493 {"setline", 2, 2, FEARG_2, arg2_setline,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002494 ret_number_bool, f_setline},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002495 {"setloclist", 2, 4, FEARG_2, arg24_setloclist,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002496 ret_number_bool, f_setloclist},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002497 {"setmatches", 1, 2, FEARG_1, arg2_list_any_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002498 ret_number_bool, f_setmatches},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002499 {"setpos", 2, 2, FEARG_2, arg2_string_list_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002500 ret_number_bool, f_setpos},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002501 {"setqflist", 1, 3, FEARG_1, arg13_setqflist,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002502 ret_number_bool, f_setqflist},
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02002503 {"setreg", 2, 3, FEARG_2, arg3_string_any_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002504 ret_number_bool, f_setreg},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002505 {"settabvar", 3, 3, FEARG_3, arg3_number_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002506 ret_void, f_settabvar},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002507 {"settabwinvar", 4, 4, FEARG_4, arg4_number_number_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002508 ret_void, f_settabwinvar},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002509 {"settagstack", 2, 3, FEARG_2, arg23_settagstack,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002510 ret_number_bool, f_settagstack},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002511 {"setwinvar", 3, 3, FEARG_3, arg3_number_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002512 ret_void, f_setwinvar},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002513 {"sha256", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002514 ret_string,
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002515#ifdef FEAT_CRYPT
Bram Moolenaar15c47602020-03-26 22:16:48 +01002516 f_sha256
2517#else
2518 NULL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002519#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002520 },
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002521 {"shellescape", 1, 2, FEARG_1, arg2_string_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002522 ret_string, f_shellescape},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002523 {"shiftwidth", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002524 ret_number, f_shiftwidth},
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02002525 {"sign_define", 1, 2, FEARG_1, arg2_string_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002526 ret_any, SIGN_FUNC(f_sign_define)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002527 {"sign_getdefined", 0, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002528 ret_list_dict_any, SIGN_FUNC(f_sign_getdefined)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002529 {"sign_getplaced", 0, 2, FEARG_1, arg02_sign_getplaced,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002530 ret_list_dict_any, SIGN_FUNC(f_sign_getplaced)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002531 {"sign_jump", 3, 3, FEARG_1, arg3_number_string_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002532 ret_number, SIGN_FUNC(f_sign_jump)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002533 {"sign_place", 4, 5, FEARG_1, arg45_sign_place,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002534 ret_number, SIGN_FUNC(f_sign_place)},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002535 {"sign_placelist", 1, 1, FEARG_1, arg1_list_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002536 ret_list_number, SIGN_FUNC(f_sign_placelist)},
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +02002537 {"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list_string,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002538 ret_number_bool, SIGN_FUNC(f_sign_undefine)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002539 {"sign_unplace", 1, 2, FEARG_1, arg2_string_dict,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002540 ret_number_bool, SIGN_FUNC(f_sign_unplace)},
Sean Dewara63780b2021-11-03 13:15:47 +00002541 {"sign_unplacelist", 1, 1, FEARG_1, arg1_list_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002542 ret_list_number, SIGN_FUNC(f_sign_unplacelist)},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002543 {"simplify", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002544 ret_string, f_simplify},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002545 {"sin", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002546 ret_float, f_sin},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002547 {"sinh", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002548 ret_float, f_sinh},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002549 {"slice", 2, 3, FEARG_1, arg23_slice,
Bram Moolenaar00eb9952022-02-05 19:23:18 +00002550 ret_slice, f_slice},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002551 {"sort", 1, 3, FEARG_1, arg13_sortuniq,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002552 ret_first_arg, f_sort},
2553 {"sound_clear", 0, 0, 0, NULL,
2554 ret_void, SOUND_FUNC(f_sound_clear)},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002555 {"sound_playevent", 1, 2, FEARG_1, arg2_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002556 ret_number, SOUND_FUNC(f_sound_playevent)},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002557 {"sound_playfile", 1, 2, FEARG_1, arg2_string_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002558 ret_number, SOUND_FUNC(f_sound_playfile)},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002559 {"sound_stop", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002560 ret_void, SOUND_FUNC(f_sound_stop)},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002561 {"soundfold", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002562 ret_string, f_soundfold},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002563 {"spellbadword", 0, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002564 ret_list_string, f_spellbadword},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002565 {"spellsuggest", 1, 3, FEARG_1, arg3_string_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002566 ret_list_string, f_spellsuggest},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002567 {"split", 1, 3, FEARG_1, arg3_string_string_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002568 ret_list_string, f_split},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002569 {"sqrt", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002570 ret_float, f_sqrt},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002571 {"srand", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002572 ret_list_number, f_srand},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002573 {"state", 0, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002574 ret_string, f_state},
Bram Moolenaar80a070c2021-08-08 15:51:10 +02002575 {"str2float", 1, 2, FEARG_1, arg2_string_bool,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002576 ret_float, f_str2float},
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02002577 {"str2list", 1, 2, FEARG_1, arg2_string_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002578 ret_list_number, f_str2list},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002579 {"str2nr", 1, 3, FEARG_1, arg3_string_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002580 ret_number, f_str2nr},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002581 {"strcharlen", 1, 1, FEARG_1, arg1_string_or_nr,
Bram Moolenaar70ce8a12021-03-14 19:02:09 +01002582 ret_number, f_strcharlen},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002583 {"strcharpart", 2, 4, FEARG_1, arg24_strpart,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002584 ret_string, f_strcharpart},
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02002585 {"strchars", 1, 2, FEARG_1, arg2_string_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002586 ret_number, f_strchars},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002587 {"strdisplaywidth", 1, 2, FEARG_1, arg2_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002588 ret_number, f_strdisplaywidth},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002589 {"strftime", 1, 2, FEARG_1, arg2_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002590 ret_string,
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002591#ifdef HAVE_STRFTIME
Bram Moolenaar15c47602020-03-26 22:16:48 +01002592 f_strftime
2593#else
2594 NULL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002595#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002596 },
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002597 {"strgetchar", 2, 2, FEARG_1, arg2_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002598 ret_number, f_strgetchar},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002599 {"stridx", 2, 3, FEARG_1, arg3_string_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002600 ret_number, f_stridx},
2601 {"string", 1, 1, FEARG_1, NULL,
2602 ret_string, f_string},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002603 {"strlen", 1, 1, FEARG_1, arg1_string_or_nr,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002604 ret_number, f_strlen},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002605 {"strpart", 2, 4, FEARG_1, arg24_strpart,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002606 ret_string, f_strpart},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002607 {"strptime", 2, 2, FEARG_1, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002608 ret_number,
Bram Moolenaar10455d42019-11-21 15:36:18 +01002609#ifdef HAVE_STRPTIME
Bram Moolenaar15c47602020-03-26 22:16:48 +01002610 f_strptime
2611#else
2612 NULL
Bram Moolenaar10455d42019-11-21 15:36:18 +01002613#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002614 },
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002615 {"strridx", 2, 3, FEARG_1, arg3_string_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002616 ret_number, f_strridx},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002617 {"strtrans", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002618 ret_string, f_strtrans},
Christian Brabandt67672ef2023-04-24 21:09:54 +01002619 {"strutf16len", 1, 2, FEARG_1, arg2_string_bool,
2620 ret_number, f_strutf16len},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002621 {"strwidth", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002622 ret_number, f_strwidth},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002623 {"submatch", 1, 2, FEARG_1, arg2_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002624 ret_string, f_submatch},
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02002625 {"substitute", 4, 4, FEARG_1, arg4_string_string_any_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002626 ret_string, f_substitute},
Bram Moolenaarc216a7a2022-12-05 13:50:55 +00002627 {"swapfilelist", 0, 0, 0, NULL,
2628 ret_list_string, f_swapfilelist},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002629 {"swapinfo", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002630 ret_dict_any, f_swapinfo},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002631 {"swapname", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002632 ret_string, f_swapname},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002633 {"synID", 3, 3, 0, arg3_lnum_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002634 ret_number, f_synID},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02002635 {"synIDattr", 2, 3, FEARG_1, arg3_number_string_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002636 ret_string, f_synIDattr},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002637 {"synIDtrans", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002638 ret_number, f_synIDtrans},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002639 {"synconcealed", 2, 2, 0, arg2_lnum_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002640 ret_list_any, f_synconcealed},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002641 {"synstack", 2, 2, 0, arg2_lnum_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002642 ret_list_number, f_synstack},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002643 {"system", 1, 2, FEARG_1, arg12_system,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002644 ret_string, f_system},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002645 {"systemlist", 1, 2, FEARG_1, arg12_system,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002646 ret_list_string, f_systemlist},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002647 {"tabpagebuflist", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002648 ret_list_number, f_tabpagebuflist},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002649 {"tabpagenr", 0, 1, 0, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002650 ret_number, f_tabpagenr},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002651 {"tabpagewinnr", 1, 2, FEARG_1, arg2_number_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002652 ret_number, f_tabpagewinnr},
2653 {"tagfiles", 0, 0, 0, NULL,
2654 ret_list_string, f_tagfiles},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002655 {"taglist", 1, 2, FEARG_1, arg2_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002656 ret_list_dict_any, f_taglist},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002657 {"tan", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002658 ret_float, f_tan},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002659 {"tanh", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002660 ret_float, f_tanh},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002661 {"tempname", 0, 0, 0, NULL,
2662 ret_string, f_tempname},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002663 {"term_dumpdiff", 2, 3, FEARG_1, arg3_string_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002664 ret_number, TERM_FUNC(f_term_dumpdiff)},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002665 {"term_dumpload", 1, 2, FEARG_1, arg2_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002666 ret_number, TERM_FUNC(f_term_dumpload)},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002667 {"term_dumpwrite", 2, 3, FEARG_2, arg3_buffer_string_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002668 ret_void, TERM_FUNC(f_term_dumpwrite)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002669 {"term_getaltscreen", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002670 ret_number, TERM_FUNC(f_term_getaltscreen)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002671 {"term_getansicolors", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002672 ret_list_string,
Bram Moolenaarbd5e6222020-03-26 23:13:34 +01002673#if defined(FEAT_TERMINAL) && (defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS))
Bram Moolenaar15c47602020-03-26 22:16:48 +01002674 f_term_getansicolors
2675#else
2676 NULL
Bram Moolenaarc6df10e2017-07-29 20:15:08 +02002677#endif
Bram Moolenaar15c47602020-03-26 22:16:48 +01002678 },
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002679 {"term_getattr", 2, 2, FEARG_1, arg2_number_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002680 ret_number, TERM_FUNC(f_term_getattr)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002681 {"term_getcursor", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002682 ret_list_any, TERM_FUNC(f_term_getcursor)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002683 {"term_getjob", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002684 ret_job, TERM_FUNC(f_term_getjob)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002685 {"term_getline", 2, 2, FEARG_1, arg2_buffer_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002686 ret_string, TERM_FUNC(f_term_getline)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002687 {"term_getscrolled", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002688 ret_number, TERM_FUNC(f_term_getscrolled)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002689 {"term_getsize", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002690 ret_list_number, TERM_FUNC(f_term_getsize)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002691 {"term_getstatus", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002692 ret_string, TERM_FUNC(f_term_getstatus)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002693 {"term_gettitle", 1, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002694 ret_string, TERM_FUNC(f_term_gettitle)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002695 {"term_gettty", 1, 2, FEARG_1, arg2_buffer_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002696 ret_string, TERM_FUNC(f_term_gettty)},
2697 {"term_list", 0, 0, 0, NULL,
2698 ret_list_number, TERM_FUNC(f_term_list)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002699 {"term_scrape", 2, 2, FEARG_1, arg2_buffer_lnum,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002700 ret_list_dict_any, TERM_FUNC(f_term_scrape)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002701 {"term_sendkeys", 2, 2, FEARG_1, arg2_buffer_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002702 ret_void, TERM_FUNC(f_term_sendkeys)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002703 {"term_setansicolors", 2, 2, FEARG_1, arg2_buffer_list_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002704 ret_void,
Bram Moolenaarbd5e6222020-03-26 23:13:34 +01002705#if defined(FEAT_TERMINAL) && (defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS))
Bram Moolenaar15c47602020-03-26 22:16:48 +01002706 f_term_setansicolors
2707#else
2708 NULL
2709#endif
2710 },
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002711 {"term_setapi", 2, 2, FEARG_1, arg2_buffer_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002712 ret_void, TERM_FUNC(f_term_setapi)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002713 {"term_setkill", 2, 2, FEARG_1, arg2_buffer_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002714 ret_void, TERM_FUNC(f_term_setkill)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002715 {"term_setrestore", 2, 2, FEARG_1, arg2_buffer_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002716 ret_void, TERM_FUNC(f_term_setrestore)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002717 {"term_setsize", 3, 3, FEARG_1, arg3_buffer_number_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002718 ret_void, TERM_FUNC(f_term_setsize)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002719 {"term_start", 1, 2, FEARG_1, arg2_string_or_list_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002720 ret_number, TERM_FUNC(f_term_start)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002721 {"term_wait", 1, 2, FEARG_1, arg2_buffer_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002722 ret_void, TERM_FUNC(f_term_wait)},
2723 {"terminalprops", 0, 0, 0, NULL,
2724 ret_dict_string, f_terminalprops},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002725 {"test_alloc_fail", 3, 3, FEARG_1, arg3_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002726 ret_void, f_test_alloc_fail},
2727 {"test_autochdir", 0, 0, 0, NULL,
2728 ret_void, f_test_autochdir},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002729 {"test_feedinput", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002730 ret_void, f_test_feedinput},
2731 {"test_garbagecollect_now", 0, 0, 0, NULL,
2732 ret_void, f_test_garbagecollect_now},
2733 {"test_garbagecollect_soon", 0, 0, 0, NULL,
2734 ret_void, f_test_garbagecollect_soon},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002735 {"test_getvalue", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002736 ret_number, f_test_getvalue},
Yegappan Lakshmanan06011e12022-01-30 12:37:29 +00002737 {"test_gui_event", 2, 2, FEARG_1, arg2_string_dict,
2738 ret_bool, f_test_gui_event},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002739 {"test_ignore_error", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002740 ret_void, f_test_ignore_error},
Christopher Plewright20b795e2022-12-20 20:01:58 +00002741 {"test_mswin_event", 2, 2, FEARG_1, arg2_string_dict,
2742 ret_number, f_test_mswin_event},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002743 {"test_null_blob", 0, 0, 0, NULL,
2744 ret_blob, f_test_null_blob},
2745 {"test_null_channel", 0, 0, 0, NULL,
2746 ret_channel, JOB_FUNC(f_test_null_channel)},
2747 {"test_null_dict", 0, 0, 0, NULL,
2748 ret_dict_any, f_test_null_dict},
2749 {"test_null_function", 0, 0, 0, NULL,
2750 ret_func_any, f_test_null_function},
2751 {"test_null_job", 0, 0, 0, NULL,
2752 ret_job, JOB_FUNC(f_test_null_job)},
2753 {"test_null_list", 0, 0, 0, NULL,
2754 ret_list_any, f_test_null_list},
2755 {"test_null_partial", 0, 0, 0, NULL,
2756 ret_func_any, f_test_null_partial},
2757 {"test_null_string", 0, 0, 0, NULL,
2758 ret_string, f_test_null_string},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002759 {"test_option_not_set", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002760 ret_void, f_test_option_not_set},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002761 {"test_override", 2, 2, FEARG_2, arg2_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002762 ret_void, f_test_override},
2763 {"test_refcount", 1, 1, FEARG_1, NULL,
2764 ret_number, f_test_refcount},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002765 {"test_setmouse", 2, 2, 0, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002766 ret_void, f_test_setmouse},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002767 {"test_settime", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002768 ret_void, f_test_settime},
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02002769 {"test_srand_seed", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002770 ret_void, f_test_srand_seed},
2771 {"test_unknown", 0, 0, 0, NULL,
2772 ret_any, f_test_unknown},
2773 {"test_void", 0, 0, 0, NULL,
2774 ret_void, f_test_void},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002775 {"timer_info", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002776 ret_list_dict_any, TIMER_FUNC(f_timer_info)},
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02002777 {"timer_pause", 2, 2, FEARG_1, arg2_number_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002778 ret_void, TIMER_FUNC(f_timer_pause)},
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02002779 {"timer_start", 2, 3, FEARG_1, arg3_number_any_dict,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002780 ret_number, TIMER_FUNC(f_timer_start)},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002781 {"timer_stop", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002782 ret_void, TIMER_FUNC(f_timer_stop)},
2783 {"timer_stopall", 0, 0, 0, NULL,
2784 ret_void, TIMER_FUNC(f_timer_stopall)},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002785 {"tolower", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002786 ret_string, f_tolower},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002787 {"toupper", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002788 ret_string, f_toupper},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002789 {"tr", 3, 3, FEARG_1, arg3_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002790 ret_string, f_tr},
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002791 {"trim", 1, 3, FEARG_1, arg3_string_string_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002792 ret_string, f_trim},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002793 {"trunc", 1, 1, FEARG_1, arg1_float_or_nr,
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01002794 ret_float, f_trunc},
Bram Moolenaar94738d82020-10-21 14:25:07 +02002795 {"type", 1, 1, FEARG_1, NULL,
2796 ret_number, f_type},
Bram Moolenaara47e05f2021-01-12 21:49:00 +01002797 {"typename", 1, 1, FEARG_1, NULL,
2798 ret_string, f_typename},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002799 {"undofile", 1, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002800 ret_string, f_undofile},
Devin J. Pohly5fee1112023-04-23 20:26:59 -05002801 {"undotree", 0, 1, FEARG_1, arg1_buffer,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002802 ret_dict_any, f_undotree},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002803 {"uniq", 1, 3, FEARG_1, arg13_sortuniq,
Bram Moolenaar08018222021-12-22 18:45:37 +00002804 ret_first_arg, f_uniq},
Yegappan Lakshmanan577922b2023-06-08 17:09:45 +01002805 {"utf16idx", 2, 4, FEARG_1, arg4_string_number_bool_bool,
Christian Brabandt67672ef2023-04-24 21:09:54 +01002806 ret_number, f_utf16idx},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002807 {"values", 1, 1, FEARG_1, arg1_dict_any,
Bram Moolenaar32517c42023-01-15 18:17:12 +00002808 ret_list_member, f_values},
LemonBoy0f7a3e12022-05-26 12:10:37 +01002809 {"virtcol", 1, 2, FEARG_1, arg2_string_or_list_bool,
2810 ret_virtcol, f_virtcol},
Bram Moolenaar5a6ec102022-05-27 21:58:00 +01002811 {"virtcol2col", 3, 3, FEARG_1, arg3_number,
2812 ret_number, f_virtcol2col},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002813 {"visualmode", 0, 1, 0, arg1_bool,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002814 ret_string, f_visualmode},
2815 {"wildmenumode", 0, 0, 0, NULL,
2816 ret_number, f_wildmenumode},
Bram Moolenaar52312242021-07-11 18:23:19 +02002817 {"win_execute", 2, 3, FEARG_2, arg23_win_execute,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002818 ret_string, f_win_execute},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002819 {"win_findbuf", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002820 ret_list_number, f_win_findbuf},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002821 {"win_getid", 0, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002822 ret_number, f_win_getid},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002823 {"win_gettype", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002824 ret_string, f_win_gettype},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002825 {"win_gotoid", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002826 ret_number_bool, f_win_gotoid},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002827 {"win_id2tabwin", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002828 ret_list_number, f_win_id2tabwin},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002829 {"win_id2win", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002830 ret_number, f_win_id2win},
Daniel Steinbergee630312022-01-10 13:36:34 +00002831 {"win_move_separator", 2, 2, FEARG_1, arg2_number,
2832 ret_number_bool, f_win_move_separator},
2833 {"win_move_statusline", 2, 2, FEARG_1, arg2_number,
2834 ret_number_bool, f_win_move_statusline},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002835 {"win_screenpos", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002836 ret_list_number, f_win_screenpos},
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002837 {"win_splitmove", 2, 3, FEARG_1, arg3_number_number_dict,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002838 ret_number_bool, f_win_splitmove},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002839 {"winbufnr", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002840 ret_number, f_winbufnr},
2841 {"wincol", 0, 0, 0, NULL,
2842 ret_number, f_wincol},
2843 {"windowsversion", 0, 0, 0, NULL,
2844 ret_string, f_windowsversion},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002845 {"winheight", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002846 ret_number, f_winheight},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002847 {"winlayout", 0, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002848 ret_list_any, f_winlayout},
2849 {"winline", 0, 0, 0, NULL,
2850 ret_number, f_winline},
Yegappan Lakshmanana26f56f2021-07-03 11:58:12 +02002851 {"winnr", 0, 1, FEARG_1, arg1_string,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002852 ret_number, f_winnr},
2853 {"winrestcmd", 0, 0, 0, NULL,
2854 ret_string, f_winrestcmd},
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02002855 {"winrestview", 1, 1, FEARG_1, arg1_dict_any,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002856 ret_void, f_winrestview},
2857 {"winsaveview", 0, 0, 0, NULL,
Bram Moolenaar43b69b32021-01-07 20:23:33 +01002858 ret_dict_number, f_winsaveview},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002859 {"winwidth", 1, 1, FEARG_1, arg1_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002860 ret_number, f_winwidth},
2861 {"wordcount", 0, 0, 0, NULL,
2862 ret_dict_number, f_wordcount},
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02002863 {"writefile", 2, 3, FEARG_1, arg23_writefile,
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01002864 ret_number_bool, f_writefile},
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02002865 {"xor", 2, 2, FEARG_1, arg2_number,
Bram Moolenaar94738d82020-10-21 14:25:07 +02002866 ret_number, f_xor},
Bram Moolenaarac92e252019-08-03 21:58:38 +02002867};
2868
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002869/*
2870 * Function given to ExpandGeneric() to obtain the list of internal
2871 * or user defined function names.
2872 */
2873 char_u *
2874get_function_name(expand_T *xp, int idx)
2875{
2876 static int intidx = -1;
2877 char_u *name;
2878
2879 if (idx == 0)
2880 intidx = -1;
2881 if (intidx < 0)
2882 {
2883 name = get_user_func_name(xp, idx);
naohiro ono5aec7552021-08-19 21:20:41 +02002884 if (name != NULL)
Bram Moolenaar1bb4de52021-01-13 19:48:46 +01002885 {
naohiro ono5aec7552021-08-19 21:20:41 +02002886 if (*name != NUL && *name != '<'
2887 && STRNCMP("g:", xp->xp_pattern, 2) == 0)
Bram Moolenaar1bb4de52021-01-13 19:48:46 +01002888 return cat_prefix_varname('g', name);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002889 return name;
Bram Moolenaar1bb4de52021-01-13 19:48:46 +01002890 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002891 }
K.Takataeeec2542021-06-02 13:28:16 +02002892 if (++intidx < (int)ARRAY_LENGTH(global_functions))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002893 {
Kota Kato90c23532023-01-18 15:27:38 +00002894 // Skip if the function doesn't have an implementation (feature not
2895 // implemented).
2896 if (global_functions[intidx].f_func == NULL)
2897 return (char_u *)"";
Bram Moolenaarac92e252019-08-03 21:58:38 +02002898 STRCPY(IObuff, global_functions[intidx].f_name);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002899 STRCAT(IObuff, "(");
Bram Moolenaarac92e252019-08-03 21:58:38 +02002900 if (global_functions[intidx].f_max_argc == 0)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002901 STRCAT(IObuff, ")");
2902 return IObuff;
2903 }
2904
2905 return NULL;
2906}
2907
2908/*
2909 * Function given to ExpandGeneric() to obtain the list of internal or
2910 * user defined variable or function names.
2911 */
2912 char_u *
2913get_expr_name(expand_T *xp, int idx)
2914{
2915 static int intidx = -1;
2916 char_u *name;
2917
2918 if (idx == 0)
2919 intidx = -1;
2920 if (intidx < 0)
2921 {
2922 name = get_function_name(xp, idx);
2923 if (name != NULL)
2924 return name;
2925 }
2926 return get_user_var_name(xp, ++intidx);
2927}
2928
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002929/*
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02002930 * Find internal function "name" in table "global_functions".
Bram Moolenaar15c47602020-03-26 22:16:48 +01002931 * Return index, or -1 if not found or "implemented" is TRUE and the function
2932 * is not implemented.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002933 */
Bram Moolenaar15c47602020-03-26 22:16:48 +01002934 static int
2935find_internal_func_opt(char_u *name, int implemented)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002936{
2937 int first = 0;
Bram Moolenaarac92e252019-08-03 21:58:38 +02002938 int last;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002939 int cmp;
2940 int x;
2941
K.Takataeeec2542021-06-02 13:28:16 +02002942 last = (int)ARRAY_LENGTH(global_functions) - 1;
Bram Moolenaarac92e252019-08-03 21:58:38 +02002943
2944 // Find the function name in the table. Binary search.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002945 while (first <= last)
2946 {
2947 x = first + ((unsigned)(last - first) >> 1);
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02002948 cmp = STRCMP(name, global_functions[x].f_name);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002949 if (cmp < 0)
2950 last = x - 1;
2951 else if (cmp > 0)
2952 first = x + 1;
Bram Moolenaar15c47602020-03-26 22:16:48 +01002953 else if (implemented && global_functions[x].f_func == NULL)
2954 break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002955 else
2956 return x;
2957 }
2958 return -1;
2959}
2960
Bram Moolenaar15c47602020-03-26 22:16:48 +01002961/*
2962 * Find internal function "name" in table "global_functions".
2963 * Return index, or -1 if not found or the function is not implemented.
2964 */
2965 int
2966find_internal_func(char_u *name)
2967{
2968 return find_internal_func_opt(name, TRUE);
2969}
2970
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02002971 int
Bram Moolenaarac92e252019-08-03 21:58:38 +02002972has_internal_func(char_u *name)
2973{
Bram Moolenaar15c47602020-03-26 22:16:48 +01002974 return find_internal_func_opt(name, TRUE) >= 0;
2975}
2976
2977 static int
2978has_internal_func_name(char_u *name)
2979{
2980 return find_internal_func_opt(name, FALSE) >= 0;
Bram Moolenaarac92e252019-08-03 21:58:38 +02002981}
2982
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002983 char *
2984internal_func_name(int idx)
2985{
2986 return global_functions[idx].f_name;
2987}
2988
Bram Moolenaar94738d82020-10-21 14:25:07 +02002989/*
Dominique Pellefe8ebdb2021-05-13 14:55:55 +02002990 * Check the argument types for builtin function "idx".
Bram Moolenaar94738d82020-10-21 14:25:07 +02002991 * Uses the list of types on the type stack: "types".
2992 * Return FAIL and gives an error message when a type is wrong.
2993 */
2994 int
Bram Moolenaar351ead02021-01-16 16:07:01 +01002995internal_func_check_arg_types(
Bram Moolenaar078a4612022-01-04 15:17:03 +00002996 type2_T *types,
Bram Moolenaar351ead02021-01-16 16:07:01 +01002997 int idx,
2998 int argcount,
2999 cctx_T *cctx)
Bram Moolenaar94738d82020-10-21 14:25:07 +02003000{
3001 argcheck_T *argchecks = global_functions[idx].f_argcheck;
Bram Moolenaar94738d82020-10-21 14:25:07 +02003002
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00003003 if (argchecks == NULL)
3004 return OK;
Bram Moolenaar94738d82020-10-21 14:25:07 +02003005
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00003006 argcontext_T context;
3007
3008 context.arg_count = argcount;
3009 context.arg_types = types;
3010 context.arg_cctx = cctx;
3011 for (int i = 0; i < argcount; ++i)
3012 if (argchecks[i] != NULL)
3013 {
3014 context.arg_idx = i;
3015 if (argchecks[i](types[i].type_curr, types[i].type_decl,
3016 &context) == FAIL)
3017 return FAIL;
3018 }
Bram Moolenaar94738d82020-10-21 14:25:07 +02003019 return OK;
3020}
3021
Bram Moolenaara1224cb2020-10-22 12:31:49 +02003022/*
Bram Moolenaar7a40ff02021-07-04 15:54:08 +02003023 * Get the argument count for function "idx".
3024 * "argcount" is the total argument count, "min_argcount" the non-optional
3025 * argument count.
3026 */
3027 void
3028internal_func_get_argcount(int idx, int *argcount, int *min_argcount)
3029{
3030 *argcount = global_functions[idx].f_max_argc;
3031 *min_argcount = global_functions[idx].f_min_argc;
3032}
3033
3034/*
Bram Moolenaara1224cb2020-10-22 12:31:49 +02003035 * Call the "f_retfunc" function to obtain the return type of function "idx".
Bram Moolenaar81330182022-02-01 12:11:58 +00003036 * "decl_type" is set to the declared type.
Bram Moolenaara1224cb2020-10-22 12:31:49 +02003037 * "argtypes" is the list of argument types or NULL when there are no
3038 * arguments.
Bram Moolenaarf78da4f2021-08-01 15:40:31 +02003039 * "argcount" may be less than the actual count when only getting the type.
Bram Moolenaara1224cb2020-10-22 12:31:49 +02003040 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003041 type_T *
Bram Moolenaar81330182022-02-01 12:11:58 +00003042internal_func_ret_type(
3043 int idx,
3044 int argcount,
3045 type2_T *argtypes,
Bram Moolenaar32517c42023-01-15 18:17:12 +00003046 type_T **decl_type,
3047 garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003048{
Bram Moolenaar81330182022-02-01 12:11:58 +00003049 type_T *ret;
3050
Bram Moolenaar32517c42023-01-15 18:17:12 +00003051 current_type_gap = type_gap;
Bram Moolenaar81330182022-02-01 12:11:58 +00003052 *decl_type = NULL;
3053 ret = global_functions[idx].f_retfunc(argcount, argtypes, decl_type);
3054 if (*decl_type == NULL)
3055 *decl_type = ret;
Bram Moolenaar32517c42023-01-15 18:17:12 +00003056 current_type_gap = NULL;
Bram Moolenaar81330182022-02-01 12:11:58 +00003057 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003058}
3059
3060/*
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01003061 * Return TRUE if "idx" is for the map() function.
3062 */
3063 int
3064internal_func_is_map(int idx)
3065{
3066 return global_functions[idx].f_func == f_map;
3067}
3068
3069/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003070 * Check the argument count to use for internal function "idx".
Bram Moolenaar389df252020-07-09 21:20:47 +02003071 * Returns -1 for failure, 0 if no method base accepted, 1 if method base is
3072 * first argument, 2 if method base is second argument, etc. 9 if method base
3073 * is last argument.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003074 */
3075 int
3076check_internal_func(int idx, int argcount)
3077{
Bram Moolenaar0917e862023-02-18 14:42:44 +00003078 funcerror_T res;
3079 char *name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003080
3081 if (argcount < global_functions[idx].f_min_argc)
3082 res = FCERR_TOOFEW;
3083 else if (argcount > global_functions[idx].f_max_argc)
3084 res = FCERR_TOOMANY;
3085 else
Bram Moolenaar389df252020-07-09 21:20:47 +02003086 return global_functions[idx].f_argtype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003087
3088 name = internal_func_name(idx);
3089 if (res == FCERR_TOOMANY)
Bram Moolenaare1242042021-12-16 20:56:57 +00003090 semsg(_(e_too_many_arguments_for_function_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003091 else
Bram Moolenaare1242042021-12-16 20:56:57 +00003092 semsg(_(e_not_enough_arguments_for_function_str), name);
Bram Moolenaar389df252020-07-09 21:20:47 +02003093 return -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003094}
3095
Bram Moolenaar0917e862023-02-18 14:42:44 +00003096 funcerror_T
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003097call_internal_func(
3098 char_u *name,
3099 int argcount,
3100 typval_T *argvars,
3101 typval_T *rettv)
3102{
3103 int i;
3104
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02003105 i = find_internal_func(name);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003106 if (i < 0)
Bram Moolenaaref140542019-12-31 21:27:13 +01003107 return FCERR_UNKNOWN;
Bram Moolenaarac92e252019-08-03 21:58:38 +02003108 if (argcount < global_functions[i].f_min_argc)
Bram Moolenaaref140542019-12-31 21:27:13 +01003109 return FCERR_TOOFEW;
Bram Moolenaarac92e252019-08-03 21:58:38 +02003110 if (argcount > global_functions[i].f_max_argc)
Bram Moolenaaref140542019-12-31 21:27:13 +01003111 return FCERR_TOOMANY;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003112 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarac92e252019-08-03 21:58:38 +02003113 global_functions[i].f_func(argvars, rettv);
Bram Moolenaaref140542019-12-31 21:27:13 +01003114 return FCERR_NONE;
Bram Moolenaarac92e252019-08-03 21:58:38 +02003115}
3116
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003117 void
3118call_internal_func_by_idx(
3119 int idx,
3120 typval_T *argvars,
3121 typval_T *rettv)
3122{
3123 global_functions[idx].f_func(argvars, rettv);
3124}
3125
Bram Moolenaarac92e252019-08-03 21:58:38 +02003126/*
3127 * Invoke a method for base->method().
3128 */
Bram Moolenaar0917e862023-02-18 14:42:44 +00003129 funcerror_T
Bram Moolenaarac92e252019-08-03 21:58:38 +02003130call_internal_method(
3131 char_u *name,
3132 int argcount,
3133 typval_T *argvars,
3134 typval_T *rettv,
3135 typval_T *basetv)
3136{
Bram Moolenaarac92e252019-08-03 21:58:38 +02003137 int fi;
3138 typval_T argv[MAX_FUNC_ARGS + 1];
3139
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02003140 fi = find_internal_func(name);
Bram Moolenaar91746392019-08-16 22:22:31 +02003141 if (fi < 0)
Bram Moolenaaref140542019-12-31 21:27:13 +01003142 return FCERR_UNKNOWN;
Bram Moolenaar91746392019-08-16 22:22:31 +02003143 if (global_functions[fi].f_argtype == 0)
Bram Moolenaaref140542019-12-31 21:27:13 +01003144 return FCERR_NOTMETHOD;
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02003145 if (argcount + 1 < global_functions[fi].f_min_argc)
Bram Moolenaaref140542019-12-31 21:27:13 +01003146 return FCERR_TOOFEW;
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02003147 if (argcount + 1 > global_functions[fi].f_max_argc)
Bram Moolenaaref140542019-12-31 21:27:13 +01003148 return FCERR_TOOMANY;
Bram Moolenaarac92e252019-08-03 21:58:38 +02003149
Bram Moolenaarb3468902022-01-01 19:42:16 +00003150 if (global_functions[fi].f_argtype == FEARG_2)
Bram Moolenaar25e42232019-08-04 15:04:10 +02003151 {
Bram Moolenaarb7f22702023-04-27 16:24:07 +01003152 if (argcount < 1)
3153 return FCERR_TOOFEW;
3154
Bram Moolenaar25e42232019-08-04 15:04:10 +02003155 // base value goes second
3156 argv[0] = argvars[0];
3157 argv[1] = *basetv;
Bram Moolenaar848db572022-09-20 19:04:32 +01003158 for (int i = 1; i < argcount; ++i)
Bram Moolenaar25e42232019-08-04 15:04:10 +02003159 argv[i + 1] = argvars[i];
3160 }
Bram Moolenaar24278d22019-08-16 21:49:22 +02003161 else if (global_functions[fi].f_argtype == FEARG_3)
3162 {
Bram Moolenaarb7f22702023-04-27 16:24:07 +01003163 if (argcount < 2)
3164 return FCERR_TOOFEW;
3165
Bram Moolenaar24278d22019-08-16 21:49:22 +02003166 // base value goes third
3167 argv[0] = argvars[0];
3168 argv[1] = argvars[1];
3169 argv[2] = *basetv;
Bram Moolenaar848db572022-09-20 19:04:32 +01003170 for (int i = 2; i < argcount; ++i)
Bram Moolenaar24278d22019-08-16 21:49:22 +02003171 argv[i + 1] = argvars[i];
3172 }
Bram Moolenaaraad222c2019-09-06 22:46:09 +02003173 else if (global_functions[fi].f_argtype == FEARG_4)
3174 {
Bram Moolenaarb7f22702023-04-27 16:24:07 +01003175 if (argcount < 3)
3176 return FCERR_TOOFEW;
3177
Bram Moolenaaraad222c2019-09-06 22:46:09 +02003178 // base value goes fourth
3179 argv[0] = argvars[0];
3180 argv[1] = argvars[1];
3181 argv[2] = argvars[2];
3182 argv[3] = *basetv;
Bram Moolenaar848db572022-09-20 19:04:32 +01003183 for (int i = 3; i < argcount; ++i)
Bram Moolenaaraad222c2019-09-06 22:46:09 +02003184 argv[i + 1] = argvars[i];
3185 }
Bram Moolenaar25e42232019-08-04 15:04:10 +02003186 else
3187 {
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02003188 // FEARG_1: base value goes first
Bram Moolenaar25e42232019-08-04 15:04:10 +02003189 argv[0] = *basetv;
Bram Moolenaar848db572022-09-20 19:04:32 +01003190 for (int i = 0; i < argcount; ++i)
Bram Moolenaar25e42232019-08-04 15:04:10 +02003191 argv[i + 1] = argvars[i];
3192 }
Bram Moolenaarac92e252019-08-03 21:58:38 +02003193 argv[argcount + 1].v_type = VAR_UNKNOWN;
3194
Bram Moolenaar7a4ea1d2019-08-04 21:35:12 +02003195 global_functions[fi].f_func(argv, rettv);
Bram Moolenaaref140542019-12-31 21:27:13 +01003196 return FCERR_NONE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003197}
3198
3199/*
3200 * Return TRUE for a non-zero Number and a non-empty String.
3201 */
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02003202 int
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003203non_zero_arg(typval_T *argvars)
3204{
3205 return ((argvars[0].v_type == VAR_NUMBER
3206 && argvars[0].vval.v_number != 0)
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01003207 || (argvars[0].v_type == VAR_BOOL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003208 && argvars[0].vval.v_number == VVAL_TRUE)
3209 || (argvars[0].v_type == VAR_STRING
3210 && argvars[0].vval.v_string != NULL
3211 && *argvars[0].vval.v_string != NUL));
3212}
3213
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003214/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003215 * "and(expr, expr)" function
3216 */
3217 static void
3218f_and(typval_T *argvars, typval_T *rettv)
3219{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02003220 if (in_vim9script()
3221 && (check_for_number_arg(argvars, 0) == FAIL
3222 || check_for_number_arg(argvars, 1) == FAIL))
3223 return;
3224
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003225 rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
3226 & tv_get_number_chk(&argvars[1], NULL);
Bram Moolenaarca851592018-06-06 21:04:07 +02003227}
3228
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003229/*
Bram Moolenaar59716a22017-03-01 20:32:44 +01003230 * "balloon_show()" function
3231 */
3232#ifdef FEAT_BEVAL
3233 static void
Bram Moolenaarbe0a2592019-05-09 13:50:16 +02003234f_balloon_gettext(typval_T *argvars UNUSED, typval_T *rettv)
3235{
3236 rettv->v_type = VAR_STRING;
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003237 if (balloonEval == NULL)
3238 return;
3239
3240 if (balloonEval->msg == NULL)
3241 rettv->vval.v_string = NULL;
3242 else
3243 rettv->vval.v_string = vim_strsave(balloonEval->msg);
Bram Moolenaarbe0a2592019-05-09 13:50:16 +02003244}
3245
3246 static void
Bram Moolenaar59716a22017-03-01 20:32:44 +01003247f_balloon_show(typval_T *argvars, typval_T *rettv UNUSED)
3248{
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003249 if (balloonEval == NULL)
3250 return;
3251
3252 if (in_vim9script()
3253 && check_for_string_or_list_arg(argvars, 0) == FAIL)
3254 return;
3255
3256 if (argvars[0].v_type == VAR_LIST
3257# ifdef FEAT_GUI
3258 && !gui.in_use
3259# endif
3260 )
Bram Moolenaar246fe032017-11-19 19:56:27 +01003261 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003262 list_T *l = argvars[0].vval.v_list;
3263
3264 // empty list removes the balloon
3265 post_balloon(balloonEval, NULL,
3266 l == NULL || l->lv_len == 0 ? NULL : l);
3267 }
3268 else
3269 {
3270 char_u *mesg;
3271
3272 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02003273 return;
3274
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003275 mesg = tv_get_string_chk(&argvars[0]);
3276 if (mesg != NULL)
3277 // empty string removes the balloon
3278 post_balloon(balloonEval, *mesg == NUL ? NULL : mesg, NULL);
Bram Moolenaar246fe032017-11-19 19:56:27 +01003279 }
3280}
3281
Bram Moolenaar669a8282017-11-19 20:13:05 +01003282# if defined(FEAT_BEVAL_TERM)
Bram Moolenaar246fe032017-11-19 19:56:27 +01003283 static void
3284f_balloon_split(typval_T *argvars, typval_T *rettv UNUSED)
3285{
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003286 if (rettv_list_alloc(rettv) != OK)
3287 return;
3288
3289 char_u *msg;
3290
3291 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
3292 return;
3293 msg = tv_get_string_chk(&argvars[0]);
3294 if (msg != NULL)
Bram Moolenaar246fe032017-11-19 19:56:27 +01003295 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003296 pumitem_T *array;
3297 int size = split_message(msg, &array);
Bram Moolenaar246fe032017-11-19 19:56:27 +01003298
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003299 // Skip the first and last item, they are always empty.
3300 for (int i = 1; i < size - 1; ++i)
3301 list_append_string(rettv->vval.v_list, array[i].pum_text, -1);
3302 while (size > 0)
3303 vim_free(array[--size].pum_text);
3304 vim_free(array);
Bram Moolenaar246fe032017-11-19 19:56:27 +01003305 }
Bram Moolenaar59716a22017-03-01 20:32:44 +01003306}
Bram Moolenaar669a8282017-11-19 20:13:05 +01003307# endif
Bram Moolenaar59716a22017-03-01 20:32:44 +01003308#endif
3309
3310/*
Bram Moolenaar6b7b7192019-01-11 13:42:41 +01003311 * Get the buffer from "arg" and give an error and return NULL if it is not
3312 * valid.
3313 */
Bram Moolenaara3347722019-05-11 21:14:24 +02003314 buf_T *
Bram Moolenaar6b7b7192019-01-11 13:42:41 +01003315get_buf_arg(typval_T *arg)
3316{
3317 buf_T *buf;
3318
3319 ++emsg_off;
3320 buf = tv_get_buf(arg, FALSE);
3321 --emsg_off;
3322 if (buf == NULL)
Bram Moolenaard82a47d2022-01-05 20:24:39 +00003323 semsg(_(e_invalid_buffer_name_str), tv_get_string(arg));
Bram Moolenaar6b7b7192019-01-11 13:42:41 +01003324 return buf;
3325}
3326
3327/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003328 * "byte2line(byte)" function
3329 */
3330 static void
3331f_byte2line(typval_T *argvars UNUSED, typval_T *rettv)
3332{
3333#ifndef FEAT_BYTEOFF
3334 rettv->vval.v_number = -1;
3335#else
3336 long boff = 0;
3337
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02003338 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
3339 return;
3340
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01003341 boff = tv_get_number(&argvars[0]) - 1; // boff gets -1 on type error
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003342 if (boff < 0)
3343 rettv->vval.v_number = -1;
3344 else
3345 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
3346 (linenr_T)0, &boff);
3347#endif
3348}
3349
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003350/*
3351 * "call(func, arglist [, dict])" function
3352 */
3353 static void
3354f_call(typval_T *argvars, typval_T *rettv)
3355{
3356 char_u *func;
3357 partial_T *partial = NULL;
3358 dict_T *selfdict = NULL;
Bram Moolenaar3d8e25a2022-01-22 11:00:02 +00003359 char_u *dot;
3360 char_u *tofree = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003361
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02003362 if (in_vim9script()
Bram Moolenaar223d0a62021-12-25 19:29:21 +00003363 && (check_for_string_or_func_arg(argvars, 0) == FAIL
3364 || check_for_list_arg(argvars, 1) == FAIL
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02003365 || check_for_opt_dict_arg(argvars, 2) == FAIL))
3366 return;
3367
Bram Moolenaard83392a2022-09-01 12:22:46 +01003368 if (check_for_list_arg(argvars, 1) == FAIL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003369 return;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003370 if (argvars[1].vval.v_list == NULL)
3371 return;
3372
3373 if (argvars[0].v_type == VAR_FUNC)
3374 func = argvars[0].vval.v_string;
3375 else if (argvars[0].v_type == VAR_PARTIAL)
3376 {
3377 partial = argvars[0].vval.v_partial;
Bram Moolenaar437bafe2016-08-01 15:40:54 +02003378 func = partial_name(partial);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003379 }
3380 else
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003381 func = tv_get_string(&argvars[0]);
Dominique Pellefe8ebdb2021-05-13 14:55:55 +02003382 if (func == NULL || *func == NUL)
3383 return; // type error, empty name or null function
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003384
Bram Moolenaar3d8e25a2022-01-22 11:00:02 +00003385 dot = vim_strchr(func, '.');
3386 if (dot != NULL)
3387 {
Bram Moolenaar4b1d9632022-02-13 21:51:08 +00003388 imported_T *import = find_imported(func, dot - func, TRUE);
Bram Moolenaar3d8e25a2022-01-22 11:00:02 +00003389
3390 if (import != NULL && SCRIPT_ID_VALID(import->imp_sid))
3391 {
3392 scriptitem_T *si = SCRIPT_ITEM(import->imp_sid);
3393
3394 if (si->sn_autoload_prefix != NULL)
3395 {
3396 // Turn "import.Func" into "scriptname#Func".
3397 tofree = concat_str(si->sn_autoload_prefix, dot + 1);
3398 if (tofree == NULL)
3399 return;
3400 func = tofree;
3401 }
3402 }
3403 }
3404
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003405 if (argvars[2].v_type != VAR_UNKNOWN)
3406 {
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01003407 if (check_for_dict_arg(argvars, 2) == FAIL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003408 return;
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01003409
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003410 selfdict = argvars[2].vval.v_dict;
3411 }
3412
3413 (void)func_call(func, &argvars[1], partial, selfdict, rettv);
Bram Moolenaar3d8e25a2022-01-22 11:00:02 +00003414
3415 vim_free(tofree);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003416}
3417
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003418/*
3419 * "changenr()" function
3420 */
3421 static void
3422f_changenr(typval_T *argvars UNUSED, typval_T *rettv)
3423{
3424 rettv->vval.v_number = curbuf->b_u_seq_cur;
3425}
3426
3427/*
3428 * "char2nr(string)" function
3429 */
3430 static void
3431f_char2nr(typval_T *argvars, typval_T *rettv)
3432{
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02003433 if (in_vim9script()
3434 && (check_for_string_arg(argvars, 0) == FAIL
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02003435 || check_for_opt_bool_arg(argvars, 1) == FAIL))
Bram Moolenaarc5809432021-03-27 21:23:30 +01003436 return;
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02003437
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003438 if (has_mbyte)
3439 {
3440 int utf8 = 0;
3441
3442 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar24f77502020-09-04 19:50:57 +02003443 utf8 = (int)tv_get_bool_chk(&argvars[1], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003444
3445 if (utf8)
Bram Moolenaarbdace832019-03-02 10:13:42 +01003446 rettv->vval.v_number = utf_ptr2char(tv_get_string(&argvars[0]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003447 else
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003448 rettv->vval.v_number = (*mb_ptr2char)(tv_get_string(&argvars[0]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003449 }
3450 else
Bram Moolenaar13505972019-01-24 15:04:48 +01003451 rettv->vval.v_number = tv_get_string(&argvars[0])[0];
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003452}
3453
Bram Moolenaar17793ef2020-12-28 12:56:58 +01003454/*
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003455 * Get the current cursor column and store it in 'rettv'. If 'charcol' is TRUE,
3456 * returns the character index of the column. Otherwise, returns the byte index
3457 * of the column.
3458 */
3459 static void
3460get_col(typval_T *argvars, typval_T *rettv, int charcol)
3461{
3462 colnr_T col = 0;
3463 pos_T *fp;
Yegappan Lakshmanan4c8d2f02022-11-12 16:07:47 +00003464 switchwin_T switchwin;
3465 int winchanged = FALSE;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003466
Yegappan Lakshmanan4c8d2f02022-11-12 16:07:47 +00003467 if (check_for_string_or_list_arg(argvars, 0) == FAIL
3468 || check_for_opt_number_arg(argvars, 1) == FAIL)
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02003469 return;
3470
Yegappan Lakshmanan4c8d2f02022-11-12 16:07:47 +00003471 if (argvars[1].v_type != VAR_UNKNOWN)
3472 {
3473 tabpage_T *tp;
3474 win_T *wp;
3475
3476 // use the window specified in the second argument
3477 wp = win_id2wp_tp((int)tv_get_number(&argvars[1]), &tp);
3478 if (wp == NULL || tp == NULL)
3479 return;
3480
3481 if (switch_win_noblock(&switchwin, wp, tp, TRUE) != OK)
3482 return;
3483
3484 check_cursor();
3485 winchanged = TRUE;
3486 }
3487
3488 int fnum = curbuf->b_fnum;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003489 fp = var2fpos(&argvars[0], FALSE, &fnum, charcol);
3490 if (fp != NULL && fnum == curbuf->b_fnum)
3491 {
3492 if (fp->col == MAXCOL)
3493 {
3494 // '> can be MAXCOL, get the length of the line then
3495 if (fp->lnum <= curbuf->b_ml.ml_line_count)
3496 col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
3497 else
3498 col = MAXCOL;
3499 }
3500 else
3501 {
3502 col = fp->col + 1;
3503 // col(".") when the cursor is on the NUL at the end of the line
3504 // because of "coladd" can be seen as an extra column.
3505 if (virtual_active() && fp == &curwin->w_cursor)
3506 {
3507 char_u *p = ml_get_cursor();
3508
3509 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
3510 curwin->w_virtcol - curwin->w_cursor.coladd))
3511 {
3512 int l;
3513
3514 if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
3515 col += l;
3516 }
3517 }
3518 }
3519 }
3520 rettv->vval.v_number = col;
Yegappan Lakshmanan4c8d2f02022-11-12 16:07:47 +00003521
3522 if (winchanged)
3523 restore_win_noblock(&switchwin, TRUE);
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003524}
3525
3526/*
3527 * "charcol()" function
3528 */
3529 static void
3530f_charcol(typval_T *argvars, typval_T *rettv)
3531{
3532 get_col(argvars, rettv, TRUE);
3533}
3534
Bram Moolenaar29b7d7a2019-07-22 23:03:57 +02003535 win_T *
Bram Moolenaaraff74912019-03-30 18:11:49 +01003536get_optional_window(typval_T *argvars, int idx)
3537{
3538 win_T *win = curwin;
3539
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00003540 if (argvars[idx].v_type == VAR_UNKNOWN)
3541 return curwin;
3542
3543 win = find_win_by_nr_or_id(&argvars[idx]);
3544 if (win == NULL)
Bram Moolenaaraff74912019-03-30 18:11:49 +01003545 {
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00003546 emsg(_(e_invalid_window_number));
3547 return NULL;
Bram Moolenaaraff74912019-03-30 18:11:49 +01003548 }
3549 return win;
3550}
3551
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003552/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003553 * "col(string)" function
3554 */
3555 static void
3556f_col(typval_T *argvars, typval_T *rettv)
3557{
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003558 get_col(argvars, rettv, FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003559}
3560
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003561/*
3562 * "confirm(message, buttons[, default [, type]])" function
3563 */
3564 static void
3565f_confirm(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
3566{
3567#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
3568 char_u *message;
3569 char_u *buttons = NULL;
3570 char_u buf[NUMBUFLEN];
3571 char_u buf2[NUMBUFLEN];
3572 int def = 1;
3573 int type = VIM_GENERIC;
3574 char_u *typestr;
3575 int error = FALSE;
3576
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02003577 if (in_vim9script()
3578 && (check_for_string_arg(argvars, 0) == FAIL
3579 || (check_for_opt_string_arg(argvars, 1) == FAIL
3580 || (argvars[1].v_type != VAR_UNKNOWN
3581 && (check_for_opt_number_arg(argvars, 2) == FAIL
3582 || (argvars[2].v_type != VAR_UNKNOWN
3583 && check_for_opt_string_arg(argvars, 3) == FAIL))))))
Bram Moolenaarc5809432021-03-27 21:23:30 +01003584 return;
3585
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003586 message = tv_get_string_chk(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003587 if (message == NULL)
3588 error = TRUE;
3589 if (argvars[1].v_type != VAR_UNKNOWN)
3590 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003591 buttons = tv_get_string_buf_chk(&argvars[1], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003592 if (buttons == NULL)
3593 error = TRUE;
3594 if (argvars[2].v_type != VAR_UNKNOWN)
3595 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003596 def = (int)tv_get_number_chk(&argvars[2], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003597 if (argvars[3].v_type != VAR_UNKNOWN)
3598 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003599 typestr = tv_get_string_buf_chk(&argvars[3], buf2);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003600 if (typestr == NULL)
3601 error = TRUE;
3602 else
3603 {
3604 switch (TOUPPER_ASC(*typestr))
3605 {
3606 case 'E': type = VIM_ERROR; break;
3607 case 'Q': type = VIM_QUESTION; break;
3608 case 'I': type = VIM_INFO; break;
3609 case 'W': type = VIM_WARNING; break;
3610 case 'G': type = VIM_GENERIC; break;
3611 }
3612 }
3613 }
3614 }
3615 }
3616
3617 if (buttons == NULL || *buttons == NUL)
3618 buttons = (char_u *)_("&Ok");
3619
3620 if (!error)
3621 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
3622 def, NULL, FALSE);
3623#endif
3624}
3625
3626/*
3627 * "copy()" function
3628 */
3629 static void
3630f_copy(typval_T *argvars, typval_T *rettv)
3631{
Bram Moolenaar381692b2022-02-02 20:01:27 +00003632 item_copy(&argvars[0], rettv, FALSE, TRUE, 0);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003633}
3634
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003635/*
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003636 * Set the cursor position.
Yegappan Lakshmanan577922b2023-06-08 17:09:45 +01003637 * If "charcol" is TRUE, then use the column number as a character offset.
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003638 * Otherwise use the column number as a byte offset.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003639 */
3640 static void
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003641set_cursorpos(typval_T *argvars, typval_T *rettv, int charcol)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003642{
Bram Moolenaar79f23442022-10-10 12:42:57 +01003643 long lnum, col;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003644 long coladd = 0;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003645 int set_curswant = TRUE;
3646
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02003647 if (in_vim9script()
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02003648 && (check_for_string_or_number_or_list_arg(argvars, 0) == FAIL
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02003649 || check_for_opt_number_arg(argvars, 1) == FAIL
3650 || (argvars[1].v_type != VAR_UNKNOWN
3651 && check_for_opt_number_arg(argvars, 2) == FAIL)))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02003652 return;
3653
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003654 rettv->vval.v_number = -1;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003655 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003656 {
3657 pos_T pos;
3658 colnr_T curswant = -1;
3659
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003660 if (list2fpos(argvars, &pos, NULL, &curswant, charcol) == FAIL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003661 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00003662 emsg(_(e_invalid_argument));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003663 return;
3664 }
Bram Moolenaar79f23442022-10-10 12:42:57 +01003665 lnum = pos.lnum;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003666 col = pos.col;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003667 coladd = pos.coladd;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003668 if (curswant >= 0)
3669 {
3670 curwin->w_curswant = curswant - 1;
3671 set_curswant = FALSE;
3672 }
3673 }
Bram Moolenaar79f23442022-10-10 12:42:57 +01003674 else if ((argvars[0].v_type == VAR_NUMBER
3675 || argvars[0].v_type == VAR_STRING)
3676 && (argvars[1].v_type == VAR_NUMBER
3677 || argvars[1].v_type == VAR_STRING))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003678 {
Bram Moolenaar79f23442022-10-10 12:42:57 +01003679 lnum = tv_get_lnum(argvars);
3680 if (lnum < 0)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00003681 semsg(_(e_invalid_argument_str), tv_get_string(&argvars[0]));
Bram Moolenaar79f23442022-10-10 12:42:57 +01003682 else if (lnum == 0)
3683 lnum = curwin->w_cursor.lnum;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003684 col = (long)tv_get_number_chk(&argvars[1], NULL);
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003685 if (charcol)
Bram Moolenaar79f23442022-10-10 12:42:57 +01003686 col = buf_charidx_to_byteidx(curbuf, lnum, col) + 1;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003687 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003688 coladd = (long)tv_get_number_chk(&argvars[2], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003689 }
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003690 else
3691 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00003692 emsg(_(e_invalid_argument));
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003693 return;
3694 }
Bram Moolenaar79f23442022-10-10 12:42:57 +01003695 if (lnum < 0 || col < 0 || coladd < 0)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01003696 return; // type error; errmsg already given
Bram Moolenaar79f23442022-10-10 12:42:57 +01003697 if (lnum > 0)
3698 curwin->w_cursor.lnum = lnum;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003699 if (col > 0)
3700 curwin->w_cursor.col = col - 1;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003701 curwin->w_cursor.coladd = coladd;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003702
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01003703 // Make sure the cursor is in a valid position.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003704 check_cursor();
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01003705 // Correct cursor for multi-byte character.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003706 if (has_mbyte)
3707 mb_adjust_cursor();
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003708
3709 curwin->w_set_curswant = set_curswant;
3710 rettv->vval.v_number = 0;
3711}
3712
Bram Moolenaar6f02b002021-01-10 20:22:54 +01003713/*
3714 * "cursor(lnum, col)" function, or
3715 * "cursor(list)"
3716 *
3717 * Moves the cursor to the specified line and column.
3718 * Returns 0 when the position could be set, -1 otherwise.
3719 */
3720 static void
3721f_cursor(typval_T *argvars, typval_T *rettv)
3722{
3723 set_cursorpos(argvars, rettv, FALSE);
3724}
3725
Bram Moolenaar4f974752019-02-17 17:44:42 +01003726#ifdef MSWIN
Bram Moolenaar4551c0a2018-06-20 22:38:21 +02003727/*
3728 * "debugbreak()" function
3729 */
3730 static void
3731f_debugbreak(typval_T *argvars, typval_T *rettv)
3732{
3733 int pid;
3734
3735 rettv->vval.v_number = FAIL;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02003736 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
3737 return;
3738
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003739 pid = (int)tv_get_number(&argvars[0]);
Bram Moolenaar4551c0a2018-06-20 22:38:21 +02003740 if (pid == 0)
Bram Moolenaar4551c0a2018-06-20 22:38:21 +02003741 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003742 emsg(_(e_invalid_argument));
3743 return;
Bram Moolenaar4551c0a2018-06-20 22:38:21 +02003744 }
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00003745
3746 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
3747 if (hProcess == NULL)
3748 return;
3749
3750 DebugBreakProcess(hProcess);
3751 CloseHandle(hProcess);
3752 rettv->vval.v_number = OK;
Bram Moolenaar4551c0a2018-06-20 22:38:21 +02003753}
3754#endif
3755
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003756/*
3757 * "deepcopy()" function
3758 */
3759 static void
3760f_deepcopy(typval_T *argvars, typval_T *rettv)
3761{
Bram Moolenaar239f8d92021-01-17 13:21:20 +01003762 varnumber_T noref = 0;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003763
Yegappan Lakshmanan8deb2b32022-09-02 15:15:27 +01003764 if (check_for_opt_bool_arg(argvars, 1) == FAIL)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02003765 return;
3766
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003767 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar239f8d92021-01-17 13:21:20 +01003768 noref = tv_get_bool_chk(&argvars[1], NULL);
Yegappan Lakshmanan8deb2b32022-09-02 15:15:27 +01003769
3770 item_copy(&argvars[0], rettv, TRUE, TRUE, noref == 0 ? get_copyID() : 0);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003771}
3772
3773/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003774 * "did_filetype()" function
3775 */
3776 static void
3777f_did_filetype(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
3778{
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003779 rettv->vval.v_number = did_filetype;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003780}
3781
3782/*
Bram Moolenaar4132eb52020-02-14 16:53:00 +01003783 * "echoraw({expr})" function
3784 */
3785 static void
3786f_echoraw(typval_T *argvars, typval_T *rettv UNUSED)
3787{
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02003788 char_u *str;
Bram Moolenaar4132eb52020-02-14 16:53:00 +01003789
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02003790 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
3791 return;
3792
3793 str = tv_get_string_chk(&argvars[0]);
Bram Moolenaar4132eb52020-02-14 16:53:00 +01003794 if (str != NULL && *str != NUL)
3795 {
3796 out_str(str);
3797 out_flush();
3798 }
3799}
3800
3801/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003802 * "empty({expr})" function
3803 */
3804 static void
3805f_empty(typval_T *argvars, typval_T *rettv)
3806{
3807 int n = FALSE;
3808
3809 switch (argvars[0].v_type)
3810 {
3811 case VAR_STRING:
3812 case VAR_FUNC:
3813 n = argvars[0].vval.v_string == NULL
3814 || *argvars[0].vval.v_string == NUL;
3815 break;
3816 case VAR_PARTIAL:
3817 n = FALSE;
3818 break;
3819 case VAR_NUMBER:
3820 n = argvars[0].vval.v_number == 0;
3821 break;
3822 case VAR_FLOAT:
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003823 n = argvars[0].vval.v_float == 0.0;
3824 break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003825 case VAR_LIST:
3826 n = argvars[0].vval.v_list == NULL
Bram Moolenaar50985eb2020-01-27 22:09:39 +01003827 || argvars[0].vval.v_list->lv_len == 0;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003828 break;
3829 case VAR_DICT:
3830 n = argvars[0].vval.v_dict == NULL
3831 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
3832 break;
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01003833 case VAR_BOOL:
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003834 case VAR_SPECIAL:
3835 n = argvars[0].vval.v_number != VVAL_TRUE;
3836 break;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003837 case VAR_CLASS:
3838 n = argvars[0].vval.v_class != NULL;
3839 break;
3840 case VAR_OBJECT:
3841 n = argvars[0].vval.v_object != NULL;
3842 break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003843
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01003844 case VAR_BLOB:
3845 n = argvars[0].vval.v_blob == NULL
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01003846 || argvars[0].vval.v_blob->bv_ga.ga_len == 0;
3847 break;
3848
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003849 case VAR_JOB:
3850#ifdef FEAT_JOB_CHANNEL
3851 n = argvars[0].vval.v_job == NULL
3852 || argvars[0].vval.v_job->jv_status != JOB_STARTED;
3853 break;
3854#endif
3855 case VAR_CHANNEL:
3856#ifdef FEAT_JOB_CHANNEL
3857 n = argvars[0].vval.v_channel == NULL
3858 || !channel_is_open(argvars[0].vval.v_channel);
3859 break;
3860#endif
3861 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02003862 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003863 case VAR_VOID:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02003864 case VAR_INSTR:
Bram Moolenaardd589232020-02-29 17:38:12 +01003865 internal_error_no_abort("f_empty(UNKNOWN)");
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003866 n = TRUE;
3867 break;
3868 }
3869
3870 rettv->vval.v_number = n;
3871}
3872
3873/*
Bram Moolenaar691ddee2019-05-09 14:52:41 +02003874 * "environ()" function
3875 */
3876 static void
3877f_environ(typval_T *argvars UNUSED, typval_T *rettv)
3878{
3879#if !defined(AMIGA)
3880 int i = 0;
3881 char_u *entry, *value;
Bram Moolenaar68aaff42022-04-17 10:57:44 +01003882# if defined (MSWIN)
3883# if !defined(_UCRT)
Bram Moolenaar691ddee2019-05-09 14:52:41 +02003884 extern wchar_t **_wenviron;
Bram Moolenaar68aaff42022-04-17 10:57:44 +01003885# endif
Bram Moolenaar691ddee2019-05-09 14:52:41 +02003886# else
3887 extern char **environ;
3888# endif
3889
Bram Moolenaar93a10962022-06-16 11:42:09 +01003890 if (rettv_dict_alloc(rettv) == FAIL)
Bram Moolenaar691ddee2019-05-09 14:52:41 +02003891 return;
3892
3893# ifdef MSWIN
3894 if (*_wenviron == NULL)
3895 return;
3896# else
3897 if (*environ == NULL)
3898 return;
3899# endif
3900
3901 for (i = 0; ; ++i)
3902 {
3903# ifdef MSWIN
3904 short_u *p;
3905
3906 if ((p = (short_u *)_wenviron[i]) == NULL)
3907 return;
3908 entry = utf16_to_enc(p, NULL);
3909# else
3910 if ((entry = (char_u *)environ[i]) == NULL)
3911 return;
3912 entry = vim_strsave(entry);
3913# endif
3914 if (entry == NULL) // out of memory
3915 return;
3916 if ((value = vim_strchr(entry, '=')) == NULL)
3917 {
3918 vim_free(entry);
3919 continue;
3920 }
3921 *value++ = NUL;
3922 dict_add_string(rettv->vval.v_dict, (char *)entry, value);
3923 vim_free(entry);
3924 }
3925#endif
3926}
3927
3928/*
Bram Moolenaar80adaa82023-07-07 18:57:40 +01003929 * "err_teapot()" function
3930 */
3931 static void
3932f_err_teapot(typval_T *argvars, typval_T *rettv UNUSED)
3933{
3934 if (argvars[0].v_type != VAR_UNKNOWN)
3935 {
3936 if (argvars[0].v_type == VAR_STRING)
3937 {
3938 char_u *s = tv_get_string_strict(&argvars[0]);
3939 if (s == NULL || *skipwhite(s) == NUL)
3940 return;
3941 }
3942
3943 int err = FALSE;
3944 int do_503 = eval_expr_to_bool(&argvars[0], &err);
3945 if (!err && do_503)
3946 {
3947 emsg(_(e_coffee_currently_not_available));
3948 return;
3949 }
3950 }
3951
3952 emsg(_(e_im_a_teapot));
3953}
3954
3955/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003956 * "escape({string}, {chars})" function
3957 */
3958 static void
3959f_escape(typval_T *argvars, typval_T *rettv)
3960{
3961 char_u buf[NUMBUFLEN];
3962
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02003963 if (in_vim9script()
3964 && (check_for_string_arg(argvars, 0) == FAIL
3965 || check_for_string_arg(argvars, 1) == FAIL))
3966 return;
3967
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003968 rettv->vval.v_string = vim_strsave_escaped(tv_get_string(&argvars[0]),
3969 tv_get_string_buf(&argvars[1], buf));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003970 rettv->v_type = VAR_STRING;
3971}
3972
3973/*
3974 * "eval()" function
3975 */
3976 static void
3977f_eval(typval_T *argvars, typval_T *rettv)
3978{
3979 char_u *s, *p;
3980
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02003981 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
3982 return;
3983
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003984 s = tv_get_string_chk(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003985 if (s != NULL)
3986 s = skipwhite(s);
3987
3988 p = s;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003989 if (s == NULL || eval1(&s, rettv, &EVALARG_EVALUATE) == FAIL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003990 {
3991 if (p != NULL && !aborting())
Bram Moolenaar108010a2021-06-27 22:03:33 +02003992 semsg(_(e_invalid_expression_str), p);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003993 need_clr_eos = FALSE;
3994 rettv->v_type = VAR_NUMBER;
3995 rettv->vval.v_number = 0;
3996 }
3997 else if (*s != NUL)
Bram Moolenaar74409f62022-01-01 15:58:22 +00003998 semsg(_(e_trailing_characters_str), s);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02003999}
4000
4001/*
4002 * "eventhandler()" function
4003 */
4004 static void
4005f_eventhandler(typval_T *argvars UNUSED, typval_T *rettv)
4006{
Bram Moolenaardfc33a62020-04-29 22:30:13 +02004007 rettv->vval.v_number = vgetc_busy || input_busy;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004008}
4009
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004010static garray_T redir_execute_ga;
4011
4012/*
4013 * Append "value[value_len]" to the execute() output.
4014 */
4015 void
4016execute_redir_str(char_u *value, int value_len)
4017{
4018 int len;
4019
4020 if (value_len == -1)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004021 len = (int)STRLEN(value); // Append the entire string
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004022 else
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004023 len = value_len; // Append only "value_len" characters
Yegappan Lakshmananfadc02a2023-01-27 21:03:12 +00004024 if (ga_grow(&redir_execute_ga, len) == FAIL)
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00004025 return;
4026
4027 mch_memmove((char *)redir_execute_ga.ga_data
4028 + redir_execute_ga.ga_len, value, len);
4029 redir_execute_ga.ga_len += len;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004030}
4031
Dominique Pelle748b3082022-01-08 12:41:16 +00004032#if defined(FEAT_LUA) || defined(PROTO)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004033/*
Yegappan Lakshmanan11328bc2021-08-06 21:34:38 +02004034 * Get next line from a string containing NL separated lines.
4035 * Called by do_cmdline() to get the next line.
4036 * Returns an allocated string, or NULL when at the end of the string.
4037 */
4038 static char_u *
4039get_str_line(
4040 int c UNUSED,
4041 void *cookie,
4042 int indent UNUSED,
4043 getline_opt_T options UNUSED)
4044{
4045 char_u *start = *(char_u **)cookie;
4046 char_u *line;
4047 char_u *p;
4048
4049 p = start;
4050 if (p == NULL || *p == NUL)
4051 return NULL;
4052 p = vim_strchr(p, '\n');
4053 if (p == NULL)
4054 line = vim_strsave(start);
4055 else
4056 {
4057 line = vim_strnsave(start, p - start);
4058 p++;
4059 }
4060
4061 *(char_u **)cookie = p;
4062 return line;
4063}
4064
4065/*
4066 * Execute a series of Ex commands in 'str'
4067 */
4068 void
4069execute_cmds_from_string(char_u *str)
4070{
4071 do_cmdline(NULL, get_str_line, (void *)&str,
4072 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED);
4073}
Dominique Pelle748b3082022-01-08 12:41:16 +00004074#endif
Yegappan Lakshmanan11328bc2021-08-06 21:34:38 +02004075
4076/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004077 * Get next line from a list.
4078 * Called by do_cmdline() to get the next line.
4079 * Returns allocated string, or NULL for end of function.
4080 */
Bram Moolenaara7583c42022-05-07 21:14:05 +01004081 char_u *
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004082get_list_line(
4083 int c UNUSED,
4084 void *cookie,
Bram Moolenaare96a2492019-06-25 04:12:16 +02004085 int indent UNUSED,
Bram Moolenaar66250c92020-08-20 15:02:42 +02004086 getline_opt_T options UNUSED)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004087{
4088 listitem_T **p = (listitem_T **)cookie;
4089 listitem_T *item = *p;
4090 char_u buf[NUMBUFLEN];
4091 char_u *s;
4092
4093 if (item == NULL)
4094 return NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004095 s = tv_get_string_buf_chk(&item->li_tv, buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004096 *p = item->li_next;
4097 return s == NULL ? NULL : vim_strsave(s);
4098}
4099
4100/*
4101 * "execute()" function
4102 */
Bram Moolenaar261f3462019-09-07 15:45:32 +02004103 void
Bram Moolenaar868b7b62019-05-29 21:44:40 +02004104execute_common(typval_T *argvars, typval_T *rettv, int arg_off)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004105{
4106 char_u *cmd = NULL;
4107 list_T *list = NULL;
4108 int save_msg_silent = msg_silent;
4109 int save_emsg_silent = emsg_silent;
4110 int save_emsg_noredir = emsg_noredir;
4111 int save_redir_execute = redir_execute;
Bram Moolenaar20951482017-12-25 13:44:43 +01004112 int save_redir_off = redir_off;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004113 garray_T save_ga;
Bram Moolenaar10ccaa12018-12-07 16:38:23 +01004114 int save_msg_col = msg_col;
Kota Kato3d3f6ac2022-08-04 18:50:14 +01004115 int save_sticky_cmdmod_flags = sticky_cmdmod_flags;
Bram Moolenaar446e7a32018-12-08 13:57:42 +01004116 int echo_output = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004117
4118 rettv->vval.v_string = NULL;
4119 rettv->v_type = VAR_STRING;
4120
Bram Moolenaar868b7b62019-05-29 21:44:40 +02004121 if (argvars[arg_off].v_type == VAR_LIST)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004122 {
Bram Moolenaar868b7b62019-05-29 21:44:40 +02004123 list = argvars[arg_off].vval.v_list;
Bram Moolenaar50985eb2020-01-27 22:09:39 +01004124 if (list == NULL || list->lv_len == 0)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004125 // empty list, no commands, empty output
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004126 return;
4127 ++list->lv_refcount;
4128 }
Bram Moolenaare2a8f072020-01-08 19:32:18 +01004129 else if (argvars[arg_off].v_type == VAR_JOB
4130 || argvars[arg_off].v_type == VAR_CHANNEL)
4131 {
Bram Moolenaar68db9962021-05-09 23:19:22 +02004132 semsg(_(e_using_invalid_value_as_string_str),
4133 vartype_name(argvars[arg_off].v_type));
Bram Moolenaare2a8f072020-01-08 19:32:18 +01004134 return;
4135 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004136 else
4137 {
Bram Moolenaar868b7b62019-05-29 21:44:40 +02004138 cmd = tv_get_string_chk(&argvars[arg_off]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004139 if (cmd == NULL)
4140 return;
4141 }
4142
Bram Moolenaar868b7b62019-05-29 21:44:40 +02004143 if (argvars[arg_off + 1].v_type != VAR_UNKNOWN)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004144 {
4145 char_u buf[NUMBUFLEN];
Bram Moolenaar3cfa5b12021-06-06 14:14:39 +02004146 char_u *s = tv_get_string_buf_chk_strict(&argvars[arg_off + 1], buf,
4147 in_vim9script());
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004148
4149 if (s == NULL)
4150 return;
Bram Moolenaar446e7a32018-12-08 13:57:42 +01004151 if (*s == NUL)
4152 echo_output = TRUE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004153 if (STRNCMP(s, "silent", 6) == 0)
4154 ++msg_silent;
4155 if (STRCMP(s, "silent!") == 0)
4156 {
4157 emsg_silent = TRUE;
4158 emsg_noredir = TRUE;
4159 }
4160 }
4161 else
4162 ++msg_silent;
4163
4164 if (redir_execute)
4165 save_ga = redir_execute_ga;
Bram Moolenaar04935fb2022-01-08 16:19:22 +00004166 ga_init2(&redir_execute_ga, sizeof(char), 500);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004167 redir_execute = TRUE;
Bram Moolenaar20951482017-12-25 13:44:43 +01004168 redir_off = FALSE;
Bram Moolenaar446e7a32018-12-08 13:57:42 +01004169 if (!echo_output)
4170 msg_col = 0; // prevent leading spaces
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004171
Kota Kato3d3f6ac2022-08-04 18:50:14 +01004172 // For "legacy call execute('cmd')" and "vim9cmd execute('cmd')" apply the
4173 // command modifiers to "cmd".
4174 sticky_cmdmod_flags = cmdmod.cmod_flags & (CMOD_LEGACY | CMOD_VIM9CMD);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004175 if (cmd != NULL)
4176 do_cmdline_cmd(cmd);
4177 else
4178 {
Bram Moolenaar50985eb2020-01-27 22:09:39 +01004179 listitem_T *item;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004180
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02004181 CHECK_LIST_MATERIALIZE(list);
Bram Moolenaar50985eb2020-01-27 22:09:39 +01004182 item = list->lv_first;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004183 do_cmdline(NULL, get_list_line, (void *)&item,
4184 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED);
4185 --list->lv_refcount;
4186 }
Kota Kato3d3f6ac2022-08-04 18:50:14 +01004187 sticky_cmdmod_flags = save_sticky_cmdmod_flags;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004188
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004189 // Need to append a NUL to the result.
Bram Moolenaard297f352017-01-29 20:31:21 +01004190 if (ga_grow(&redir_execute_ga, 1) == OK)
4191 {
4192 ((char *)redir_execute_ga.ga_data)[redir_execute_ga.ga_len] = NUL;
4193 rettv->vval.v_string = redir_execute_ga.ga_data;
4194 }
4195 else
4196 {
4197 ga_clear(&redir_execute_ga);
4198 rettv->vval.v_string = NULL;
4199 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004200 msg_silent = save_msg_silent;
4201 emsg_silent = save_emsg_silent;
4202 emsg_noredir = save_emsg_noredir;
4203
4204 redir_execute = save_redir_execute;
4205 if (redir_execute)
4206 redir_execute_ga = save_ga;
Bram Moolenaar20951482017-12-25 13:44:43 +01004207 redir_off = save_redir_off;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004208
Bram Moolenaar10ccaa12018-12-07 16:38:23 +01004209 // "silent reg" or "silent echo x" leaves msg_col somewhere in the line.
Bram Moolenaar446e7a32018-12-08 13:57:42 +01004210 if (echo_output)
4211 // When not working silently: put it in column zero. A following
4212 // "echon" will overwrite the message, unavoidably.
4213 msg_col = 0;
4214 else
4215 // When working silently: Put it back where it was, since nothing
4216 // should have been written.
4217 msg_col = save_msg_col;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004218}
4219
4220/*
Bram Moolenaar868b7b62019-05-29 21:44:40 +02004221 * "execute()" function
4222 */
4223 static void
4224f_execute(typval_T *argvars, typval_T *rettv)
4225{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02004226 if (in_vim9script()
4227 && (check_for_string_or_list_arg(argvars, 0) == FAIL
4228 || check_for_opt_string_arg(argvars, 1) == FAIL))
4229 return;
4230
Bram Moolenaar868b7b62019-05-29 21:44:40 +02004231 execute_common(argvars, rettv, 0);
4232}
4233
4234/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004235 * "exists()" function
4236 */
Bram Moolenaarbb7ee7a2021-08-02 20:06:50 +02004237 void
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004238f_exists(typval_T *argvars, typval_T *rettv)
4239{
4240 char_u *p;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004241 int n = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004242
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02004243 if (in_vim9script() && check_for_nonempty_string_arg(argvars, 0) == FAIL)
4244 return;
4245
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004246 p = tv_get_string(&argvars[0]);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004247 if (*p == '$') // environment variable
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004248 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004249 // first try "normal" environment variables (fast)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004250 if (mch_getenv(p + 1) != NULL)
4251 n = TRUE;
4252 else
4253 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004254 // try expanding things like $VIM and ${HOME}
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004255 p = expand_env_save(p);
4256 if (p != NULL && *p != '$')
4257 n = TRUE;
4258 vim_free(p);
4259 }
4260 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004261 else if (*p == '&' || *p == '+') // option
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004262 {
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004263 n = (eval_option(&p, NULL, TRUE) == OK);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004264 if (*skipwhite(p) != NUL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004265 n = FALSE; // trailing garbage
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004266 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004267 else if (*p == '*') // internal or user defined function
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004268 {
Bram Moolenaarb54c3ff2016-07-31 14:11:58 +02004269 n = function_exists(p + 1, FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004270 }
Bram Moolenaar15c47602020-03-26 22:16:48 +01004271 else if (*p == '?') // internal function only
4272 {
4273 n = has_internal_func_name(p + 1);
4274 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004275 else if (*p == ':')
4276 {
4277 n = cmd_exists(p + 1);
4278 }
4279 else if (*p == '#')
4280 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004281 if (p[1] == '#')
4282 n = autocmd_supported(p + 2);
4283 else
4284 n = au_exists(p + 1);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004285 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004286 else // internal variable
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004287 {
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01004288 n = var_exists(p);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004289 }
4290
4291 rettv->vval.v_number = n;
4292}
4293
Bram Moolenaar26735992021-08-08 14:43:22 +02004294 static void
4295f_exists_compiled(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
4296{
4297 emsg(_(e_exists_compiled_can_only_be_used_in_def_function));
4298}
4299
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004300/*
4301 * "expand()" function
4302 */
4303 static void
4304f_expand(typval_T *argvars, typval_T *rettv)
4305{
4306 char_u *s;
4307 int len;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004308 int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
4309 expand_T xpc;
4310 int error = FALSE;
4311 char_u *result;
Bram Moolenaar8f187fc2020-09-26 18:47:11 +02004312#ifdef BACKSLASH_IN_FILENAME
4313 char_u *p_csl_save = p_csl;
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02004314#endif
Bram Moolenaar8f187fc2020-09-26 18:47:11 +02004315
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02004316 if (in_vim9script()
4317 && (check_for_string_arg(argvars, 0) == FAIL
4318 || check_for_opt_bool_arg(argvars, 1) == FAIL
4319 || (argvars[1].v_type != VAR_UNKNOWN
4320 && check_for_opt_bool_arg(argvars, 2) == FAIL)))
4321 return;
4322
4323#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaar8f187fc2020-09-26 18:47:11 +02004324 // avoid using 'completeslash' here
4325 p_csl = empty_option;
4326#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004327
4328 rettv->v_type = VAR_STRING;
4329 if (argvars[1].v_type != VAR_UNKNOWN
4330 && argvars[2].v_type != VAR_UNKNOWN
Bram Moolenaar551d25e2020-09-02 21:37:56 +02004331 && tv_get_bool_chk(&argvars[2], &error)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004332 && !error)
Bram Moolenaar45cf6e92017-04-30 20:25:19 +02004333 rettv_list_set(rettv, NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004334
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004335 s = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004336 if (*s == '%' || *s == '#' || *s == '<')
4337 {
Bram Moolenaar57544522022-04-12 12:54:11 +01004338 char *errormsg = NULL;
4339
4340 if (p_verbose == 0)
4341 ++emsg_off;
Bram Moolenaara96edb72022-04-28 17:52:24 +01004342 result = eval_vars(s, s, &len, NULL, &errormsg, NULL, FALSE);
Bram Moolenaar57544522022-04-12 12:54:11 +01004343 if (p_verbose == 0)
4344 --emsg_off;
4345 else if (errormsg != NULL)
4346 emsg(errormsg);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004347 if (rettv->v_type == VAR_LIST)
4348 {
Bram Moolenaar93a10962022-06-16 11:42:09 +01004349 if (rettv_list_alloc(rettv) == OK && result != NULL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004350 list_append_string(rettv->vval.v_list, result, -1);
Bram Moolenaar86173482019-10-01 17:02:16 +02004351 vim_free(result);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004352 }
4353 else
4354 rettv->vval.v_string = result;
4355 }
4356 else
4357 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004358 // When the optional second argument is non-zero, don't remove matches
4359 // for 'wildignore' and don't put matches for 'suffixes' at the end.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004360 if (argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaar551d25e2020-09-02 21:37:56 +02004361 && tv_get_bool_chk(&argvars[1], &error))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004362 options |= WILD_KEEP_ALL;
4363 if (!error)
4364 {
4365 ExpandInit(&xpc);
4366 xpc.xp_context = EXPAND_FILES;
4367 if (p_wic)
4368 options += WILD_ICASE;
4369 if (rettv->v_type == VAR_STRING)
4370 rettv->vval.v_string = ExpandOne(&xpc, s, NULL,
4371 options, WILD_ALL);
Bram Moolenaar93a10962022-06-16 11:42:09 +01004372 else if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004373 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004374 ExpandOne(&xpc, s, NULL, options, WILD_ALL_KEEP);
Bram Moolenaar848db572022-09-20 19:04:32 +01004375 for (int i = 0; i < xpc.xp_numfiles; i++)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004376 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
4377 ExpandCleanup(&xpc);
4378 }
4379 }
4380 else
4381 rettv->vval.v_string = NULL;
4382 }
Bram Moolenaar8f187fc2020-09-26 18:47:11 +02004383#ifdef BACKSLASH_IN_FILENAME
4384 p_csl = p_csl_save;
4385#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004386}
4387
4388/*
Bram Moolenaar80dad482019-06-09 17:22:31 +02004389 * "expandcmd()" function
4390 * Expand all the special characters in a command string.
4391 */
4392 static void
4393f_expandcmd(typval_T *argvars, typval_T *rettv)
4394{
4395 exarg_T eap;
4396 char_u *cmdstr;
4397 char *errormsg = NULL;
Yegappan Lakshmanan2b74b682022-04-03 21:30:32 +01004398 int emsgoff = TRUE;
Bram Moolenaar80dad482019-06-09 17:22:31 +02004399
Yegappan Lakshmanan2b74b682022-04-03 21:30:32 +01004400 if (in_vim9script()
4401 && (check_for_string_arg(argvars, 0) == FAIL
4402 || check_for_opt_dict_arg(argvars, 1) == FAIL))
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02004403 return;
4404
Yegappan Lakshmanan2b74b682022-04-03 21:30:32 +01004405 if (argvars[1].v_type == VAR_DICT
Bram Moolenaard61efa52022-07-23 09:52:04 +01004406 && dict_get_bool(argvars[1].vval.v_dict, "errmsg", VVAL_FALSE))
Yegappan Lakshmanan2b74b682022-04-03 21:30:32 +01004407 emsgoff = FALSE;
4408
Bram Moolenaar80dad482019-06-09 17:22:31 +02004409 rettv->v_type = VAR_STRING;
4410 cmdstr = vim_strsave(tv_get_string(&argvars[0]));
4411
Yegappan Lakshmanan960dcbd2023-03-07 17:45:11 +00004412 CLEAR_FIELD(eap);
Bram Moolenaar80dad482019-06-09 17:22:31 +02004413 eap.cmd = cmdstr;
4414 eap.arg = cmdstr;
Bram Moolenaar8071cb22019-07-12 17:58:01 +02004415 eap.argt |= EX_NOSPC;
Bram Moolenaar80dad482019-06-09 17:22:31 +02004416 eap.usefilter = FALSE;
4417 eap.nextcmd = NULL;
4418 eap.cmdidx = CMD_USER;
4419
Yegappan Lakshmanan2b74b682022-04-03 21:30:32 +01004420 if (emsgoff)
4421 ++emsg_off;
4422 if (expand_filename(&eap, &cmdstr, &errormsg) == FAIL)
4423 if (!emsgoff && errormsg != NULL && *errormsg != NUL)
4424 emsg(errormsg);
4425 if (emsgoff)
4426 --emsg_off;
Bram Moolenaar80dad482019-06-09 17:22:31 +02004427
4428 rettv->vval.v_string = cmdstr;
4429}
4430
4431/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004432 * "feedkeys()" function
4433 */
4434 static void
4435f_feedkeys(typval_T *argvars, typval_T *rettv UNUSED)
4436{
4437 int remap = TRUE;
4438 int insert = FALSE;
4439 char_u *keys, *flags;
4440 char_u nbuf[NUMBUFLEN];
4441 int typed = FALSE;
4442 int execute = FALSE;
Bram Moolenaara9725222022-01-16 13:30:33 +00004443 int context = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004444 int dangerous = FALSE;
Bram Moolenaar5e66b422019-01-24 21:58:10 +01004445 int lowlevel = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004446
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004447 // This is not allowed in the sandbox. If the commands would still be
4448 // executed in the sandbox it would be OK, but it probably happens later,
4449 // when "sandbox" is no longer set.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004450 if (check_secure())
4451 return;
4452
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02004453 if (in_vim9script()
4454 && (check_for_string_arg(argvars, 0) == FAIL
4455 || check_for_opt_string_arg(argvars, 1) == FAIL))
4456 return;
4457
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004458 keys = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004459
4460 if (argvars[1].v_type != VAR_UNKNOWN)
4461 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004462 flags = tv_get_string_buf(&argvars[1], nbuf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004463 for ( ; *flags != NUL; ++flags)
4464 {
4465 switch (*flags)
4466 {
4467 case 'n': remap = FALSE; break;
4468 case 'm': remap = TRUE; break;
4469 case 't': typed = TRUE; break;
4470 case 'i': insert = TRUE; break;
4471 case 'x': execute = TRUE; break;
Bram Moolenaara9725222022-01-16 13:30:33 +00004472 case 'c': context = TRUE; break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004473 case '!': dangerous = TRUE; break;
Bram Moolenaar5e66b422019-01-24 21:58:10 +01004474 case 'L': lowlevel = TRUE; break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004475 }
4476 }
4477 }
4478
4479 if (*keys != NUL || execute)
4480 {
Christopher Plewright20b795e2022-12-20 20:01:58 +00004481 if (lowlevel
4482#ifdef FEAT_VTP
4483 && (!is_term_win32()
4484 || (keys[0] == 3 && ctrl_c_interrupts && typed))
4485#endif
4486 )
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004487 {
Bram Moolenaar5e66b422019-01-24 21:58:10 +01004488#ifdef USE_INPUT_BUF
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004489 ch_log(NULL, "feedkeys() lowlevel: %s", keys);
Bram Moolenaar9645e2d2020-03-20 20:48:49 +01004490
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004491 int len = (int)STRLEN(keys);
4492 for (int idx = 0; idx < len; ++idx)
4493 {
4494 // if a CTRL-C was typed, set got_int, similar to what
4495 // happens in fill_input_buf()
4496 if (keys[idx] == 3 && ctrl_c_interrupts && typed)
4497 got_int = TRUE;
4498 add_to_input_buf(keys + idx, 1);
4499 }
Bram Moolenaar5e66b422019-01-24 21:58:10 +01004500#else
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004501 emsg(_(e_lowlevel_input_not_supported));
Bram Moolenaar5e66b422019-01-24 21:58:10 +01004502#endif
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004503 }
4504 else
4505 {
4506 // Need to escape K_SPECIAL and CSI before putting the string in
4507 // the typeahead buffer.
4508 char_u *keys_esc = vim_strsave_escape_csi(keys);
4509 if (keys_esc == NULL)
4510 return;
4511
4512 ch_log(NULL, "feedkeys(%s): %s", typed ? "typed" : "", keys);
4513
4514 ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
4515 insert ? 0 : typebuf.tb_len, !typed, FALSE);
4516 if (vgetc_busy
Bram Moolenaar5d7be4f2017-06-25 13:40:17 +02004517#ifdef FEAT_TIMERS
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004518 || timer_busy
Bram Moolenaar5d7be4f2017-06-25 13:40:17 +02004519#endif
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004520 || input_busy)
4521 typebuf_was_filled = TRUE;
4522
Bram Moolenaar8d4ce562019-01-30 22:01:40 +01004523 vim_free(keys_esc);
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004524 }
Bram Moolenaar8d4ce562019-01-30 22:01:40 +01004525
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004526 if (execute)
4527 {
4528 int save_msg_scroll = msg_scroll;
4529 sctx_T save_sctx;
4530
4531 // Avoid a 1 second delay when the keys start Insert mode.
4532 msg_scroll = FALSE;
4533
4534 ch_log(NULL, "feedkeys() executing");
4535
4536 if (context)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004537 {
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004538 save_sctx = current_sctx;
4539 current_sctx.sc_sid = 0;
4540 current_sctx.sc_version = 0;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004541 }
Bram Moolenaarb55ae8c2022-12-02 13:37:36 +00004542
4543 if (!dangerous)
4544 {
4545 ++ex_normal_busy;
4546 ++in_feedkeys;
4547 }
4548 exec_normal(TRUE, lowlevel, TRUE);
4549 if (!dangerous)
4550 {
4551 --ex_normal_busy;
4552 --in_feedkeys;
4553 }
4554
4555 msg_scroll |= save_msg_scroll;
4556
4557 if (context)
4558 current_sctx = save_sctx;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004559 }
4560 }
4561}
4562
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004563/*
4564 * "fnameescape({string})" function
4565 */
4566 static void
4567f_fnameescape(typval_T *argvars, typval_T *rettv)
4568{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02004569 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
4570 return;
4571
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004572 rettv->vval.v_string = vim_strsave_fnameescape(
Bram Moolenaar21c1a0c2021-10-17 17:20:23 +01004573 tv_get_string(&argvars[0]), VSE_NONE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004574 rettv->v_type = VAR_STRING;
4575}
4576
4577/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004578 * "foreground()" function
4579 */
4580 static void
4581f_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
4582{
4583#ifdef FEAT_GUI
4584 if (gui.in_use)
Bram Moolenaarafde13b2019-04-28 19:46:49 +02004585 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004586 gui_mch_set_foreground();
Bram Moolenaarafde13b2019-04-28 19:46:49 +02004587 return;
4588 }
4589#endif
4590#if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004591 win32_set_foreground();
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004592#endif
4593}
4594
Bakudankun375141e2022-09-09 18:46:47 +01004595/*
4596 * "function()" function
4597 * "funcref()" function
4598 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004599 static void
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004600common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004601{
4602 char_u *s;
4603 char_u *name;
4604 int use_string = FALSE;
4605 partial_T *arg_pt = NULL;
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004606 char_u *trans_name = NULL;
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02004607 int is_global = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004608
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02004609 if (in_vim9script()
Bram Moolenaarae1068a2021-12-25 19:43:44 +00004610 && (check_for_string_or_func_arg(argvars, 0) == FAIL
4611 || check_for_opt_list_arg(argvars, 1) == FAIL
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02004612 || (argvars[1].v_type != VAR_UNKNOWN
4613 && check_for_opt_dict_arg(argvars, 2) == FAIL)))
4614 return;
4615
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004616 if (argvars[0].v_type == VAR_FUNC)
4617 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004618 // function(MyFunc, [arg], dict)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004619 s = argvars[0].vval.v_string;
4620 }
4621 else if (argvars[0].v_type == VAR_PARTIAL
4622 && argvars[0].vval.v_partial != NULL)
4623 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004624 // function(dict.MyFunc, [arg])
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004625 arg_pt = argvars[0].vval.v_partial;
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004626 s = partial_name(arg_pt);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004627 }
4628 else
4629 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004630 // function('MyFunc', [arg], dict)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004631 s = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004632 use_string = TRUE;
4633 }
Bram Moolenaar60b6e6f2021-08-28 12:49:27 +02004634 if (s == NULL)
4635 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00004636 semsg(_(e_invalid_argument_str), "NULL");
Bram Moolenaar60b6e6f2021-08-28 12:49:27 +02004637 return;
4638 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004639
Bram Moolenaar843b8842016-08-21 14:36:15 +02004640 if ((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL) || is_funcref)
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004641 {
4642 name = s;
Bram Moolenaareba3b7f2021-11-30 18:25:08 +00004643 trans_name = save_function_name(&name, &is_global, FALSE,
4644 TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004645 if (*name != NUL)
4646 s = NULL;
4647 }
4648
Bram Moolenaar843b8842016-08-21 14:36:15 +02004649 if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s))
4650 || (is_funcref && trans_name == NULL))
Yegappan Lakshmanan655b7342022-03-06 14:27:10 +00004651 semsg(_(e_invalid_argument_str),
4652 use_string ? tv_get_string(&argvars[0]) : s);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004653 // Don't check an autoload name for existence here.
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004654 else if (trans_name != NULL && (is_funcref
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00004655 ? find_func(trans_name, is_global) == NULL
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02004656 : !translated_function_exists(trans_name, is_global)))
Bram Moolenaara6f79292022-01-04 21:30:47 +00004657 semsg(_(e_unknown_function_str_2), s);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004658 else
4659 {
4660 int dict_idx = 0;
4661 int arg_idx = 0;
4662 list_T *list = NULL;
4663
4664 if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004665 // Expand s: and <SID> into <SNR>nr_, so that the function can
4666 // also be called from another script. Using trans_function_name()
4667 // would also work, but some plugins depend on the name being
4668 // printable text.
Yegappan Lakshmanane7f4abd2021-12-24 20:47:38 +00004669 name = get_scriptlocal_funcname(s);
Bram Moolenaarc2f17f72022-02-21 13:13:50 +00004670 else if (trans_name != NULL && *trans_name == K_SPECIAL)
4671 name = alloc_printable_func_name(trans_name);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004672 else
4673 name = vim_strsave(s);
4674
4675 if (argvars[1].v_type != VAR_UNKNOWN)
4676 {
4677 if (argvars[2].v_type != VAR_UNKNOWN)
4678 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004679 // function(name, [args], dict)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004680 arg_idx = 1;
4681 dict_idx = 2;
4682 }
4683 else if (argvars[1].v_type == VAR_DICT)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004684 // function(name, dict)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004685 dict_idx = 1;
4686 else
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004687 // function(name, [args])
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004688 arg_idx = 1;
4689 if (dict_idx > 0)
4690 {
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01004691 if (check_for_dict_arg(argvars, dict_idx) == FAIL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004692 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004693 vim_free(name);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004694 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004695 }
4696 if (argvars[dict_idx].vval.v_dict == NULL)
4697 dict_idx = 0;
4698 }
4699 if (arg_idx > 0)
4700 {
4701 if (argvars[arg_idx].v_type != VAR_LIST)
4702 {
Bram Moolenaard82a47d2022-01-05 20:24:39 +00004703 emsg(_(e_second_argument_of_function_must_be_list_or_dict));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004704 vim_free(name);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004705 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004706 }
4707 list = argvars[arg_idx].vval.v_list;
4708 if (list == NULL || list->lv_len == 0)
4709 arg_idx = 0;
Bram Moolenaar4c054e92019-11-10 00:13:50 +01004710 else if (list->lv_len > MAX_FUNC_ARGS)
4711 {
Yegappan Lakshmanan5018a832022-04-02 21:12:21 +01004712 emsg_funcname(e_too_many_arguments_for_function_str, s);
Bram Moolenaar4c054e92019-11-10 00:13:50 +01004713 vim_free(name);
4714 goto theend;
4715 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004716 }
4717 }
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004718 if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL || is_funcref)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004719 {
Bram Moolenaarc799fe22019-05-28 23:08:19 +02004720 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004721
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004722 // result is a VAR_PARTIAL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004723 if (pt == NULL)
4724 vim_free(name);
4725 else
4726 {
4727 if (arg_idx > 0 || (arg_pt != NULL && arg_pt->pt_argc > 0))
4728 {
4729 listitem_T *li;
4730 int i = 0;
4731 int arg_len = 0;
4732 int lv_len = 0;
4733
4734 if (arg_pt != NULL)
4735 arg_len = arg_pt->pt_argc;
4736 if (list != NULL)
4737 lv_len = list->lv_len;
4738 pt->pt_argc = arg_len + lv_len;
Bram Moolenaarc799fe22019-05-28 23:08:19 +02004739 pt->pt_argv = ALLOC_MULT(typval_T, pt->pt_argc);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004740 if (pt->pt_argv == NULL)
4741 {
4742 vim_free(pt);
4743 vim_free(name);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004744 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004745 }
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004746 for (i = 0; i < arg_len; i++)
4747 copy_tv(&arg_pt->pt_argv[i], &pt->pt_argv[i]);
4748 if (lv_len > 0)
Bram Moolenaar50985eb2020-01-27 22:09:39 +01004749 {
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02004750 CHECK_LIST_MATERIALIZE(list);
Bram Moolenaaraeea7212020-04-02 18:50:46 +02004751 FOR_ALL_LIST_ITEMS(list, li)
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004752 copy_tv(&li->li_tv, &pt->pt_argv[i++]);
Bram Moolenaar50985eb2020-01-27 22:09:39 +01004753 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004754 }
4755
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004756 // For "function(dict.func, [], dict)" and "func" is a partial
4757 // use "dict". That is backwards compatible.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004758 if (dict_idx > 0)
4759 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004760 // The dict is bound explicitly, pt_auto is FALSE.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004761 pt->pt_dict = argvars[dict_idx].vval.v_dict;
4762 ++pt->pt_dict->dv_refcount;
4763 }
4764 else if (arg_pt != NULL)
4765 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004766 // If the dict was bound automatically the result is also
4767 // bound automatically.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004768 pt->pt_dict = arg_pt->pt_dict;
4769 pt->pt_auto = arg_pt->pt_auto;
4770 if (pt->pt_dict != NULL)
4771 ++pt->pt_dict->dv_refcount;
4772 }
4773
4774 pt->pt_refcount = 1;
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004775 if (arg_pt != NULL && arg_pt->pt_func != NULL)
4776 {
4777 pt->pt_func = arg_pt->pt_func;
4778 func_ptr_ref(pt->pt_func);
4779 vim_free(name);
4780 }
4781 else if (is_funcref)
4782 {
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00004783 pt->pt_func = find_func(trans_name, is_global);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004784 func_ptr_ref(pt->pt_func);
4785 vim_free(name);
4786 }
4787 else
4788 {
4789 pt->pt_name = name;
4790 func_ref(name);
4791 }
Bram Moolenaar92368aa2022-02-07 17:50:39 +00004792
4793 if (arg_pt != NULL)
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +00004794 {
4795 pt->pt_outer_partial = arg_pt;
4796 ++arg_pt->pt_refcount;
4797 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004798 }
4799 rettv->v_type = VAR_PARTIAL;
4800 rettv->vval.v_partial = pt;
4801 }
4802 else
4803 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004804 // result is a VAR_FUNC
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004805 rettv->v_type = VAR_FUNC;
4806 rettv->vval.v_string = name;
4807 func_ref(name);
4808 }
4809 }
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004810theend:
4811 vim_free(trans_name);
4812}
4813
4814/*
4815 * "funcref()" function
4816 */
4817 static void
4818f_funcref(typval_T *argvars, typval_T *rettv)
4819{
4820 common_function(argvars, rettv, TRUE);
4821}
4822
4823/*
4824 * "function()" function
4825 */
4826 static void
4827f_function(typval_T *argvars, typval_T *rettv)
4828{
4829 common_function(argvars, rettv, FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004830}
4831
4832/*
4833 * "garbagecollect()" function
4834 */
4835 static void
4836f_garbagecollect(typval_T *argvars, typval_T *rettv UNUSED)
4837{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02004838 if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL)
4839 return;
4840
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004841 // This is postponed until we are back at the toplevel, because we may be
4842 // using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]".
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004843 want_garbage_collect = TRUE;
4844
Bram Moolenaar2df47312020-09-05 17:30:44 +02004845 if (argvars[0].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[0]) == 1)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004846 garbage_collect_at_exit = TRUE;
4847}
4848
4849/*
4850 * "get()" function
4851 */
4852 static void
4853f_get(typval_T *argvars, typval_T *rettv)
4854{
4855 listitem_T *li;
4856 list_T *l;
4857 dictitem_T *di;
4858 dict_T *d;
4859 typval_T *tv = NULL;
Bram Moolenaarf91aac52019-07-28 13:21:01 +02004860 int what_is_dict = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004861
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004862 if (argvars[0].v_type == VAR_BLOB)
4863 {
4864 int error = FALSE;
4865 int idx = tv_get_number_chk(&argvars[1], &error);
4866
4867 if (!error)
4868 {
4869 rettv->v_type = VAR_NUMBER;
Bram Moolenaar2ea773b2019-01-15 22:16:42 +01004870 if (idx < 0)
4871 idx = blob_len(argvars[0].vval.v_blob) + idx;
4872 if (idx < 0 || idx >= blob_len(argvars[0].vval.v_blob))
4873 rettv->vval.v_number = -1;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004874 else
Bram Moolenaar2ea773b2019-01-15 22:16:42 +01004875 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004876 rettv->vval.v_number = blob_get(argvars[0].vval.v_blob, idx);
Bram Moolenaar2ea773b2019-01-15 22:16:42 +01004877 tv = rettv;
4878 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004879 }
4880 }
4881 else if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004882 {
4883 if ((l = argvars[0].vval.v_list) != NULL)
4884 {
4885 int error = FALSE;
4886
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004887 li = list_find(l, (long)tv_get_number_chk(&argvars[1], &error));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004888 if (!error && li != NULL)
4889 tv = &li->li_tv;
4890 }
4891 }
4892 else if (argvars[0].v_type == VAR_DICT)
4893 {
4894 if ((d = argvars[0].vval.v_dict) != NULL)
4895 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004896 di = dict_find(d, tv_get_string(&argvars[1]), -1);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004897 if (di != NULL)
4898 tv = &di->di_tv;
4899 }
4900 }
4901 else if (argvars[0].v_type == VAR_PARTIAL || argvars[0].v_type == VAR_FUNC)
4902 {
4903 partial_T *pt;
4904 partial_T fref_pt;
4905
4906 if (argvars[0].v_type == VAR_PARTIAL)
4907 pt = argvars[0].vval.v_partial;
4908 else
4909 {
Bram Moolenaara80faa82020-04-12 19:37:17 +02004910 CLEAR_FIELD(fref_pt);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004911 fref_pt.pt_name = argvars[0].vval.v_string;
4912 pt = &fref_pt;
4913 }
4914
4915 if (pt != NULL)
4916 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004917 char_u *what = tv_get_string(&argvars[1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004918
4919 if (STRCMP(what, "func") == 0 || STRCMP(what, "name") == 0)
4920 {
Bram Moolenaar1ae8c262022-06-27 11:45:52 +01004921 char_u *name = partial_name(pt);
4922
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004923 rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING);
Bram Moolenaar1ae8c262022-06-27 11:45:52 +01004924 if (name == NULL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004925 rettv->vval.v_string = NULL;
4926 else
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004927 {
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004928 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar1ae8c262022-06-27 11:45:52 +01004929 func_ref(name);
4930 if (*what == 'n' && pt->pt_name == NULL
4931 && pt->pt_func != NULL)
4932 // use <SNR> instead of the byte code
4933 name = printable_func_name(pt->pt_func);
4934 rettv->vval.v_string = vim_strsave(name);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004935 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004936 }
4937 else if (STRCMP(what, "dict") == 0)
Bram Moolenaarf91aac52019-07-28 13:21:01 +02004938 {
4939 what_is_dict = TRUE;
4940 if (pt->pt_dict != NULL)
4941 rettv_dict_set(rettv, pt->pt_dict);
4942 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004943 else if (STRCMP(what, "args") == 0)
4944 {
4945 rettv->v_type = VAR_LIST;
4946 if (rettv_list_alloc(rettv) == OK)
4947 {
4948 int i;
4949
4950 for (i = 0; i < pt->pt_argc; ++i)
4951 list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]);
4952 }
4953 }
4954 else
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00004955 semsg(_(e_invalid_argument_str), what);
Bram Moolenaarf91aac52019-07-28 13:21:01 +02004956
4957 // When {what} == "dict" and pt->pt_dict == NULL, evaluate the
4958 // third argument
4959 if (!what_is_dict)
4960 return;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004961 }
4962 }
4963 else
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00004964 semsg(_(e_argument_of_str_must_be_list_dictionary_or_blob), "get()");
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004965
4966 if (tv == NULL)
4967 {
4968 if (argvars[2].v_type != VAR_UNKNOWN)
4969 copy_tv(&argvars[2], rettv);
4970 }
4971 else
4972 copy_tv(tv, rettv);
4973}
4974
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02004975/*
Bram Moolenaar07ad8162018-02-13 13:59:59 +01004976 * "getchangelist()" function
4977 */
4978 static void
4979f_getchangelist(typval_T *argvars, typval_T *rettv)
4980{
Bram Moolenaar07ad8162018-02-13 13:59:59 +01004981 buf_T *buf;
4982 int i;
4983 list_T *l;
4984 dict_T *d;
LemonBoydb0ea7f2022-04-10 17:59:26 +01004985 int changelistindex;
Bram Moolenaar07ad8162018-02-13 13:59:59 +01004986
Bram Moolenaar93a10962022-06-16 11:42:09 +01004987 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar07ad8162018-02-13 13:59:59 +01004988 return;
4989
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02004990 if (in_vim9script() && check_for_opt_buffer_arg(argvars, 0) == FAIL)
4991 return;
4992
Bram Moolenaar4c313b12019-08-24 22:58:31 +02004993 if (argvars[0].v_type == VAR_UNKNOWN)
4994 buf = curbuf;
4995 else
Bram Moolenaara5d38412020-09-02 21:02:35 +02004996 buf = tv_get_buf_from_arg(&argvars[0]);
Bram Moolenaar07ad8162018-02-13 13:59:59 +01004997 if (buf == NULL)
4998 return;
4999
5000 l = list_alloc();
5001 if (l == NULL)
5002 return;
Bram Moolenaar07ad8162018-02-13 13:59:59 +01005003 if (list_append_list(rettv->vval.v_list, l) == FAIL)
Bram Moolenaar9ba61942022-08-31 11:25:06 +01005004 {
5005 vim_free(l);
Bram Moolenaar07ad8162018-02-13 13:59:59 +01005006 return;
Bram Moolenaar9ba61942022-08-31 11:25:06 +01005007 }
5008
Bram Moolenaar07ad8162018-02-13 13:59:59 +01005009 /*
LemonBoydb0ea7f2022-04-10 17:59:26 +01005010 * The current window change list index tracks only the position for the
5011 * current buffer. For other buffers use the stored index for the current
5012 * window, or, if that's not available, the change list length.
Bram Moolenaar07ad8162018-02-13 13:59:59 +01005013 */
LemonBoydb0ea7f2022-04-10 17:59:26 +01005014 if (buf == curwin->w_buffer)
5015 {
5016 changelistindex = curwin->w_changelistidx;
5017 }
5018 else
5019 {
5020 wininfo_T *wip;
5021
5022 FOR_ALL_BUF_WININFO(buf, wip)
5023 if (wip->wi_win == curwin)
5024 break;
5025 changelistindex = wip != NULL ? wip->wi_changelistidx
5026 : buf->b_changelistlen;
5027 }
5028 list_append_number(rettv->vval.v_list, (varnumber_T)changelistindex);
Bram Moolenaar07ad8162018-02-13 13:59:59 +01005029
5030 for (i = 0; i < buf->b_changelistlen; ++i)
5031 {
5032 if (buf->b_changelist[i].lnum == 0)
5033 continue;
5034 if ((d = dict_alloc()) == NULL)
5035 return;
5036 if (list_append_dict(l, d) == FAIL)
5037 return;
Bram Moolenaare0be1672018-07-08 16:50:37 +02005038 dict_add_number(d, "lnum", (long)buf->b_changelist[i].lnum);
5039 dict_add_number(d, "col", (long)buf->b_changelist[i].col);
Bram Moolenaare0be1672018-07-08 16:50:37 +02005040 dict_add_number(d, "coladd", (long)buf->b_changelist[i].coladd);
Bram Moolenaar07ad8162018-02-13 13:59:59 +01005041 }
Bram Moolenaar07ad8162018-02-13 13:59:59 +01005042}
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005043
Bram Moolenaar6f02b002021-01-10 20:22:54 +01005044 static void
5045getpos_both(
5046 typval_T *argvars,
5047 typval_T *rettv,
5048 int getcurpos,
5049 int charcol)
5050{
5051 pos_T *fp = NULL;
5052 pos_T pos;
5053 win_T *wp = curwin;
5054 list_T *l;
5055 int fnum = -1;
5056
5057 if (rettv_list_alloc(rettv) == OK)
5058 {
5059 l = rettv->vval.v_list;
5060 if (getcurpos)
5061 {
5062 if (argvars[0].v_type != VAR_UNKNOWN)
5063 {
5064 wp = find_win_by_nr_or_id(&argvars[0]);
5065 if (wp != NULL)
5066 fp = &wp->w_cursor;
5067 }
5068 else
5069 fp = &curwin->w_cursor;
5070 if (fp != NULL && charcol)
5071 {
5072 pos = *fp;
Bram Moolenaar91458462021-01-13 20:08:38 +01005073 pos.col =
5074 buf_byteidx_to_charidx(wp->w_buffer, pos.lnum, pos.col);
Bram Moolenaar6f02b002021-01-10 20:22:54 +01005075 fp = &pos;
5076 }
5077 }
5078 else
5079 fp = var2fpos(&argvars[0], TRUE, &fnum, charcol);
5080 if (fnum != -1)
5081 list_append_number(l, (varnumber_T)fnum);
5082 else
5083 list_append_number(l, (varnumber_T)0);
5084 list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum
5085 : (varnumber_T)0);
5086 list_append_number(l, (fp != NULL)
5087 ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1)
5088 : (varnumber_T)0);
5089 list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd :
5090 (varnumber_T)0);
5091 if (getcurpos)
5092 {
5093 int save_set_curswant = curwin->w_set_curswant;
5094 colnr_T save_curswant = curwin->w_curswant;
5095 colnr_T save_virtcol = curwin->w_virtcol;
5096
5097 if (wp == curwin)
5098 update_curswant();
5099 list_append_number(l, wp == NULL ? 0 : wp->w_curswant == MAXCOL
5100 ? (varnumber_T)MAXCOL : (varnumber_T)wp->w_curswant + 1);
5101
5102 // Do not change "curswant", as it is unexpected that a get
5103 // function has a side effect.
5104 if (wp == curwin && save_set_curswant)
5105 {
5106 curwin->w_set_curswant = save_set_curswant;
5107 curwin->w_curswant = save_curswant;
5108 curwin->w_virtcol = save_virtcol;
5109 curwin->w_valid &= ~VALID_VIRTCOL;
5110 }
5111 }
5112 }
5113 else
5114 rettv->vval.v_number = FALSE;
5115}
5116
5117/*
5118 * "getcharpos()" function
5119 */
5120 static void
5121f_getcharpos(typval_T *argvars UNUSED, typval_T *rettv)
5122{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005123 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
5124 return;
5125
Bram Moolenaar6f02b002021-01-10 20:22:54 +01005126 getpos_both(argvars, rettv, FALSE, TRUE);
5127}
5128
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005129/*
5130 * "getcharsearch()" function
5131 */
5132 static void
5133f_getcharsearch(typval_T *argvars UNUSED, typval_T *rettv)
5134{
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00005135 if (rettv_dict_alloc(rettv) != OK)
5136 return;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005137
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00005138 dict_T *dict = rettv->vval.v_dict;
5139
5140 dict_add_string(dict, "char", last_csearch());
5141 dict_add_number(dict, "forward", last_csearch_forward());
5142 dict_add_number(dict, "until", last_csearch_until());
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005143}
5144
5145/*
Bram Moolenaar691ddee2019-05-09 14:52:41 +02005146 * "getenv()" function
5147 */
5148 static void
5149f_getenv(typval_T *argvars, typval_T *rettv)
5150{
5151 int mustfree = FALSE;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005152 char_u *p;
Bram Moolenaar691ddee2019-05-09 14:52:41 +02005153
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005154 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
5155 return;
5156
5157 p = vim_getenv(tv_get_string(&argvars[0]), &mustfree);
Bram Moolenaar691ddee2019-05-09 14:52:41 +02005158 if (p == NULL)
5159 {
5160 rettv->v_type = VAR_SPECIAL;
5161 rettv->vval.v_number = VVAL_NULL;
5162 return;
5163 }
5164 if (!mustfree)
5165 p = vim_strsave(p);
5166 rettv->vval.v_string = p;
5167 rettv->v_type = VAR_STRING;
5168}
5169
5170/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005171 * "getfontname()" function
5172 */
5173 static void
5174f_getfontname(typval_T *argvars UNUSED, typval_T *rettv)
5175{
5176 rettv->v_type = VAR_STRING;
5177 rettv->vval.v_string = NULL;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005178
5179 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
5180 return;
5181
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005182#ifdef FEAT_GUI
5183 if (gui.in_use)
5184 {
5185 GuiFont font;
5186 char_u *name = NULL;
5187
5188 if (argvars[0].v_type == VAR_UNKNOWN)
5189 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005190 // Get the "Normal" font. Either the name saved by
5191 // hl_set_font_name() or from the font ID.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005192 font = gui.norm_font;
5193 name = hl_get_font_name();
5194 }
5195 else
5196 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005197 name = tv_get_string(&argvars[0]);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005198 if (STRCMP(name, "*") == 0) // don't use font dialog
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005199 return;
5200 font = gui_mch_get_font(name, FALSE);
5201 if (font == NOFONT)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005202 return; // Invalid font name, return empty string.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005203 }
5204 rettv->vval.v_string = gui_mch_get_fontname(font, name);
5205 if (argvars[0].v_type != VAR_UNKNOWN)
5206 gui_mch_free_font(font);
5207 }
5208#endif
5209}
5210
5211/*
Bram Moolenaar4f505882018-02-10 21:06:32 +01005212 * "getjumplist()" function
5213 */
5214 static void
5215f_getjumplist(typval_T *argvars, typval_T *rettv)
5216{
Bram Moolenaar4f505882018-02-10 21:06:32 +01005217 win_T *wp;
5218 int i;
5219 list_T *l;
5220 dict_T *d;
Bram Moolenaar4f505882018-02-10 21:06:32 +01005221
Bram Moolenaar93a10962022-06-16 11:42:09 +01005222 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar4f505882018-02-10 21:06:32 +01005223 return;
5224
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005225 if (in_vim9script()
5226 && (check_for_opt_number_arg(argvars, 0) == FAIL
5227 || (argvars[0].v_type != VAR_UNKNOWN
5228 && check_for_opt_number_arg(argvars, 1) == FAIL)))
5229 return;
5230
Bram Moolenaar00aa0692019-04-27 20:37:57 +02005231 wp = find_tabwin(&argvars[0], &argvars[1], NULL);
Bram Moolenaar4f505882018-02-10 21:06:32 +01005232 if (wp == NULL)
5233 return;
5234
Bram Moolenaar57ee2b62019-02-12 22:15:06 +01005235 cleanup_jumplist(wp, TRUE);
5236
Bram Moolenaar4f505882018-02-10 21:06:32 +01005237 l = list_alloc();
5238 if (l == NULL)
5239 return;
Bram Moolenaar4f505882018-02-10 21:06:32 +01005240 if (list_append_list(rettv->vval.v_list, l) == FAIL)
Bram Moolenaar9ba61942022-08-31 11:25:06 +01005241 {
5242 vim_free(l);
Bram Moolenaar4f505882018-02-10 21:06:32 +01005243 return;
Bram Moolenaar9ba61942022-08-31 11:25:06 +01005244 }
5245
Bram Moolenaar4f505882018-02-10 21:06:32 +01005246 list_append_number(rettv->vval.v_list, (varnumber_T)wp->w_jumplistidx);
5247
5248 for (i = 0; i < wp->w_jumplistlen; ++i)
5249 {
Bram Moolenaara7e18d22018-02-11 14:29:49 +01005250 if (wp->w_jumplist[i].fmark.mark.lnum == 0)
5251 continue;
Bram Moolenaar4f505882018-02-10 21:06:32 +01005252 if ((d = dict_alloc()) == NULL)
5253 return;
5254 if (list_append_dict(l, d) == FAIL)
5255 return;
Bram Moolenaare0be1672018-07-08 16:50:37 +02005256 dict_add_number(d, "lnum", (long)wp->w_jumplist[i].fmark.mark.lnum);
5257 dict_add_number(d, "col", (long)wp->w_jumplist[i].fmark.mark.col);
Bram Moolenaare0be1672018-07-08 16:50:37 +02005258 dict_add_number(d, "coladd", (long)wp->w_jumplist[i].fmark.mark.coladd);
Bram Moolenaare0be1672018-07-08 16:50:37 +02005259 dict_add_number(d, "bufnr", (long)wp->w_jumplist[i].fmark.fnum);
Bram Moolenaara7e18d22018-02-11 14:29:49 +01005260 if (wp->w_jumplist[i].fname != NULL)
Bram Moolenaare0be1672018-07-08 16:50:37 +02005261 dict_add_string(d, "filename", wp->w_jumplist[i].fname);
Bram Moolenaar4f505882018-02-10 21:06:32 +01005262 }
Bram Moolenaar4f505882018-02-10 21:06:32 +01005263}
5264
5265/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005266 * "getpid()" function
5267 */
5268 static void
5269f_getpid(typval_T *argvars UNUSED, typval_T *rettv)
5270{
5271 rettv->vval.v_number = mch_get_pid();
5272}
5273
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005274/*
5275 * "getcurpos()" function
5276 */
5277 static void
5278f_getcurpos(typval_T *argvars, typval_T *rettv)
5279{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005280 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
5281 return;
5282
Bram Moolenaar6f02b002021-01-10 20:22:54 +01005283 getpos_both(argvars, rettv, TRUE, FALSE);
5284}
5285
5286 static void
5287f_getcursorcharpos(typval_T *argvars, typval_T *rettv)
5288{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005289 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
5290 return;
5291
Bram Moolenaar6f02b002021-01-10 20:22:54 +01005292 getpos_both(argvars, rettv, TRUE, TRUE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005293}
5294
5295/*
5296 * "getpos(string)" function
5297 */
5298 static void
5299f_getpos(typval_T *argvars, typval_T *rettv)
5300{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005301 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
5302 return;
5303
Bram Moolenaar6f02b002021-01-10 20:22:54 +01005304 getpos_both(argvars, rettv, FALSE, FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005305}
5306
5307/*
zeertzjqd3f00f52021-12-24 12:02:43 +00005308 * Common between getreg(), getreginfo() and getregtype(): get the register
5309 * name from the first argument.
Bram Moolenaar51e64b22021-12-24 10:48:30 +00005310 * Returns zero on error.
5311 */
5312 static int
5313getreg_get_regname(typval_T *argvars)
5314{
5315 char_u *strregname;
5316
5317 if (argvars[0].v_type != VAR_UNKNOWN)
5318 {
5319 strregname = tv_get_string_chk(&argvars[0]);
5320 if (strregname != NULL && in_vim9script() && STRLEN(strregname) > 1)
5321 {
5322 semsg(_(e_register_name_must_be_one_char_str), strregname);
5323 strregname = NULL;
5324 }
5325 if (strregname == NULL) // type error; errmsg already given
5326 return 0;
5327 }
5328 else
5329 // Default to v:register
5330 strregname = get_vim_var_str(VV_REG);
5331
5332 return *strregname == 0 ? '"' : *strregname;
5333}
5334
5335/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005336 * "getreg()" function
5337 */
5338 static void
5339f_getreg(typval_T *argvars, typval_T *rettv)
5340{
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005341 int regname;
5342 int arg2 = FALSE;
5343 int return_list = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005344
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02005345 if (in_vim9script()
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005346 && (check_for_opt_string_arg(argvars, 0) == FAIL
5347 || (argvars[0].v_type != VAR_UNKNOWN
5348 && (check_for_opt_bool_arg(argvars, 1) == FAIL
5349 || (argvars[1].v_type != VAR_UNKNOWN
5350 && check_for_opt_bool_arg(argvars, 2) == FAIL)))))
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02005351 return;
5352
Bram Moolenaar51e64b22021-12-24 10:48:30 +00005353 regname = getreg_get_regname(argvars);
5354 if (regname == 0)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005355 return;
5356
Bram Moolenaar51e64b22021-12-24 10:48:30 +00005357 if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_UNKNOWN)
5358 {
5359 int error = FALSE;
5360
5361 arg2 = (int)tv_get_bool_chk(&argvars[1], &error);
5362
5363 if (!error && argvars[2].v_type != VAR_UNKNOWN)
5364 return_list = (int)tv_get_bool_chk(&argvars[2], &error);
5365 if (error)
5366 return;
5367 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005368
5369 if (return_list)
5370 {
5371 rettv->v_type = VAR_LIST;
5372 rettv->vval.v_list = (list_T *)get_reg_contents(regname,
5373 (arg2 ? GREG_EXPR_SRC : 0) | GREG_LIST);
5374 if (rettv->vval.v_list == NULL)
5375 (void)rettv_list_alloc(rettv);
5376 else
5377 ++rettv->vval.v_list->lv_refcount;
5378 }
5379 else
5380 {
5381 rettv->v_type = VAR_STRING;
5382 rettv->vval.v_string = get_reg_contents(regname,
5383 arg2 ? GREG_EXPR_SRC : 0);
5384 }
5385}
5386
5387/*
5388 * "getregtype()" function
5389 */
5390 static void
5391f_getregtype(typval_T *argvars, typval_T *rettv)
5392{
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005393 int regname;
5394 char_u buf[NUMBUFLEN + 2];
5395 long reglen = 0;
5396
Bram Moolenaar51e64b22021-12-24 10:48:30 +00005397 // on error return an empty string
5398 rettv->v_type = VAR_STRING;
5399 rettv->vval.v_string = NULL;
5400
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005401 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
5402 return;
5403
Bram Moolenaar51e64b22021-12-24 10:48:30 +00005404 regname = getreg_get_regname(argvars);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005405 if (regname == 0)
Bram Moolenaar51e64b22021-12-24 10:48:30 +00005406 return;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005407
5408 buf[0] = NUL;
5409 buf[1] = NUL;
5410 switch (get_reg_type(regname, &reglen))
5411 {
5412 case MLINE: buf[0] = 'V'; break;
5413 case MCHAR: buf[0] = 'v'; break;
5414 case MBLOCK:
5415 buf[0] = Ctrl_V;
5416 sprintf((char *)buf + 1, "%ld", reglen + 1);
5417 break;
5418 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005419 rettv->vval.v_string = vim_strsave(buf);
5420}
5421
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02005422/*
Bram Moolenaarf49cc602018-11-11 15:21:05 +01005423 * "gettagstack()" function
5424 */
5425 static void
5426f_gettagstack(typval_T *argvars, typval_T *rettv)
5427{
5428 win_T *wp = curwin; // default is current window
5429
Bram Moolenaar93a10962022-06-16 11:42:09 +01005430 if (rettv_dict_alloc(rettv) == FAIL)
Bram Moolenaarf49cc602018-11-11 15:21:05 +01005431 return;
5432
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005433 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
5434 return;
5435
Bram Moolenaarf49cc602018-11-11 15:21:05 +01005436 if (argvars[0].v_type != VAR_UNKNOWN)
5437 {
5438 wp = find_win_by_nr_or_id(&argvars[0]);
5439 if (wp == NULL)
5440 return;
5441 }
5442
5443 get_tagstack(wp, rettv->vval.v_dict);
5444}
5445
Bram Moolenaar0b39c3f2020-08-30 15:52:10 +02005446/*
5447 * "gettext()" function
5448 */
5449 static void
5450f_gettext(typval_T *argvars, typval_T *rettv)
5451{
Yegappan Lakshmanan8deb2b32022-09-02 15:15:27 +01005452 if (check_for_nonempty_string_arg(argvars, 0) == FAIL)
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02005453 return;
5454
Yegappan Lakshmanan8deb2b32022-09-02 15:15:27 +01005455 rettv->v_type = VAR_STRING;
5456 rettv->vval.v_string = vim_strsave((char_u *)_(argvars[0].vval.v_string));
Bram Moolenaar0b39c3f2020-08-30 15:52:10 +02005457}
5458
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005459// for VIM_VERSION_ defines
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005460#include "version.h"
5461
5462/*
5463 * "has()" function
5464 */
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005465 void
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005466f_has(typval_T *argvars, typval_T *rettv)
5467{
5468 int i;
5469 char_u *name;
Bram Moolenaar79296512020-03-22 16:17:14 +01005470 int x = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005471 int n = FALSE;
Bram Moolenaar79296512020-03-22 16:17:14 +01005472 typedef struct {
5473 char *name;
5474 short present;
5475 } has_item_T;
5476 static has_item_T has_list[] =
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005477 {
Bram Moolenaar79296512020-03-22 16:17:14 +01005478 {"amiga",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005479#ifdef AMIGA
Bram Moolenaar79296512020-03-22 16:17:14 +01005480 1
Bram Moolenaar39536dd2019-01-29 22:58:21 +01005481#else
Bram Moolenaar79296512020-03-22 16:17:14 +01005482 0
Bram Moolenaar39536dd2019-01-29 22:58:21 +01005483#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005484 },
5485 {"arp",
5486#if defined(AMIGA) && defined(FEAT_ARP)
5487 1
5488#else
5489 0
5490#endif
5491 },
Bram Moolenaar79296512020-03-22 16:17:14 +01005492 {"haiku",
5493#ifdef __HAIKU__
5494 1
5495#else
5496 0
5497#endif
5498 },
5499 {"bsd",
5500#if defined(BSD) && !defined(MACOS_X)
5501 1
5502#else
5503 0
5504#endif
5505 },
5506 {"hpux",
5507#ifdef hpux
5508 1
5509#else
5510 0
5511#endif
5512 },
5513 {"linux",
5514#ifdef __linux__
5515 1
5516#else
5517 0
5518#endif
5519 },
5520 {"mac", // Mac OS X (and, once, Mac OS Classic)
5521#ifdef MACOS_X
5522 1
5523#else
5524 0
5525#endif
5526 },
5527 {"osx", // Mac OS X
5528#ifdef MACOS_X
5529 1
5530#else
5531 0
5532#endif
5533 },
5534 {"macunix", // Mac OS X, with the darwin feature
5535#if defined(MACOS_X) && defined(MACOS_X_DARWIN)
5536 1
5537#else
5538 0
5539#endif
5540 },
5541 {"osxdarwin", // synonym for macunix
5542#if defined(MACOS_X) && defined(MACOS_X_DARWIN)
5543 1
5544#else
5545 0
5546#endif
5547 },
5548 {"qnx",
5549#ifdef __QNX__
5550 1
5551#else
5552 0
5553#endif
5554 },
5555 {"sun",
5556#ifdef SUN_SYSTEM
5557 1
5558#else
5559 0
5560#endif
5561 },
5562 {"unix",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005563#ifdef UNIX
Bram Moolenaar79296512020-03-22 16:17:14 +01005564 1
5565#else
5566 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005567#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005568 },
5569 {"vms",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005570#ifdef VMS
Bram Moolenaar79296512020-03-22 16:17:14 +01005571 1
5572#else
5573 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005574#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005575 },
5576 {"win32",
Bram Moolenaar4f974752019-02-17 17:44:42 +01005577#ifdef MSWIN
Bram Moolenaar79296512020-03-22 16:17:14 +01005578 1
5579#else
5580 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005581#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005582 },
5583 {"win32unix",
K.Takata972db232022-02-04 10:45:38 +00005584#ifdef WIN32UNIX
Bram Moolenaar79296512020-03-22 16:17:14 +01005585 1
5586#else
5587 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005588#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005589 },
5590 {"win64",
Bram Moolenaar44b443c2019-02-18 22:14:18 +01005591#ifdef _WIN64
Bram Moolenaar79296512020-03-22 16:17:14 +01005592 1
5593#else
5594 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005595#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005596 },
Bram Moolenaar424bcae2022-01-31 14:59:41 +00005597 {"ebcdic", 0 },
Bram Moolenaar79296512020-03-22 16:17:14 +01005598 {"fname_case",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005599#ifndef CASE_INSENSITIVE_FILENAME
Bram Moolenaar79296512020-03-22 16:17:14 +01005600 1
5601#else
5602 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005603#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005604 },
5605 {"acl",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005606#ifdef HAVE_ACL
Bram Moolenaar79296512020-03-22 16:17:14 +01005607 1
5608#else
5609 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005610#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005611 },
5612 {"arabic",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005613#ifdef FEAT_ARABIC
Bram Moolenaar79296512020-03-22 16:17:14 +01005614 1
5615#else
5616 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005617#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005618 },
5619 {"autocmd", 1},
5620 {"autochdir",
Bram Moolenaar83ec2a72018-07-27 22:08:59 +02005621#ifdef FEAT_AUTOCHDIR
Bram Moolenaar79296512020-03-22 16:17:14 +01005622 1
5623#else
5624 0
Bram Moolenaar83ec2a72018-07-27 22:08:59 +02005625#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005626 },
5627 {"autoservername",
Bram Moolenaare42a6d22017-11-12 19:21:51 +01005628#ifdef FEAT_AUTOSERVERNAME
Bram Moolenaar79296512020-03-22 16:17:14 +01005629 1
5630#else
5631 0
Bram Moolenaare42a6d22017-11-12 19:21:51 +01005632#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005633 },
5634 {"balloon_eval",
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01005635#ifdef FEAT_BEVAL_GUI
Bram Moolenaar79296512020-03-22 16:17:14 +01005636 1
5637#else
5638 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005639#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005640 },
5641 {"balloon_multiline",
Bram Moolenaar0bd663a2022-01-22 10:24:47 +00005642#ifdef FEAT_BEVAL_GUI
Bram Moolenaar79296512020-03-22 16:17:14 +01005643 1
5644#else
5645 0
5646#endif
5647 },
5648 {"balloon_eval_term",
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01005649#ifdef FEAT_BEVAL_TERM
Bram Moolenaar79296512020-03-22 16:17:14 +01005650 1
5651#else
5652 0
Bram Moolenaar51b0f372017-11-18 18:52:04 +01005653#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005654 },
Bram Moolenaar2ee347f2022-08-26 17:53:44 +01005655 {"builtin_terms", 1},
5656 {"all_builtin_terms", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01005657 {"browsefilter",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005658#if defined(FEAT_BROWSE) && (defined(USE_FILE_CHOOSER) \
Bram Moolenaar4f974752019-02-17 17:44:42 +01005659 || defined(FEAT_GUI_MSWIN) \
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005660 || defined(FEAT_GUI_MOTIF))
Bram Moolenaar79296512020-03-22 16:17:14 +01005661 1
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005662#else
Bram Moolenaar79296512020-03-22 16:17:14 +01005663 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005664#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01005665 },
5666 {"byte_offset",
5667#ifdef FEAT_BYTEOFF
5668 1
5669#else
5670 0
5671#endif
5672 },
5673 {"channel",
5674#ifdef FEAT_JOB_CHANNEL
5675 1
5676#else
5677 0
5678#endif
5679 },
Bram Moolenaar8e145b82022-05-21 20:17:31 +01005680 {"cindent", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01005681 {"clientserver",
5682#ifdef FEAT_CLIENTSERVER
5683 1
5684#else
5685 0
5686#endif
5687 },
5688 {"clipboard",
5689#ifdef FEAT_CLIPBOARD
5690 1
5691#else
5692 0
5693#endif
5694 },
5695 {"cmdline_compl", 1},
5696 {"cmdline_hist", 1},
Martin Tournoij7904fa42022-10-04 16:28:45 +01005697 {"cmdwin", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01005698 {"comments", 1},
5699 {"conceal",
5700#ifdef FEAT_CONCEAL
5701 1
5702#else
5703 0
5704#endif
5705 },
5706 {"cryptv",
5707#ifdef FEAT_CRYPT
5708 1
5709#else
5710 0
5711#endif
5712 },
5713 {"crypt-blowfish",
5714#ifdef FEAT_CRYPT
5715 1
5716#else
5717 0
5718#endif
5719 },
5720 {"crypt-blowfish2",
5721#ifdef FEAT_CRYPT
5722 1
5723#else
5724 0
5725#endif
5726 },
5727 {"cscope",
5728#ifdef FEAT_CSCOPE
5729 1
5730#else
5731 0
5732#endif
5733 },
5734 {"cursorbind", 1},
5735 {"cursorshape",
5736#ifdef CURSOR_SHAPE
5737 1
5738#else
5739 0
5740#endif
5741 },
5742 {"debug",
5743#ifdef DEBUG
5744 1
5745#else
5746 0
5747#endif
5748 },
5749 {"dialog_con",
5750#ifdef FEAT_CON_DIALOG
5751 1
5752#else
5753 0
5754#endif
5755 },
5756 {"dialog_gui",
5757#ifdef FEAT_GUI_DIALOG
5758 1
5759#else
5760 0
5761#endif
5762 },
5763 {"diff",
5764#ifdef FEAT_DIFF
5765 1
5766#else
5767 0
5768#endif
5769 },
5770 {"digraphs",
5771#ifdef FEAT_DIGRAPHS
5772 1
5773#else
5774 0
5775#endif
5776 },
5777 {"directx",
5778#ifdef FEAT_DIRECTX
5779 1
5780#else
5781 0
5782#endif
5783 },
5784 {"dnd",
5785#ifdef FEAT_DND
5786 1
5787#else
5788 0
5789#endif
5790 },
Bram Moolenaar1d1ce612021-06-27 19:02:52 +02005791 {"drop_file",
5792#ifdef HAVE_DROP_FILE
5793 1
5794#else
5795 0
5796#endif
5797 },
Bram Moolenaar79296512020-03-22 16:17:14 +01005798 {"emacs_tags",
5799#ifdef FEAT_EMACS_TAGS
5800 1
5801#else
5802 0
5803#endif
5804 },
5805 {"eval", 1}, // always present, of course!
5806 {"ex_extra", 1}, // graduated feature
5807 {"extra_search",
5808#ifdef FEAT_SEARCH_EXTRA
5809 1
5810#else
5811 0
5812#endif
5813 },
Bram Moolenaarf80f40a2022-08-25 16:02:23 +01005814 {"file_in_path", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01005815 {"filterpipe",
5816#if defined(FEAT_FILTERPIPE) && !defined(VIMDLL)
5817 1
5818#else
5819 0
5820#endif
5821 },
5822 {"find_in_path",
5823#ifdef FEAT_FIND_ID
5824 1
5825#else
5826 0
5827#endif
5828 },
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01005829 {"float", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01005830 {"folding",
5831#ifdef FEAT_FOLDING
5832 1
5833#else
5834 0
5835#endif
5836 },
Bram Moolenaarc8ac3a02022-09-04 12:29:28 +01005837 {"footer", 0},
Bram Moolenaar79296512020-03-22 16:17:14 +01005838 {"fork",
5839#if !defined(USE_SYSTEM) && defined(UNIX)
5840 1
5841#else
5842 0
5843#endif
5844 },
5845 {"gettext",
5846#ifdef FEAT_GETTEXT
5847 1
5848#else
5849 0
5850#endif
5851 },
5852 {"gui",
5853#ifdef FEAT_GUI
5854 1
5855#else
5856 0
5857#endif
5858 },
Bram Moolenaar0b962e52022-04-03 18:02:37 +01005859 {"gui_neXtaw", 0 },
5860 {"gui_athena", 0 },
Bram Moolenaar79296512020-03-22 16:17:14 +01005861 {"gui_gtk",
5862#ifdef FEAT_GUI_GTK
5863 1
5864#else
5865 0
5866#endif
5867 },
5868 {"gui_gtk2",
5869#if defined(FEAT_GUI_GTK) && !defined(USE_GTK3)
5870 1
5871#else
5872 0
5873#endif
5874 },
5875 {"gui_gtk3",
5876#if defined(FEAT_GUI_GTK) && defined(USE_GTK3)
5877 1
5878#else
5879 0
5880#endif
5881 },
5882 {"gui_gnome",
5883#ifdef FEAT_GUI_GNOME
5884 1
5885#else
5886 0
5887#endif
5888 },
5889 {"gui_haiku",
5890#ifdef FEAT_GUI_HAIKU
5891 1
5892#else
5893 0
5894#endif
5895 },
Bram Moolenaar097148e2020-08-11 21:58:20 +02005896 {"gui_mac", 0},
Bram Moolenaar79296512020-03-22 16:17:14 +01005897 {"gui_motif",
5898#ifdef FEAT_GUI_MOTIF
5899 1
5900#else
5901 0
5902#endif
5903 },
5904 {"gui_photon",
5905#ifdef FEAT_GUI_PHOTON
5906 1
5907#else
5908 0
5909#endif
5910 },
5911 {"gui_win32",
5912#ifdef FEAT_GUI_MSWIN
5913 1
5914#else
5915 0
5916#endif
5917 },
5918 {"iconv",
5919#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
5920 1
5921#else
5922 0
5923#endif
5924 },
5925 {"insert_expand", 1},
Bram Moolenaarbfe13cc2020-04-12 17:53:12 +02005926 {"ipv6",
5927#ifdef FEAT_IPV6
5928 1
5929#else
5930 0
5931#endif
5932 },
Bram Moolenaar79296512020-03-22 16:17:14 +01005933 {"job",
5934#ifdef FEAT_JOB_CHANNEL
5935 1
5936#else
5937 0
5938#endif
5939 },
Bram Moolenaar739f13a2021-12-13 13:12:53 +00005940 {"jumplist", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01005941 {"keymap",
5942#ifdef FEAT_KEYMAP
5943 1
5944#else
5945 0
5946#endif
5947 },
5948 {"lambda", 1}, // always with FEAT_EVAL, since 7.4.2120 with closure
5949 {"langmap",
5950#ifdef FEAT_LANGMAP
5951 1
5952#else
5953 0
5954#endif
5955 },
5956 {"libcall",
5957#ifdef FEAT_LIBCALL
5958 1
5959#else
5960 0
5961#endif
5962 },
5963 {"linebreak",
5964#ifdef FEAT_LINEBREAK
5965 1
5966#else
5967 0
5968#endif
5969 },
Bram Moolenaar8e145b82022-05-21 20:17:31 +01005970 {"lispindent", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01005971 {"listcmds", 1},
5972 {"localmap", 1},
5973 {"lua",
5974#if defined(FEAT_LUA) && !defined(DYNAMIC_LUA)
5975 1
5976#else
5977 0
5978#endif
5979 },
5980 {"menu",
5981#ifdef FEAT_MENU
5982 1
5983#else
5984 0
5985#endif
5986 },
5987 {"mksession",
5988#ifdef FEAT_SESSION
5989 1
5990#else
5991 0
5992#endif
5993 },
5994 {"modify_fname", 1},
5995 {"mouse", 1},
5996 {"mouseshape",
5997#ifdef FEAT_MOUSESHAPE
5998 1
5999#else
6000 0
6001#endif
6002 },
6003 {"mouse_dec",
6004#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_DEC)
6005 1
6006#else
6007 0
6008#endif
6009 },
6010 {"mouse_gpm",
Bram Moolenaar33fc4a62022-02-23 18:07:38 +00006011#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_GPM) && !defined(DYNAMIC_GPM)
Bram Moolenaar79296512020-03-22 16:17:14 +01006012 1
6013#else
6014 0
6015#endif
6016 },
6017 {"mouse_jsbterm",
6018#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_JSB)
6019 1
6020#else
6021 0
6022#endif
6023 },
6024 {"mouse_netterm",
6025#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_NET)
6026 1
6027#else
6028 0
6029#endif
6030 },
6031 {"mouse_pterm",
6032#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_PTERM)
6033 1
6034#else
6035 0
6036#endif
6037 },
6038 {"mouse_sgr",
6039#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_XTERM)
6040 1
6041#else
6042 0
6043#endif
6044 },
6045 {"mouse_sysmouse",
6046#if (defined(UNIX) || defined(VMS)) && defined(FEAT_SYSMOUSE)
6047 1
6048#else
6049 0
6050#endif
6051 },
6052 {"mouse_urxvt",
6053#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_URXVT)
6054 1
6055#else
6056 0
6057#endif
6058 },
6059 {"mouse_xterm",
6060#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_XTERM)
6061 1
6062#else
6063 0
6064#endif
6065 },
6066 {"multi_byte", 1},
6067 {"multi_byte_ime",
6068#ifdef FEAT_MBYTE_IME
6069 1
6070#else
6071 0
6072#endif
6073 },
6074 {"multi_lang",
6075#ifdef FEAT_MULTI_LANG
6076 1
6077#else
6078 0
6079#endif
6080 },
6081 {"mzscheme",
6082#if defined(FEAT_MZSCHEME) && !defined(DYNAMIC_MZSCHEME)
6083 1
6084#else
6085 0
6086#endif
6087 },
Leah Neukirchen0a7984a2021-10-14 21:27:55 +01006088 {"nanotime",
6089#ifdef ST_MTIM_NSEC
6090 1
6091#else
6092 0
6093#endif
6094 },
Bram Moolenaar79296512020-03-22 16:17:14 +01006095 {"num64", 1},
6096 {"ole",
6097#ifdef FEAT_OLE
6098 1
6099#else
6100 0
6101#endif
6102 },
6103 {"packages",
6104#ifdef FEAT_EVAL
6105 1
6106#else
6107 0
6108#endif
6109 },
Bram Moolenaar2bd9dbc2022-08-25 18:12:06 +01006110 {"path_extra", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01006111 {"perl",
6112#if defined(FEAT_PERL) && !defined(DYNAMIC_PERL)
6113 1
6114#else
6115 0
6116#endif
6117 },
6118 {"persistent_undo",
6119#ifdef FEAT_PERSISTENT_UNDO
6120 1
6121#else
6122 0
6123#endif
6124 },
6125 {"python_compiled",
6126#if defined(FEAT_PYTHON)
6127 1
6128#else
6129 0
6130#endif
6131 },
6132 {"python_dynamic",
6133#if defined(FEAT_PYTHON) && defined(DYNAMIC_PYTHON)
6134 1
6135#else
6136 0
6137#endif
6138 },
6139 {"python",
6140#if defined(FEAT_PYTHON) && !defined(DYNAMIC_PYTHON)
6141 1
6142#else
6143 0
6144#endif
6145 },
6146 {"pythonx",
6147#if (defined(FEAT_PYTHON) && !defined(DYNAMIC_PYTHON)) \
6148 || (defined(FEAT_PYTHON3) && !defined(DYNAMIC_PYTHON3))
6149 1
6150#else
6151 0
6152#endif
6153 },
6154 {"python3_compiled",
6155#if defined(FEAT_PYTHON3)
6156 1
6157#else
6158 0
6159#endif
6160 },
6161 {"python3_dynamic",
6162#if defined(FEAT_PYTHON3) && defined(DYNAMIC_PYTHON3)
6163 1
6164#else
6165 0
6166#endif
6167 },
6168 {"python3",
6169#if defined(FEAT_PYTHON3) && !defined(DYNAMIC_PYTHON3)
6170 1
6171#else
6172 0
6173#endif
6174 },
6175 {"popupwin",
6176#ifdef FEAT_PROP_POPUP
6177 1
6178#else
6179 0
6180#endif
6181 },
6182 {"postscript",
6183#ifdef FEAT_POSTSCRIPT
6184 1
6185#else
6186 0
6187#endif
6188 },
6189 {"printer",
6190#ifdef FEAT_PRINTER
6191 1
6192#else
6193 0
6194#endif
6195 },
6196 {"profile",
6197#ifdef FEAT_PROFILE
6198 1
6199#else
6200 0
6201#endif
6202 },
Ernie Rael076de792023-03-16 21:43:15 +00006203 {"prof_nsec",
Bram Moolenaar08210f82023-04-13 19:15:54 +01006204#ifdef PROF_NSEC
Ernie Rael076de792023-03-16 21:43:15 +00006205 1
6206#else
6207 0
6208#endif
6209 },
Bram Moolenaar79296512020-03-22 16:17:14 +01006210 {"reltime",
6211#ifdef FEAT_RELTIME
6212 1
6213#else
6214 0
6215#endif
6216 },
6217 {"quickfix",
6218#ifdef FEAT_QUICKFIX
6219 1
6220#else
6221 0
6222#endif
6223 },
6224 {"rightleft",
6225#ifdef FEAT_RIGHTLEFT
6226 1
6227#else
6228 0
6229#endif
6230 },
6231 {"ruby",
6232#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
6233 1
6234#else
6235 0
6236#endif
6237 },
6238 {"scrollbind", 1},
Martin Tournoijba43e762022-10-13 22:12:15 +01006239 {"showcmd", 1},
6240 {"cmdline_info", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01006241 {"signs",
6242#ifdef FEAT_SIGNS
6243 1
6244#else
6245 0
6246#endif
6247 },
Bram Moolenaar8e145b82022-05-21 20:17:31 +01006248 {"smartindent", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01006249 {"startuptime",
6250#ifdef STARTUPTIME
6251 1
6252#else
6253 0
6254#endif
6255 },
6256 {"statusline",
6257#ifdef FEAT_STL_OPT
6258 1
6259#else
6260 0
6261#endif
6262 },
6263 {"netbeans_intg",
6264#ifdef FEAT_NETBEANS_INTG
6265 1
6266#else
6267 0
6268#endif
6269 },
Christian Brabandtf573c6e2021-06-20 14:02:16 +02006270 {"sodium",
K.Takatad68b2fc2022-02-12 11:18:37 +00006271#if defined(FEAT_SODIUM) && !defined(DYNAMIC_SODIUM)
Christian Brabandtf573c6e2021-06-20 14:02:16 +02006272 1
6273#else
6274 0
6275#endif
6276 },
Bram Moolenaar79296512020-03-22 16:17:14 +01006277 {"sound",
6278#ifdef FEAT_SOUND
6279 1
6280#else
6281 0
6282#endif
6283 },
6284 {"spell",
6285#ifdef FEAT_SPELL
6286 1
6287#else
6288 0
6289#endif
6290 },
6291 {"syntax",
6292#ifdef FEAT_SYN_HL
6293 1
6294#else
6295 0
6296#endif
6297 },
6298 {"system",
6299#if defined(USE_SYSTEM) || !defined(UNIX)
6300 1
6301#else
6302 0
6303#endif
6304 },
Yegappan Lakshmanan655b7342022-03-06 14:27:10 +00006305 {"tag_binary", 1}, // graduated feature
Bram Moolenaar79296512020-03-22 16:17:14 +01006306 {"tcl",
6307#if defined(FEAT_TCL) && !defined(DYNAMIC_TCL)
6308 1
6309#else
6310 0
6311#endif
6312 },
6313 {"termguicolors",
6314#ifdef FEAT_TERMGUICOLORS
6315 1
6316#else
6317 0
6318#endif
6319 },
6320 {"terminal",
6321#if defined(FEAT_TERMINAL) && !defined(MSWIN)
6322 1
6323#else
6324 0
6325#endif
6326 },
6327 {"terminfo",
6328#ifdef TERMINFO
6329 1
6330#else
6331 0
6332#endif
6333 },
6334 {"termresponse",
6335#ifdef FEAT_TERMRESPONSE
6336 1
6337#else
6338 0
6339#endif
6340 },
Bram Moolenaar88774872022-08-16 20:24:29 +01006341 {"textobjects", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01006342 {"textprop",
6343#ifdef FEAT_PROP_POPUP
6344 1
6345#else
6346 0
6347#endif
6348 },
6349 {"tgetent",
6350#ifdef HAVE_TGETENT
6351 1
6352#else
6353 0
6354#endif
6355 },
6356 {"timers",
6357#ifdef FEAT_TIMERS
6358 1
6359#else
6360 0
6361#endif
6362 },
Bram Moolenaar651fca82021-11-29 20:39:38 +00006363 {"title", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01006364 {"toolbar",
6365#ifdef FEAT_TOOLBAR
6366 1
6367#else
6368 0
6369#endif
6370 },
6371 {"unnamedplus",
6372#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
6373 1
6374#else
6375 0
6376#endif
6377 },
6378 {"user-commands", 1}, // was accidentally included in 5.4
6379 {"user_commands", 1},
6380 {"vartabs",
6381#ifdef FEAT_VARTABS
6382 1
6383#else
6384 0
6385#endif
6386 },
6387 {"vertsplit", 1},
6388 {"viminfo",
6389#ifdef FEAT_VIMINFO
6390 1
6391#else
6392 0
6393#endif
6394 },
Bram Moolenaarb79ee0c2022-01-01 12:17:00 +00006395 {"vim9script", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01006396 {"vimscript-1", 1},
6397 {"vimscript-2", 1},
6398 {"vimscript-3", 1},
6399 {"vimscript-4", 1},
6400 {"virtualedit", 1},
6401 {"visual", 1},
6402 {"visualextra", 1},
6403 {"vreplace", 1},
6404 {"vtp",
6405#ifdef FEAT_VTP
6406 1
6407#else
6408 0
6409#endif
6410 },
Bram Moolenaar074fbd42022-08-26 16:41:14 +01006411 {"wildignore", 1},
Bram Moolenaar54162322022-08-26 16:58:51 +01006412 {"wildmenu", 1},
Bram Moolenaar79296512020-03-22 16:17:14 +01006413 {"windows", 1},
6414 {"winaltkeys",
6415#ifdef FEAT_WAK
6416 1
6417#else
6418 0
6419#endif
6420 },
6421 {"writebackup",
6422#ifdef FEAT_WRITEBACKUP
6423 1
6424#else
6425 0
6426#endif
6427 },
6428 {"xim",
6429#ifdef FEAT_XIM
6430 1
6431#else
6432 0
6433#endif
6434 },
6435 {"xfontset",
6436#ifdef FEAT_XFONTSET
6437 1
6438#else
6439 0
6440#endif
6441 },
6442 {"xpm",
6443#if defined(FEAT_XPM_W32) || defined(HAVE_XPM)
6444 1
6445#else
6446 0
6447#endif
6448 },
6449 {"xpm_w32", // for backward compatibility
6450#ifdef FEAT_XPM_W32
6451 1
6452#else
6453 0
6454#endif
6455 },
6456 {"xsmp",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006457#ifdef USE_XSMP
Bram Moolenaar79296512020-03-22 16:17:14 +01006458 1
6459#else
6460 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006461#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01006462 },
6463 {"xsmp_interact",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006464#ifdef USE_XSMP_INTERACT
Bram Moolenaar79296512020-03-22 16:17:14 +01006465 1
6466#else
6467 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006468#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01006469 },
6470 {"xterm_clipboard",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006471#ifdef FEAT_XCLIPBOARD
Bram Moolenaar79296512020-03-22 16:17:14 +01006472 1
6473#else
6474 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006475#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01006476 },
6477 {"xterm_save",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006478#ifdef FEAT_XTERM_SAVE
Bram Moolenaar79296512020-03-22 16:17:14 +01006479 1
6480#else
6481 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006482#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01006483 },
6484 {"X11",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006485#if defined(UNIX) && defined(FEAT_X11)
Bram Moolenaar79296512020-03-22 16:17:14 +01006486 1
6487#else
6488 0
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006489#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01006490 },
Bram Moolenaar80adaa82023-07-07 18:57:40 +01006491 {":tearoff",
6492// same #ifdef as used for ex_tearoff().
6493#if defined(FEAT_GUI_MSWIN) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
6494 1
6495#else
6496 0
6497#endif
6498 },
Bram Moolenaar79296512020-03-22 16:17:14 +01006499 {NULL, 0}
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006500 };
6501
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02006502 if (in_vim9script()
6503 && (check_for_string_arg(argvars, 0) == FAIL
6504 || check_for_opt_bool_arg(argvars, 1) == FAIL))
6505 return;
6506
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006507 name = tv_get_string(&argvars[0]);
Bram Moolenaar79296512020-03-22 16:17:14 +01006508 for (i = 0; has_list[i].name != NULL; ++i)
6509 if (STRICMP(name, has_list[i].name) == 0)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006510 {
Bram Moolenaar79296512020-03-22 16:17:14 +01006511 x = TRUE;
6512 n = has_list[i].present;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006513 break;
6514 }
6515
Bram Moolenaar79296512020-03-22 16:17:14 +01006516 // features also in has_list[] but sometimes enabled at runtime
6517 if (x == TRUE && n == FALSE)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006518 {
Bram Moolenaar79296512020-03-22 16:17:14 +01006519 if (0)
Bram Moolenaar86b9a3e2020-04-07 19:57:29 +02006520 {
6521 // intentionally empty
6522 }
Bram Moolenaar79296512020-03-22 16:17:14 +01006523#ifdef VIMDLL
6524 else if (STRICMP(name, "filterpipe") == 0)
6525 n = gui.in_use || gui.starting;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006526#endif
6527#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
6528 else if (STRICMP(name, "iconv") == 0)
6529 n = iconv_enabled(FALSE);
6530#endif
6531#ifdef DYNAMIC_LUA
6532 else if (STRICMP(name, "lua") == 0)
6533 n = lua_enabled(FALSE);
6534#endif
6535#ifdef DYNAMIC_MZSCHEME
6536 else if (STRICMP(name, "mzscheme") == 0)
6537 n = mzscheme_enabled(FALSE);
6538#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01006539#ifdef DYNAMIC_PERL
6540 else if (STRICMP(name, "perl") == 0)
6541 n = perl_enabled(FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006542#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006543#ifdef DYNAMIC_PYTHON
6544 else if (STRICMP(name, "python") == 0)
6545 n = python_enabled(FALSE);
6546#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006547#ifdef DYNAMIC_PYTHON3
6548 else if (STRICMP(name, "python3") == 0)
6549 n = python3_enabled(FALSE);
6550#endif
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01006551#if defined(DYNAMIC_PYTHON) || defined(DYNAMIC_PYTHON3)
6552 else if (STRICMP(name, "pythonx") == 0)
6553 {
6554# if defined(DYNAMIC_PYTHON) && defined(DYNAMIC_PYTHON3)
6555 if (p_pyx == 0)
6556 n = python3_enabled(FALSE) || python_enabled(FALSE);
6557 else if (p_pyx == 3)
6558 n = python3_enabled(FALSE);
6559 else if (p_pyx == 2)
6560 n = python_enabled(FALSE);
6561# elif defined(DYNAMIC_PYTHON)
6562 n = python_enabled(FALSE);
6563# elif defined(DYNAMIC_PYTHON3)
6564 n = python3_enabled(FALSE);
6565# endif
6566 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006567#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01006568#ifdef DYNAMIC_RUBY
6569 else if (STRICMP(name, "ruby") == 0)
6570 n = ruby_enabled(FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006571#endif
Bram Moolenaar79296512020-03-22 16:17:14 +01006572#ifdef DYNAMIC_TCL
6573 else if (STRICMP(name, "tcl") == 0)
6574 n = tcl_enabled(FALSE);
Bram Moolenaar4b8366b2019-05-04 17:34:34 +02006575#endif
K.Takatad68b2fc2022-02-12 11:18:37 +00006576#ifdef DYNAMIC_SODIUM
6577 else if (STRICMP(name, "sodium") == 0)
6578 n = sodium_enabled(FALSE);
6579#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01006580#if defined(FEAT_TERMINAL) && defined(MSWIN)
Bram Moolenaara83e3962017-08-17 14:39:07 +02006581 else if (STRICMP(name, "terminal") == 0)
6582 n = terminal_enabled();
6583#endif
Bram Moolenaar33fc4a62022-02-23 18:07:38 +00006584#ifdef DYNAMIC_GPM
6585 else if (STRICMP(name, "mouse_gpm") == 0)
6586 n = gpm_available();
6587#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006588 }
6589
Bram Moolenaar79296512020-03-22 16:17:14 +01006590 // features not in has_list[]
6591 if (x == FALSE)
6592 {
6593 if (STRNICMP(name, "patch", 5) == 0)
6594 {
6595 x = TRUE;
6596 if (name[5] == '-'
6597 && STRLEN(name) >= 11
K.Takatad90f91f2022-07-30 15:43:59 +01006598 && (name[6] >= '1' && name[6] <= '9'))
Bram Moolenaar79296512020-03-22 16:17:14 +01006599 {
K.Takatad90f91f2022-07-30 15:43:59 +01006600 char *end;
6601 int major, minor;
Bram Moolenaar79296512020-03-22 16:17:14 +01006602
K.Takatad90f91f2022-07-30 15:43:59 +01006603 // This works for patch-8.1.2, patch-9.0.3, patch-10.0.4, etc.
6604 // Not for patch-9.10.5.
6605 major = (int)strtoul((char *)name + 6, &end, 10);
6606 if (*end == '.' && vim_isdigit(end[1])
6607 && end[2] == '.' && vim_isdigit(end[3]))
6608 {
6609 minor = atoi(end + 1);
6610
6611 // Expect "patch-9.9.01234".
6612 n = (major < VIM_VERSION_MAJOR
6613 || (major == VIM_VERSION_MAJOR
6614 && (minor < VIM_VERSION_MINOR
6615 || (minor == VIM_VERSION_MINOR
6616 && has_patch(atoi(end + 3))))));
6617 }
Bram Moolenaar79296512020-03-22 16:17:14 +01006618 }
Bram Moolenaar5154a882022-07-18 20:48:50 +01006619 else if (isdigit(name[5]))
Bram Moolenaar79296512020-03-22 16:17:14 +01006620 n = has_patch(atoi((char *)name + 5));
6621 }
6622 else if (STRICMP(name, "vim_starting") == 0)
6623 {
6624 x = TRUE;
6625 n = (starting != 0);
6626 }
6627 else if (STRICMP(name, "ttyin") == 0)
6628 {
6629 x = TRUE;
6630 n = mch_input_isatty();
6631 }
6632 else if (STRICMP(name, "ttyout") == 0)
6633 {
6634 x = TRUE;
6635 n = stdout_isatty;
6636 }
6637 else if (STRICMP(name, "multi_byte_encoding") == 0)
6638 {
6639 x = TRUE;
6640 n = has_mbyte;
6641 }
6642 else if (STRICMP(name, "gui_running") == 0)
6643 {
6644 x = TRUE;
6645#ifdef FEAT_GUI
6646 n = (gui.in_use || gui.starting);
6647#endif
6648 }
6649 else if (STRICMP(name, "browse") == 0)
6650 {
6651 x = TRUE;
6652#if defined(FEAT_GUI) && defined(FEAT_BROWSE)
6653 n = gui.in_use; // gui_mch_browse() works when GUI is running
6654#endif
6655 }
6656 else if (STRICMP(name, "syntax_items") == 0)
6657 {
6658 x = TRUE;
6659#ifdef FEAT_SYN_HL
6660 n = syntax_present(curwin);
6661#endif
6662 }
6663 else if (STRICMP(name, "vcon") == 0)
6664 {
6665 x = TRUE;
6666#ifdef FEAT_VTP
6667 n = is_term_win32() && has_vtp_working();
6668#endif
6669 }
6670 else if (STRICMP(name, "netbeans_enabled") == 0)
6671 {
6672 x = TRUE;
6673#ifdef FEAT_NETBEANS_INTG
6674 n = netbeans_active();
6675#endif
6676 }
6677 else if (STRICMP(name, "mouse_gpm_enabled") == 0)
6678 {
6679 x = TRUE;
6680#ifdef FEAT_MOUSE_GPM
6681 n = gpm_enabled();
6682#endif
6683 }
6684 else if (STRICMP(name, "conpty") == 0)
6685 {
6686 x = TRUE;
6687#if defined(FEAT_TERMINAL) && defined(MSWIN)
6688 n = use_conpty();
6689#endif
6690 }
6691 else if (STRICMP(name, "clipboard_working") == 0)
6692 {
6693 x = TRUE;
6694#ifdef FEAT_CLIPBOARD
6695 n = clip_star.available;
6696#endif
6697 }
6698 }
6699
Bram Moolenaar04637e22020-09-05 18:45:29 +02006700 if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1]))
Bram Moolenaar79296512020-03-22 16:17:14 +01006701 // return whether feature could ever be enabled
6702 rettv->vval.v_number = x;
6703 else
6704 // return whether feature is enabled
6705 rettv->vval.v_number = n;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006706}
6707
6708/*
Bram Moolenaar8cebd432020-11-08 12:49:47 +01006709 * Return TRUE if "feature" can change later.
6710 * Also when checking for the feature has side effects, such as loading a DLL.
6711 */
6712 int
6713dynamic_feature(char_u *feature)
6714{
6715 return (feature == NULL
Bram Moolenaar8cebd432020-11-08 12:49:47 +01006716#if defined(FEAT_GUI) && defined(FEAT_BROWSE)
6717 || (STRICMP(feature, "browse") == 0 && !gui.in_use)
6718#endif
6719#ifdef VIMDLL
6720 || STRICMP(feature, "filterpipe") == 0
6721#endif
Bram Moolenaar29b281b2020-11-10 20:58:00 +01006722#if defined(FEAT_GUI) && !defined(ALWAYS_USE_GUI) && !defined(VIMDLL)
Bram Moolenaar8cebd432020-11-08 12:49:47 +01006723 // this can only change on Unix where the ":gui" command could be
6724 // used.
6725 || (STRICMP(feature, "gui_running") == 0 && !gui.in_use)
6726#endif
6727#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
6728 || STRICMP(feature, "iconv") == 0
6729#endif
6730#ifdef DYNAMIC_LUA
6731 || STRICMP(feature, "lua") == 0
6732#endif
6733#ifdef FEAT_MOUSE_GPM
6734 || (STRICMP(feature, "mouse_gpm_enabled") == 0 && !gpm_enabled())
6735#endif
6736#ifdef DYNAMIC_MZSCHEME
6737 || STRICMP(feature, "mzscheme") == 0
6738#endif
6739#ifdef FEAT_NETBEANS_INTG
6740 || STRICMP(feature, "netbeans_enabled") == 0
6741#endif
6742#ifdef DYNAMIC_PERL
6743 || STRICMP(feature, "perl") == 0
6744#endif
6745#ifdef DYNAMIC_PYTHON
6746 || STRICMP(feature, "python") == 0
6747#endif
6748#ifdef DYNAMIC_PYTHON3
6749 || STRICMP(feature, "python3") == 0
6750#endif
6751#if defined(DYNAMIC_PYTHON) || defined(DYNAMIC_PYTHON3)
6752 || STRICMP(feature, "pythonx") == 0
6753#endif
6754#ifdef DYNAMIC_RUBY
6755 || STRICMP(feature, "ruby") == 0
6756#endif
6757#ifdef FEAT_SYN_HL
6758 || STRICMP(feature, "syntax_items") == 0
6759#endif
6760#ifdef DYNAMIC_TCL
6761 || STRICMP(feature, "tcl") == 0
6762#endif
6763 // once "starting" is zero it will stay that way
6764 || (STRICMP(feature, "vim_starting") == 0 && starting != 0)
6765 || STRICMP(feature, "multi_byte_encoding") == 0
6766#if defined(FEAT_TERMINAL) && defined(MSWIN)
6767 || STRICMP(feature, "conpty") == 0
6768#endif
6769 );
6770}
6771
6772/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006773 * "haslocaldir()" function
6774 */
6775 static void
6776f_haslocaldir(typval_T *argvars, typval_T *rettv)
6777{
Bram Moolenaar00aa0692019-04-27 20:37:57 +02006778 tabpage_T *tp = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006779 win_T *wp = NULL;
6780
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02006781 if (in_vim9script()
6782 && (check_for_opt_number_arg(argvars, 0) == FAIL
6783 || (argvars[0].v_type != VAR_UNKNOWN
6784 && check_for_opt_number_arg(argvars, 1) == FAIL)))
6785 return;
6786
Bram Moolenaar00aa0692019-04-27 20:37:57 +02006787 wp = find_tabwin(&argvars[0], &argvars[1], &tp);
6788
6789 // Check for window-local and tab-local directories
6790 if (wp != NULL && wp->w_localdir != NULL)
6791 rettv->vval.v_number = 1;
6792 else if (tp != NULL && tp->tp_localdir != NULL)
6793 rettv->vval.v_number = 2;
6794 else
6795 rettv->vval.v_number = 0;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006796}
6797
6798/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006799 * "highlightID(name)" function
6800 */
6801 static void
6802f_hlID(typval_T *argvars, typval_T *rettv)
6803{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02006804 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
6805 return;
6806
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006807 rettv->vval.v_number = syn_name2id(tv_get_string(&argvars[0]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006808}
6809
6810/*
6811 * "highlight_exists()" function
6812 */
6813 static void
6814f_hlexists(typval_T *argvars, typval_T *rettv)
6815{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02006816 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
6817 return;
6818
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006819 rettv->vval.v_number = highlight_exists(tv_get_string(&argvars[0]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006820}
6821
6822/*
6823 * "hostname()" function
6824 */
6825 static void
6826f_hostname(typval_T *argvars UNUSED, typval_T *rettv)
6827{
6828 char_u hostname[256];
6829
6830 mch_get_host_name(hostname, 256);
6831 rettv->v_type = VAR_STRING;
6832 rettv->vval.v_string = vim_strsave(hostname);
6833}
6834
6835/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006836 * "index()" function
6837 */
6838 static void
6839f_index(typval_T *argvars, typval_T *rettv)
6840{
6841 list_T *l;
6842 listitem_T *item;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006843 blob_T *b;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006844 long idx = 0;
6845 int ic = FALSE;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006846 int error = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006847
6848 rettv->vval.v_number = -1;
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02006849
6850 if (in_vim9script()
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02006851 && (check_for_list_or_blob_arg(argvars, 0) == FAIL
6852 || (argvars[0].v_type == VAR_BLOB
6853 && check_for_number_arg(argvars, 1) == FAIL)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02006854 || check_for_opt_number_arg(argvars, 2) == FAIL
6855 || (argvars[2].v_type != VAR_UNKNOWN
6856 && check_for_opt_bool_arg(argvars, 3) == FAIL)))
6857 return;
6858
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006859 if (argvars[0].v_type == VAR_BLOB)
6860 {
6861 typval_T tv;
6862 int start = 0;
6863
6864 if (argvars[2].v_type != VAR_UNKNOWN)
6865 {
6866 start = tv_get_number_chk(&argvars[2], &error);
6867 if (error)
6868 return;
6869 }
6870 b = argvars[0].vval.v_blob;
6871 if (b == NULL)
6872 return;
Bram Moolenaar05500ec2019-01-13 19:10:33 +01006873 if (start < 0)
6874 {
6875 start = blob_len(b) + start;
6876 if (start < 0)
6877 start = 0;
6878 }
6879
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006880 for (idx = start; idx < blob_len(b); ++idx)
6881 {
6882 tv.v_type = VAR_NUMBER;
6883 tv.vval.v_number = blob_get(b, idx);
6884 if (tv_equal(&tv, &argvars[1], ic, FALSE))
6885 {
6886 rettv->vval.v_number = idx;
6887 return;
6888 }
6889 }
6890 return;
6891 }
6892 else if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006893 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00006894 emsg(_(e_list_or_blob_required));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006895 return;
6896 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006897
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006898 l = argvars[0].vval.v_list;
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00006899 if (l == NULL)
6900 return;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006901
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00006902 CHECK_LIST_MATERIALIZE(l);
6903 item = l->lv_first;
6904 if (argvars[2].v_type != VAR_UNKNOWN)
6905 {
6906 // Start at specified item. Use the cached index that list_find()
6907 // sets, so that a negative number also works.
6908 item = list_find(l, (long)tv_get_number_chk(&argvars[2], &error));
6909 idx = l->lv_u.mat.lv_idx;
6910 if (argvars[3].v_type != VAR_UNKNOWN)
6911 ic = (int)tv_get_bool_chk(&argvars[3], &error);
6912 if (error)
6913 item = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006914 }
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00006915
6916 for ( ; item != NULL; item = item->li_next, ++idx)
6917 if (tv_equal(&item->li_tv, &argvars[1], ic, FALSE))
6918 {
6919 rettv->vval.v_number = idx;
6920 break;
6921 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006922}
6923
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01006924/*
6925 * Evaluate 'expr' with the v:key and v:val arguments and return the result.
6926 * The expression is expected to return a boolean value. The caller should set
6927 * the VV_KEY and VV_VAL vim variables before calling this function.
6928 */
6929 static int
6930indexof_eval_expr(typval_T *expr)
6931{
6932 typval_T argv[3];
6933 typval_T newtv;
6934 varnumber_T found;
6935 int error = FALSE;
6936
6937 argv[0] = *get_vim_var_tv(VV_KEY);
6938 argv[1] = *get_vim_var_tv(VV_VAL);
6939 newtv.v_type = VAR_UNKNOWN;
6940
zeertzjqad0c4422023-08-17 22:15:47 +02006941 if (eval_expr_typval(expr, FALSE, argv, 2, NULL, &newtv) == FAIL)
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01006942 return FALSE;
6943
6944 found = tv_get_bool_chk(&newtv, &error);
Yegappan Lakshmanan63acae12022-08-14 12:07:11 +01006945 clear_tv(&newtv);
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01006946
6947 return error ? FALSE : found;
6948}
6949
6950/*
Yegappan Lakshmanan3fbf6cd2022-08-13 21:35:13 +01006951 * Evaluate 'expr' for each byte in the Blob 'b' starting with the byte at
6952 * 'startidx' and return the index of the byte where 'expr' is TRUE. Returns
6953 * -1 if 'expr' doesn't evaluate to TRUE for any of the bytes.
6954 */
6955 static int
6956indexof_blob(blob_T *b, long startidx, typval_T *expr)
6957{
6958 long idx = 0;
6959
6960 if (b == NULL)
6961 return -1;
6962
6963 if (startidx < 0)
6964 {
6965 // negative index: index from the last byte
6966 startidx = blob_len(b) + startidx;
6967 if (startidx < 0)
6968 startidx = 0;
6969 }
6970
6971 set_vim_var_type(VV_KEY, VAR_NUMBER);
6972 set_vim_var_type(VV_VAL, VAR_NUMBER);
6973
6974 for (idx = startidx; idx < blob_len(b); ++idx)
6975 {
6976 set_vim_var_nr(VV_KEY, idx);
6977 set_vim_var_nr(VV_VAL, blob_get(b, idx));
6978
6979 if (indexof_eval_expr(expr))
6980 return idx;
6981 }
6982
6983 return -1;
6984}
6985
6986/*
6987 * Evaluate 'expr' for each item in the List 'l' starting with the item at
6988 * 'startidx' and return the index of the item where 'expr' is TRUE. Returns
6989 * -1 if 'expr' doesn't evaluate to TRUE for any of the items.
6990 */
6991 static int
6992indexof_list(list_T *l, long startidx, typval_T *expr)
6993{
6994 listitem_T *item;
6995 long idx = 0;
Yegappan Lakshmanan63acae12022-08-14 12:07:11 +01006996 int found;
Yegappan Lakshmanan3fbf6cd2022-08-13 21:35:13 +01006997
6998 if (l == NULL)
6999 return -1;
7000
7001 CHECK_LIST_MATERIALIZE(l);
7002
7003 if (startidx == 0)
7004 item = l->lv_first;
7005 else
7006 {
7007 // Start at specified item. Use the cached index that list_find()
7008 // sets, so that a negative number also works.
7009 item = list_find(l, startidx);
7010 if (item != NULL)
7011 idx = l->lv_u.mat.lv_idx;
7012 }
7013
7014 set_vim_var_type(VV_KEY, VAR_NUMBER);
7015
7016 for ( ; item != NULL; item = item->li_next, ++idx)
7017 {
7018 set_vim_var_nr(VV_KEY, idx);
7019 copy_tv(&item->li_tv, get_vim_var_tv(VV_VAL));
7020
Yegappan Lakshmanan63acae12022-08-14 12:07:11 +01007021 found = indexof_eval_expr(expr);
7022 clear_tv(get_vim_var_tv(VV_VAL));
7023
7024 if (found)
Yegappan Lakshmanan3fbf6cd2022-08-13 21:35:13 +01007025 return idx;
7026 }
7027
7028 return -1;
7029}
7030
7031/*
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01007032 * "indexof()" function
7033 */
7034 static void
7035f_indexof(typval_T *argvars, typval_T *rettv)
7036{
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01007037 long startidx = 0;
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01007038 typval_T save_val;
7039 typval_T save_key;
7040 int save_did_emsg;
7041
7042 rettv->vval.v_number = -1;
7043
7044 if (check_for_list_or_blob_arg(argvars, 0) == FAIL
7045 || check_for_string_or_func_arg(argvars, 1) == FAIL
7046 || check_for_opt_dict_arg(argvars, 2) == FAIL)
7047 return;
7048
7049 if ((argvars[1].v_type == VAR_STRING && argvars[1].vval.v_string == NULL)
7050 || (argvars[1].v_type == VAR_FUNC
7051 && argvars[1].vval.v_partial == NULL))
7052 return;
7053
7054 if (argvars[2].v_type == VAR_DICT)
7055 startidx = dict_get_number_def(argvars[2].vval.v_dict, "startidx", 0);
7056
7057 prepare_vimvar(VV_VAL, &save_val);
7058 prepare_vimvar(VV_KEY, &save_key);
7059
7060 // We reset "did_emsg" to be able to detect whether an error occurred
7061 // during evaluation of the expression.
7062 save_did_emsg = did_emsg;
7063 did_emsg = FALSE;
7064
7065 if (argvars[0].v_type == VAR_BLOB)
Yegappan Lakshmanan3fbf6cd2022-08-13 21:35:13 +01007066 rettv->vval.v_number = indexof_blob(argvars[0].vval.v_blob, startidx,
7067 &argvars[1]);
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01007068 else
Yegappan Lakshmanan3fbf6cd2022-08-13 21:35:13 +01007069 rettv->vval.v_number = indexof_list(argvars[0].vval.v_list, startidx,
7070 &argvars[1]);
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01007071
Yegappan Lakshmananb2186552022-08-13 13:09:20 +01007072 restore_vimvar(VV_KEY, &save_key);
7073 restore_vimvar(VV_VAL, &save_val);
7074 did_emsg |= save_did_emsg;
7075}
7076
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007077static int inputsecret_flag = 0;
7078
7079/*
7080 * "input()" function
7081 * Also handles inputsecret() when inputsecret is set.
7082 */
7083 static void
7084f_input(typval_T *argvars, typval_T *rettv)
7085{
7086 get_user_input(argvars, rettv, FALSE, inputsecret_flag);
7087}
7088
7089/*
7090 * "inputdialog()" function
7091 */
7092 static void
7093f_inputdialog(typval_T *argvars, typval_T *rettv)
7094{
7095#if defined(FEAT_GUI_TEXTDIALOG)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007096 // Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions'
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007097 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
7098 {
7099 char_u *message;
7100 char_u buf[NUMBUFLEN];
7101 char_u *defstr = (char_u *)"";
7102
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007103 if (in_vim9script()
7104 && (check_for_string_arg(argvars, 0) == FAIL
7105 || check_for_opt_string_arg(argvars, 1) == FAIL
7106 || (argvars[1].v_type != VAR_UNKNOWN
7107 && check_for_opt_string_arg(argvars, 2) == FAIL)))
7108 return;
7109
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007110 message = tv_get_string_chk(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007111 if (argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007112 && (defstr = tv_get_string_buf_chk(&argvars[1], buf)) != NULL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007113 vim_strncpy(IObuff, defstr, IOSIZE - 1);
7114 else
7115 IObuff[0] = NUL;
7116 if (message != NULL && defstr != NULL
7117 && do_dialog(VIM_QUESTION, NULL, message,
7118 (char_u *)_("&OK\n&Cancel"), 1, IObuff, FALSE) == 1)
7119 rettv->vval.v_string = vim_strsave(IObuff);
7120 else
7121 {
7122 if (message != NULL && defstr != NULL
7123 && argvars[1].v_type != VAR_UNKNOWN
7124 && argvars[2].v_type != VAR_UNKNOWN)
7125 rettv->vval.v_string = vim_strsave(
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007126 tv_get_string_buf(&argvars[2], buf));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007127 else
7128 rettv->vval.v_string = NULL;
7129 }
7130 rettv->v_type = VAR_STRING;
7131 }
7132 else
7133#endif
7134 get_user_input(argvars, rettv, TRUE, inputsecret_flag);
7135}
7136
7137/*
7138 * "inputlist()" function
7139 */
7140 static void
7141f_inputlist(typval_T *argvars, typval_T *rettv)
7142{
Bram Moolenaar50985eb2020-01-27 22:09:39 +01007143 list_T *l;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007144 listitem_T *li;
7145 int selected;
7146 int mouse_used;
7147
7148#ifdef NO_CONSOLE_INPUT
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007149 // While starting up, there is no place to enter text. When running tests
7150 // with --not-a-term we assume feedkeys() will be used.
Bram Moolenaar91d348a2017-07-29 20:16:03 +02007151 if (no_console_input() && !is_not_a_term())
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007152 return;
7153#endif
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007154 if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL)
7155 return;
7156
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007157 if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL)
7158 {
Bram Moolenaar3a846e62022-01-01 16:21:00 +00007159 semsg(_(e_argument_of_str_must_be_list), "inputlist()");
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007160 return;
7161 }
7162
7163 msg_start();
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007164 msg_row = Rows - 1; // for when 'cmdheight' > 1
7165 lines_left = Rows; // avoid more prompt
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007166 msg_scroll = TRUE;
7167 msg_clr_eos();
7168
Bram Moolenaar50985eb2020-01-27 22:09:39 +01007169 l = argvars[0].vval.v_list;
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02007170 CHECK_LIST_MATERIALIZE(l);
Bram Moolenaar00d253e2020-04-06 22:13:01 +02007171 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007172 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01007173 msg_puts((char *)tv_get_string(&li->li_tv));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007174 msg_putchar('\n');
7175 }
7176
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007177 // Ask for choice.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007178 selected = prompt_for_number(&mouse_used);
7179 if (mouse_used)
7180 selected -= lines_left;
7181
7182 rettv->vval.v_number = selected;
7183}
7184
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007185static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
7186
7187/*
7188 * "inputrestore()" function
7189 */
7190 static void
7191f_inputrestore(typval_T *argvars UNUSED, typval_T *rettv)
7192{
7193 if (ga_userinput.ga_len > 0)
7194 {
7195 --ga_userinput.ga_len;
7196 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
Bram Moolenaarc41badb2021-06-07 22:04:52 +02007197 + ga_userinput.ga_len, TRUE);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007198 // default return is zero == OK
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007199 }
7200 else if (p_verbose > 1)
7201 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01007202 verb_msg(_("called inputrestore() more often than inputsave()"));
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007203 rettv->vval.v_number = 1; // Failed
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007204 }
7205}
7206
7207/*
7208 * "inputsave()" function
7209 */
7210 static void
7211f_inputsave(typval_T *argvars UNUSED, typval_T *rettv)
7212{
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007213 // Add an entry to the stack of typeahead storage.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007214 if (ga_grow(&ga_userinput, 1) == OK)
7215 {
7216 save_typeahead((tasave_T *)(ga_userinput.ga_data)
7217 + ga_userinput.ga_len);
7218 ++ga_userinput.ga_len;
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007219 // default return is zero == OK
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007220 }
7221 else
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007222 rettv->vval.v_number = 1; // Failed
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007223}
7224
7225/*
7226 * "inputsecret()" function
7227 */
7228 static void
7229f_inputsecret(typval_T *argvars, typval_T *rettv)
7230{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007231 if (in_vim9script()
7232 && (check_for_string_arg(argvars, 0) == FAIL
7233 || check_for_opt_string_arg(argvars, 1) == FAIL))
7234 return;
7235
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007236 ++cmdline_star;
7237 ++inputsecret_flag;
7238 f_input(argvars, rettv);
7239 --cmdline_star;
7240 --inputsecret_flag;
7241}
7242
7243/*
Bram Moolenaar67a2deb2019-11-25 00:05:32 +01007244 * "interrupt()" function
7245 */
7246 static void
7247f_interrupt(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
7248{
7249 got_int = TRUE;
7250}
7251
7252/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007253 * "invert(expr)" function
7254 */
7255 static void
7256f_invert(typval_T *argvars, typval_T *rettv)
7257{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007258 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
7259 return;
7260
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007261 rettv->vval.v_number = ~tv_get_number_chk(&argvars[0], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007262}
7263
7264/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007265 * "islocked()" function
7266 */
7267 static void
7268f_islocked(typval_T *argvars, typval_T *rettv)
7269{
7270 lval_T lv;
7271 char_u *end;
7272 dictitem_T *di;
7273
7274 rettv->vval.v_number = -1;
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02007275
7276 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
7277 return;
7278
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007279 end = get_lval(tv_get_string(&argvars[0]), NULL, &lv, FALSE, FALSE,
Bram Moolenaarbd77aa92021-08-12 17:06:05 +02007280 GLV_NO_AUTOLOAD | GLV_READ_ONLY | GLV_NO_DECL,
7281 FNE_CHECK_START);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007282 if (end != NULL && lv.ll_name != NULL)
7283 {
7284 if (*end != NUL)
Bram Moolenaar1840a7b2021-07-13 20:32:29 +02007285 {
7286 semsg(_(lv.ll_name == lv.ll_name_end
Bram Moolenaar0bd663a2022-01-22 10:24:47 +00007287 ? e_invalid_argument_str : e_trailing_characters_str), end);
Bram Moolenaar1840a7b2021-07-13 20:32:29 +02007288 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007289 else
7290 {
7291 if (lv.ll_tv == NULL)
7292 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01007293 di = find_var(lv.ll_name, NULL, TRUE);
7294 if (di != NULL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007295 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007296 // Consider a variable locked when:
7297 // 1. the variable itself is locked
7298 // 2. the value of the variable is locked.
7299 // 3. the List or Dict value is locked.
Bram Moolenaar79518e22017-02-17 16:31:35 +01007300 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
7301 || tv_islocked(&di->di_tv));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007302 }
7303 }
7304 else if (lv.ll_range)
Bram Moolenaar677658a2022-01-05 16:09:06 +00007305 emsg(_(e_range_not_allowed));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007306 else if (lv.ll_newkey != NULL)
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00007307 semsg(_(e_key_not_present_in_dictionary_str), lv.ll_newkey);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007308 else if (lv.ll_list != NULL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007309 // List item.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007310 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
7311 else
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007312 // Dictionary item.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007313 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
7314 }
7315 }
7316
7317 clear_lval(&lv);
7318}
7319
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007320/*
zeertzjqcdc83932022-09-12 13:38:41 +01007321 * "keytrans()" function
7322 */
7323 static void
7324f_keytrans(typval_T *argvars, typval_T *rettv)
7325{
7326 char_u *escaped;
7327
7328 rettv->v_type = VAR_STRING;
7329 if (check_for_string_arg(argvars, 0) == FAIL
7330 || argvars[0].vval.v_string == NULL)
7331 return;
7332 // Need to escape K_SPECIAL and CSI for mb_unescape().
7333 escaped = vim_strsave_escape_csi(argvars[0].vval.v_string);
7334 rettv->vval.v_string = str2special_save(escaped, TRUE, TRUE);
7335 vim_free(escaped);
7336}
7337
7338/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007339 * "last_buffer_nr()" function.
7340 */
7341 static void
7342f_last_buffer_nr(typval_T *argvars UNUSED, typval_T *rettv)
7343{
7344 int n = 0;
7345 buf_T *buf;
7346
Bram Moolenaar29323592016-07-24 22:04:11 +02007347 FOR_ALL_BUFFERS(buf)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007348 if (n < buf->b_fnum)
7349 n = buf->b_fnum;
7350
7351 rettv->vval.v_number = n;
7352}
7353
7354/*
7355 * "len()" function
7356 */
LemonBoy58f331a2022-04-02 21:59:06 +01007357 void
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007358f_len(typval_T *argvars, typval_T *rettv)
7359{
7360 switch (argvars[0].v_type)
7361 {
7362 case VAR_STRING:
7363 case VAR_NUMBER:
7364 rettv->vval.v_number = (varnumber_T)STRLEN(
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007365 tv_get_string(&argvars[0]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007366 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007367 case VAR_BLOB:
7368 rettv->vval.v_number = blob_len(argvars[0].vval.v_blob);
7369 break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007370 case VAR_LIST:
7371 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
7372 break;
7373 case VAR_DICT:
7374 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
7375 break;
7376 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02007377 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007378 case VAR_VOID:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01007379 case VAR_BOOL:
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007380 case VAR_SPECIAL:
7381 case VAR_FLOAT:
7382 case VAR_FUNC:
7383 case VAR_PARTIAL:
7384 case VAR_JOB:
7385 case VAR_CHANNEL:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02007386 case VAR_INSTR:
Bram Moolenaar00b28d62022-12-08 15:32:33 +00007387 case VAR_CLASS:
7388 case VAR_OBJECT:
Bram Moolenaara6f79292022-01-04 21:30:47 +00007389 emsg(_(e_invalid_type_for_len));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007390 break;
7391 }
7392}
7393
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007394 static void
Bram Moolenaar6d721c72017-01-17 16:56:28 +01007395libcall_common(typval_T *argvars UNUSED, typval_T *rettv, int type)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007396{
7397#ifdef FEAT_LIBCALL
7398 char_u *string_in;
7399 char_u **string_result;
7400 int nr_result;
7401#endif
7402
7403 rettv->v_type = type;
7404 if (type != VAR_NUMBER)
7405 rettv->vval.v_string = NULL;
7406
7407 if (check_restricted() || check_secure())
7408 return;
7409
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02007410 if (in_vim9script()
7411 && (check_for_string_arg(argvars, 0) == FAIL
7412 || check_for_string_arg(argvars, 1) == FAIL
7413 || check_for_string_or_number_arg(argvars, 2) == FAIL))
7414 return;
7415
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007416#ifdef FEAT_LIBCALL
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007417 // The first two args must be strings, otherwise it's meaningless
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007418 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
7419 {
7420 string_in = NULL;
7421 if (argvars[2].v_type == VAR_STRING)
7422 string_in = argvars[2].vval.v_string;
7423 if (type == VAR_NUMBER)
Bram Moolenaar87e15872021-09-02 19:53:07 +02007424 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007425 string_result = NULL;
Bram Moolenaar87e15872021-09-02 19:53:07 +02007426 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007427 else
Bram Moolenaar87e15872021-09-02 19:53:07 +02007428 {
7429 rettv->vval.v_string = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007430 string_result = &rettv->vval.v_string;
Bram Moolenaar87e15872021-09-02 19:53:07 +02007431 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007432 if (mch_libcall(argvars[0].vval.v_string,
7433 argvars[1].vval.v_string,
7434 string_in,
7435 argvars[2].vval.v_number,
7436 string_result,
7437 &nr_result) == OK
7438 && type == VAR_NUMBER)
7439 rettv->vval.v_number = nr_result;
7440 }
7441#endif
7442}
7443
7444/*
7445 * "libcall()" function
7446 */
7447 static void
7448f_libcall(typval_T *argvars, typval_T *rettv)
7449{
7450 libcall_common(argvars, rettv, VAR_STRING);
7451}
7452
7453/*
7454 * "libcallnr()" function
7455 */
7456 static void
7457f_libcallnr(typval_T *argvars, typval_T *rettv)
7458{
7459 libcall_common(argvars, rettv, VAR_NUMBER);
7460}
7461
7462/*
Bram Moolenaar8e0a8e72019-09-02 22:56:24 +02007463 * "line(string, [winid])" function
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007464 */
7465 static void
7466f_line(typval_T *argvars, typval_T *rettv)
7467{
7468 linenr_T lnum = 0;
Bram Moolenaar8e0a8e72019-09-02 22:56:24 +02007469 pos_T *fp = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007470 int fnum;
Bram Moolenaar8e0a8e72019-09-02 22:56:24 +02007471 int id;
7472 tabpage_T *tp;
7473 win_T *wp;
Bram Moolenaar18f47402022-01-06 13:24:51 +00007474 switchwin_T switchwin;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007475
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02007476 if (in_vim9script()
7477 && (check_for_string_arg(argvars, 0) == FAIL
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02007478 || check_for_opt_number_arg(argvars, 1) == FAIL))
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +02007479 return;
7480
Bram Moolenaar8e0a8e72019-09-02 22:56:24 +02007481 if (argvars[1].v_type != VAR_UNKNOWN)
7482 {
7483 // use window specified in the second argument
7484 id = (int)tv_get_number(&argvars[1]);
7485 wp = win_id2wp_tp(id, &tp);
7486 if (wp != NULL && tp != NULL)
7487 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00007488 if (switch_win_noblock(&switchwin, wp, tp, TRUE) == OK)
Bram Moolenaar8e0a8e72019-09-02 22:56:24 +02007489 {
7490 check_cursor();
Bram Moolenaar6f02b002021-01-10 20:22:54 +01007491 fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
Bram Moolenaar8e0a8e72019-09-02 22:56:24 +02007492 }
Bram Moolenaar18f47402022-01-06 13:24:51 +00007493 restore_win_noblock(&switchwin, TRUE);
Bram Moolenaar8e0a8e72019-09-02 22:56:24 +02007494 }
7495 }
7496 else
7497 // use current window
Bram Moolenaar6f02b002021-01-10 20:22:54 +01007498 fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
Bram Moolenaar8e0a8e72019-09-02 22:56:24 +02007499
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007500 if (fp != NULL)
7501 lnum = fp->lnum;
7502 rettv->vval.v_number = lnum;
7503}
7504
7505/*
7506 * "line2byte(lnum)" function
7507 */
7508 static void
7509f_line2byte(typval_T *argvars UNUSED, typval_T *rettv)
7510{
7511#ifndef FEAT_BYTEOFF
7512 rettv->vval.v_number = -1;
7513#else
7514 linenr_T lnum;
7515
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007516 if (in_vim9script() && check_for_lnum_arg(argvars, 0) == FAIL)
7517 return;
7518
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007519 lnum = tv_get_lnum(argvars);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007520 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
7521 rettv->vval.v_number = -1;
7522 else
7523 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
7524 if (rettv->vval.v_number >= 0)
7525 ++rettv->vval.v_number;
7526#endif
7527}
7528
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007529#ifdef FEAT_LUA
7530/*
7531 * "luaeval()" function
7532 */
7533 static void
7534f_luaeval(typval_T *argvars, typval_T *rettv)
7535{
7536 char_u *str;
7537 char_u buf[NUMBUFLEN];
7538
Bram Moolenaar8c62a082019-02-08 14:34:10 +01007539 if (check_restricted() || check_secure())
7540 return;
7541
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02007542 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
7543 return;
7544
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007545 str = tv_get_string_buf(&argvars[0], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007546 do_luaeval(str, argvars + 1, rettv);
7547}
7548#endif
7549
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007550typedef enum
7551{
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007552 MATCH_END, // matchend()
7553 MATCH_MATCH, // match()
7554 MATCH_STR, // matchstr()
7555 MATCH_LIST, // matchlist()
7556 MATCH_POS // matchstrpos()
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007557} matchtype_T;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007558
7559 static void
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007560find_some_match(typval_T *argvars, typval_T *rettv, matchtype_T type)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007561{
7562 char_u *str = NULL;
7563 long len = 0;
7564 char_u *expr = NULL;
7565 char_u *pat;
7566 regmatch_T regmatch;
7567 char_u patbuf[NUMBUFLEN];
7568 char_u strbuf[NUMBUFLEN];
7569 char_u *save_cpo;
7570 long start = 0;
7571 long nth = 1;
7572 colnr_T startcol = 0;
7573 int match = 0;
7574 list_T *l = NULL;
7575 listitem_T *li = NULL;
7576 long idx = 0;
7577 char_u *tofree = NULL;
7578
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007579 // Make 'cpoptions' empty, the 'l' flag should not be used here.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007580 save_cpo = p_cpo;
Bram Moolenaare5a2dc82021-01-03 19:52:05 +01007581 p_cpo = empty_option;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007582
7583 rettv->vval.v_number = -1;
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007584 if (type == MATCH_LIST || type == MATCH_POS)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007585 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007586 // type MATCH_LIST: return empty list when there are no matches.
7587 // type MATCH_POS: return ["", -1, -1, -1]
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007588 if (rettv_list_alloc(rettv) == FAIL)
7589 goto theend;
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007590 if (type == MATCH_POS
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007591 && (list_append_string(rettv->vval.v_list,
7592 (char_u *)"", 0) == FAIL
7593 || list_append_number(rettv->vval.v_list,
7594 (varnumber_T)-1) == FAIL
7595 || list_append_number(rettv->vval.v_list,
7596 (varnumber_T)-1) == FAIL
7597 || list_append_number(rettv->vval.v_list,
7598 (varnumber_T)-1) == FAIL))
7599 {
7600 list_free(rettv->vval.v_list);
7601 rettv->vval.v_list = NULL;
7602 goto theend;
7603 }
7604 }
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007605 else if (type == MATCH_STR)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007606 {
7607 rettv->v_type = VAR_STRING;
7608 rettv->vval.v_string = NULL;
7609 }
7610
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02007611 if (in_vim9script()
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007612 && (check_for_string_or_list_arg(argvars, 0) == FAIL
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02007613 || check_for_string_arg(argvars, 1) == FAIL
7614 || check_for_opt_number_arg(argvars, 2) == FAIL
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02007615 || (argvars[2].v_type != VAR_UNKNOWN
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02007616 && check_for_opt_number_arg(argvars, 3) == FAIL)))
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +02007617 goto theend;
7618
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007619 if (argvars[0].v_type == VAR_LIST)
7620 {
7621 if ((l = argvars[0].vval.v_list) == NULL)
7622 goto theend;
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02007623 CHECK_LIST_MATERIALIZE(l);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007624 li = l->lv_first;
7625 }
7626 else
7627 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007628 expr = str = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007629 len = (long)STRLEN(str);
7630 }
7631
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007632 pat = tv_get_string_buf_chk(&argvars[1], patbuf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007633 if (pat == NULL)
7634 goto theend;
7635
7636 if (argvars[2].v_type != VAR_UNKNOWN)
7637 {
7638 int error = FALSE;
7639
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007640 start = (long)tv_get_number_chk(&argvars[2], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007641 if (error)
7642 goto theend;
7643 if (l != NULL)
7644 {
7645 li = list_find(l, start);
7646 if (li == NULL)
7647 goto theend;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007648 idx = l->lv_u.mat.lv_idx; // use the cached index
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007649 }
7650 else
7651 {
7652 if (start < 0)
7653 start = 0;
7654 if (start > len)
7655 goto theend;
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007656 // When "count" argument is there ignore matches before "start",
7657 // otherwise skip part of the string. Differs when pattern is "^"
7658 // or "\<".
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007659 if (argvars[3].v_type != VAR_UNKNOWN)
7660 startcol = start;
7661 else
7662 {
7663 str += start;
7664 len -= start;
7665 }
7666 }
7667
7668 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007669 nth = (long)tv_get_number_chk(&argvars[3], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007670 if (error)
7671 goto theend;
7672 }
7673
7674 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
7675 if (regmatch.regprog != NULL)
7676 {
7677 regmatch.rm_ic = p_ic;
7678
7679 for (;;)
7680 {
7681 if (l != NULL)
7682 {
7683 if (li == NULL)
7684 {
7685 match = FALSE;
7686 break;
7687 }
7688 vim_free(tofree);
7689 expr = str = echo_string(&li->li_tv, &tofree, strbuf, 0);
7690 if (str == NULL)
7691 break;
7692 }
7693
=?UTF-8?q?Dundar=20G=C3=B6c?=420fabc2022-01-28 15:28:04 +00007694 match = vim_regexec_nl(&regmatch, str, startcol);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007695
7696 if (match && --nth <= 0)
7697 break;
7698 if (l == NULL && !match)
7699 break;
7700
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007701 // Advance to just after the match.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007702 if (l != NULL)
7703 {
7704 li = li->li_next;
7705 ++idx;
7706 }
7707 else
7708 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007709 startcol = (colnr_T)(regmatch.startp[0]
7710 + (*mb_ptr2len)(regmatch.startp[0]) - str);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007711 if (startcol > (colnr_T)len
7712 || str + startcol <= regmatch.startp[0])
7713 {
7714 match = FALSE;
7715 break;
7716 }
7717 }
7718 }
7719
7720 if (match)
7721 {
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007722 if (type == MATCH_POS)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007723 {
7724 listitem_T *li1 = rettv->vval.v_list->lv_first;
7725 listitem_T *li2 = li1->li_next;
7726 listitem_T *li3 = li2->li_next;
7727 listitem_T *li4 = li3->li_next;
7728
7729 vim_free(li1->li_tv.vval.v_string);
7730 li1->li_tv.vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaardf44a272020-06-07 20:49:05 +02007731 regmatch.endp[0] - regmatch.startp[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007732 li3->li_tv.vval.v_number =
7733 (varnumber_T)(regmatch.startp[0] - expr);
7734 li4->li_tv.vval.v_number =
7735 (varnumber_T)(regmatch.endp[0] - expr);
7736 if (l != NULL)
7737 li2->li_tv.vval.v_number = (varnumber_T)idx;
7738 }
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007739 else if (type == MATCH_LIST)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007740 {
7741 int i;
7742
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007743 // return list with matched string and submatches
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007744 for (i = 0; i < NSUBEXP; ++i)
7745 {
7746 if (regmatch.endp[i] == NULL)
7747 {
7748 if (list_append_string(rettv->vval.v_list,
7749 (char_u *)"", 0) == FAIL)
7750 break;
7751 }
7752 else if (list_append_string(rettv->vval.v_list,
7753 regmatch.startp[i],
7754 (int)(regmatch.endp[i] - regmatch.startp[i]))
7755 == FAIL)
7756 break;
7757 }
7758 }
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007759 else if (type == MATCH_STR)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007760 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007761 // return matched string
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007762 if (l != NULL)
7763 copy_tv(&li->li_tv, rettv);
7764 else
7765 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaardf44a272020-06-07 20:49:05 +02007766 regmatch.endp[0] - regmatch.startp[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007767 }
7768 else if (l != NULL)
7769 rettv->vval.v_number = idx;
7770 else
7771 {
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007772 if (type != MATCH_END)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007773 rettv->vval.v_number =
7774 (varnumber_T)(regmatch.startp[0] - str);
7775 else
7776 rettv->vval.v_number =
7777 (varnumber_T)(regmatch.endp[0] - str);
7778 rettv->vval.v_number += (varnumber_T)(str - expr);
7779 }
7780 }
7781 vim_regfree(regmatch.regprog);
7782 }
7783
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007784theend:
7785 if (type == MATCH_POS && l == NULL && rettv->vval.v_list != NULL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007786 // matchstrpos() without a list: drop the second item.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007787 listitem_remove(rettv->vval.v_list,
7788 rettv->vval.v_list->lv_first->li_next);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007789 vim_free(tofree);
7790 p_cpo = save_cpo;
7791}
7792
7793/*
7794 * "match()" function
7795 */
7796 static void
7797f_match(typval_T *argvars, typval_T *rettv)
7798{
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007799 find_some_match(argvars, rettv, MATCH_MATCH);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007800}
7801
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007802/*
7803 * "matchend()" function
7804 */
7805 static void
7806f_matchend(typval_T *argvars, typval_T *rettv)
7807{
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007808 find_some_match(argvars, rettv, MATCH_END);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007809}
7810
7811/*
7812 * "matchlist()" function
7813 */
7814 static void
7815f_matchlist(typval_T *argvars, typval_T *rettv)
7816{
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007817 find_some_match(argvars, rettv, MATCH_LIST);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007818}
7819
7820/*
7821 * "matchstr()" function
7822 */
7823 static void
7824f_matchstr(typval_T *argvars, typval_T *rettv)
7825{
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007826 find_some_match(argvars, rettv, MATCH_STR);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007827}
7828
7829/*
7830 * "matchstrpos()" function
7831 */
7832 static void
7833f_matchstrpos(typval_T *argvars, typval_T *rettv)
7834{
Bram Moolenaar8d9f0ef2017-08-27 13:51:01 +02007835 find_some_match(argvars, rettv, MATCH_POS);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007836}
7837
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007838 static void
7839max_min(typval_T *argvars, typval_T *rettv, int domax)
7840{
7841 varnumber_T n = 0;
7842 varnumber_T i;
7843 int error = FALSE;
7844
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007845 if (in_vim9script() && check_for_list_or_dict_arg(argvars, 0) == FAIL)
7846 return;
7847
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007848 if (argvars[0].v_type == VAR_LIST)
7849 {
7850 list_T *l;
7851 listitem_T *li;
7852
7853 l = argvars[0].vval.v_list;
Bram Moolenaar9f2d0202020-01-30 16:40:10 +01007854 if (l != NULL && l->lv_len > 0)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007855 {
Bram Moolenaar9f2d0202020-01-30 16:40:10 +01007856 if (l->lv_first == &range_list_item)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007857 {
Bram Moolenaar9f2d0202020-01-30 16:40:10 +01007858 if ((l->lv_u.nonmat.lv_stride > 0) ^ domax)
7859 n = l->lv_u.nonmat.lv_start;
7860 else
=?UTF-8?q?Dundar=20G=C3=B6c?=d5cec1f2022-01-29 15:19:23 +00007861 n = l->lv_u.nonmat.lv_start + ((varnumber_T)l->lv_len - 1)
Bram Moolenaar9f2d0202020-01-30 16:40:10 +01007862 * l->lv_u.nonmat.lv_stride;
7863 }
7864 else
7865 {
7866 li = l->lv_first;
7867 if (li != NULL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007868 {
Bram Moolenaar9f2d0202020-01-30 16:40:10 +01007869 n = tv_get_number_chk(&li->li_tv, &error);
Bram Moolenaarab65fc72021-02-04 22:07:16 +01007870 if (error)
7871 return; // type error; errmsg already given
Bram Moolenaar9f2d0202020-01-30 16:40:10 +01007872 for (;;)
7873 {
7874 li = li->li_next;
7875 if (li == NULL)
7876 break;
7877 i = tv_get_number_chk(&li->li_tv, &error);
Bram Moolenaarab65fc72021-02-04 22:07:16 +01007878 if (error)
7879 return; // type error; errmsg already given
Bram Moolenaar9f2d0202020-01-30 16:40:10 +01007880 if (domax ? i > n : i < n)
7881 n = i;
7882 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007883 }
7884 }
7885 }
7886 }
7887 else if (argvars[0].v_type == VAR_DICT)
7888 {
7889 dict_T *d;
7890 int first = TRUE;
7891 hashitem_T *hi;
7892 int todo;
7893
7894 d = argvars[0].vval.v_dict;
7895 if (d != NULL)
7896 {
7897 todo = (int)d->dv_hashtab.ht_used;
Yegappan Lakshmanan14113fd2023-03-07 17:13:51 +00007898 FOR_ALL_HASHTAB_ITEMS(&d->dv_hashtab, hi, todo)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007899 {
7900 if (!HASHITEM_EMPTY(hi))
7901 {
7902 --todo;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007903 i = tv_get_number_chk(&HI2DI(hi)->di_tv, &error);
Bram Moolenaarab65fc72021-02-04 22:07:16 +01007904 if (error)
7905 return; // type error; errmsg already given
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007906 if (first)
7907 {
7908 n = i;
7909 first = FALSE;
7910 }
7911 else if (domax ? i > n : i < n)
7912 n = i;
7913 }
7914 }
7915 }
7916 }
7917 else
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00007918 semsg(_(e_argument_of_str_must_be_list_or_dictionary), domax ? "max()" : "min()");
Bram Moolenaarab65fc72021-02-04 22:07:16 +01007919
7920 rettv->vval.v_number = n;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007921}
7922
7923/*
7924 * "max()" function
7925 */
7926 static void
7927f_max(typval_T *argvars, typval_T *rettv)
7928{
7929 max_min(argvars, rettv, TRUE);
7930}
7931
7932/*
7933 * "min()" function
7934 */
7935 static void
7936f_min(typval_T *argvars, typval_T *rettv)
7937{
7938 max_min(argvars, rettv, FALSE);
7939}
7940
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007941#if defined(FEAT_MZSCHEME) || defined(PROTO)
7942/*
7943 * "mzeval()" function
7944 */
7945 static void
7946f_mzeval(typval_T *argvars, typval_T *rettv)
7947{
7948 char_u *str;
7949 char_u buf[NUMBUFLEN];
7950
Bram Moolenaar8c62a082019-02-08 14:34:10 +01007951 if (check_restricted() || check_secure())
7952 return;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007953
7954 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
7955 return;
7956
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007957 str = tv_get_string_buf(&argvars[0], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007958 do_mzeval(str, rettv);
7959}
7960
7961 void
7962mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv)
7963{
7964 typval_T argvars[3];
7965
7966 argvars[0].v_type = VAR_STRING;
7967 argvars[0].vval.v_string = name;
7968 copy_tv(args, &argvars[1]);
7969 argvars[2].v_type = VAR_UNKNOWN;
7970 f_call(argvars, rettv);
7971 clear_tv(&argvars[1]);
7972}
7973#endif
7974
7975/*
7976 * "nextnonblank()" function
7977 */
7978 static void
7979f_nextnonblank(typval_T *argvars, typval_T *rettv)
7980{
7981 linenr_T lnum;
7982
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02007983 if (in_vim9script() && check_for_lnum_arg(argvars, 0) == FAIL)
7984 return;
7985
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007986 for (lnum = tv_get_lnum(argvars); ; ++lnum)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007987 {
7988 if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count)
7989 {
7990 lnum = 0;
7991 break;
7992 }
7993 if (*skipwhite(ml_get(lnum)) != NUL)
7994 break;
7995 }
7996 rettv->vval.v_number = lnum;
7997}
7998
7999/*
8000 * "nr2char()" function
8001 */
8002 static void
8003f_nr2char(typval_T *argvars, typval_T *rettv)
8004{
8005 char_u buf[NUMBUFLEN];
8006
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02008007 if (in_vim9script()
8008 && (check_for_number_arg(argvars, 0) == FAIL
8009 || check_for_opt_bool_arg(argvars, 1) == FAIL))
8010 return;
8011
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008012 if (has_mbyte)
8013 {
8014 int utf8 = 0;
8015
8016 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaared6a4302020-09-05 20:29:41 +02008017 utf8 = (int)tv_get_bool_chk(&argvars[1], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008018 if (utf8)
Bram Moolenaarbdace832019-03-02 10:13:42 +01008019 buf[utf_char2bytes((int)tv_get_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008020 else
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008021 buf[(*mb_char2bytes)((int)tv_get_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008022 }
8023 else
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008024 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008025 buf[0] = (char_u)tv_get_number(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008026 buf[1] = NUL;
8027 }
8028 rettv->v_type = VAR_STRING;
8029 rettv->vval.v_string = vim_strsave(buf);
8030}
8031
8032/*
8033 * "or(expr, expr)" function
8034 */
8035 static void
8036f_or(typval_T *argvars, typval_T *rettv)
8037{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008038 if (in_vim9script()
8039 && (check_for_number_arg(argvars, 0) == FAIL
8040 || check_for_number_arg(argvars, 1) == FAIL))
8041 return;
8042
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008043 rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
8044 | tv_get_number_chk(&argvars[1], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008045}
8046
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008047#ifdef FEAT_PERL
8048/*
8049 * "perleval()" function
8050 */
8051 static void
8052f_perleval(typval_T *argvars, typval_T *rettv)
8053{
8054 char_u *str;
8055 char_u buf[NUMBUFLEN];
8056
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008057 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
8058 return;
8059
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008060 str = tv_get_string_buf(&argvars[0], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008061 do_perleval(str, rettv);
8062}
8063#endif
8064
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008065/*
8066 * "prevnonblank()" function
8067 */
8068 static void
8069f_prevnonblank(typval_T *argvars, typval_T *rettv)
8070{
8071 linenr_T lnum;
8072
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008073 if (in_vim9script() && check_for_lnum_arg(argvars, 0) == FAIL)
8074 return;
8075
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008076 lnum = tv_get_lnum(argvars);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008077 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
8078 lnum = 0;
8079 else
8080 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
8081 --lnum;
8082 rettv->vval.v_number = lnum;
8083}
8084
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008085// This dummy va_list is here because:
8086// - passing a NULL pointer doesn't work when va_list isn't a pointer
8087// - locally in the function results in a "used before set" warning
8088// - using va_start() to initialize it gives "function with fixed args" error
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008089static va_list ap;
8090
8091/*
8092 * "printf()" function
8093 */
8094 static void
8095f_printf(typval_T *argvars, typval_T *rettv)
8096{
8097 char_u buf[NUMBUFLEN];
8098 int len;
8099 char_u *s;
8100 int saved_did_emsg = did_emsg;
8101 char *fmt;
8102
8103 rettv->v_type = VAR_STRING;
8104 rettv->vval.v_string = NULL;
8105
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02008106 if (in_vim9script() && check_for_string_or_number_arg(argvars, 0) == FAIL)
8107 return;
8108
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008109 // Get the required length, allocate the buffer and do it for real.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008110 did_emsg = FALSE;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008111 fmt = (char *)tv_get_string_buf(&argvars[0], buf);
Bram Moolenaar8327d1d2017-07-11 22:34:51 +02008112 len = vim_vsnprintf_typval(NULL, 0, fmt, ap, argvars + 1);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008113 if (!did_emsg)
8114 {
8115 s = alloc(len + 1);
8116 if (s != NULL)
8117 {
8118 rettv->vval.v_string = s;
Bram Moolenaar8327d1d2017-07-11 22:34:51 +02008119 (void)vim_vsnprintf_typval((char *)s, len + 1, fmt,
8120 ap, argvars + 1);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008121 }
8122 }
8123 did_emsg |= saved_did_emsg;
8124}
8125
8126/*
Bram Moolenaare9bd5722019-08-17 19:36:06 +02008127 * "pum_getpos()" function
8128 */
8129 static void
8130f_pum_getpos(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
8131{
Bram Moolenaar93a10962022-06-16 11:42:09 +01008132 if (rettv_dict_alloc(rettv) == FAIL)
Bram Moolenaare9bd5722019-08-17 19:36:06 +02008133 return;
Bram Moolenaare9bd5722019-08-17 19:36:06 +02008134 pum_set_event_info(rettv->vval.v_dict);
Bram Moolenaare9bd5722019-08-17 19:36:06 +02008135}
8136
8137/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008138 * "pumvisible()" function
8139 */
8140 static void
8141f_pumvisible(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
8142{
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008143 if (pum_visible())
8144 rettv->vval.v_number = 1;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008145}
8146
8147#ifdef FEAT_PYTHON3
8148/*
8149 * "py3eval()" function
8150 */
8151 static void
8152f_py3eval(typval_T *argvars, typval_T *rettv)
8153{
8154 char_u *str;
8155 char_u buf[NUMBUFLEN];
8156
Bram Moolenaar8c62a082019-02-08 14:34:10 +01008157 if (check_restricted() || check_secure())
8158 return;
8159
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008160 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
8161 return;
8162
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01008163 if (p_pyx == 0)
8164 p_pyx = 3;
8165
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008166 str = tv_get_string_buf(&argvars[0], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008167 do_py3eval(str, rettv);
8168}
8169#endif
8170
8171#ifdef FEAT_PYTHON
8172/*
8173 * "pyeval()" function
8174 */
8175 static void
8176f_pyeval(typval_T *argvars, typval_T *rettv)
8177{
8178 char_u *str;
8179 char_u buf[NUMBUFLEN];
8180
Bram Moolenaar8c62a082019-02-08 14:34:10 +01008181 if (check_restricted() || check_secure())
8182 return;
8183
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008184 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
8185 return;
8186
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01008187 if (p_pyx == 0)
8188 p_pyx = 2;
8189
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008190 str = tv_get_string_buf(&argvars[0], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008191 do_pyeval(str, rettv);
8192}
8193#endif
8194
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01008195#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
8196/*
8197 * "pyxeval()" function
8198 */
8199 static void
8200f_pyxeval(typval_T *argvars, typval_T *rettv)
8201{
Bram Moolenaar8c62a082019-02-08 14:34:10 +01008202 if (check_restricted() || check_secure())
8203 return;
8204
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008205 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
8206 return;
8207
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01008208# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
8209 init_pyxversion();
8210 if (p_pyx == 2)
8211 f_pyeval(argvars, rettv);
8212 else
8213 f_py3eval(argvars, rettv);
8214# elif defined(FEAT_PYTHON)
8215 f_pyeval(argvars, rettv);
8216# elif defined(FEAT_PYTHON3)
8217 f_py3eval(argvars, rettv);
8218# endif
8219}
8220#endif
8221
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008222static UINT32_T srand_seed_for_testing = 0;
8223static int srand_seed_for_testing_is_used = FALSE;
8224
8225 static void
8226f_test_srand_seed(typval_T *argvars, typval_T *rettv UNUSED)
8227{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008228 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
8229 return;
8230
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008231 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar7633fe52020-06-22 19:10:56 +02008232 srand_seed_for_testing_is_used = FALSE;
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008233 else
8234 {
Bram Moolenaar7633fe52020-06-22 19:10:56 +02008235 srand_seed_for_testing = (UINT32_T)tv_get_number(&argvars[0]);
8236 srand_seed_for_testing_is_used = TRUE;
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008237 }
8238}
8239
8240 static void
8241init_srand(UINT32_T *x)
8242{
8243#ifndef MSWIN
8244 static int dev_urandom_state = NOTDONE; // FAIL or OK once tried
8245#endif
8246
8247 if (srand_seed_for_testing_is_used)
8248 {
Bram Moolenaar7633fe52020-06-22 19:10:56 +02008249 *x = srand_seed_for_testing;
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008250 return;
8251 }
8252#ifndef MSWIN
8253 if (dev_urandom_state != FAIL)
8254 {
8255 int fd = open("/dev/urandom", O_RDONLY);
8256 struct {
8257 union {
8258 UINT32_T number;
8259 char bytes[sizeof(UINT32_T)];
8260 } contents;
8261 } buf;
8262
8263 // Attempt reading /dev/urandom.
8264 if (fd == -1)
8265 dev_urandom_state = FAIL;
8266 else
8267 {
8268 buf.contents.number = 0;
8269 if (read(fd, buf.contents.bytes, sizeof(UINT32_T))
8270 != sizeof(UINT32_T))
8271 dev_urandom_state = FAIL;
8272 else
8273 {
8274 dev_urandom_state = OK;
8275 *x = buf.contents.number;
8276 }
8277 close(fd);
8278 }
8279 }
8280 if (dev_urandom_state != OK)
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008281#endif
Yasuhiro Matsumotof0a9c002022-12-05 21:55:55 +00008282 {
8283 // Reading /dev/urandom doesn't work, fall back to:
8284 // - randombytes_random()
8285 // - reltime() or time()
8286 // - XOR with process ID
8287#if defined(FEAT_SODIUM)
K.Takataa8cdb4e2022-12-06 16:17:01 +00008288 if (crypt_sodium_init() >= 0)
8289 *x = crypt_sodium_randombytes_random();
Yasuhiro Matsumotof0a9c002022-12-05 21:55:55 +00008290 else
8291#endif
8292 {
8293#if defined(FEAT_RELTIME)
8294 proftime_T res;
8295 profile_start(&res);
8296# if defined(MSWIN)
8297 *x = (UINT32_T)res.LowPart;
8298# else
Ernie Rael076de792023-03-16 21:43:15 +00008299 *x = (UINT32_T)res.tv_fsec;
Yasuhiro Matsumotof0a9c002022-12-05 21:55:55 +00008300# endif
8301#else
8302 *x = vim_time();
8303#endif
8304 *x ^= mch_get_pid();
8305 }
8306 }
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008307}
8308
kylo252ae6f1d82022-02-16 19:24:07 +00008309#define ROTL(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008310#define SPLITMIX32(x, z) ( \
kylo252ae6f1d82022-02-16 19:24:07 +00008311 (z) = ((x) += 0x9e3779b9), \
8312 (z) = ((z) ^ ((z) >> 16)) * 0x85ebca6b, \
8313 (z) = ((z) ^ ((z) >> 13)) * 0xc2b2ae35, \
8314 (z) ^ ((z) >> 16) \
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008315 )
8316#define SHUFFLE_XOSHIRO128STARSTAR(x, y, z, w) \
kylo252ae6f1d82022-02-16 19:24:07 +00008317 result = ROTL((y) * 5, 7) * 9; \
8318 t = (y) << 9; \
8319 (z) ^= (x); \
8320 (w) ^= (y); \
8321 (y) ^= (z), (x) ^= (w); \
8322 (z) ^= t; \
8323 (w) = ROTL(w, 11);
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008324
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008325/*
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008326 * "rand()" function
8327 */
8328 static void
8329f_rand(typval_T *argvars, typval_T *rettv)
8330{
8331 list_T *l = NULL;
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008332 static UINT32_T gx, gy, gz, gw;
8333 static int initialized = FALSE;
Bram Moolenaarf8c1f922019-11-28 22:13:14 +01008334 listitem_T *lx, *ly, *lz, *lw;
Bram Moolenaar0fd797e2020-11-05 20:46:32 +01008335 UINT32_T x = 0, y, z, w, t, result;
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008336
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008337 if (in_vim9script() && check_for_opt_list_arg(argvars, 0) == FAIL)
8338 return;
8339
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008340 if (argvars[0].v_type == VAR_UNKNOWN)
8341 {
Bram Moolenaarf8c1f922019-11-28 22:13:14 +01008342 // When no argument is given use the global seed list.
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008343 if (initialized == FALSE)
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008344 {
Bram Moolenaarf8c1f922019-11-28 22:13:14 +01008345 // Initialize the global seed list.
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008346 init_srand(&x);
8347
8348 gx = SPLITMIX32(x, z);
8349 gy = SPLITMIX32(x, z);
8350 gz = SPLITMIX32(x, z);
8351 gw = SPLITMIX32(x, z);
8352 initialized = TRUE;
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008353 }
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008354
8355 SHUFFLE_XOSHIRO128STARSTAR(gx, gy, gz, gw);
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008356 }
8357 else if (argvars[0].v_type == VAR_LIST)
8358 {
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008359 l = argvars[0].vval.v_list;
Bram Moolenaarf8c1f922019-11-28 22:13:14 +01008360 if (l == NULL || list_len(l) != 4)
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008361 goto theend;
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008362
8363 lx = list_find(l, 0L);
8364 ly = list_find(l, 1L);
8365 lz = list_find(l, 2L);
8366 lw = list_find(l, 3L);
8367 if (lx->li_tv.v_type != VAR_NUMBER) goto theend;
8368 if (ly->li_tv.v_type != VAR_NUMBER) goto theend;
8369 if (lz->li_tv.v_type != VAR_NUMBER) goto theend;
8370 if (lw->li_tv.v_type != VAR_NUMBER) goto theend;
8371 x = (UINT32_T)lx->li_tv.vval.v_number;
8372 y = (UINT32_T)ly->li_tv.vval.v_number;
8373 z = (UINT32_T)lz->li_tv.vval.v_number;
8374 w = (UINT32_T)lw->li_tv.vval.v_number;
8375
8376 SHUFFLE_XOSHIRO128STARSTAR(x, y, z, w);
8377
8378 lx->li_tv.vval.v_number = (varnumber_T)x;
8379 ly->li_tv.vval.v_number = (varnumber_T)y;
8380 lz->li_tv.vval.v_number = (varnumber_T)z;
8381 lw->li_tv.vval.v_number = (varnumber_T)w;
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008382 }
8383 else
8384 goto theend;
8385
8386 rettv->v_type = VAR_NUMBER;
Bram Moolenaarf8c1f922019-11-28 22:13:14 +01008387 rettv->vval.v_number = (varnumber_T)result;
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008388 return;
8389
8390theend:
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00008391 semsg(_(e_invalid_argument_str), tv_get_string(&argvars[0]));
Bram Moolenaarf8c1f922019-11-28 22:13:14 +01008392 rettv->v_type = VAR_NUMBER;
8393 rettv->vval.v_number = -1;
Bram Moolenaar06b0b4b2019-11-25 15:40:55 +01008394}
8395
8396/*
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008397 * "srand()" function
8398 */
8399 static void
8400f_srand(typval_T *argvars, typval_T *rettv)
8401{
8402 UINT32_T x = 0, z;
8403
8404 if (rettv_list_alloc(rettv) == FAIL)
8405 return;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008406
8407 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
8408 return;
8409
Bram Moolenaar4f645c52020-02-08 16:40:39 +01008410 if (argvars[0].v_type == VAR_UNKNOWN)
8411 {
8412 init_srand(&x);
8413 }
8414 else
8415 {
8416 int error = FALSE;
8417
8418 x = (UINT32_T)tv_get_number_chk(&argvars[0], &error);
8419 if (error)
8420 return;
8421 }
8422
8423 list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32(x, z));
8424 list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32(x, z));
8425 list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32(x, z));
8426 list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32(x, z));
8427}
8428
8429#undef ROTL
8430#undef SPLITMIX32
8431#undef SHUFFLE_XOSHIRO128STARSTAR
8432
8433/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008434 * "range()" function
8435 */
8436 static void
8437f_range(typval_T *argvars, typval_T *rettv)
8438{
8439 varnumber_T start;
8440 varnumber_T end;
8441 varnumber_T stride = 1;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008442 int error = FALSE;
8443
Bram Moolenaar93a10962022-06-16 11:42:09 +01008444 if (rettv_list_alloc(rettv) == FAIL)
Yegappan Lakshmananca195cc2022-06-14 13:42:26 +01008445 return;
8446
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008447 if (in_vim9script()
8448 && (check_for_number_arg(argvars, 0) == FAIL
8449 || check_for_opt_number_arg(argvars, 1) == FAIL
8450 || (argvars[1].v_type != VAR_UNKNOWN
8451 && check_for_opt_number_arg(argvars, 2) == FAIL)))
8452 return;
8453
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008454 start = tv_get_number_chk(&argvars[0], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008455 if (argvars[1].v_type == VAR_UNKNOWN)
8456 {
8457 end = start - 1;
8458 start = 0;
8459 }
8460 else
8461 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008462 end = tv_get_number_chk(&argvars[1], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008463 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008464 stride = tv_get_number_chk(&argvars[2], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008465 }
8466
8467 if (error)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008468 return; // type error; errmsg already given
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008469 if (stride == 0)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008470 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00008471 emsg(_(e_stride_is_zero));
8472 return;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008473 }
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00008474 if (stride > 0 ? end + 1 < start : end - 1 > start)
8475 {
8476 emsg(_(e_start_past_end));
8477 return;
8478 }
8479
8480 list_T *list = rettv->vval.v_list;
8481
8482 // Create a non-materialized list. This is much more efficient and
8483 // works with ":for". If used otherwise CHECK_LIST_MATERIALIZE() must
8484 // be called.
8485 list->lv_first = &range_list_item;
8486 list->lv_u.nonmat.lv_start = start;
8487 list->lv_u.nonmat.lv_end = end;
8488 list->lv_u.nonmat.lv_stride = stride;
8489 list->lv_len = (end - start) / stride + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008490}
8491
8492/*
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02008493 * Materialize "list".
8494 * Do not call directly, use CHECK_LIST_MATERIALIZE()
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008495 */
8496 void
8497range_list_materialize(list_T *list)
8498{
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02008499 varnumber_T start = list->lv_u.nonmat.lv_start;
8500 varnumber_T end = list->lv_u.nonmat.lv_end;
Bram Moolenaar70c43d82022-01-26 21:01:15 +00008501 int stride = list->lv_u.nonmat.lv_stride;
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02008502 varnumber_T i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008503
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02008504 list->lv_first = NULL;
8505 list->lv_u.mat.lv_last = NULL;
8506 list->lv_len = 0;
8507 list->lv_u.mat.lv_idx_item = NULL;
8508 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
Bram Moolenaar70c43d82022-01-26 21:01:15 +00008509 {
=?UTF-8?q?Dundar=20G=C3=B6c?=420fabc2022-01-28 15:28:04 +00008510 if (list_append_number(list, i) == FAIL)
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02008511 break;
Bram Moolenaar70c43d82022-01-26 21:01:15 +00008512 if (list->lv_lock & VAR_ITEMS_LOCKED)
8513 list->lv_u.mat.lv_last->li_tv.v_lock = VAR_LOCKED;
8514 }
8515 list->lv_lock &= ~VAR_ITEMS_LOCKED;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008516}
8517
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008518/*
8519 * "getreginfo()" function
8520 */
8521 static void
8522f_getreginfo(typval_T *argvars, typval_T *rettv)
8523{
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008524 int regname;
8525 char_u buf[NUMBUFLEN + 2];
8526 long reglen = 0;
8527 dict_T *dict;
8528 list_T *list;
8529
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008530 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
8531 return;
8532
zeertzjqd3f00f52021-12-24 12:02:43 +00008533 regname = getreg_get_regname(argvars);
8534 if (regname == 0)
8535 return;
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008536
zeertzjqd3f00f52021-12-24 12:02:43 +00008537 if (regname == '@')
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008538 regname = '"';
8539
8540 if (rettv_dict_alloc(rettv) == FAIL)
8541 return;
8542 dict = rettv->vval.v_dict;
8543
8544 list = (list_T *)get_reg_contents(regname, GREG_EXPR_SRC | GREG_LIST);
8545 if (list == NULL)
8546 return;
Bram Moolenaar91639192020-06-29 19:55:58 +02008547 (void)dict_add_list(dict, "regcontents", list);
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008548
8549 buf[0] = NUL;
8550 buf[1] = NUL;
8551 switch (get_reg_type(regname, &reglen))
8552 {
8553 case MLINE: buf[0] = 'V'; break;
8554 case MCHAR: buf[0] = 'v'; break;
8555 case MBLOCK:
8556 vim_snprintf((char *)buf, sizeof(buf), "%c%ld", Ctrl_V,
8557 reglen + 1);
8558 break;
8559 }
Bram Moolenaar91639192020-06-29 19:55:58 +02008560 (void)dict_add_string(dict, (char *)"regtype", buf);
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008561
8562 buf[0] = get_register_name(get_unname_register());
8563 buf[1] = NUL;
8564 if (regname == '"')
Bram Moolenaar91639192020-06-29 19:55:58 +02008565 (void)dict_add_string(dict, (char *)"points_to", buf);
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008566 else
8567 {
8568 dictitem_T *item = dictitem_alloc((char_u *)"isunnamed");
8569
8570 if (item != NULL)
8571 {
Bram Moolenaar82946e12022-11-24 11:31:29 +00008572 item->di_tv.v_type = VAR_BOOL;
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008573 item->di_tv.vval.v_number = regname == buf[0]
Bram Moolenaar418a29f2021-02-10 22:23:41 +01008574 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar91639192020-06-29 19:55:58 +02008575 (void)dict_add(dict, item);
Bram Moolenaarbb861e22020-06-07 18:16:36 +02008576 }
8577 }
8578}
8579
Bram Moolenaar0b6d9112018-05-22 20:35:17 +02008580 static void
8581return_register(int regname, typval_T *rettv)
8582{
8583 char_u buf[2] = {0, 0};
8584
8585 buf[0] = (char_u)regname;
8586 rettv->v_type = VAR_STRING;
8587 rettv->vval.v_string = vim_strsave(buf);
8588}
8589
8590/*
8591 * "reg_executing()" function
8592 */
8593 static void
8594f_reg_executing(typval_T *argvars UNUSED, typval_T *rettv)
8595{
8596 return_register(reg_executing, rettv);
8597}
8598
8599/*
8600 * "reg_recording()" function
8601 */
8602 static void
8603f_reg_recording(typval_T *argvars UNUSED, typval_T *rettv)
8604{
8605 return_register(reg_recording, rettv);
8606}
8607
Bram Moolenaar7416f3e2017-03-18 18:10:13 +01008608/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008609 * "rename({from}, {to})" function
8610 */
8611 static void
8612f_rename(typval_T *argvars, typval_T *rettv)
8613{
8614 char_u buf[NUMBUFLEN];
8615
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008616 rettv->vval.v_number = -1;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008617 if (check_restricted() || check_secure())
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008618 return;
8619
8620 if (in_vim9script()
8621 && (check_for_string_arg(argvars, 0) == FAIL
8622 || check_for_string_arg(argvars, 1) == FAIL))
8623 return;
8624
8625 rettv->vval.v_number = vim_rename(tv_get_string(&argvars[0]),
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008626 tv_get_string_buf(&argvars[1], buf));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008627}
8628
8629/*
8630 * "repeat()" function
8631 */
8632 static void
8633f_repeat(typval_T *argvars, typval_T *rettv)
8634{
8635 char_u *p;
Bakudankun375141e2022-09-09 18:46:47 +01008636 varnumber_T n;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008637 int slen;
8638 int len;
8639 char_u *r;
8640 int i;
8641
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02008642 if (in_vim9script()
Bakudankun375141e2022-09-09 18:46:47 +01008643 && (check_for_string_or_number_or_list_or_blob_arg(argvars, 0)
8644 == FAIL
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008645 || check_for_number_arg(argvars, 1) == FAIL))
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02008646 return;
8647
Bakudankun375141e2022-09-09 18:46:47 +01008648 n = tv_get_number(&argvars[1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008649 if (argvars[0].v_type == VAR_LIST)
8650 {
8651 if (rettv_list_alloc(rettv) == OK && argvars[0].vval.v_list != NULL)
8652 while (n-- > 0)
8653 if (list_extend(rettv->vval.v_list,
8654 argvars[0].vval.v_list, NULL) == FAIL)
8655 break;
8656 }
Bakudankun375141e2022-09-09 18:46:47 +01008657 else if (argvars[0].v_type == VAR_BLOB)
8658 {
8659 if (rettv_blob_alloc(rettv) == FAIL
8660 || argvars[0].vval.v_blob == NULL
8661 || n <= 0)
8662 return;
8663
8664 slen = argvars[0].vval.v_blob->bv_ga.ga_len;
8665 len = (int)slen * n;
8666 if (len <= 0)
8667 return;
8668
8669 if (ga_grow(&rettv->vval.v_blob->bv_ga, len) == FAIL)
8670 return;
8671
8672 rettv->vval.v_blob->bv_ga.ga_len = len;
8673
8674 for (i = 0; i < slen; ++i)
8675 if (blob_get(argvars[0].vval.v_blob, i) != 0)
8676 break;
8677
8678 if (i == slen)
8679 // No need to copy since all bytes are already zero
8680 return;
8681
8682 for (i = 0; i < n; ++i)
8683 blob_set_range(rettv->vval.v_blob,
8684 (long)i * slen, ((long)i + 1) * slen - 1, argvars);
8685 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008686 else
8687 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008688 p = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008689 rettv->v_type = VAR_STRING;
8690 rettv->vval.v_string = NULL;
8691
8692 slen = (int)STRLEN(p);
8693 len = slen * n;
8694 if (len <= 0)
8695 return;
8696
8697 r = alloc(len + 1);
8698 if (r != NULL)
8699 {
8700 for (i = 0; i < n; i++)
8701 mch_memmove(r + i * slen, p, (size_t)slen);
8702 r[len] = NUL;
8703 }
8704
8705 rettv->vval.v_string = r;
8706 }
8707}
8708
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008709#define SP_NOMOVE 0x01 // don't move cursor
8710#define SP_REPEAT 0x02 // repeat to find outer pair
8711#define SP_RETCOUNT 0x04 // return matchcount
8712#define SP_SETPCMARK 0x08 // set previous context mark
8713#define SP_START 0x10 // accept match at start position
8714#define SP_SUBPAT 0x20 // return nr of matching sub-pattern
8715#define SP_END 0x40 // leave cursor at end of match
8716#define SP_COLUMN 0x80 // start at cursor column
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008717
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008718/*
8719 * Get flags for a search function.
8720 * Possibly sets "p_ws".
8721 * Returns BACKWARD, FORWARD or zero (for an error).
8722 */
8723 static int
8724get_search_arg(typval_T *varp, int *flagsp)
8725{
8726 int dir = FORWARD;
8727 char_u *flags;
8728 char_u nbuf[NUMBUFLEN];
8729 int mask;
8730
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00008731 if (varp->v_type == VAR_UNKNOWN)
8732 return FORWARD;
8733
8734 flags = tv_get_string_buf_chk(varp, nbuf);
8735 if (flags == NULL)
8736 return 0; // type error; errmsg already given
8737 while (*flags != NUL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008738 {
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00008739 switch (*flags)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008740 {
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00008741 case 'b': dir = BACKWARD; break;
8742 case 'w': p_ws = TRUE; break;
8743 case 'W': p_ws = FALSE; break;
8744 default: mask = 0;
8745 if (flagsp != NULL)
8746 switch (*flags)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008747 {
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00008748 case 'c': mask = SP_START; break;
8749 case 'e': mask = SP_END; break;
8750 case 'm': mask = SP_RETCOUNT; break;
8751 case 'n': mask = SP_NOMOVE; break;
8752 case 'p': mask = SP_SUBPAT; break;
8753 case 'r': mask = SP_REPEAT; break;
8754 case 's': mask = SP_SETPCMARK; break;
8755 case 'z': mask = SP_COLUMN; break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008756 }
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00008757 if (mask == 0)
8758 {
8759 semsg(_(e_invalid_argument_str), flags);
8760 dir = 0;
8761 }
8762 else
8763 *flagsp |= mask;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008764 }
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +00008765 if (dir == 0)
8766 break;
8767 ++flags;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008768 }
8769 return dir;
8770}
8771
8772/*
8773 * Shared by search() and searchpos() functions.
8774 */
8775 static int
8776search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
8777{
8778 int flags;
8779 char_u *pat;
8780 pos_T pos;
8781 pos_T save_cursor;
8782 int save_p_ws = p_ws;
8783 int dir;
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008784 int retval = 0; // default: FAIL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008785 long lnum_stop = 0;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008786#ifdef FEAT_RELTIME
8787 long time_limit = 0;
8788#endif
8789 int options = SEARCH_KEEP;
8790 int subpatnum;
Bram Moolenaar92ea26b2019-10-18 20:53:34 +02008791 searchit_arg_T sia;
Bram Moolenaara9c01042020-06-07 14:50:50 +02008792 int use_skip = FALSE;
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008793 pos_T firstpos;
8794
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02008795 if (in_vim9script()
8796 && (check_for_string_arg(argvars, 0) == FAIL
8797 || check_for_opt_string_arg(argvars, 1) == FAIL
8798 || (argvars[1].v_type != VAR_UNKNOWN
8799 && (check_for_opt_number_arg(argvars, 2) == FAIL
8800 || (argvars[2].v_type != VAR_UNKNOWN
8801 && check_for_opt_number_arg(argvars, 3) == FAIL)))))
8802 goto theend;
8803
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008804 pat = tv_get_string(&argvars[0]);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008805 dir = get_search_arg(&argvars[1], flagsp); // may set p_ws
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008806 if (dir == 0)
8807 goto theend;
8808 flags = *flagsp;
8809 if (flags & SP_START)
8810 options |= SEARCH_START;
8811 if (flags & SP_END)
8812 options |= SEARCH_END;
8813 if (flags & SP_COLUMN)
8814 options |= SEARCH_COL;
8815
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008816 // Optional arguments: line number to stop searching, timeout and skip.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008817 if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN)
8818 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008819 lnum_stop = (long)tv_get_number_chk(&argvars[2], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008820 if (lnum_stop < 0)
8821 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008822 if (argvars[3].v_type != VAR_UNKNOWN)
8823 {
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008824#ifdef FEAT_RELTIME
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008825 time_limit = (long)tv_get_number_chk(&argvars[3], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008826 if (time_limit < 0)
8827 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008828#endif
Bram Moolenaara9c01042020-06-07 14:50:50 +02008829 use_skip = eval_expr_valid_arg(&argvars[4]);
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008830 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008831 }
8832
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008833 /*
8834 * This function does not accept SP_REPEAT and SP_RETCOUNT flags.
8835 * Check to make sure only those flags are set.
8836 * Also, Only the SP_NOMOVE or the SP_SETPCMARK flag can be set. Both
8837 * flags cannot be set. Check for that condition also.
8838 */
8839 if (((flags & (SP_REPEAT | SP_RETCOUNT)) != 0)
8840 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
8841 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00008842 semsg(_(e_invalid_argument_str), tv_get_string(&argvars[1]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008843 goto theend;
8844 }
8845
8846 pos = save_cursor = curwin->w_cursor;
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008847 CLEAR_FIELD(firstpos);
Bram Moolenaara80faa82020-04-12 19:37:17 +02008848 CLEAR_FIELD(sia);
Bram Moolenaar92ea26b2019-10-18 20:53:34 +02008849 sia.sa_stop_lnum = (linenr_T)lnum_stop;
8850#ifdef FEAT_RELTIME
Paul Ollis65745772022-06-05 16:55:54 +01008851 sia.sa_tm = time_limit;
Bram Moolenaar92ea26b2019-10-18 20:53:34 +02008852#endif
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008853
8854 // Repeat until {skip} returns FALSE.
8855 for (;;)
8856 {
8857 subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
Bram Moolenaar92ea26b2019-10-18 20:53:34 +02008858 options, RE_SEARCH, &sia);
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008859 // finding the first match again means there is no match where {skip}
8860 // evaluates to zero.
8861 if (firstpos.lnum != 0 && EQUAL_POS(pos, firstpos))
8862 subpatnum = FAIL;
8863
Bram Moolenaara9c01042020-06-07 14:50:50 +02008864 if (subpatnum == FAIL || !use_skip)
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008865 // didn't find it or no skip argument
8866 break;
Bram Moolenaar3d79f0a2023-01-22 20:14:26 +00008867 if (firstpos.lnum == 0)
8868 firstpos = pos;
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008869
Bram Moolenaara9c01042020-06-07 14:50:50 +02008870 // If the skip expression matches, ignore this match.
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008871 {
8872 int do_skip;
8873 int err;
8874 pos_T save_pos = curwin->w_cursor;
8875
8876 curwin->w_cursor = pos;
Bram Moolenaara9c01042020-06-07 14:50:50 +02008877 err = FALSE;
8878 do_skip = eval_expr_to_bool(&argvars[4], &err);
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008879 curwin->w_cursor = save_pos;
8880 if (err)
8881 {
8882 // Evaluating {skip} caused an error, break here.
8883 subpatnum = FAIL;
8884 break;
8885 }
8886 if (!do_skip)
8887 break;
8888 }
zeertzjq180246c2022-06-23 12:04:46 +01008889
8890 // clear the start flag to avoid getting stuck here
8891 options &= ~SEARCH_START;
Bram Moolenaaradc17a52020-06-06 18:37:51 +02008892 }
8893
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008894 if (subpatnum != FAIL)
8895 {
8896 if (flags & SP_SUBPAT)
8897 retval = subpatnum;
8898 else
8899 retval = pos.lnum;
8900 if (flags & SP_SETPCMARK)
8901 setpcmark();
8902 curwin->w_cursor = pos;
8903 if (match_pos != NULL)
8904 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008905 // Store the match cursor position
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008906 match_pos->lnum = pos.lnum;
8907 match_pos->col = pos.col + 1;
8908 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008909 // "/$" will put the cursor after the end of the line, may need to
8910 // correct that here
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008911 check_cursor();
8912 }
8913
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01008914 // If 'n' flag is used: restore cursor position.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008915 if (flags & SP_NOMOVE)
8916 curwin->w_cursor = save_cursor;
8917 else
8918 curwin->w_set_curswant = TRUE;
8919theend:
8920 p_ws = save_p_ws;
8921
8922 return retval;
8923}
8924
Bram Moolenaare99be0e2019-03-26 22:51:09 +01008925#ifdef FEAT_RUBY
8926/*
8927 * "rubyeval()" function
8928 */
8929 static void
8930f_rubyeval(typval_T *argvars, typval_T *rettv)
8931{
8932 char_u *str;
8933 char_u buf[NUMBUFLEN];
8934
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008935 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
8936 return;
8937
Bram Moolenaare99be0e2019-03-26 22:51:09 +01008938 str = tv_get_string_buf(&argvars[0], buf);
8939 do_rubyeval(str, rettv);
8940}
8941#endif
8942
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008943/*
8944 * "screenattr()" function
8945 */
8946 static void
8947f_screenattr(typval_T *argvars, typval_T *rettv)
8948{
8949 int row;
8950 int col;
8951 int c;
8952
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008953 if (in_vim9script()
8954 && (check_for_number_arg(argvars, 0) == FAIL
8955 || check_for_number_arg(argvars, 1) == FAIL))
8956 return;
8957
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008958 row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
8959 col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008960 if (row < 0 || row >= screen_Rows
8961 || col < 0 || col >= screen_Columns)
8962 c = -1;
8963 else
8964 c = ScreenAttrs[LineOffset[row] + col];
8965 rettv->vval.v_number = c;
8966}
8967
8968/*
8969 * "screenchar()" function
8970 */
8971 static void
8972f_screenchar(typval_T *argvars, typval_T *rettv)
8973{
8974 int row;
8975 int col;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008976 int c;
8977
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02008978 if (in_vim9script()
8979 && (check_for_number_arg(argvars, 0) == FAIL
8980 || check_for_number_arg(argvars, 1) == FAIL))
8981 return;
8982
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008983 row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
8984 col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
Bram Moolenaar2912abb2019-03-29 14:16:42 +01008985 if (row < 0 || row >= screen_Rows || col < 0 || col >= screen_Columns)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008986 c = -1;
8987 else
8988 {
zeertzjq47eec672023-06-01 20:26:55 +01008989 char_u buf[MB_MAXBYTES + 1];
8990 screen_getbytes(row, col, buf, NULL);
8991 c = (*mb_ptr2char)(buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008992 }
8993 rettv->vval.v_number = c;
8994}
8995
8996/*
Bram Moolenaar2912abb2019-03-29 14:16:42 +01008997 * "screenchars()" function
8998 */
8999 static void
9000f_screenchars(typval_T *argvars, typval_T *rettv)
9001{
9002 int row;
9003 int col;
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009004 int c;
9005 int i;
9006
9007 if (rettv_list_alloc(rettv) == FAIL)
9008 return;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02009009
9010 if (in_vim9script()
9011 && (check_for_number_arg(argvars, 0) == FAIL
9012 || check_for_number_arg(argvars, 1) == FAIL))
9013 return;
9014
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009015 row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
9016 col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
9017 if (row < 0 || row >= screen_Rows || col < 0 || col >= screen_Columns)
9018 return;
9019
zeertzjq47eec672023-06-01 20:26:55 +01009020 char_u buf[MB_MAXBYTES + 1];
9021 screen_getbytes(row, col, buf, NULL);
9022 int pcc[MAX_MCO];
9023 if (enc_utf8)
9024 c = utfc_ptr2char(buf, pcc);
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009025 else
zeertzjq47eec672023-06-01 20:26:55 +01009026 c = (*mb_ptr2char)(buf);
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009027 list_append_number(rettv->vval.v_list, (varnumber_T)c);
9028
9029 if (enc_utf8)
zeertzjq47eec672023-06-01 20:26:55 +01009030 for (i = 0; i < Screen_mco && pcc[i] != 0; ++i)
9031 list_append_number(rettv->vval.v_list, (varnumber_T)pcc[i]);
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009032}
9033
9034/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009035 * "screencol()" function
9036 *
9037 * First column is 1 to be consistent with virtcol().
9038 */
9039 static void
9040f_screencol(typval_T *argvars UNUSED, typval_T *rettv)
9041{
9042 rettv->vval.v_number = screen_screencol() + 1;
9043}
9044
9045/*
9046 * "screenrow()" function
9047 */
9048 static void
9049f_screenrow(typval_T *argvars UNUSED, typval_T *rettv)
9050{
9051 rettv->vval.v_number = screen_screenrow() + 1;
9052}
9053
9054/*
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009055 * "screenstring()" function
9056 */
9057 static void
9058f_screenstring(typval_T *argvars, typval_T *rettv)
9059{
9060 int row;
9061 int col;
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009062 char_u buf[MB_MAXBYTES + 1];
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009063
9064 rettv->vval.v_string = NULL;
9065 rettv->v_type = VAR_STRING;
9066
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02009067 if (in_vim9script()
9068 && (check_for_number_arg(argvars, 0) == FAIL
9069 || check_for_number_arg(argvars, 1) == FAIL))
9070 return;
9071
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009072 row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
9073 col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
9074 if (row < 0 || row >= screen_Rows || col < 0 || col >= screen_Columns)
9075 return;
9076
zeertzjq47eec672023-06-01 20:26:55 +01009077 screen_getbytes(row, col, buf, NULL);
Bram Moolenaar2912abb2019-03-29 14:16:42 +01009078 rettv->vval.v_string = vim_strsave(buf);
9079}
9080
9081/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009082 * "search()" function
9083 */
9084 static void
9085f_search(typval_T *argvars, typval_T *rettv)
9086{
9087 int flags = 0;
9088
9089 rettv->vval.v_number = search_cmn(argvars, NULL, &flags);
9090}
9091
9092/*
9093 * "searchdecl()" function
9094 */
9095 static void
9096f_searchdecl(typval_T *argvars, typval_T *rettv)
9097{
Bram Moolenaar30788d32020-09-05 21:35:16 +02009098 int locally = TRUE;
9099 int thisblock = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009100 int error = FALSE;
9101 char_u *name;
9102
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009103 rettv->vval.v_number = 1; // default: FAIL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009104
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02009105 if (in_vim9script()
9106 && (check_for_string_arg(argvars, 0) == FAIL
9107 || check_for_opt_bool_arg(argvars, 1) == FAIL
9108 || (argvars[1].v_type != VAR_UNKNOWN
9109 && check_for_opt_bool_arg(argvars, 2) == FAIL)))
9110 return;
9111
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009112 name = tv_get_string_chk(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009113 if (argvars[1].v_type != VAR_UNKNOWN)
9114 {
Bram Moolenaar30788d32020-09-05 21:35:16 +02009115 locally = !(int)tv_get_bool_chk(&argvars[1], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009116 if (!error && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar30788d32020-09-05 21:35:16 +02009117 thisblock = (int)tv_get_bool_chk(&argvars[2], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009118 }
9119 if (!error && name != NULL)
9120 rettv->vval.v_number = find_decl(name, (int)STRLEN(name),
9121 locally, thisblock, SEARCH_KEEP) == FAIL;
9122}
9123
9124/*
9125 * Used by searchpair() and searchpairpos()
9126 */
9127 static int
9128searchpair_cmn(typval_T *argvars, pos_T *match_pos)
9129{
9130 char_u *spat, *mpat, *epat;
Bram Moolenaar48570482017-10-30 21:48:41 +01009131 typval_T *skip;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009132 int save_p_ws = p_ws;
9133 int dir;
9134 int flags = 0;
9135 char_u nbuf1[NUMBUFLEN];
9136 char_u nbuf2[NUMBUFLEN];
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009137 int retval = 0; // default: FAIL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009138 long lnum_stop = 0;
9139 long time_limit = 0;
9140
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +02009141 if (in_vim9script()
9142 && (check_for_string_arg(argvars, 0) == FAIL
9143 || check_for_string_arg(argvars, 1) == FAIL
9144 || check_for_string_arg(argvars, 2) == FAIL
9145 || check_for_opt_string_arg(argvars, 3) == FAIL
9146 || (argvars[3].v_type != VAR_UNKNOWN
9147 && argvars[4].v_type != VAR_UNKNOWN
9148 && (check_for_opt_number_arg(argvars, 5) == FAIL
9149 || (argvars[5].v_type != VAR_UNKNOWN
9150 && check_for_opt_number_arg(argvars, 6) == FAIL)))))
9151 goto theend;
9152
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009153 // Get the three pattern arguments: start, middle, end. Will result in an
9154 // error if not a valid argument.
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009155 spat = tv_get_string_chk(&argvars[0]);
9156 mpat = tv_get_string_buf_chk(&argvars[1], nbuf1);
9157 epat = tv_get_string_buf_chk(&argvars[2], nbuf2);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009158 if (spat == NULL || mpat == NULL || epat == NULL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009159 goto theend; // type error
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009160
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009161 // Handle the optional fourth argument: flags
9162 dir = get_search_arg(&argvars[3], &flags); // may set p_ws
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009163 if (dir == 0)
9164 goto theend;
9165
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009166 // Don't accept SP_END or SP_SUBPAT.
9167 // Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009168 if ((flags & (SP_END | SP_SUBPAT)) != 0
9169 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
9170 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00009171 semsg(_(e_invalid_argument_str), tv_get_string(&argvars[3]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009172 goto theend;
9173 }
9174
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009175 // Using 'r' implies 'W', otherwise it doesn't work.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009176 if (flags & SP_REPEAT)
9177 p_ws = FALSE;
9178
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009179 // Optional fifth argument: skip expression
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009180 if (argvars[3].v_type == VAR_UNKNOWN
9181 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar48570482017-10-30 21:48:41 +01009182 skip = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009183 else
9184 {
Bram Moolenaara9c01042020-06-07 14:50:50 +02009185 // Type is checked later.
Bram Moolenaar48570482017-10-30 21:48:41 +01009186 skip = &argvars[4];
Bram Moolenaara9c01042020-06-07 14:50:50 +02009187
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009188 if (argvars[5].v_type != VAR_UNKNOWN)
9189 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009190 lnum_stop = (long)tv_get_number_chk(&argvars[5], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009191 if (lnum_stop < 0)
Bram Moolenaar3dddb092018-06-24 19:01:59 +02009192 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00009193 semsg(_(e_invalid_argument_str), tv_get_string(&argvars[5]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009194 goto theend;
Bram Moolenaar3dddb092018-06-24 19:01:59 +02009195 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009196#ifdef FEAT_RELTIME
9197 if (argvars[6].v_type != VAR_UNKNOWN)
9198 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009199 time_limit = (long)tv_get_number_chk(&argvars[6], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009200 if (time_limit < 0)
Bram Moolenaar3dddb092018-06-24 19:01:59 +02009201 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00009202 semsg(_(e_invalid_argument_str), tv_get_string(&argvars[6]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009203 goto theend;
Bram Moolenaar3dddb092018-06-24 19:01:59 +02009204 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009205 }
9206#endif
9207 }
9208 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009209
9210 retval = do_searchpair(spat, mpat, epat, dir, skip, flags,
9211 match_pos, lnum_stop, time_limit);
9212
9213theend:
9214 p_ws = save_p_ws;
9215
9216 return retval;
9217}
9218
9219/*
9220 * "searchpair()" function
9221 */
9222 static void
9223f_searchpair(typval_T *argvars, typval_T *rettv)
9224{
9225 rettv->vval.v_number = searchpair_cmn(argvars, NULL);
9226}
9227
9228/*
9229 * "searchpairpos()" function
9230 */
9231 static void
9232f_searchpairpos(typval_T *argvars, typval_T *rettv)
9233{
9234 pos_T match_pos;
9235 int lnum = 0;
9236 int col = 0;
9237
9238 if (rettv_list_alloc(rettv) == FAIL)
9239 return;
9240
9241 if (searchpair_cmn(argvars, &match_pos) > 0)
9242 {
9243 lnum = match_pos.lnum;
9244 col = match_pos.col;
9245 }
9246
9247 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
9248 list_append_number(rettv->vval.v_list, (varnumber_T)col);
9249}
9250
9251/*
9252 * Search for a start/middle/end thing.
9253 * Used by searchpair(), see its documentation for the details.
9254 * Returns 0 or -1 for no match,
9255 */
9256 long
9257do_searchpair(
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009258 char_u *spat, // start pattern
9259 char_u *mpat, // middle pattern
9260 char_u *epat, // end pattern
9261 int dir, // BACKWARD or FORWARD
9262 typval_T *skip, // skip expression
9263 int flags, // SP_SETPCMARK and other SP_ values
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009264 pos_T *match_pos,
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009265 linenr_T lnum_stop, // stop at this line if not zero
9266 long time_limit UNUSED) // stop after this many msec
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009267{
9268 char_u *save_cpo;
9269 char_u *pat, *pat2 = NULL, *pat3 = NULL;
9270 long retval = 0;
9271 pos_T pos;
9272 pos_T firstpos;
9273 pos_T foundpos;
9274 pos_T save_cursor;
9275 pos_T save_pos;
9276 int n;
9277 int r;
9278 int nest = 1;
Bram Moolenaar48570482017-10-30 21:48:41 +01009279 int use_skip = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009280 int err;
9281 int options = SEARCH_KEEP;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009282
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009283 // Make 'cpoptions' empty, the 'l' flag should not be used here.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009284 save_cpo = p_cpo;
9285 p_cpo = empty_option;
9286
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009287 // Make two search patterns: start/end (pat2, for in nested pairs) and
9288 // start/middle/end (pat3, for the top pair).
Bram Moolenaar964b3742019-05-24 18:54:09 +02009289 pat2 = alloc(STRLEN(spat) + STRLEN(epat) + 17);
9290 pat3 = alloc(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 25);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009291 if (pat2 == NULL || pat3 == NULL)
9292 goto theend;
Bram Moolenaar6e450a52017-01-06 20:03:58 +01009293 sprintf((char *)pat2, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009294 if (*mpat == NUL)
9295 STRCPY(pat3, pat2);
9296 else
Bram Moolenaar6e450a52017-01-06 20:03:58 +01009297 sprintf((char *)pat3, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009298 spat, epat, mpat);
9299 if (flags & SP_START)
9300 options |= SEARCH_START;
9301
Bram Moolenaar48570482017-10-30 21:48:41 +01009302 if (skip != NULL)
Bram Moolenaara9c01042020-06-07 14:50:50 +02009303 use_skip = eval_expr_valid_arg(skip);
Bram Moolenaar48570482017-10-30 21:48:41 +01009304
Bram Moolenaar5ea38d12022-06-16 21:20:48 +01009305#ifdef FEAT_RELTIME
9306 if (time_limit > 0)
9307 init_regexp_timeout(time_limit);
9308#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009309 save_cursor = curwin->w_cursor;
9310 pos = curwin->w_cursor;
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01009311 CLEAR_POS(&firstpos);
9312 CLEAR_POS(&foundpos);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009313 pat = pat3;
9314 for (;;)
9315 {
Bram Moolenaar92ea26b2019-10-18 20:53:34 +02009316 searchit_arg_T sia;
9317
Bram Moolenaara80faa82020-04-12 19:37:17 +02009318 CLEAR_FIELD(sia);
Bram Moolenaar92ea26b2019-10-18 20:53:34 +02009319 sia.sa_stop_lnum = lnum_stop;
Bram Moolenaar5d24a222018-12-23 19:10:09 +01009320 n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
Bram Moolenaar92ea26b2019-10-18 20:53:34 +02009321 options, RE_SEARCH, &sia);
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01009322 if (n == FAIL || (firstpos.lnum != 0 && EQUAL_POS(pos, firstpos)))
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009323 // didn't find it or found the first match again: FAIL
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009324 break;
9325
9326 if (firstpos.lnum == 0)
9327 firstpos = pos;
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01009328 if (EQUAL_POS(pos, foundpos))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009329 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009330 // Found the same position again. Can happen with a pattern that
9331 // has "\zs" at the end and searching backwards. Advance one
9332 // character and try again.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009333 if (dir == BACKWARD)
9334 decl(&pos);
9335 else
9336 incl(&pos);
9337 }
9338 foundpos = pos;
9339
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009340 // clear the start flag to avoid getting stuck here
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009341 options &= ~SEARCH_START;
9342
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009343 // If the skip pattern matches, ignore this match.
Bram Moolenaar48570482017-10-30 21:48:41 +01009344 if (use_skip)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009345 {
9346 save_pos = curwin->w_cursor;
9347 curwin->w_cursor = pos;
Bram Moolenaar48570482017-10-30 21:48:41 +01009348 err = FALSE;
9349 r = eval_expr_to_bool(skip, &err);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009350 curwin->w_cursor = save_pos;
9351 if (err)
9352 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009353 // Evaluating {skip} caused an error, break here.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009354 curwin->w_cursor = save_cursor;
9355 retval = -1;
9356 break;
9357 }
9358 if (r)
9359 continue;
9360 }
9361
9362 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
9363 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009364 // Found end when searching backwards or start when searching
9365 // forward: nested pair.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009366 ++nest;
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009367 pat = pat2; // nested, don't search for middle
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009368 }
9369 else
9370 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009371 // Found end when searching forward or start when searching
9372 // backward: end of (nested) pair; or found middle in outer pair.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009373 if (--nest == 1)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009374 pat = pat3; // outer level, search for middle
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009375 }
9376
9377 if (nest == 0)
9378 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009379 // Found the match: return matchcount or line number.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009380 if (flags & SP_RETCOUNT)
9381 ++retval;
9382 else
9383 retval = pos.lnum;
9384 if (flags & SP_SETPCMARK)
9385 setpcmark();
9386 curwin->w_cursor = pos;
9387 if (!(flags & SP_REPEAT))
9388 break;
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009389 nest = 1; // search for next unmatched
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009390 }
9391 }
9392
9393 if (match_pos != NULL)
9394 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009395 // Store the match cursor position
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009396 match_pos->lnum = curwin->w_cursor.lnum;
9397 match_pos->col = curwin->w_cursor.col + 1;
9398 }
9399
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009400 // If 'n' flag is used or search failed: restore cursor position.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009401 if ((flags & SP_NOMOVE) || retval == 0)
9402 curwin->w_cursor = save_cursor;
9403
9404theend:
Bram Moolenaar5ea38d12022-06-16 21:20:48 +01009405#ifdef FEAT_RELTIME
Bram Moolenaar0f618382022-08-26 21:33:04 +01009406 if (time_limit > 0)
9407 disable_regexp_timeout();
Bram Moolenaar5ea38d12022-06-16 21:20:48 +01009408#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009409 vim_free(pat2);
9410 vim_free(pat3);
9411 if (p_cpo == empty_option)
9412 p_cpo = save_cpo;
9413 else
Bram Moolenaare5a2dc82021-01-03 19:52:05 +01009414 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009415 // Darn, evaluating the {skip} expression changed the value.
Bram Moolenaare5a2dc82021-01-03 19:52:05 +01009416 // If it's still empty it was changed and restored, need to restore in
9417 // the complicated way.
9418 if (*p_cpo == NUL)
Bram Moolenaar31e5c602022-04-15 13:53:33 +01009419 set_option_value_give_err((char_u *)"cpo", 0L, save_cpo, 0);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009420 free_string_option(save_cpo);
Bram Moolenaare5a2dc82021-01-03 19:52:05 +01009421 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009422
9423 return retval;
9424}
9425
9426/*
9427 * "searchpos()" function
9428 */
9429 static void
9430f_searchpos(typval_T *argvars, typval_T *rettv)
9431{
9432 pos_T match_pos;
9433 int lnum = 0;
9434 int col = 0;
9435 int n;
9436 int flags = 0;
9437
9438 if (rettv_list_alloc(rettv) == FAIL)
9439 return;
9440
9441 n = search_cmn(argvars, &match_pos, &flags);
9442 if (n > 0)
9443 {
9444 lnum = match_pos.lnum;
9445 col = match_pos.col;
9446 }
9447
9448 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
9449 list_append_number(rettv->vval.v_list, (varnumber_T)col);
9450 if (flags & SP_SUBPAT)
9451 list_append_number(rettv->vval.v_list, (varnumber_T)n);
9452}
9453
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009454/*
9455 * Set the cursor or mark position.
zeertzjq47eec672023-06-01 20:26:55 +01009456 * If "charpos" is TRUE, then use the column number as a character offset.
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009457 * Otherwise use the column number as a byte offset.
9458 */
9459 static void
9460set_position(typval_T *argvars, typval_T *rettv, int charpos)
9461{
9462 pos_T pos;
9463 int fnum;
9464 char_u *name;
9465 colnr_T curswant = -1;
9466
9467 rettv->vval.v_number = -1;
9468
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02009469 if (in_vim9script()
9470 && (check_for_string_arg(argvars, 0) == FAIL
9471 || check_for_list_arg(argvars, 1) == FAIL))
9472 return;
9473
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009474 name = tv_get_string_chk(argvars);
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009475 if (name == NULL)
9476 return;
9477
9478 if (list2fpos(&argvars[1], &pos, &fnum, &curswant, charpos) != OK)
9479 return;
9480
9481 if (pos.col != MAXCOL && --pos.col < 0)
9482 pos.col = 0;
9483 if ((name[0] == '.' && name[1] == NUL))
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009484 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009485 // set cursor; "fnum" is ignored
9486 curwin->w_cursor = pos;
9487 if (curswant >= 0)
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009488 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009489 curwin->w_curswant = curswant - 1;
9490 curwin->w_set_curswant = FALSE;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009491 }
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009492 check_cursor();
9493 rettv->vval.v_number = 0;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009494 }
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009495 else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL)
9496 {
9497 // set mark
9498 if (setmark_pos(name[1], &pos, fnum) == OK)
9499 rettv->vval.v_number = 0;
9500 }
9501 else
9502 emsg(_(e_invalid_argument));
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009503}
9504/*
9505 * "setcharpos()" function
9506 */
9507 static void
9508f_setcharpos(typval_T *argvars, typval_T *rettv)
9509{
9510 set_position(argvars, rettv, TRUE);
9511}
9512
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009513 static void
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009514f_setcharsearch(typval_T *argvars, typval_T *rettv UNUSED)
9515{
9516 dict_T *d;
9517 dictitem_T *di;
9518 char_u *csearch;
9519
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01009520 if (check_for_dict_arg(argvars, 0) == FAIL)
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02009521 return;
9522
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009523 if ((d = argvars[0].vval.v_dict) == NULL)
9524 return;
9525
9526 csearch = dict_get_string(d, "char", FALSE);
9527 if (csearch != NULL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009528 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009529 if (enc_utf8)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009530 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009531 int pcc[MAX_MCO];
9532 int c = utfc_ptr2char(csearch, pcc);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009533
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009534 set_last_csearch(c, csearch, utfc_ptr2len(csearch));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009535 }
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009536 else
9537 set_last_csearch(PTR2CHAR(csearch),
9538 csearch, mb_ptr2len(csearch));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009539 }
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00009540
9541 di = dict_find(d, (char_u *)"forward", -1);
9542 if (di != NULL)
9543 set_csearch_direction((int)tv_get_number(&di->di_tv)
9544 ? FORWARD : BACKWARD);
9545
9546 di = dict_find(d, (char_u *)"until", -1);
9547 if (di != NULL)
9548 set_csearch_until(!!tv_get_number(&di->di_tv));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009549}
9550
9551/*
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009552 * "setcursorcharpos" function
9553 */
9554 static void
Bram Moolenaar3af15ab2021-01-17 16:16:23 +01009555f_setcursorcharpos(typval_T *argvars, typval_T *rettv)
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009556{
9557 set_cursorpos(argvars, rettv, TRUE);
9558}
9559
9560/*
Bram Moolenaar691ddee2019-05-09 14:52:41 +02009561 * "setenv()" function
9562 */
9563 static void
9564f_setenv(typval_T *argvars, typval_T *rettv UNUSED)
9565{
9566 char_u namebuf[NUMBUFLEN];
9567 char_u valbuf[NUMBUFLEN];
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02009568 char_u *name;
Bram Moolenaar691ddee2019-05-09 14:52:41 +02009569
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02009570 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
9571 return;
9572
9573 name = tv_get_string_buf(&argvars[0], namebuf);
Bram Moolenaar691ddee2019-05-09 14:52:41 +02009574 if (argvars[1].v_type == VAR_SPECIAL
9575 && argvars[1].vval.v_number == VVAL_NULL)
LemonBoy77142312022-04-15 20:50:46 +01009576 vim_unsetenv_ext(name);
Bram Moolenaar691ddee2019-05-09 14:52:41 +02009577 else
LemonBoy77142312022-04-15 20:50:46 +01009578 vim_setenv_ext(name, tv_get_string_buf(&argvars[1], valbuf));
Bram Moolenaar691ddee2019-05-09 14:52:41 +02009579}
9580
9581/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009582 * "setfperm({fname}, {mode})" function
9583 */
9584 static void
9585f_setfperm(typval_T *argvars, typval_T *rettv)
9586{
9587 char_u *fname;
9588 char_u modebuf[NUMBUFLEN];
9589 char_u *mode_str;
9590 int i;
9591 int mask;
9592 int mode = 0;
9593
9594 rettv->vval.v_number = 0;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02009595
9596 if (in_vim9script()
9597 && (check_for_string_arg(argvars, 0) == FAIL
9598 || check_for_string_arg(argvars, 1) == FAIL))
9599 return;
9600
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009601 fname = tv_get_string_chk(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009602 if (fname == NULL)
9603 return;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009604 mode_str = tv_get_string_buf_chk(&argvars[1], modebuf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009605 if (mode_str == NULL)
9606 return;
9607 if (STRLEN(mode_str) != 9)
9608 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00009609 semsg(_(e_invalid_argument_str), mode_str);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009610 return;
9611 }
9612
9613 mask = 1;
9614 for (i = 8; i >= 0; --i)
9615 {
9616 if (mode_str[i] != '-')
9617 mode |= mask;
9618 mask = mask << 1;
9619 }
9620 rettv->vval.v_number = mch_setperm(fname, mode) == OK;
9621}
9622
9623/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009624 * "setpos()" function
9625 */
9626 static void
9627f_setpos(typval_T *argvars, typval_T *rettv)
9628{
Bram Moolenaar6f02b002021-01-10 20:22:54 +01009629 set_position(argvars, rettv, FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009630}
9631
9632/*
Bram Moolenaar7633fe52020-06-22 19:10:56 +02009633 * Translate a register type string to the yank type and block length
9634 */
9635 static int
9636get_yank_type(char_u **pp, char_u *yank_type, long *block_len)
9637{
9638 char_u *stropt = *pp;
9639 switch (*stropt)
9640 {
9641 case 'v': case 'c': // character-wise selection
9642 *yank_type = MCHAR;
9643 break;
9644 case 'V': case 'l': // line-wise selection
9645 *yank_type = MLINE;
9646 break;
9647 case 'b': case Ctrl_V: // block-wise selection
9648 *yank_type = MBLOCK;
9649 if (VIM_ISDIGIT(stropt[1]))
9650 {
9651 ++stropt;
9652 *block_len = getdigits(&stropt) - 1;
9653 --stropt;
9654 }
9655 break;
9656 default:
9657 return FAIL;
9658 }
9659 *pp = stropt;
9660 return OK;
9661}
9662
9663/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009664 * "setreg()" function
9665 */
9666 static void
9667f_setreg(typval_T *argvars, typval_T *rettv)
9668{
9669 int regname;
9670 char_u *strregname;
9671 char_u *stropt;
9672 char_u *strval;
9673 int append;
9674 char_u yank_type;
9675 long block_len;
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009676 typval_T *regcontents;
9677 int pointreg;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009678
Yegappan Lakshmanana764e732021-07-25 15:57:32 +02009679 if (in_vim9script()
9680 && (check_for_string_arg(argvars, 0) == FAIL
9681 || check_for_opt_string_arg(argvars, 2) == FAIL))
9682 return;
9683
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009684 pointreg = 0;
9685 regcontents = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009686 block_len = -1;
9687 yank_type = MAUTO;
9688 append = FALSE;
9689
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009690 strregname = tv_get_string_chk(argvars);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009691 rettv->vval.v_number = 1; // FAIL is default
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009692
9693 if (strregname == NULL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009694 return; // type error; errmsg already given
Bram Moolenaar418a29f2021-02-10 22:23:41 +01009695 if (in_vim9script() && STRLEN(strregname) > 1)
9696 {
9697 semsg(_(e_register_name_must_be_one_char_str), strregname);
9698 return;
9699 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009700 regname = *strregname;
9701 if (regname == 0 || regname == '@')
9702 regname = '"';
9703
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009704 if (argvars[1].v_type == VAR_DICT)
9705 {
9706 dict_T *d = argvars[1].vval.v_dict;
Bram Moolenaar7633fe52020-06-22 19:10:56 +02009707 dictitem_T *di;
9708
9709 if (d == NULL || d->dv_hashtab.ht_used == 0)
9710 {
9711 // Empty dict, clear the register (like setreg(0, []))
9712 char_u *lstval[2] = {NULL, NULL};
9713 write_reg_contents_lst(regname, lstval, 0, FALSE, MAUTO, -1);
9714 return;
9715 }
9716
9717 di = dict_find(d, (char_u *)"regcontents", -1);
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009718 if (di != NULL)
9719 regcontents = &di->di_tv;
9720
Bram Moolenaard61efa52022-07-23 09:52:04 +01009721 stropt = dict_get_string(d, "regtype", FALSE);
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009722 if (stropt != NULL)
Bram Moolenaar7633fe52020-06-22 19:10:56 +02009723 {
9724 int ret = get_yank_type(&stropt, &yank_type, &block_len);
9725
9726 if (ret == FAIL || *++stropt != NUL)
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009727 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00009728 semsg(_(e_invalid_value_for_argument_str), "value");
Bram Moolenaar7633fe52020-06-22 19:10:56 +02009729 return;
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009730 }
Bram Moolenaar7633fe52020-06-22 19:10:56 +02009731 }
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009732
9733 if (regname == '"')
9734 {
Bram Moolenaard61efa52022-07-23 09:52:04 +01009735 stropt = dict_get_string(d, "points_to", FALSE);
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009736 if (stropt != NULL)
9737 {
9738 pointreg = *stropt;
9739 regname = pointreg;
9740 }
9741 }
Bram Moolenaard61efa52022-07-23 09:52:04 +01009742 else if (dict_get_bool(d, "isunnamed", -1) > 0)
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009743 pointreg = regname;
9744 }
9745 else
9746 regcontents = &argvars[1];
9747
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009748 if (argvars[2].v_type != VAR_UNKNOWN)
9749 {
Bram Moolenaar7633fe52020-06-22 19:10:56 +02009750 if (yank_type != MAUTO)
9751 {
Bram Moolenaare1242042021-12-16 20:56:57 +00009752 semsg(_(e_too_many_arguments_for_function_str), "setreg");
Bram Moolenaar7633fe52020-06-22 19:10:56 +02009753 return;
9754 }
9755
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009756 stropt = tv_get_string_chk(&argvars[2]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009757 if (stropt == NULL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009758 return; // type error
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009759 for (; *stropt != NUL; ++stropt)
9760 switch (*stropt)
9761 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009762 case 'a': case 'A': // append
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009763 append = TRUE;
9764 break;
Bram Moolenaar7633fe52020-06-22 19:10:56 +02009765 default:
9766 get_yank_type(&stropt, &yank_type, &block_len);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009767 }
9768 }
9769
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009770 if (regcontents && regcontents->v_type == VAR_LIST)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009771 {
9772 char_u **lstval;
9773 char_u **allocval;
9774 char_u buf[NUMBUFLEN];
9775 char_u **curval;
9776 char_u **curallocval;
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009777 list_T *ll = regcontents->vval.v_list;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009778 listitem_T *li;
9779 int len;
9780
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009781 // If the list is NULL handle like an empty list.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009782 len = ll == NULL ? 0 : ll->lv_len;
9783
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009784 // First half: use for pointers to result lines; second half: use for
9785 // pointers to allocated copies.
Bram Moolenaarc799fe22019-05-28 23:08:19 +02009786 lstval = ALLOC_MULT(char_u *, (len + 1) * 2);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009787 if (lstval == NULL)
9788 return;
9789 curval = lstval;
9790 allocval = lstval + len + 2;
9791 curallocval = allocval;
9792
Bram Moolenaar50985eb2020-01-27 22:09:39 +01009793 if (ll != NULL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009794 {
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02009795 CHECK_LIST_MATERIALIZE(ll);
Bram Moolenaar00d253e2020-04-06 22:13:01 +02009796 FOR_ALL_LIST_ITEMS(ll, li)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009797 {
Bram Moolenaar50985eb2020-01-27 22:09:39 +01009798 strval = tv_get_string_buf_chk(&li->li_tv, buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009799 if (strval == NULL)
9800 goto free_lstval;
Bram Moolenaar50985eb2020-01-27 22:09:39 +01009801 if (strval == buf)
9802 {
9803 // Need to make a copy, next tv_get_string_buf_chk() will
9804 // overwrite the string.
9805 strval = vim_strsave(buf);
9806 if (strval == NULL)
9807 goto free_lstval;
9808 *curallocval++ = strval;
9809 }
9810 *curval++ = strval;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009811 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009812 }
9813 *curval++ = NULL;
9814
9815 write_reg_contents_lst(regname, lstval, -1,
9816 append, yank_type, block_len);
9817free_lstval:
9818 while (curallocval > allocval)
9819 vim_free(*--curallocval);
9820 vim_free(lstval);
9821 }
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009822 else if (regcontents)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009823 {
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009824 strval = tv_get_string_chk(regcontents);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009825 if (strval == NULL)
9826 return;
9827 write_reg_contents_ex(regname, strval, -1,
9828 append, yank_type, block_len);
9829 }
Bram Moolenaarbb861e22020-06-07 18:16:36 +02009830 if (pointreg != 0)
9831 get_yank_register(pointreg, TRUE);
9832
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009833 rettv->vval.v_number = 0;
9834}
9835
9836/*
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009837 * "settagstack()" function
9838 */
9839 static void
9840f_settagstack(typval_T *argvars, typval_T *rettv)
9841{
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009842 win_T *wp;
9843 dict_T *d;
9844 int action = 'r';
9845
9846 rettv->vval.v_number = -1;
9847
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02009848 if (in_vim9script()
9849 && (check_for_number_arg(argvars, 0) == FAIL
9850 || check_for_dict_arg(argvars, 1) == FAIL
9851 || check_for_opt_string_arg(argvars, 2) == FAIL))
9852 return;
9853
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009854 // first argument: window number or id
9855 wp = find_win_by_nr_or_id(&argvars[0]);
9856 if (wp == NULL)
9857 return;
9858
9859 // second argument: dict with items to set in the tag stack
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01009860 if (check_for_dict_arg(argvars, 1) == FAIL)
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009861 return;
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009862 d = argvars[1].vval.v_dict;
9863 if (d == NULL)
9864 return;
9865
9866 // third argument: action - 'a' for append and 'r' for replace.
9867 // default is to replace the stack.
9868 if (argvars[2].v_type == VAR_UNKNOWN)
9869 action = 'r';
Yegappan Lakshmanan8deb2b32022-09-02 15:15:27 +01009870 else if (check_for_string_arg(argvars, 2) == FAIL)
9871 return;
9872 else
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009873 {
9874 char_u *actstr;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009875 actstr = tv_get_string_chk(&argvars[2]);
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009876 if (actstr == NULL)
9877 return;
Bram Moolenaar271fa082020-01-02 14:02:16 +01009878 if ((*actstr == 'r' || *actstr == 'a' || *actstr == 't')
9879 && actstr[1] == NUL)
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009880 action = *actstr;
9881 else
9882 {
Bram Moolenaard82a47d2022-01-05 20:24:39 +00009883 semsg(_(e_invalid_action_str_2), actstr);
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009884 return;
9885 }
9886 }
Bram Moolenaarf49cc602018-11-11 15:21:05 +01009887
9888 if (set_tagstack(wp, d, action) == OK)
9889 rettv->vval.v_number = 0;
9890}
9891
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009892#ifdef FEAT_CRYPT
9893/*
9894 * "sha256({string})" function
9895 */
9896 static void
9897f_sha256(typval_T *argvars, typval_T *rettv)
9898{
9899 char_u *p;
9900
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02009901 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
9902 return;
9903
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009904 p = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009905 rettv->vval.v_string = vim_strsave(
9906 sha256_bytes(p, (int)STRLEN(p), NULL, 0));
9907 rettv->v_type = VAR_STRING;
9908}
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01009909#endif // FEAT_CRYPT
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009910
9911/*
9912 * "shellescape({string})" function
9913 */
9914 static void
9915f_shellescape(typval_T *argvars, typval_T *rettv)
9916{
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02009917 int do_special;
Bram Moolenaar20615522017-06-05 18:46:26 +02009918
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02009919 if (in_vim9script()
9920 && (check_for_string_arg(argvars, 0) == FAIL
9921 || check_for_opt_bool_arg(argvars, 1) == FAIL))
9922 return;
9923
9924 do_special = non_zero_arg(&argvars[1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009925 rettv->vval.v_string = vim_strsave_shellescape(
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009926 tv_get_string(&argvars[0]), do_special, do_special);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009927 rettv->v_type = VAR_STRING;
9928}
9929
9930/*
9931 * shiftwidth() function
9932 */
9933 static void
9934f_shiftwidth(typval_T *argvars UNUSED, typval_T *rettv)
9935{
Bram Moolenaarf9514162018-11-22 03:08:29 +01009936 rettv->vval.v_number = 0;
9937
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02009938 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
9939 return;
9940
Bram Moolenaarf9514162018-11-22 03:08:29 +01009941 if (argvars[0].v_type != VAR_UNKNOWN)
9942 {
9943 long col;
9944
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009945 col = (long)tv_get_number_chk(argvars, NULL);
Bram Moolenaarf9514162018-11-22 03:08:29 +01009946 if (col < 0)
9947 return; // type error; errmsg already given
9948#ifdef FEAT_VARTABS
9949 rettv->vval.v_number = get_sw_value_col(curbuf, col);
9950 return;
9951#endif
9952 }
9953
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009954 rettv->vval.v_number = get_sw_value(curbuf);
9955}
9956
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009957/*
9958 * "soundfold({word})" function
9959 */
9960 static void
9961f_soundfold(typval_T *argvars, typval_T *rettv)
9962{
9963 char_u *s;
9964
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02009965 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
9966 return;
9967
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009968 rettv->v_type = VAR_STRING;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009969 s = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009970#ifdef FEAT_SPELL
9971 rettv->vval.v_string = eval_soundfold(s);
9972#else
9973 rettv->vval.v_string = vim_strsave(s);
9974#endif
9975}
9976
9977/*
9978 * "spellbadword()" function
9979 */
9980 static void
9981f_spellbadword(typval_T *argvars UNUSED, typval_T *rettv)
9982{
9983 char_u *word = (char_u *)"";
9984 hlf_T attr = HLF_COUNT;
9985 int len = 0;
Bram Moolenaar152e79e2020-06-10 15:32:08 +02009986#ifdef FEAT_SPELL
9987 int wo_spell_save = curwin->w_p_spell;
9988
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02009989 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
9990 return;
9991
Bram Moolenaar152e79e2020-06-10 15:32:08 +02009992 if (!curwin->w_p_spell)
9993 {
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00009994 parse_spelllang(curwin);
Bram Moolenaar152e79e2020-06-10 15:32:08 +02009995 curwin->w_p_spell = TRUE;
9996 }
9997
9998 if (*curwin->w_s->b_p_spl == NUL)
9999 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +000010000 emsg(_(e_spell_checking_is_not_possible));
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010001 curwin->w_p_spell = wo_spell_save;
10002 return;
10003 }
10004#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010005
10006 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010007 {
10008#ifdef FEAT_SPELL
10009 curwin->w_p_spell = wo_spell_save;
10010#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010011 return;
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010012 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010013
10014#ifdef FEAT_SPELL
10015 if (argvars[0].v_type == VAR_UNKNOWN)
10016 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010017 // Find the start and length of the badly spelled word.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010018 len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr);
10019 if (len != 0)
Bram Moolenaarb73fa622017-12-21 20:27:47 +010010020 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010021 word = ml_get_cursor();
Bram Moolenaarb73fa622017-12-21 20:27:47 +010010022 curwin->w_set_curswant = TRUE;
10023 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010024 }
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010025 else if (*curbuf->b_s.b_p_spl != NUL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010026 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010027 char_u *str = tv_get_string_chk(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010028 int capcol = -1;
10029
10030 if (str != NULL)
10031 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010032 // Check the argument for spelling.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010033 while (*str != NUL)
10034 {
10035 len = spell_check(curwin, str, &attr, &capcol, FALSE);
10036 if (attr != HLF_COUNT)
10037 {
10038 word = str;
10039 break;
10040 }
10041 str += len;
Bram Moolenaar66ab9162018-07-20 20:28:48 +020010042 capcol -= len;
Bram Moolenaar0c779e82019-08-09 17:01:02 +020010043 len = 0;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010044 }
10045 }
10046 }
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010047 curwin->w_p_spell = wo_spell_save;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010048#endif
10049
10050 list_append_string(rettv->vval.v_list, word, len);
10051 list_append_string(rettv->vval.v_list, (char_u *)(
10052 attr == HLF_SPB ? "bad" :
10053 attr == HLF_SPR ? "rare" :
10054 attr == HLF_SPL ? "local" :
10055 attr == HLF_SPC ? "caps" :
10056 ""), -1);
10057}
10058
10059/*
10060 * "spellsuggest()" function
10061 */
10062 static void
10063f_spellsuggest(typval_T *argvars UNUSED, typval_T *rettv)
10064{
10065#ifdef FEAT_SPELL
10066 char_u *str;
10067 int typeerr = FALSE;
10068 int maxcount;
10069 garray_T ga;
10070 int i;
10071 listitem_T *li;
10072 int need_capital = FALSE;
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010073 int wo_spell_save = curwin->w_p_spell;
10074
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +020010075 if (in_vim9script()
10076 && (check_for_string_arg(argvars, 0) == FAIL
10077 || check_for_opt_number_arg(argvars, 1) == FAIL
10078 || (argvars[1].v_type != VAR_UNKNOWN
10079 && check_for_opt_bool_arg(argvars, 2) == FAIL)))
10080 return;
10081
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010082 if (!curwin->w_p_spell)
10083 {
Yegappan Lakshmananaf936912023-02-20 12:16:39 +000010084 parse_spelllang(curwin);
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010085 curwin->w_p_spell = TRUE;
10086 }
10087
10088 if (*curwin->w_s->b_p_spl == NUL)
10089 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +000010090 emsg(_(e_spell_checking_is_not_possible));
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010091 curwin->w_p_spell = wo_spell_save;
10092 return;
10093 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010094#endif
10095
10096 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010097 {
10098#ifdef FEAT_SPELL
10099 curwin->w_p_spell = wo_spell_save;
10100#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010101 return;
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010102 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010103
10104#ifdef FEAT_SPELL
=?UTF-8?q?Dundar=20G=C3=B6c?=dd410372022-05-15 13:59:11 +010010105 str = tv_get_string(&argvars[0]);
10106 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010107 {
=?UTF-8?q?Dundar=20G=C3=B6c?=dd410372022-05-15 13:59:11 +010010108 maxcount = (int)tv_get_number_chk(&argvars[1], &typeerr);
10109 if (maxcount <= 0)
10110 return;
10111 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010112 {
=?UTF-8?q?Dundar=20G=C3=B6c?=dd410372022-05-15 13:59:11 +010010113 need_capital = (int)tv_get_bool_chk(&argvars[2], &typeerr);
10114 if (typeerr)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010115 return;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010116 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010117 }
=?UTF-8?q?Dundar=20G=C3=B6c?=dd410372022-05-15 13:59:11 +010010118 else
10119 maxcount = 25;
10120
10121 spell_suggest_list(&ga, str, maxcount, need_capital, FALSE);
10122
10123 for (i = 0; i < ga.ga_len; ++i)
10124 {
10125 str = ((char_u **)ga.ga_data)[i];
10126
10127 li = listitem_alloc();
10128 if (li == NULL)
10129 vim_free(str);
10130 else
10131 {
10132 li->li_tv.v_type = VAR_STRING;
10133 li->li_tv.v_lock = 0;
10134 li->li_tv.vval.v_string = str;
10135 list_append(rettv->vval.v_list, li);
10136 }
10137 }
10138 ga_clear(&ga);
Bram Moolenaar152e79e2020-06-10 15:32:08 +020010139 curwin->w_p_spell = wo_spell_save;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010140#endif
10141}
10142
10143 static void
10144f_split(typval_T *argvars, typval_T *rettv)
10145{
10146 char_u *str;
10147 char_u *end;
10148 char_u *pat = NULL;
10149 regmatch_T regmatch;
10150 char_u patbuf[NUMBUFLEN];
10151 char_u *save_cpo;
10152 int match;
10153 colnr_T col = 0;
10154 int keepempty = FALSE;
10155 int typeerr = FALSE;
10156
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +020010157 if (in_vim9script()
10158 && (check_for_string_arg(argvars, 0) == FAIL
10159 || check_for_opt_string_arg(argvars, 1) == FAIL
10160 || (argvars[1].v_type != VAR_UNKNOWN
10161 && check_for_opt_bool_arg(argvars, 2) == FAIL)))
10162 return;
10163
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010164 // Make 'cpoptions' empty, the 'l' flag should not be used here.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010165 save_cpo = p_cpo;
Bram Moolenaare5a2dc82021-01-03 19:52:05 +010010166 p_cpo = empty_option;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010167
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010168 str = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010169 if (argvars[1].v_type != VAR_UNKNOWN)
10170 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010171 pat = tv_get_string_buf_chk(&argvars[1], patbuf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010172 if (pat == NULL)
10173 typeerr = TRUE;
10174 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar3986b942020-09-06 16:09:04 +020010175 keepempty = (int)tv_get_bool_chk(&argvars[2], &typeerr);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010176 }
10177 if (pat == NULL || *pat == NUL)
10178 pat = (char_u *)"[\\x01- ]\\+";
10179
10180 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar7d5e7442020-07-21 22:25:51 +020010181 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010182 if (typeerr)
Bram Moolenaar7d5e7442020-07-21 22:25:51 +020010183 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010184
10185 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
10186 if (regmatch.regprog != NULL)
10187 {
10188 regmatch.rm_ic = FALSE;
10189 while (*str != NUL || keepempty)
10190 {
10191 if (*str == NUL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010192 match = FALSE; // empty item at the end
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010193 else
10194 match = vim_regexec_nl(&regmatch, str, col);
10195 if (match)
10196 end = regmatch.startp[0];
10197 else
10198 end = str + STRLEN(str);
10199 if (keepempty || end > str || (rettv->vval.v_list->lv_len > 0
10200 && *str != NUL && match && end < regmatch.endp[0]))
10201 {
10202 if (list_append_string(rettv->vval.v_list, str,
10203 (int)(end - str)) == FAIL)
10204 break;
10205 }
10206 if (!match)
10207 break;
Bram Moolenaar13505972019-01-24 15:04:48 +010010208 // Advance to just after the match.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010209 if (regmatch.endp[0] > str)
10210 col = 0;
10211 else
Bram Moolenaar13505972019-01-24 15:04:48 +010010212 // Don't get stuck at the same match.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010213 col = (*mb_ptr2len)(regmatch.endp[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010214 str = regmatch.endp[0];
10215 }
10216
10217 vim_regfree(regmatch.regprog);
10218 }
10219
Bram Moolenaar7d5e7442020-07-21 22:25:51 +020010220theend:
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010221 p_cpo = save_cpo;
10222}
10223
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010224/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010225 * "submatch()" function
10226 */
10227 static void
10228f_submatch(typval_T *argvars, typval_T *rettv)
10229{
10230 int error = FALSE;
10231 int no;
10232 int retList = 0;
10233
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +020010234 if (in_vim9script()
10235 && (check_for_number_arg(argvars, 0) == FAIL
10236 || check_for_opt_bool_arg(argvars, 1) == FAIL))
10237 return;
10238
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010239 no = (int)tv_get_number_chk(&argvars[0], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010240 if (error)
10241 return;
Bram Moolenaar989f5922016-08-21 15:26:54 +020010242 if (no < 0 || no >= NSUBEXP)
10243 {
Bram Moolenaard82a47d2022-01-05 20:24:39 +000010244 semsg(_(e_invalid_submatch_number_nr), no);
Bram Moolenaar79518e22017-02-17 16:31:35 +010010245 return;
Bram Moolenaar989f5922016-08-21 15:26:54 +020010246 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010247 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarad304702020-09-06 18:22:53 +020010248 retList = (int)tv_get_bool_chk(&argvars[1], &error);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010249 if (error)
10250 return;
10251
10252 if (retList == 0)
10253 {
10254 rettv->v_type = VAR_STRING;
10255 rettv->vval.v_string = reg_submatch(no);
10256 }
10257 else
10258 {
10259 rettv->v_type = VAR_LIST;
10260 rettv->vval.v_list = reg_submatch_list(no);
10261 }
10262}
10263
10264/*
10265 * "substitute()" function
10266 */
10267 static void
10268f_substitute(typval_T *argvars, typval_T *rettv)
10269{
10270 char_u patbuf[NUMBUFLEN];
10271 char_u subbuf[NUMBUFLEN];
10272 char_u flagsbuf[NUMBUFLEN];
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +020010273 char_u *str;
10274 char_u *pat;
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010275 char_u *sub = NULL;
10276 typval_T *expr = NULL;
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +020010277 char_u *flg;
10278
10279 if (in_vim9script()
10280 && (check_for_string_arg(argvars, 0) == FAIL
10281 || check_for_string_arg(argvars, 1) == FAIL
10282 || check_for_string_arg(argvars, 3) == FAIL))
10283 return;
10284
10285 str = tv_get_string_chk(&argvars[0]);
10286 pat = tv_get_string_buf_chk(&argvars[1], patbuf);
10287 flg = tv_get_string_buf_chk(&argvars[3], flagsbuf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010288
LemonBoyf3b48952022-05-05 13:53:03 +010010289 if (argvars[2].v_type == VAR_FUNC
10290 || argvars[2].v_type == VAR_PARTIAL
Bram Moolenaar00b28d62022-12-08 15:32:33 +000010291 || argvars[2].v_type == VAR_INSTR
10292 || argvars[2].v_type == VAR_CLASS
10293 || argvars[2].v_type == VAR_OBJECT)
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010294 expr = &argvars[2];
10295 else
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010296 sub = tv_get_string_buf_chk(&argvars[2], subbuf);
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010297
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010298 rettv->v_type = VAR_STRING;
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010299 if (str == NULL || pat == NULL || (sub == NULL && expr == NULL)
10300 || flg == NULL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010301 rettv->vval.v_string = NULL;
10302 else
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010303 rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010304}
10305
10306/*
Bram Moolenaarc216a7a2022-12-05 13:50:55 +000010307 * "swapfilelist()" function
10308 */
10309 static void
10310f_swapfilelist(typval_T *argvars UNUSED, typval_T *rettv)
10311{
10312 if (rettv_list_alloc(rettv) == FAIL)
10313 return;
10314 recover_names(NULL, FALSE, rettv->vval.v_list, 0, NULL);
10315}
10316
10317/*
Bram Moolenaar00f123a2018-08-21 20:28:54 +020010318 * "swapinfo(swap_filename)" function
10319 */
10320 static void
10321f_swapinfo(typval_T *argvars, typval_T *rettv)
10322{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010323 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
10324 return;
10325
Bram Moolenaar00f123a2018-08-21 20:28:54 +020010326 if (rettv_dict_alloc(rettv) == OK)
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010327 get_b0_dict(tv_get_string(argvars), rettv->vval.v_dict);
Bram Moolenaar00f123a2018-08-21 20:28:54 +020010328}
10329
10330/*
Bram Moolenaar110bd602018-09-16 18:46:59 +020010331 * "swapname(expr)" function
10332 */
10333 static void
10334f_swapname(typval_T *argvars, typval_T *rettv)
10335{
10336 buf_T *buf;
10337
10338 rettv->v_type = VAR_STRING;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010339
10340 if (in_vim9script() && check_for_buffer_arg(argvars, 0) == FAIL)
10341 return;
10342
Bram Moolenaarf2d79fa2019-01-03 22:19:27 +010010343 buf = tv_get_buf(&argvars[0], FALSE);
Bram Moolenaar110bd602018-09-16 18:46:59 +020010344 if (buf == NULL || buf->b_ml.ml_mfp == NULL
10345 || buf->b_ml.ml_mfp->mf_fname == NULL)
10346 rettv->vval.v_string = NULL;
10347 else
10348 rettv->vval.v_string = vim_strsave(buf->b_ml.ml_mfp->mf_fname);
10349}
10350
10351/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010352 * "synID(lnum, col, trans)" function
10353 */
10354 static void
10355f_synID(typval_T *argvars UNUSED, typval_T *rettv)
10356{
10357 int id = 0;
10358#ifdef FEAT_SYN_HL
10359 linenr_T lnum;
10360 colnr_T col;
10361 int trans;
10362 int transerr = FALSE;
10363
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +020010364 if (in_vim9script()
Yegappan Lakshmanancd917202021-07-21 19:09:09 +020010365 && (check_for_lnum_arg(argvars, 0) == FAIL
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +020010366 || check_for_number_arg(argvars, 1) == FAIL
10367 || check_for_bool_arg(argvars, 2) == FAIL))
10368 return;
10369
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010370 lnum = tv_get_lnum(argvars); // -1 on type error
10371 col = (linenr_T)tv_get_number(&argvars[1]) - 1; // -1 on type error
Bram Moolenaarfcb6d702020-09-05 21:41:56 +020010372 trans = (int)tv_get_bool_chk(&argvars[2], &transerr);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010373
10374 if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
10375 && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
=?UTF-8?q?Dundar=20G=C3=B6c?=420fabc2022-01-28 15:28:04 +000010376 id = syn_get_id(curwin, lnum, col, trans, NULL, FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010377#endif
10378
10379 rettv->vval.v_number = id;
10380}
10381
10382/*
10383 * "synIDattr(id, what [, mode])" function
10384 */
10385 static void
10386f_synIDattr(typval_T *argvars UNUSED, typval_T *rettv)
10387{
10388 char_u *p = NULL;
10389#ifdef FEAT_SYN_HL
10390 int id;
10391 char_u *what;
10392 char_u *mode;
10393 char_u modebuf[NUMBUFLEN];
10394 int modec;
10395
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +020010396 if (in_vim9script()
10397 && (check_for_number_arg(argvars, 0) == FAIL
Yegappan Lakshmananf8dbd582021-09-26 19:04:05 +010010398 || check_for_string_arg(argvars, 1) == FAIL
10399 || check_for_opt_string_arg(argvars, 2) == FAIL))
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +020010400 return;
10401
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010402 id = (int)tv_get_number(&argvars[0]);
10403 what = tv_get_string(&argvars[1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010404 if (argvars[2].v_type != VAR_UNKNOWN)
10405 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010406 mode = tv_get_string_buf(&argvars[2], modebuf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010407 modec = TOLOWER_ASC(mode[0]);
10408 if (modec != 't' && modec != 'c' && modec != 'g')
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010409 modec = 0; // replace invalid with current
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010410 }
10411 else
10412 {
10413#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
10414 if (USE_24BIT)
10415 modec = 'g';
10416 else
10417#endif
10418 if (t_colors > 1)
Dominique Pelle4781d6f2021-05-18 21:46:31 +020010419 modec = 'c';
10420 else
10421 modec = 't';
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010422 }
10423
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010424 switch (TOLOWER_ASC(what[0]))
10425 {
10426 case 'b':
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010427 if (TOLOWER_ASC(what[1]) == 'g') // bg[#]
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010428 p = highlight_color(id, what, modec);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010429 else // bold
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010430 p = highlight_has_attr(id, HL_BOLD, modec);
10431 break;
10432
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010433 case 'f': // fg[#] or font
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010434 p = highlight_color(id, what, modec);
10435 break;
10436
10437 case 'i':
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010438 if (TOLOWER_ASC(what[1]) == 'n') // inverse
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010439 p = highlight_has_attr(id, HL_INVERSE, modec);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010440 else // italic
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010441 p = highlight_has_attr(id, HL_ITALIC, modec);
10442 break;
10443
Martin Tournoijba43e762022-10-13 22:12:15 +010010444 case 'n':
Bram Moolenaarde786322022-07-30 14:56:17 +010010445 if (TOLOWER_ASC(what[1]) == 'o') // nocombine
10446 p = highlight_has_attr(id, HL_NOCOMBINE, modec);
10447 else // name
10448 p = get_highlight_name_ext(NULL, id - 1, FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010449 break;
10450
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010451 case 'r': // reverse
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010452 p = highlight_has_attr(id, HL_INVERSE, modec);
10453 break;
10454
10455 case 's':
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010456 if (TOLOWER_ASC(what[1]) == 'p') // sp[#]
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010457 p = highlight_color(id, what, modec);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010458 // strikeout
Bram Moolenaarcf4b00c2017-09-02 18:33:56 +020010459 else if (TOLOWER_ASC(what[1]) == 't' &&
10460 TOLOWER_ASC(what[2]) == 'r')
10461 p = highlight_has_attr(id, HL_STRIKETHROUGH, modec);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010462 else // standout
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010463 p = highlight_has_attr(id, HL_STANDOUT, modec);
10464 break;
10465
10466 case 'u':
Bram Moolenaar84f54632022-06-29 18:39:11 +010010467 if (STRLEN(what) >= 9)
10468 {
10469 if (TOLOWER_ASC(what[5]) == 'l')
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010470 // underline
Bram Moolenaar84f54632022-06-29 18:39:11 +010010471 p = highlight_has_attr(id, HL_UNDERLINE, modec);
10472 else if (TOLOWER_ASC(what[5]) != 'd')
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010473 // undercurl
Bram Moolenaar84f54632022-06-29 18:39:11 +010010474 p = highlight_has_attr(id, HL_UNDERCURL, modec);
10475 else if (TOLOWER_ASC(what[6]) != 'o')
10476 // underdashed
10477 p = highlight_has_attr(id, HL_UNDERDASHED, modec);
10478 else if (TOLOWER_ASC(what[7]) == 'u')
10479 // underdouble
10480 p = highlight_has_attr(id, HL_UNDERDOUBLE, modec);
10481 else
10482 // underdotted
10483 p = highlight_has_attr(id, HL_UNDERDOTTED, modec);
10484 }
10485 else
10486 // ul
10487 p = highlight_color(id, what, modec);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010488 break;
10489 }
10490
10491 if (p != NULL)
10492 p = vim_strsave(p);
10493#endif
10494 rettv->v_type = VAR_STRING;
10495 rettv->vval.v_string = p;
10496}
10497
10498/*
10499 * "synIDtrans(id)" function
10500 */
10501 static void
10502f_synIDtrans(typval_T *argvars UNUSED, typval_T *rettv)
10503{
10504 int id;
10505
10506#ifdef FEAT_SYN_HL
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010507 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
10508 return;
10509
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010510 id = (int)tv_get_number(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010511
10512 if (id > 0)
10513 id = syn_get_final_id(id);
10514 else
10515#endif
10516 id = 0;
10517
10518 rettv->vval.v_number = id;
10519}
10520
10521/*
10522 * "synconcealed(lnum, col)" function
10523 */
10524 static void
10525f_synconcealed(typval_T *argvars UNUSED, typval_T *rettv)
10526{
10527#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
10528 linenr_T lnum;
10529 colnr_T col;
10530 int syntax_flags = 0;
10531 int cchar;
10532 int matchid = 0;
10533 char_u str[NUMBUFLEN];
10534#endif
10535
Bram Moolenaar45cf6e92017-04-30 20:25:19 +020010536 rettv_list_set(rettv, NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010537
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +020010538 if (in_vim9script()
Yegappan Lakshmanancd917202021-07-21 19:09:09 +020010539 && (check_for_lnum_arg(argvars, 0) == FAIL
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +020010540 || check_for_number_arg(argvars, 1) == FAIL))
10541 return;
10542
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010543#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010544 lnum = tv_get_lnum(argvars); // -1 on type error
10545 col = (colnr_T)tv_get_number(&argvars[1]) - 1; // -1 on type error
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010546
Bram Moolenaara80faa82020-04-12 19:37:17 +020010547 CLEAR_FIELD(str);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010548
Bram Moolenaar93a10962022-06-16 11:42:09 +010010549 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010550 {
10551 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
10552 && col >= 0 && col <= (long)STRLEN(ml_get(lnum))
10553 && curwin->w_p_cole > 0)
10554 {
10555 (void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE);
10556 syntax_flags = get_syntax_info(&matchid);
10557
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010558 // get the conceal character
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010559 if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3)
10560 {
10561 cchar = syn_get_sub_char();
Bram Moolenaar4d785892017-06-22 22:00:50 +020010562 if (cchar == NUL && curwin->w_p_cole == 1)
Bram Moolenaareed9d462021-02-15 20:38:25 +010010563 cchar = (curwin->w_lcs_chars.conceal == NUL) ? ' '
10564 : curwin->w_lcs_chars.conceal;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010565 if (cchar != NUL)
10566 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010567 if (has_mbyte)
10568 (*mb_char2bytes)(cchar, str);
10569 else
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010570 str[0] = cchar;
10571 }
10572 }
10573 }
10574
10575 list_append_number(rettv->vval.v_list,
10576 (syntax_flags & HL_CONCEAL) != 0);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010577 // -1 to auto-determine strlen
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010578 list_append_string(rettv->vval.v_list, str, -1);
10579 list_append_number(rettv->vval.v_list, matchid);
10580 }
10581#endif
10582}
10583
10584/*
10585 * "synstack(lnum, col)" function
10586 */
10587 static void
10588f_synstack(typval_T *argvars UNUSED, typval_T *rettv)
10589{
10590#ifdef FEAT_SYN_HL
10591 linenr_T lnum;
10592 colnr_T col;
10593 int i;
10594 int id;
10595#endif
10596
Bram Moolenaar45cf6e92017-04-30 20:25:19 +020010597 rettv_list_set(rettv, NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010598
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +020010599 if (in_vim9script()
Yegappan Lakshmanancd917202021-07-21 19:09:09 +020010600 && (check_for_lnum_arg(argvars, 0) == FAIL
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +020010601 || check_for_number_arg(argvars, 1) == FAIL))
10602 return;
10603
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010604#ifdef FEAT_SYN_HL
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010605 lnum = tv_get_lnum(argvars); // -1 on type error
10606 col = (colnr_T)tv_get_number(&argvars[1]) - 1; // -1 on type error
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010607
10608 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
10609 && col >= 0 && col <= (long)STRLEN(ml_get(lnum))
Bram Moolenaar93a10962022-06-16 11:42:09 +010010610 && rettv_list_alloc(rettv) == OK)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010611 {
=?UTF-8?q?Dundar=20G=C3=B6c?=420fabc2022-01-28 15:28:04 +000010612 (void)syn_get_id(curwin, lnum, col, FALSE, NULL, TRUE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010613 for (i = 0; ; ++i)
10614 {
10615 id = syn_get_stack_item(i);
10616 if (id < 0)
10617 break;
10618 if (list_append_number(rettv->vval.v_list, id) == FAIL)
10619 break;
10620 }
10621 }
10622#endif
10623}
10624
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010625/*
10626 * "tabpagebuflist()" function
10627 */
10628 static void
10629f_tabpagebuflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
10630{
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010631 tabpage_T *tp;
10632 win_T *wp = NULL;
10633
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010634 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
10635 return;
10636
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010637 if (argvars[0].v_type == VAR_UNKNOWN)
10638 wp = firstwin;
10639 else
10640 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010641 tp = find_tabpage((int)tv_get_number(&argvars[0]));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010642 if (tp != NULL)
10643 wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
10644 }
Bram Moolenaar93a10962022-06-16 11:42:09 +010010645 if (wp != NULL && rettv_list_alloc(rettv) == OK)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010646 {
10647 for (; wp != NULL; wp = wp->w_next)
10648 if (list_append_number(rettv->vval.v_list,
10649 wp->w_buffer->b_fnum) == FAIL)
10650 break;
10651 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010652}
10653
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010654/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010655 * "tagfiles()" function
10656 */
10657 static void
10658f_tagfiles(typval_T *argvars UNUSED, typval_T *rettv)
10659{
10660 char_u *fname;
10661 tagname_T tn;
10662 int first;
10663
10664 if (rettv_list_alloc(rettv) == FAIL)
10665 return;
10666 fname = alloc(MAXPATHL);
10667 if (fname == NULL)
10668 return;
10669
10670 for (first = TRUE; ; first = FALSE)
10671 if (get_tagfname(&tn, first, fname) == FAIL
10672 || list_append_string(rettv->vval.v_list, fname, -1) == FAIL)
10673 break;
10674 tagname_free(&tn);
10675 vim_free(fname);
10676}
10677
10678/*
10679 * "taglist()" function
10680 */
10681 static void
10682f_taglist(typval_T *argvars, typval_T *rettv)
10683{
Bram Moolenaarc6aafba2017-03-21 17:09:10 +010010684 char_u *fname = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010685 char_u *tag_pattern;
10686
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010687 if (in_vim9script()
10688 && (check_for_string_arg(argvars, 0) == FAIL
10689 || check_for_opt_string_arg(argvars, 1) == FAIL))
10690 return;
10691
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010692 tag_pattern = tv_get_string(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010693
10694 rettv->vval.v_number = FALSE;
10695 if (*tag_pattern == NUL)
10696 return;
10697
Bram Moolenaarc6aafba2017-03-21 17:09:10 +010010698 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010699 fname = tv_get_string(&argvars[1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010700 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaarc6aafba2017-03-21 17:09:10 +010010701 (void)get_tags(rettv->vval.v_list, tag_pattern, fname);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010702}
10703
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010704/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010705 * "type(expr)" function
10706 */
10707 static void
10708f_type(typval_T *argvars, typval_T *rettv)
10709{
10710 int n = -1;
10711
10712 switch (argvars[0].v_type)
10713 {
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +010010714 case VAR_NUMBER: n = VAR_TYPE_NUMBER; break;
10715 case VAR_STRING: n = VAR_TYPE_STRING; break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010716 case VAR_PARTIAL:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +010010717 case VAR_FUNC: n = VAR_TYPE_FUNC; break;
10718 case VAR_LIST: n = VAR_TYPE_LIST; break;
10719 case VAR_DICT: n = VAR_TYPE_DICT; break;
10720 case VAR_FLOAT: n = VAR_TYPE_FLOAT; break;
10721 case VAR_BOOL: n = VAR_TYPE_BOOL; break;
10722 case VAR_SPECIAL: n = VAR_TYPE_NONE; break;
Bram Moolenaarf562e722016-07-19 17:25:25 +020010723 case VAR_JOB: n = VAR_TYPE_JOB; break;
10724 case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010725 case VAR_BLOB: n = VAR_TYPE_BLOB; break;
Bram Moolenaarf18332f2021-05-07 17:55:55 +020010726 case VAR_INSTR: n = VAR_TYPE_INSTR; break;
Bram Moolenaar00b28d62022-12-08 15:32:33 +000010727 case VAR_CLASS: n = VAR_TYPE_CLASS; break;
10728 case VAR_OBJECT: n = VAR_TYPE_OBJECT; break;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010729 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +020010730 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010010731 case VAR_VOID:
Bram Moolenaardd589232020-02-29 17:38:12 +010010732 internal_error_no_abort("f_type(UNKNOWN)");
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010733 n = -1;
10734 break;
10735 }
10736 rettv->vval.v_number = n;
10737}
10738
10739/*
LemonBoy0f7a3e12022-05-26 12:10:37 +010010740 * "virtcol(string, bool)" function
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010741 */
10742 static void
10743f_virtcol(typval_T *argvars, typval_T *rettv)
10744{
LemonBoy0f7a3e12022-05-26 12:10:37 +010010745 colnr_T vcol_start = 0;
10746 colnr_T vcol_end = 0;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010747 pos_T *fp;
10748 int fnum = curbuf->b_fnum;
Bram Moolenaarb3d33d82020-01-15 20:36:55 +010010749 int len;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010750
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010751 if (in_vim9script()
LemonBoy0f7a3e12022-05-26 12:10:37 +010010752 && (check_for_string_or_list_arg(argvars, 0) == FAIL
10753 || (argvars[1].v_type != VAR_UNKNOWN
10754 && check_for_bool_arg(argvars, 1) == FAIL)))
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010755 return;
10756
Bram Moolenaar6f02b002021-01-10 20:22:54 +010010757 fp = var2fpos(&argvars[0], FALSE, &fnum, FALSE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010758 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
LemonBoy0f7a3e12022-05-26 12:10:37 +010010759 && fnum == curbuf->b_fnum)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010760 {
Bram Moolenaarb3d33d82020-01-15 20:36:55 +010010761 // Limit the column to a valid value, getvvcol() doesn't check.
10762 if (fp->col < 0)
10763 fp->col = 0;
10764 else
10765 {
10766 len = (int)STRLEN(ml_get(fp->lnum));
10767 if (fp->col > len)
10768 fp->col = len;
10769 }
LemonBoy0f7a3e12022-05-26 12:10:37 +010010770 getvvcol(curwin, fp, &vcol_start, NULL, &vcol_end);
10771 ++vcol_start;
10772 ++vcol_end;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010773 }
10774
LemonBoy0f7a3e12022-05-26 12:10:37 +010010775 if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1]))
10776 {
10777 if (rettv_list_alloc(rettv) == OK)
10778 {
10779 list_append_number(rettv->vval.v_list, vcol_start);
10780 list_append_number(rettv->vval.v_list, vcol_end);
10781 }
10782 else
10783 rettv->vval.v_number = 0;
10784 }
10785 else
10786 rettv->vval.v_number = vcol_end;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010787}
10788
10789/*
10790 * "visualmode()" function
10791 */
10792 static void
10793f_visualmode(typval_T *argvars, typval_T *rettv)
10794{
10795 char_u str[2];
10796
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010797 if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL)
10798 return;
10799
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010800 rettv->v_type = VAR_STRING;
10801 str[0] = curbuf->b_visual_mode_eval;
10802 str[1] = NUL;
10803 rettv->vval.v_string = vim_strsave(str);
10804
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010805 // A non-zero number or non-empty string argument: reset mode.
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010806 if (non_zero_arg(&argvars[0]))
10807 curbuf->b_visual_mode_eval = NUL;
10808}
10809
10810/*
10811 * "wildmenumode()" function
10812 */
10813 static void
10814f_wildmenumode(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
10815{
Bram Moolenaar24959102022-05-07 20:01:16 +010010816 if (wild_menu_showing || ((State & MODE_CMDLINE) && cmdline_pum_active()))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010817 rettv->vval.v_number = 1;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010818}
10819
10820/*
Bram Moolenaar0c1e3742019-12-27 13:49:24 +010010821 * "windowsversion()" function
10822 */
10823 static void
10824f_windowsversion(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
10825{
10826 rettv->v_type = VAR_STRING;
10827 rettv->vval.v_string = vim_strsave((char_u *)windowsVersion);
10828}
10829
10830/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010831 * "wordcount()" function
10832 */
10833 static void
10834f_wordcount(typval_T *argvars UNUSED, typval_T *rettv)
10835{
10836 if (rettv_dict_alloc(rettv) == FAIL)
10837 return;
10838 cursor_pos_info(rettv->vval.v_dict);
10839}
10840
10841/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010842 * "xor(expr, expr)" function
10843 */
10844 static void
10845f_xor(typval_T *argvars, typval_T *rettv)
10846{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +020010847 if (in_vim9script()
10848 && (check_for_number_arg(argvars, 0) == FAIL
10849 || check_for_number_arg(argvars, 1) == FAIL))
10850 return;
10851
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010852 rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
10853 ^ tv_get_number_chk(&argvars[1], NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010854}
10855
Bram Moolenaar5d18efe2019-12-01 21:11:22 +010010856#endif // FEAT_EVAL