blob: db439cbd616a286ace3387bb0dd2d41b28576e9e [file] [log] [blame]
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * typval.c: functions that deal with a typval
12 */
13
14#include "vim.h"
15
16#if defined(FEAT_EVAL) || defined(PROTO)
17
18/*
19 * Allocate memory for a variable type-value, and make it empty (0 or NULL
20 * value).
21 */
22 typval_T *
23alloc_tv(void)
24{
25 return ALLOC_CLEAR_ONE(typval_T);
26}
27
28/*
29 * Allocate memory for a variable type-value, and assign a string to it.
30 * The string "s" must have been allocated, it is consumed.
31 * Return NULL for out of memory, the variable otherwise.
32 */
33 typval_T *
34alloc_string_tv(char_u *s)
35{
36 typval_T *rettv;
37
38 rettv = alloc_tv();
39 if (rettv != NULL)
40 {
41 rettv->v_type = VAR_STRING;
42 rettv->vval.v_string = s;
43 }
44 else
45 vim_free(s);
46 return rettv;
47}
48
49/*
50 * Free the memory for a variable type-value.
51 */
52 void
53free_tv(typval_T *varp)
54{
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +000055 if (varp == NULL)
56 return;
Bram Moolenaar00b28d62022-12-08 15:32:33 +000057
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +000058 switch (varp->v_type)
59 {
60 case VAR_FUNC:
61 func_unref(varp->vval.v_string);
62 // FALLTHROUGH
63 case VAR_STRING:
64 vim_free(varp->vval.v_string);
65 break;
66 case VAR_PARTIAL:
67 partial_unref(varp->vval.v_partial);
68 break;
69 case VAR_BLOB:
70 blob_unref(varp->vval.v_blob);
71 break;
72 case VAR_LIST:
73 list_unref(varp->vval.v_list);
74 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +010075 case VAR_TUPLE:
76 tuple_unref(varp->vval.v_tuple);
77 break;
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +000078 case VAR_DICT:
79 dict_unref(varp->vval.v_dict);
80 break;
81 case VAR_JOB:
82#ifdef FEAT_JOB_CHANNEL
83 job_unref(varp->vval.v_job);
84 break;
85#endif
86 case VAR_CHANNEL:
87#ifdef FEAT_JOB_CHANNEL
88 channel_unref(varp->vval.v_channel);
89 break;
90#endif
91 case VAR_CLASS:
92 class_unref(varp->vval.v_class);
93 break;
94 case VAR_OBJECT:
95 object_unref(varp->vval.v_object);
96 break;
97
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +020098 case VAR_TYPEALIAS:
99 typealias_unref(varp->vval.v_typealias);
100 break;
101
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000102 case VAR_NUMBER:
103 case VAR_FLOAT:
104 case VAR_ANY:
105 case VAR_UNKNOWN:
106 case VAR_VOID:
107 case VAR_BOOL:
108 case VAR_SPECIAL:
109 case VAR_INSTR:
110 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200111 }
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000112 vim_free(varp);
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200113}
114
115/*
116 * Free the memory for a variable value and set the value to NULL or 0.
117 */
118 void
119clear_tv(typval_T *varp)
120{
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000121 if (varp == NULL)
122 return;
123
124 switch (varp->v_type)
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200125 {
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000126 case VAR_FUNC:
127 func_unref(varp->vval.v_string);
128 // FALLTHROUGH
129 case VAR_STRING:
130 VIM_CLEAR(varp->vval.v_string);
131 break;
132 case VAR_PARTIAL:
133 partial_unref(varp->vval.v_partial);
134 varp->vval.v_partial = NULL;
135 break;
136 case VAR_BLOB:
137 blob_unref(varp->vval.v_blob);
138 varp->vval.v_blob = NULL;
139 break;
140 case VAR_LIST:
141 list_unref(varp->vval.v_list);
142 varp->vval.v_list = NULL;
143 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100144 case VAR_TUPLE:
145 tuple_unref(varp->vval.v_tuple);
146 varp->vval.v_tuple = NULL;
147 break;
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000148 case VAR_DICT:
149 dict_unref(varp->vval.v_dict);
150 varp->vval.v_dict = NULL;
151 break;
152 case VAR_NUMBER:
153 case VAR_BOOL:
154 case VAR_SPECIAL:
155 varp->vval.v_number = 0;
156 break;
157 case VAR_FLOAT:
158 varp->vval.v_float = 0.0;
159 break;
160 case VAR_JOB:
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200161#ifdef FEAT_JOB_CHANNEL
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000162 job_unref(varp->vval.v_job);
163 varp->vval.v_job = NULL;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200164#endif
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000165 break;
166 case VAR_CHANNEL:
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200167#ifdef FEAT_JOB_CHANNEL
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000168 channel_unref(varp->vval.v_channel);
169 varp->vval.v_channel = NULL;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200170#endif
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000171 break;
172 case VAR_INSTR:
173 VIM_CLEAR(varp->vval.v_instr);
174 break;
175 case VAR_CLASS:
176 class_unref(varp->vval.v_class);
177 varp->vval.v_class = NULL;
178 break;
179 case VAR_OBJECT:
180 object_unref(varp->vval.v_object);
181 varp->vval.v_object = NULL;
182 break;
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200183 case VAR_TYPEALIAS:
184 typealias_unref(varp->vval.v_typealias);
185 varp->vval.v_typealias = NULL;
186 break;
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000187 case VAR_UNKNOWN:
188 case VAR_ANY:
189 case VAR_VOID:
190 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200191 }
Yegappan Lakshmanan032713f2023-01-25 21:05:38 +0000192 varp->v_lock = 0;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200193}
194
195/*
196 * Set the value of a variable to NULL without freeing items.
197 */
198 void
199init_tv(typval_T *varp)
200{
201 if (varp != NULL)
202 CLEAR_POINTER(varp);
203}
204
Bram Moolenaar36967b32020-08-17 21:41:02 +0200205 static varnumber_T
Bram Moolenaarbe19d782023-03-09 22:06:49 +0000206tv_get_bool_or_number_chk(
207 typval_T *varp,
208 int *denote,
209 int want_bool,
210 int vim9_string_error) // in Vim9 using a string is an error
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200211{
212 varnumber_T n = 0L;
213
214 switch (varp->v_type)
215 {
216 case VAR_NUMBER:
Bram Moolenaarbade44e2020-09-26 22:39:24 +0200217 if (in_vim9script() && want_bool && varp->vval.v_number != 0
Bram Moolenaard70840e2020-08-22 15:06:35 +0200218 && varp->vval.v_number != 1)
219 {
220 semsg(_(e_using_number_as_bool_nr), varp->vval.v_number);
221 break;
222 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200223 return varp->vval.v_number;
224 case VAR_FLOAT:
Bram Moolenaar9d00e4a2022-01-05 17:49:15 +0000225 emsg(_(e_using_float_as_number));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200226 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200227 case VAR_FUNC:
228 case VAR_PARTIAL:
Bram Moolenaara6f79292022-01-04 21:30:47 +0000229 emsg(_(e_using_funcref_as_number));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200230 break;
231 case VAR_STRING:
Bram Moolenaarbe19d782023-03-09 22:06:49 +0000232 if (vim9_string_error && in_vim9script())
Bram Moolenaar56acb092020-08-16 14:48:19 +0200233 {
Bram Moolenaarea2d4072020-11-12 12:08:51 +0100234 emsg_using_string_as(varp, !want_bool);
Bram Moolenaar56acb092020-08-16 14:48:19 +0200235 break;
236 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200237 if (varp->vval.v_string != NULL)
238 vim_str2nr(varp->vval.v_string, NULL, NULL,
Bram Moolenaar5fb78c32023-03-04 20:47:39 +0000239 STR2NR_ALL, &n, NULL, 0, FALSE, NULL);
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200240 return n;
241 case VAR_LIST:
Bram Moolenaar677658a2022-01-05 16:09:06 +0000242 emsg(_(e_using_list_as_number));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200243 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100244 case VAR_TUPLE:
245 emsg(_(e_using_tuple_as_number));
246 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200247 case VAR_DICT:
Bram Moolenaara6f79292022-01-04 21:30:47 +0000248 emsg(_(e_using_dictionary_as_number));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200249 break;
250 case VAR_BOOL:
251 case VAR_SPECIAL:
Bram Moolenaar36967b32020-08-17 21:41:02 +0200252 if (!want_bool && in_vim9script())
Bram Moolenaar56acb092020-08-16 14:48:19 +0200253 {
Bram Moolenaard92cc132020-11-18 17:17:15 +0100254 if (varp->v_type == VAR_BOOL)
255 emsg(_(e_using_bool_as_number));
256 else
Bram Moolenaard88be5b2022-01-04 19:57:55 +0000257 emsg(_(e_using_special_as_number));
Bram Moolenaar56acb092020-08-16 14:48:19 +0200258 break;
259 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200260 return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
261 case VAR_JOB:
262#ifdef FEAT_JOB_CHANNEL
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000263 emsg(_(e_using_job_as_number));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200264 break;
265#endif
266 case VAR_CHANNEL:
267#ifdef FEAT_JOB_CHANNEL
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000268 emsg(_(e_using_channel_as_number));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200269 break;
270#endif
271 case VAR_BLOB:
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000272 emsg(_(e_using_blob_as_number));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200273 break;
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000274 case VAR_CLASS:
Ernie Raele75fde62023-12-21 17:18:54 +0100275 case VAR_TYPEALIAS:
276 check_typval_is_value(varp);
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000277 break;
278 case VAR_OBJECT:
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100279 {
Ernie Raelbe828252024-07-26 18:37:02 +0200280 if (varp->vval.v_object == NULL)
281 emsg(_(e_using_object_as_string));
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100282 else
Ernie Raelbe828252024-07-26 18:37:02 +0200283 {
284 class_T *cl = varp->vval.v_object->obj_class;
285 if (cl != NULL && IS_ENUM(cl))
286 semsg(_(e_using_enum_str_as_number), cl->class_name);
287 else
288 emsg(_(e_using_object_as_number));
289 }
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100290 }
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000291 break;
Bram Moolenaarf57b43c2021-06-15 22:13:27 +0200292 case VAR_VOID:
293 emsg(_(e_cannot_use_void_value));
294 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200295 case VAR_UNKNOWN:
296 case VAR_ANY:
Bram Moolenaarf18332f2021-05-07 17:55:55 +0200297 case VAR_INSTR:
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200298 internal_error_no_abort("tv_get_number(UNKNOWN)");
299 break;
300 }
301 if (denote == NULL) // useful for values that must be unsigned
302 n = -1;
303 else
304 *denote = TRUE;
305 return n;
306}
307
Bram Moolenaar36967b32020-08-17 21:41:02 +0200308/*
309 * Get the number value of a variable.
310 * If it is a String variable, uses vim_str2nr().
311 * For incompatible types, return 0.
312 * tv_get_number_chk() is similar to tv_get_number(), but informs the
313 * caller of incompatible types: it sets *denote to TRUE if "denote"
314 * is not NULL or returns -1 otherwise.
315 */
316 varnumber_T
317tv_get_number(typval_T *varp)
318{
319 int error = FALSE;
320
321 return tv_get_number_chk(varp, &error); // return 0L on error
322}
323
Bram Moolenaarbe19d782023-03-09 22:06:49 +0000324/*
Christian Brabandtee17b6f2023-09-09 11:23:50 +0200325 * Like tv_get_number() but in Vim9 script do convert a number in a string to a
Bram Moolenaarbe19d782023-03-09 22:06:49 +0000326 * number without giving an error.
327 */
328 varnumber_T
329tv_to_number(typval_T *varp)
330{
331 int error = FALSE;
332
333 return tv_get_bool_or_number_chk(varp, &error, FALSE, FALSE);
334}
335
Bram Moolenaar36967b32020-08-17 21:41:02 +0200336 varnumber_T
337tv_get_number_chk(typval_T *varp, int *denote)
338{
Bram Moolenaarbe19d782023-03-09 22:06:49 +0000339 return tv_get_bool_or_number_chk(varp, denote, FALSE, TRUE);
Bram Moolenaar36967b32020-08-17 21:41:02 +0200340}
341
342/*
343 * Get the boolean value of "varp". This is like tv_get_number_chk(),
Bram Moolenaard70840e2020-08-22 15:06:35 +0200344 * but in Vim9 script accepts Number (0 and 1) and Bool/Special.
Bram Moolenaar36967b32020-08-17 21:41:02 +0200345 */
346 varnumber_T
347tv_get_bool(typval_T *varp)
348{
Bram Moolenaarbe19d782023-03-09 22:06:49 +0000349 return tv_get_bool_or_number_chk(varp, NULL, TRUE, TRUE);
Bram Moolenaar36967b32020-08-17 21:41:02 +0200350}
351
Bram Moolenaare15eebd2020-08-18 19:11:38 +0200352/*
353 * Get the boolean value of "varp". This is like tv_get_number_chk(),
354 * but in Vim9 script accepts Number and Bool.
355 */
356 varnumber_T
357tv_get_bool_chk(typval_T *varp, int *denote)
358{
Bram Moolenaarbe19d782023-03-09 22:06:49 +0000359 return tv_get_bool_or_number_chk(varp, denote, TRUE, TRUE);
Bram Moolenaare15eebd2020-08-18 19:11:38 +0200360}
361
Bram Moolenaar28fbbea2021-12-22 21:40:33 +0000362 static float_T
363tv_get_float_chk(typval_T *varp, int *error)
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200364{
365 switch (varp->v_type)
366 {
367 case VAR_NUMBER:
368 return (float_T)(varp->vval.v_number);
369 case VAR_FLOAT:
370 return varp->vval.v_float;
371 case VAR_FUNC:
372 case VAR_PARTIAL:
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000373 emsg(_(e_using_funcref_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200374 break;
375 case VAR_STRING:
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000376 emsg(_(e_using_string_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200377 break;
378 case VAR_LIST:
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000379 emsg(_(e_using_list_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200380 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100381 case VAR_TUPLE:
382 emsg(_(e_using_tuple_as_float));
383 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200384 case VAR_DICT:
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000385 emsg(_(e_using_dictionary_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200386 break;
387 case VAR_BOOL:
Bram Moolenaarb2810f12022-01-08 21:38:52 +0000388 emsg(_(e_using_boolean_value_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200389 break;
390 case VAR_SPECIAL:
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000391 emsg(_(e_using_special_value_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200392 break;
393 case VAR_JOB:
394# ifdef FEAT_JOB_CHANNEL
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000395 emsg(_(e_using_job_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200396 break;
397# endif
398 case VAR_CHANNEL:
399# ifdef FEAT_JOB_CHANNEL
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000400 emsg(_(e_using_channel_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200401 break;
402# endif
403 case VAR_BLOB:
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000404 emsg(_(e_using_blob_as_float));
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200405 break;
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000406 case VAR_CLASS:
Ernie Raele75fde62023-12-21 17:18:54 +0100407 case VAR_TYPEALIAS:
408 check_typval_is_value(varp);
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000409 break;
410 case VAR_OBJECT:
411 emsg(_(e_using_object_as_float));
412 break;
Bram Moolenaarf57b43c2021-06-15 22:13:27 +0200413 case VAR_VOID:
414 emsg(_(e_cannot_use_void_value));
415 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200416 case VAR_UNKNOWN:
417 case VAR_ANY:
Bram Moolenaarf18332f2021-05-07 17:55:55 +0200418 case VAR_INSTR:
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200419 internal_error_no_abort("tv_get_float(UNKNOWN)");
420 break;
421 }
Bram Moolenaar28fbbea2021-12-22 21:40:33 +0000422 if (error != NULL)
423 *error = TRUE;
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200424 return 0;
425}
Bram Moolenaar28fbbea2021-12-22 21:40:33 +0000426
427 float_T
428tv_get_float(typval_T *varp)
429{
430 return tv_get_float_chk(varp, NULL);
431}
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200432
433/*
Ernie Rael51d04d12022-05-04 15:40:22 +0100434 * Give an error and return FAIL unless "args[idx]" is unknown
435 */
436 int
437check_for_unknown_arg(typval_T *args, int idx)
438{
439 if (args[idx].v_type != VAR_UNKNOWN)
440 {
441 semsg(_(e_too_many_arguments), idx + 1);
442 return FAIL;
443 }
444 return OK;
445}
446
447/*
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +0200448 * Give an error and return FAIL unless "args[idx]" is a string.
Bram Moolenaar7bb4e742020-12-09 12:41:50 +0100449 */
450 int
Bram Moolenaar32105ae2021-03-27 18:59:25 +0100451check_for_string_arg(typval_T *args, int idx)
Bram Moolenaar7bb4e742020-12-09 12:41:50 +0100452{
Bram Moolenaar32105ae2021-03-27 18:59:25 +0100453 if (args[idx].v_type != VAR_STRING)
Bram Moolenaar7bb4e742020-12-09 12:41:50 +0100454 {
rbtnnddc80af2021-12-17 18:01:31 +0000455 semsg(_(e_string_required_for_argument_nr), idx + 1);
Bram Moolenaar7bb4e742020-12-09 12:41:50 +0100456 return FAIL;
457 }
458 return OK;
459}
460
461/*
Bram Moolenaar32105ae2021-03-27 18:59:25 +0100462 * Give an error and return FAIL unless "args[idx]" is a non-empty string.
Bram Moolenaar2a9d5d32020-12-12 18:58:40 +0100463 */
464 int
Bram Moolenaar32105ae2021-03-27 18:59:25 +0100465check_for_nonempty_string_arg(typval_T *args, int idx)
Bram Moolenaar2a9d5d32020-12-12 18:58:40 +0100466{
Bram Moolenaar32105ae2021-03-27 18:59:25 +0100467 if (check_for_string_arg(args, idx) == FAIL)
Bram Moolenaar2a9d5d32020-12-12 18:58:40 +0100468 return FAIL;
Bram Moolenaar32105ae2021-03-27 18:59:25 +0100469 if (args[idx].vval.v_string == NULL || *args[idx].vval.v_string == NUL)
Bram Moolenaar2a9d5d32020-12-12 18:58:40 +0100470 {
Bram Moolenaare8e30782021-04-10 21:46:05 +0200471 semsg(_(e_non_empty_string_required_for_argument_nr), idx + 1);
Bram Moolenaar2a9d5d32020-12-12 18:58:40 +0100472 return FAIL;
473 }
474 return OK;
475}
476
477/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200478 * Check for an optional string argument at 'idx'
479 */
480 int
481check_for_opt_string_arg(typval_T *args, int idx)
482{
483 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100484 || check_for_string_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200485}
486
487/*
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +0200488 * Give an error and return FAIL unless "args[idx]" is a number.
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200489 */
490 int
491check_for_number_arg(typval_T *args, int idx)
492{
493 if (args[idx].v_type != VAR_NUMBER)
494 {
rbtnnddc80af2021-12-17 18:01:31 +0000495 semsg(_(e_number_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200496 return FAIL;
497 }
498 return OK;
499}
500
501/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200502 * Check for an optional number argument at 'idx'
503 */
504 int
505check_for_opt_number_arg(typval_T *args, int idx)
506{
507 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100508 || check_for_number_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200509}
510
511/*
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200512 * Give an error and return FAIL unless "args[idx]" is a float or a number.
513 */
514 int
515check_for_float_or_nr_arg(typval_T *args, int idx)
516{
517 if (args[idx].v_type != VAR_FLOAT && args[idx].v_type != VAR_NUMBER)
518 {
rbtnnddc80af2021-12-17 18:01:31 +0000519 semsg(_(e_float_or_number_required_for_argument_nr), idx + 1);
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200520 return FAIL;
521 }
522 return OK;
523}
524
525/*
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +0200526 * Give an error and return FAIL unless "args[idx]" is a bool.
527 */
528 int
529check_for_bool_arg(typval_T *args, int idx)
530{
531 if (args[idx].v_type != VAR_BOOL
532 && !(args[idx].v_type == VAR_NUMBER
533 && (args[idx].vval.v_number == 0
534 || args[idx].vval.v_number == 1)))
535 {
rbtnnddc80af2021-12-17 18:01:31 +0000536 semsg(_(e_bool_required_for_argument_nr), idx + 1);
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +0200537 return FAIL;
538 }
539 return OK;
540}
541
542/*
zeertzjqe0a2ab32025-02-02 09:14:35 +0100543 * Give an error and return FAIL unless "args[idx]" is a bool or a number.
544 */
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100545 static int
zeertzjqe0a2ab32025-02-02 09:14:35 +0100546check_for_bool_or_number_arg(typval_T *args, int idx)
547{
548 if (args[idx].v_type != VAR_BOOL && args[idx].v_type != VAR_NUMBER)
549 {
550 semsg(_(e_bool_or_number_required_for_argument_nr), idx + 1);
551 return FAIL;
552 }
553 return OK;
554}
555
556/*
Bram Moolenaara29856f2021-09-13 21:36:27 +0200557 * Check for an optional bool argument at 'idx'.
558 * Return FAIL if the type is wrong.
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200559 */
560 int
561check_for_opt_bool_arg(typval_T *args, int idx)
562{
Bram Moolenaara29856f2021-09-13 21:36:27 +0200563 if (args[idx].v_type == VAR_UNKNOWN)
564 return OK;
565 return check_for_bool_arg(args, idx);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200566}
567
568/*
zeertzjqe0a2ab32025-02-02 09:14:35 +0100569 * Check for an optional bool or number argument at 'idx'.
570 * Return FAIL if the type is wrong.
571 */
572 int
573check_for_opt_bool_or_number_arg(typval_T *args, int idx)
574{
575 if (args[idx].v_type == VAR_UNKNOWN)
576 return OK;
577 return check_for_bool_or_number_arg(args, idx);
578}
579
580/*
Yegappan Lakshmanan5dfe4672021-09-14 17:54:30 +0200581 * Give an error and return FAIL unless "args[idx]" is a blob.
582 */
583 int
584check_for_blob_arg(typval_T *args, int idx)
585{
586 if (args[idx].v_type != VAR_BLOB)
587 {
rbtnnddc80af2021-12-17 18:01:31 +0000588 semsg(_(e_blob_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan5dfe4672021-09-14 17:54:30 +0200589 return FAIL;
590 }
591 return OK;
592}
593
594/*
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +0200595 * Give an error and return FAIL unless "args[idx]" is a list.
596 */
597 int
598check_for_list_arg(typval_T *args, int idx)
599{
600 if (args[idx].v_type != VAR_LIST)
601 {
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +0200602 semsg(_(e_list_required_for_argument_nr), idx + 1);
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +0200603 return FAIL;
604 }
605 return OK;
606}
607
608/*
Bram Moolenaard83392a2022-09-01 12:22:46 +0100609 * Give an error and return FAIL unless "args[idx]" is a non-NULL list.
610 */
611 int
612check_for_nonnull_list_arg(typval_T *args, int idx)
613{
614 if (check_for_list_arg(args, idx) == FAIL)
615 return FAIL;
616
617 if (args[idx].vval.v_list == NULL)
618 {
619 semsg(_(e_non_null_list_required_for_argument_nr), idx + 1);
620 return FAIL;
621 }
622 return OK;
623}
624
625/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200626 * Check for an optional list argument at 'idx'
627 */
628 int
629check_for_opt_list_arg(typval_T *args, int idx)
630{
631 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100632 || check_for_list_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200633}
634
635/*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100636 * Give an error and return FAIL unless "args[idx]" is a tuple.
637 */
638 int
639check_for_tuple_arg(typval_T *args, int idx)
640{
641 if (args[idx].v_type != VAR_TUPLE)
642 {
643 semsg(_(e_tuple_required_for_argument_nr), idx + 1);
644 return FAIL;
645 }
646 return OK;
647}
648
649/*
Yegappan Lakshmanana9a7c0c2021-07-17 19:11:07 +0200650 * Give an error and return FAIL unless "args[idx]" is a dict.
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +0200651 */
652 int
653check_for_dict_arg(typval_T *args, int idx)
654{
655 if (args[idx].v_type != VAR_DICT)
656 {
rbtnnddc80af2021-12-17 18:01:31 +0000657 semsg(_(e_dict_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +0200658 return FAIL;
659 }
660 return OK;
661}
662
663/*
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +0100664 * Give an error and return FAIL unless "args[idx]" is a non-NULL dict.
665 */
666 int
667check_for_nonnull_dict_arg(typval_T *args, int idx)
668{
669 if (check_for_dict_arg(args, idx) == FAIL)
670 return FAIL;
671
672 if (args[idx].vval.v_dict == NULL)
673 {
674 semsg(_(e_non_null_dict_required_for_argument_nr), idx + 1);
675 return FAIL;
676 }
677 return OK;
678}
679
680/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200681 * Check for an optional dict argument at 'idx'
682 */
683 int
684check_for_opt_dict_arg(typval_T *args, int idx)
685{
686 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100687 || check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200688}
689
Yegappan Lakshmananfa378352024-02-01 22:05:27 +0100690/*
691 * Check for an optional non-NULL dict argument at 'idx'
692 */
693 int
694check_for_opt_nonnull_dict_arg(typval_T *args, int idx)
695{
696 return (args[idx].v_type == VAR_UNKNOWN
697 || check_for_nonnull_dict_arg(args, idx) != FAIL) ? OK : FAIL;
698}
699
Dominique Pelle748b3082022-01-08 12:41:16 +0000700#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200701/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200702 * Give an error and return FAIL unless "args[idx]" is a channel or a job.
703 */
704 int
705check_for_chan_or_job_arg(typval_T *args, int idx)
706{
707 if (args[idx].v_type != VAR_CHANNEL && args[idx].v_type != VAR_JOB)
708 {
rbtnnddc80af2021-12-17 18:01:31 +0000709 semsg(_(e_chan_or_job_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200710 return FAIL;
711 }
712 return OK;
713}
714
715/*
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +0200716 * Give an error and return FAIL unless "args[idx]" is an optional channel or a
717 * job.
718 */
719 int
720check_for_opt_chan_or_job_arg(typval_T *args, int idx)
721{
722 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100723 || check_for_chan_or_job_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanan7973de32021-07-24 16:16:15 +0200724}
725
726/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200727 * Give an error and return FAIL unless "args[idx]" is a job.
728 */
729 int
730check_for_job_arg(typval_T *args, int idx)
731{
732 if (args[idx].v_type != VAR_JOB)
733 {
rbtnnddc80af2021-12-17 18:01:31 +0000734 semsg(_(e_job_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200735 return FAIL;
736 }
737 return OK;
738}
739
740/*
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200741 * Check for an optional job argument at 'idx'.
742 */
743 int
744check_for_opt_job_arg(typval_T *args, int idx)
745{
746 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100747 || check_for_job_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200748}
Bram Moolenaar3b8c7082022-11-30 20:20:56 +0000749#else
750/*
751 * Give an error and return FAIL unless "args[idx]" is an optional channel or a
752 * job. Used without the +channel feature, thus only VAR_UNKNOWN is accepted.
753 */
754 int
755check_for_opt_chan_or_job_arg(typval_T *args, int idx)
756{
757 return args[idx].v_type == VAR_UNKNOWN ? OK : FAIL;
758}
Dominique Pelle748b3082022-01-08 12:41:16 +0000759#endif
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200760
761/*
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200762 * Give an error and return FAIL unless "args[idx]" is a string or
763 * a number.
764 */
765 int
766check_for_string_or_number_arg(typval_T *args, int idx)
767{
768 if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_NUMBER)
769 {
rbtnnddc80af2021-12-17 18:01:31 +0000770 semsg(_(e_string_or_number_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200771 return FAIL;
772 }
773 return OK;
774}
775
776/*
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200777 * Check for an optional string or number argument at 'idx'.
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200778 */
779 int
780check_for_opt_string_or_number_arg(typval_T *args, int idx)
781{
782 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100783 || check_for_string_or_number_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200784}
785
786/*
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200787 * Give an error and return FAIL unless "args[idx]" is a buffer number.
788 * Buffer number can be a number or a string.
789 */
790 int
791check_for_buffer_arg(typval_T *args, int idx)
792{
793 return check_for_string_or_number_arg(args, idx);
794}
795
796/*
797 * Check for an optional buffer argument at 'idx'
798 */
799 int
800check_for_opt_buffer_arg(typval_T *args, int idx)
801{
802 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100803 || check_for_buffer_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200804}
805
806/*
807 * Give an error and return FAIL unless "args[idx]" is a line number.
808 * Line number can be a number or a string.
809 */
810 int
811check_for_lnum_arg(typval_T *args, int idx)
812{
813 return check_for_string_or_number_arg(args, idx);
814}
815
816/*
817 * Check for an optional line number argument at 'idx'
818 */
819 int
820check_for_opt_lnum_arg(typval_T *args, int idx)
821{
822 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100823 || check_for_lnum_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200824}
825
Dominique Pelle748b3082022-01-08 12:41:16 +0000826#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200827/*
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +0200828 * Give an error and return FAIL unless "args[idx]" is a string or a blob.
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200829 */
830 int
831check_for_string_or_blob_arg(typval_T *args, int idx)
832{
833 if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_BLOB)
834 {
rbtnnddc80af2021-12-17 18:01:31 +0000835 semsg(_(e_string_or_blob_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200836 return FAIL;
837 }
838 return OK;
839}
Dominique Pelle748b3082022-01-08 12:41:16 +0000840#endif
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200841
842/*
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +0200843 * Give an error and return FAIL unless "args[idx]" is a string or a list.
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200844 */
845 int
846check_for_string_or_list_arg(typval_T *args, int idx)
847{
848 if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_LIST)
849 {
rbtnnddc80af2021-12-17 18:01:31 +0000850 semsg(_(e_string_or_list_required_for_argument_nr), idx + 1);
Yegappan Lakshmanancd917202021-07-21 19:09:09 +0200851 return FAIL;
852 }
853 return OK;
854}
855
856/*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100857 * Give an error and return FAIL unless "args[idx]" is a string, a list, a
858 * tuple or a blob.
rbtnn0ccb5842021-12-18 18:33:46 +0000859 */
860 int
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100861check_for_string_or_list_or_tuple_or_blob_arg(typval_T *args, int idx)
rbtnn0ccb5842021-12-18 18:33:46 +0000862{
863 if (args[idx].v_type != VAR_STRING
864 && args[idx].v_type != VAR_LIST
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100865 && args[idx].v_type != VAR_TUPLE
rbtnn0ccb5842021-12-18 18:33:46 +0000866 && args[idx].v_type != VAR_BLOB)
867 {
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100868 semsg(_(e_string_list_tuple_or_blob_required_for_argument_nr), idx + 1);
rbtnn0ccb5842021-12-18 18:33:46 +0000869 return FAIL;
870 }
871 return OK;
872}
873
874/*
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200875 * Check for an optional string or list argument at 'idx'
876 */
877 int
878check_for_opt_string_or_list_arg(typval_T *args, int idx)
879{
880 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100881 || check_for_string_or_list_arg(args, idx) != FAIL) ? OK : FAIL;
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200882}
883
884/*
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200885 * Give an error and return FAIL unless "args[idx]" is a string or a dict.
886 */
887 int
888check_for_string_or_dict_arg(typval_T *args, int idx)
889{
890 if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_DICT)
891 {
rbtnnddc80af2021-12-17 18:01:31 +0000892 semsg(_(e_string_or_dict_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200893 return FAIL;
894 }
895 return OK;
896}
897
898/*
899 * Give an error and return FAIL unless "args[idx]" is a string or a number
900 * or a list.
901 */
902 int
903check_for_string_or_number_or_list_arg(typval_T *args, int idx)
904{
905 if (args[idx].v_type != VAR_STRING
906 && args[idx].v_type != VAR_NUMBER
907 && args[idx].v_type != VAR_LIST)
908 {
rbtnn0ccb5842021-12-18 18:33:46 +0000909 semsg(_(e_string_number_or_list_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200910 return FAIL;
911 }
912 return OK;
913}
914
915/*
Yegappan Lakshmanan7e6a2a62021-07-28 11:51:48 +0200916 * Give an error and return FAIL unless "args[idx]" is an optional string
917 * or number or a list
918 */
919 int
920check_for_opt_string_or_number_or_list_arg(typval_T *args, int idx)
921{
922 return (args[idx].v_type == VAR_UNKNOWN
zeertzjqcd2d5c12022-09-12 14:09:30 +0100923 || check_for_string_or_number_or_list_arg(args, idx)
924 != FAIL) ? OK : FAIL;
Yegappan Lakshmanan7e6a2a62021-07-28 11:51:48 +0200925}
926
927/*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100928 * Give an error and return FAIL unless "args[idx]" is a string, a number, a
929 * list, a tuple or a blob.
Bakudankun375141e2022-09-09 18:46:47 +0100930 */
931 int
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100932check_for_repeat_func_arg(typval_T *args, int idx)
Bakudankun375141e2022-09-09 18:46:47 +0100933{
934 if (args[idx].v_type != VAR_STRING
935 && args[idx].v_type != VAR_NUMBER
936 && args[idx].v_type != VAR_LIST
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100937 && args[idx].v_type != VAR_TUPLE
Bakudankun375141e2022-09-09 18:46:47 +0100938 && args[idx].v_type != VAR_BLOB)
939 {
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100940 semsg(_(e_repeatable_type_required_for_argument_nr), idx + 1);
Bakudankun375141e2022-09-09 18:46:47 +0100941 return FAIL;
942 }
943 return OK;
944}
945
946/*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100947 * Give an error and return FAIL unless "args[idx]" is a string, a list, a
948 * tuple or a dict.
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200949 */
950 int
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100951check_for_string_list_tuple_or_dict_arg(typval_T *args, int idx)
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200952{
953 if (args[idx].v_type != VAR_STRING
954 && args[idx].v_type != VAR_LIST
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100955 && args[idx].v_type != VAR_TUPLE
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200956 && args[idx].v_type != VAR_DICT)
957 {
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100958 semsg(_(e_string_list_tuple_or_dict_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200959 return FAIL;
960 }
961 return OK;
962}
963
964/*
Bram Moolenaar223d0a62021-12-25 19:29:21 +0000965 * Give an error and return FAIL unless "args[idx]" is a string
966 * or a function reference.
967 */
968 int
969check_for_string_or_func_arg(typval_T *args, int idx)
970{
971 if (args[idx].v_type != VAR_PARTIAL
972 && args[idx].v_type != VAR_FUNC
973 && args[idx].v_type != VAR_STRING)
974 {
975 semsg(_(e_string_or_function_required_for_argument_nr), idx + 1);
976 return FAIL;
977 }
978 return OK;
979}
980
981/*
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +0200982 * Give an error and return FAIL unless "args[idx]" is a list or a blob.
983 */
984 int
985check_for_list_or_blob_arg(typval_T *args, int idx)
986{
987 if (args[idx].v_type != VAR_LIST && args[idx].v_type != VAR_BLOB)
988 {
rbtnn0ccb5842021-12-18 18:33:46 +0000989 semsg(_(e_list_or_blob_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200990 return FAIL;
991 }
992 return OK;
993}
994
995/*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100996 * Give an error and return FAIL unless "args[idx]" is a list or a tuple.
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200997 */
998 int
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +0100999check_for_list_or_tuple_arg(typval_T *args, int idx)
1000{
1001 if (args[idx].v_type != VAR_LIST && args[idx].v_type != VAR_TUPLE)
1002 {
1003 semsg(_(e_list_or_tuple_required_for_argument_nr), idx + 1);
1004 return FAIL;
1005 }
1006 return OK;
1007}
1008
1009/*
1010 * Give an error and return FAIL unless "args[idx]" is a list, a tuple or a
1011 * blob.
1012 */
1013 int
1014check_for_list_or_tuple_or_blob_arg(typval_T *args, int idx)
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001015{
1016 if (args[idx].v_type != VAR_LIST
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001017 && args[idx].v_type != VAR_TUPLE
1018 && args[idx].v_type != VAR_BLOB)
1019 {
1020 semsg(_(e_list_or_tuple_or_blob_required_for_argument_nr), idx + 1);
1021 return FAIL;
1022 }
1023 return OK;
1024}
1025
1026/*
1027 * Give an error and return FAIL unless "args[idx]" is a list, a tuple or a
1028 * dict
1029 */
1030 int
1031check_for_list_or_tuple_or_dict_arg(typval_T *args, int idx)
1032{
1033 if (args[idx].v_type != VAR_LIST
1034 && args[idx].v_type != VAR_TUPLE
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001035 && args[idx].v_type != VAR_DICT)
1036 {
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001037 semsg(_(e_list_or_tuple_or_dict_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001038 return FAIL;
1039 }
1040 return OK;
1041}
1042
1043/*
1044 * Give an error and return FAIL unless "args[idx]" is a list or dict or a
1045 * blob.
1046 */
1047 int
1048check_for_list_or_dict_or_blob_arg(typval_T *args, int idx)
1049{
1050 if (args[idx].v_type != VAR_LIST
1051 && args[idx].v_type != VAR_DICT
1052 && args[idx].v_type != VAR_BLOB)
1053 {
rbtnnddc80af2021-12-17 18:01:31 +00001054 semsg(_(e_list_dict_or_blob_required_for_argument_nr), idx + 1);
Yegappan Lakshmanan0ad871d2021-07-23 20:37:56 +02001055 return FAIL;
1056 }
1057 return OK;
1058}
1059
1060/*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001061 * Give an error and return FAIL unless "args[idx]" is a list, a tuple, a dict,
1062 * a blob or a string.
Bram Moolenaar2d877592021-12-16 08:21:09 +00001063 */
1064 int
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001065check_for_list_tuple_dict_blob_or_string_arg(typval_T *args, int idx)
Bram Moolenaar2d877592021-12-16 08:21:09 +00001066{
1067 if (args[idx].v_type != VAR_LIST
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001068 && args[idx].v_type != VAR_TUPLE
Bram Moolenaar2d877592021-12-16 08:21:09 +00001069 && args[idx].v_type != VAR_DICT
1070 && args[idx].v_type != VAR_BLOB
1071 && args[idx].v_type != VAR_STRING)
1072 {
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001073 semsg(_(e_list_tuple_dict_blob_or_string_required_for_argument_nr), idx + 1);
Bram Moolenaar2d877592021-12-16 08:21:09 +00001074 return FAIL;
1075 }
1076 return OK;
1077}
1078
1079/*
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001080 * Give an error and return FAIL unless "args[idx]" is an optional buffer
1081 * number or a dict.
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001082 */
1083 int
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001084check_for_opt_buffer_or_dict_arg(typval_T *args, int idx)
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001085{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001086 if (args[idx].v_type != VAR_UNKNOWN
1087 && args[idx].v_type != VAR_STRING
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001088 && args[idx].v_type != VAR_NUMBER
1089 && args[idx].v_type != VAR_DICT)
1090 {
rbtnnddc80af2021-12-17 18:01:31 +00001091 semsg(_(e_string_required_for_argument_nr), idx + 1);
Yegappan Lakshmanancd917202021-07-21 19:09:09 +02001092 return FAIL;
1093 }
1094 return OK;
1095}
1096
1097/*
LemonBoyafe04662023-08-23 21:08:11 +02001098 * Give an error and return FAIL unless "args[idx]" is an object.
1099 */
1100 int
1101check_for_object_arg(typval_T *args, int idx)
1102{
1103 if (args[idx].v_type != VAR_OBJECT)
1104 {
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02001105 semsg(_(e_object_required_for_argument_nr), idx + 1);
LemonBoyafe04662023-08-23 21:08:11 +02001106 return FAIL;
1107 }
1108 return OK;
1109}
1110
1111/*
Yegappan Lakshmananfeaccd22023-10-28 15:53:55 +02001112 * Returns TRUE if "tv" is a type alias for a class
1113 */
Yegappan Lakshmanana04003a2024-10-27 21:54:11 +01001114 static int
Yegappan Lakshmananfeaccd22023-10-28 15:53:55 +02001115tv_class_alias(typval_T *tv)
1116{
1117 return tv->v_type == VAR_TYPEALIAS &&
1118 tv->vval.v_typealias->ta_type->tt_type == VAR_OBJECT;
1119}
1120
1121/*
Ernie Rael2025af12023-12-12 16:58:00 +01001122 * Give an error and return FAIL unless "args[idx]" is a class
1123 * or class typealias.
LemonBoyafe04662023-08-23 21:08:11 +02001124 */
1125 int
Ernie Rael2025af12023-12-12 16:58:00 +01001126check_for_class_or_typealias_args(typval_T *args, int idx)
LemonBoyafe04662023-08-23 21:08:11 +02001127{
Ernie Rael2025af12023-12-12 16:58:00 +01001128 for (int i = idx; args[i].v_type != VAR_UNKNOWN; ++i)
LemonBoyafe04662023-08-23 21:08:11 +02001129 {
Ernie Rael2025af12023-12-12 16:58:00 +01001130 if (args[i].v_type != VAR_CLASS && !tv_class_alias(&args[idx]))
1131 {
1132 semsg(_(e_class_or_typealias_required_for_argument_nr), i + 1);
1133 return FAIL;
1134 }
LemonBoyafe04662023-08-23 21:08:11 +02001135 }
1136 return OK;
1137}
1138
1139/*
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001140 * Get the string value of a variable.
1141 * If it is a Number variable, the number is converted into a string.
1142 * tv_get_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
1143 * tv_get_string_buf() uses a given buffer.
1144 * If the String variable has never been set, return an empty string.
1145 * Never returns NULL;
1146 * tv_get_string_chk() and tv_get_string_buf_chk() are similar, but return
1147 * NULL on error.
1148 */
1149 char_u *
1150tv_get_string(typval_T *varp)
1151{
1152 static char_u mybuf[NUMBUFLEN];
1153
1154 return tv_get_string_buf(varp, mybuf);
1155}
1156
Bram Moolenaarf2b26bc2021-01-30 23:05:11 +01001157/*
1158 * Like tv_get_string() but don't allow number to string conversion for Vim9.
1159 */
1160 char_u *
1161tv_get_string_strict(typval_T *varp)
1162{
1163 static char_u mybuf[NUMBUFLEN];
1164 char_u *res = tv_get_string_buf_chk_strict(
1165 varp, mybuf, in_vim9script());
1166
1167 return res != NULL ? res : (char_u *)"";
1168}
1169
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001170 char_u *
1171tv_get_string_buf(typval_T *varp, char_u *buf)
1172{
Bram Moolenaar1328bde2021-06-05 20:51:38 +02001173 char_u *res = tv_get_string_buf_chk(varp, buf);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001174
1175 return res != NULL ? res : (char_u *)"";
1176}
1177
1178/*
1179 * Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
1180 */
1181 char_u *
1182tv_get_string_chk(typval_T *varp)
1183{
1184 static char_u mybuf[NUMBUFLEN];
1185
1186 return tv_get_string_buf_chk(varp, mybuf);
1187}
1188
1189 char_u *
1190tv_get_string_buf_chk(typval_T *varp, char_u *buf)
1191{
Bram Moolenaarf2b26bc2021-01-30 23:05:11 +01001192 return tv_get_string_buf_chk_strict(varp, buf, FALSE);
1193}
1194
1195 char_u *
1196tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict)
1197{
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001198 switch (varp->v_type)
1199 {
1200 case VAR_NUMBER:
Bram Moolenaarf2b26bc2021-01-30 23:05:11 +01001201 if (strict)
1202 {
1203 emsg(_(e_using_number_as_string));
1204 break;
1205 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001206 vim_snprintf((char *)buf, NUMBUFLEN, "%lld",
1207 (varnumber_T)varp->vval.v_number);
1208 return buf;
1209 case VAR_FUNC:
1210 case VAR_PARTIAL:
Bram Moolenaara6f79292022-01-04 21:30:47 +00001211 emsg(_(e_using_funcref_as_string));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001212 break;
1213 case VAR_LIST:
Bram Moolenaara6f79292022-01-04 21:30:47 +00001214 emsg(_(e_using_list_as_string));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001215 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001216 case VAR_TUPLE:
1217 emsg(_(e_using_tuple_as_string));
1218 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001219 case VAR_DICT:
Bram Moolenaara6f79292022-01-04 21:30:47 +00001220 emsg(_(e_using_dictionary_as_string));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001221 break;
1222 case VAR_FLOAT:
Bram Moolenaar7a2217b2021-06-06 12:33:49 +02001223 if (strict)
1224 {
Bram Moolenaar0699b042022-01-01 16:01:23 +00001225 emsg(_(e_using_float_as_string));
Bram Moolenaar7a2217b2021-06-06 12:33:49 +02001226 break;
1227 }
1228 vim_snprintf((char *)buf, NUMBUFLEN, "%g", varp->vval.v_float);
1229 return buf;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001230 case VAR_STRING:
1231 if (varp->vval.v_string != NULL)
1232 return varp->vval.v_string;
1233 return (char_u *)"";
1234 case VAR_BOOL:
1235 case VAR_SPECIAL:
1236 STRCPY(buf, get_var_special_name(varp->vval.v_number));
1237 return buf;
Bram Moolenaar6ed545e2022-05-09 20:09:23 +01001238 case VAR_BLOB:
Bram Moolenaard82a47d2022-01-05 20:24:39 +00001239 emsg(_(e_using_blob_as_string));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001240 break;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001241 case VAR_CLASS:
Ernie Raele75fde62023-12-21 17:18:54 +01001242 case VAR_TYPEALIAS:
1243 check_typval_is_value(varp);
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001244 break;
1245 case VAR_OBJECT:
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001246 {
Ernie Raelbe828252024-07-26 18:37:02 +02001247 if (varp->vval.v_object == NULL)
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001248 emsg(_(e_using_object_as_string));
Ernie Raelbe828252024-07-26 18:37:02 +02001249 else
1250 {
1251 class_T *cl = varp->vval.v_object->obj_class;
1252 if (cl != NULL && IS_ENUM(cl))
1253 semsg(_(e_using_enum_str_as_string), cl->class_name);
1254 else
1255 emsg(_(e_using_object_as_string));
1256 }
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001257 }
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001258 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001259 case VAR_JOB:
1260#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar1328bde2021-06-05 20:51:38 +02001261 if (in_vim9script())
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001262 {
Bram Moolenaar1328bde2021-06-05 20:51:38 +02001263 semsg(_(e_using_invalid_value_as_string_str), "job");
1264 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001265 }
Bram Moolenaar1328bde2021-06-05 20:51:38 +02001266 return job_to_string_buf(varp, buf);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001267#endif
1268 break;
1269 case VAR_CHANNEL:
1270#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar1328bde2021-06-05 20:51:38 +02001271 if (in_vim9script())
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001272 {
Bram Moolenaar1328bde2021-06-05 20:51:38 +02001273 semsg(_(e_using_invalid_value_as_string_str), "channel");
1274 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001275 }
Bram Moolenaar1328bde2021-06-05 20:51:38 +02001276 return channel_to_string_buf(varp, buf);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001277#endif
1278 break;
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02001279 case VAR_VOID:
1280 emsg(_(e_cannot_use_void_value));
1281 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001282 case VAR_UNKNOWN:
1283 case VAR_ANY:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001284 case VAR_INSTR:
Bram Moolenaar68db9962021-05-09 23:19:22 +02001285 semsg(_(e_using_invalid_value_as_string_str),
1286 vartype_name(varp->v_type));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001287 break;
1288 }
1289 return NULL;
1290}
1291
1292/*
1293 * Turn a typeval into a string. Similar to tv_get_string_buf() but uses
1294 * string() on Dict, List, etc.
1295 */
1296 char_u *
1297tv_stringify(typval_T *varp, char_u *buf)
1298{
1299 if (varp->v_type == VAR_LIST
1300 || varp->v_type == VAR_DICT
1301 || varp->v_type == VAR_BLOB
1302 || varp->v_type == VAR_FUNC
1303 || varp->v_type == VAR_PARTIAL
1304 || varp->v_type == VAR_FLOAT)
1305 {
1306 typval_T tmp;
1307
Christian Brabandt7dfc9e62025-04-22 20:01:04 +02001308 init_tv(&tmp);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001309 f_string(varp, &tmp);
1310 tv_get_string_buf(&tmp, buf);
1311 clear_tv(varp);
1312 *varp = tmp;
1313 return tmp.vval.v_string;
1314 }
1315 return tv_get_string_buf(varp, buf);
1316}
1317
1318/*
1319 * Return TRUE if typeval "tv" and its value are set to be locked (immutable).
1320 * Also give an error message, using "name" or _("name") when use_gettext is
1321 * TRUE.
1322 */
1323 int
1324tv_check_lock(typval_T *tv, char_u *name, int use_gettext)
1325{
1326 int lock = 0;
1327
1328 switch (tv->v_type)
1329 {
1330 case VAR_BLOB:
1331 if (tv->vval.v_blob != NULL)
1332 lock = tv->vval.v_blob->bv_lock;
1333 break;
1334 case VAR_LIST:
1335 if (tv->vval.v_list != NULL)
1336 lock = tv->vval.v_list->lv_lock;
1337 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001338 case VAR_TUPLE:
1339 if (tv->vval.v_tuple != NULL)
1340 lock = tv->vval.v_tuple->tv_lock;
1341 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001342 case VAR_DICT:
1343 if (tv->vval.v_dict != NULL)
1344 lock = tv->vval.v_dict->dv_lock;
1345 break;
1346 default:
1347 break;
1348 }
Bram Moolenaara187c432020-09-16 21:08:28 +02001349 return value_check_lock(tv->v_lock, name, use_gettext)
1350 || (lock != 0 && value_check_lock(lock, name, use_gettext));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001351}
1352
1353/*
1354 * Copy the values from typval_T "from" to typval_T "to".
1355 * When needed allocates string or increases reference count.
1356 * Does not make a copy of a list, blob or dict but copies the reference!
1357 * It is OK for "from" and "to" to point to the same item. This is used to
1358 * make a copy later.
1359 */
1360 void
1361copy_tv(typval_T *from, typval_T *to)
1362{
1363 to->v_type = from->v_type;
1364 to->v_lock = 0;
1365 switch (from->v_type)
1366 {
1367 case VAR_NUMBER:
1368 case VAR_BOOL:
1369 case VAR_SPECIAL:
1370 to->vval.v_number = from->vval.v_number;
1371 break;
1372 case VAR_FLOAT:
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001373 to->vval.v_float = from->vval.v_float;
1374 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001375 case VAR_JOB:
1376#ifdef FEAT_JOB_CHANNEL
1377 to->vval.v_job = from->vval.v_job;
1378 if (to->vval.v_job != NULL)
1379 ++to->vval.v_job->jv_refcount;
1380 break;
1381#endif
1382 case VAR_CHANNEL:
1383#ifdef FEAT_JOB_CHANNEL
1384 to->vval.v_channel = from->vval.v_channel;
1385 if (to->vval.v_channel != NULL)
1386 ++to->vval.v_channel->ch_refcount;
1387 break;
1388#endif
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001389 case VAR_INSTR:
1390 to->vval.v_instr = from->vval.v_instr;
1391 break;
1392
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001393 case VAR_CLASS:
1394 copy_class(from, to);
1395 break;
1396
1397 case VAR_OBJECT:
1398 copy_object(from, to);
1399 break;
1400
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001401 case VAR_STRING:
1402 case VAR_FUNC:
1403 if (from->vval.v_string == NULL)
1404 to->vval.v_string = NULL;
1405 else
1406 {
1407 to->vval.v_string = vim_strsave(from->vval.v_string);
1408 if (from->v_type == VAR_FUNC)
1409 func_ref(to->vval.v_string);
1410 }
1411 break;
1412 case VAR_PARTIAL:
1413 if (from->vval.v_partial == NULL)
1414 to->vval.v_partial = NULL;
1415 else
1416 {
1417 to->vval.v_partial = from->vval.v_partial;
1418 ++to->vval.v_partial->pt_refcount;
1419 }
1420 break;
1421 case VAR_BLOB:
1422 if (from->vval.v_blob == NULL)
1423 to->vval.v_blob = NULL;
1424 else
1425 {
1426 to->vval.v_blob = from->vval.v_blob;
1427 ++to->vval.v_blob->bv_refcount;
1428 }
1429 break;
1430 case VAR_LIST:
1431 if (from->vval.v_list == NULL)
1432 to->vval.v_list = NULL;
1433 else
1434 {
1435 to->vval.v_list = from->vval.v_list;
1436 ++to->vval.v_list->lv_refcount;
1437 }
1438 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001439 case VAR_TUPLE:
1440 if (from->vval.v_tuple == NULL)
1441 to->vval.v_tuple = NULL;
1442 else
1443 {
1444 to->vval.v_tuple = from->vval.v_tuple;
1445 ++to->vval.v_tuple->tv_refcount;
1446 }
1447 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001448 case VAR_DICT:
1449 if (from->vval.v_dict == NULL)
1450 to->vval.v_dict = NULL;
1451 else
1452 {
1453 to->vval.v_dict = from->vval.v_dict;
1454 ++to->vval.v_dict->dv_refcount;
1455 }
1456 break;
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02001457 case VAR_TYPEALIAS:
1458 if (from->vval.v_typealias == NULL)
1459 to->vval.v_typealias = NULL;
1460 else
1461 {
1462 to->vval.v_typealias = from->vval.v_typealias;
1463 ++to->vval.v_typealias->ta_refcount;
1464 }
1465 break;
Bram Moolenaar61a417b2021-06-15 22:54:28 +02001466 case VAR_VOID:
1467 emsg(_(e_cannot_use_void_value));
1468 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001469 case VAR_UNKNOWN:
1470 case VAR_ANY:
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001471 internal_error_no_abort("copy_tv(UNKNOWN)");
1472 break;
1473 }
1474}
1475
1476/*
Bram Moolenaar265f8112021-12-19 12:33:05 +00001477 * Compare "tv1" and "tv2".
1478 * Put the result in "tv1". Caller should clear "tv2".
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001479 */
1480 int
1481typval_compare(
Bram Moolenaar265f8112021-12-19 12:33:05 +00001482 typval_T *tv1, // first operand
1483 typval_T *tv2, // second operand
1484 exprtype_T type, // operator
1485 int ic) // ignore case
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001486{
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001487 varnumber_T n1, n2;
Bram Moolenaar265f8112021-12-19 12:33:05 +00001488 int res = 0;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001489 int type_is = type == EXPR_IS || type == EXPR_ISNOT;
1490
Ernie Raele75fde62023-12-21 17:18:54 +01001491 if (check_typval_is_value(tv1) == FAIL
1492 || check_typval_is_value(tv2) == FAIL)
1493 {
1494 clear_tv(tv1);
1495 return FAIL;
1496 }
1497 else if (type_is && tv1->v_type != tv2->v_type)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001498 {
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001499 // For "is" a different type always means FALSE, for "isnot"
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001500 // it means TRUE.
1501 n1 = (type == EXPR_ISNOT);
1502 }
Bram Moolenaar7a222242022-03-01 19:23:24 +00001503 else if (((tv1->v_type == VAR_SPECIAL && tv1->vval.v_number == VVAL_NULL)
1504 || (tv2->v_type == VAR_SPECIAL
1505 && tv2->vval.v_number == VVAL_NULL))
1506 && tv1->v_type != tv2->v_type
1507 && (type == EXPR_EQUAL || type == EXPR_NEQUAL))
1508 {
1509 n1 = typval_compare_null(tv1, tv2);
1510 if (n1 == MAYBE)
1511 {
1512 clear_tv(tv1);
1513 return FAIL;
1514 }
1515 if (type == EXPR_NEQUAL)
1516 n1 = !n1;
1517 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001518 else if (tv1->v_type == VAR_BLOB || tv2->v_type == VAR_BLOB)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001519 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001520 if (typval_compare_blob(tv1, tv2, type, &res) == FAIL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001521 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001522 clear_tv(tv1);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001523 return FAIL;
1524 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001525 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001526 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001527 else if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001528 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001529 if (typval_compare_list(tv1, tv2, type, ic, &res) == FAIL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001530 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001531 clear_tv(tv1);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001532 return FAIL;
1533 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001534 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001535 }
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001536 else if (tv1->v_type == VAR_TUPLE || tv2->v_type == VAR_TUPLE)
1537 {
1538 if (typval_compare_tuple(tv1, tv2, type, ic, &res) == FAIL)
1539 {
1540 clear_tv(tv1);
1541 return FAIL;
1542 }
1543 n1 = res;
1544 }
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001545 else if (tv1->v_type == VAR_OBJECT || tv2->v_type == VAR_OBJECT)
1546 {
1547 if (typval_compare_object(tv1, tv2, type, ic, &res) == FAIL)
1548 {
1549 clear_tv(tv1);
1550 return FAIL;
1551 }
1552 n1 = res;
1553 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001554 else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001555 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001556 if (typval_compare_dict(tv1, tv2, type, ic, &res) == FAIL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001557 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001558 clear_tv(tv1);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001559 return FAIL;
1560 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001561 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001562 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001563 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC
1564 || tv1->v_type == VAR_PARTIAL || tv2->v_type == VAR_PARTIAL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001565 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001566 if (typval_compare_func(tv1, tv2, type, ic, &res) == FAIL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001567 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001568 clear_tv(tv1);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001569 return FAIL;
1570 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001571 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001572 }
1573
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001574 // If one of the two variables is a float, compare as a float.
1575 // When using "=~" or "!~", always compare as string.
Bram Moolenaar265f8112021-12-19 12:33:05 +00001576 else if ((tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001577 && type != EXPR_MATCH && type != EXPR_NOMATCH)
1578 {
1579 float_T f1, f2;
Bram Moolenaar28fbbea2021-12-22 21:40:33 +00001580 int error = FALSE;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001581
Bram Moolenaar28fbbea2021-12-22 21:40:33 +00001582 f1 = tv_get_float_chk(tv1, &error);
1583 if (!error)
1584 f2 = tv_get_float_chk(tv2, &error);
1585 if (error)
1586 {
1587 clear_tv(tv1);
1588 return FAIL;
1589 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001590 n1 = FALSE;
1591 switch (type)
1592 {
1593 case EXPR_IS:
1594 case EXPR_EQUAL: n1 = (f1 == f2); break;
1595 case EXPR_ISNOT:
1596 case EXPR_NEQUAL: n1 = (f1 != f2); break;
1597 case EXPR_GREATER: n1 = (f1 > f2); break;
1598 case EXPR_GEQUAL: n1 = (f1 >= f2); break;
1599 case EXPR_SMALLER: n1 = (f1 < f2); break;
1600 case EXPR_SEQUAL: n1 = (f1 <= f2); break;
1601 case EXPR_UNKNOWN:
1602 case EXPR_MATCH:
1603 default: break; // avoid gcc warning
1604 }
1605 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001606
1607 // If one of the two variables is a number, compare as a number.
1608 // When using "=~" or "!~", always compare as string.
Bram Moolenaar265f8112021-12-19 12:33:05 +00001609 else if ((tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001610 && type != EXPR_MATCH && type != EXPR_NOMATCH)
1611 {
Bram Moolenaar28fbbea2021-12-22 21:40:33 +00001612 int error = FALSE;
1613
1614 n1 = tv_get_number_chk(tv1, &error);
1615 if (!error)
1616 n2 = tv_get_number_chk(tv2, &error);
1617 if (error)
1618 {
1619 clear_tv(tv1);
1620 return FAIL;
1621 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001622 switch (type)
1623 {
1624 case EXPR_IS:
1625 case EXPR_EQUAL: n1 = (n1 == n2); break;
1626 case EXPR_ISNOT:
1627 case EXPR_NEQUAL: n1 = (n1 != n2); break;
1628 case EXPR_GREATER: n1 = (n1 > n2); break;
1629 case EXPR_GEQUAL: n1 = (n1 >= n2); break;
1630 case EXPR_SMALLER: n1 = (n1 < n2); break;
1631 case EXPR_SEQUAL: n1 = (n1 <= n2); break;
1632 case EXPR_UNKNOWN:
1633 case EXPR_MATCH:
1634 default: break; // avoid gcc warning
1635 }
1636 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001637 else if (in_vim9script() && (tv1->v_type == VAR_BOOL
1638 || tv2->v_type == VAR_BOOL
1639 || (tv1->v_type == VAR_SPECIAL
1640 && tv2->v_type == VAR_SPECIAL)))
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001641 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001642 if (tv1->v_type != tv2->v_type)
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001643 {
1644 semsg(_(e_cannot_compare_str_with_str),
Bram Moolenaar265f8112021-12-19 12:33:05 +00001645 vartype_name(tv1->v_type), vartype_name(tv2->v_type));
1646 clear_tv(tv1);
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001647 return FAIL;
1648 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001649 n1 = tv1->vval.v_number;
1650 n2 = tv2->vval.v_number;
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001651 switch (type)
1652 {
1653 case EXPR_IS:
1654 case EXPR_EQUAL: n1 = (n1 == n2); break;
1655 case EXPR_ISNOT:
1656 case EXPR_NEQUAL: n1 = (n1 != n2); break;
1657 default:
Bram Moolenaar0c357522021-07-18 14:43:43 +02001658 semsg(_(e_invalid_operation_for_str),
Bram Moolenaar265f8112021-12-19 12:33:05 +00001659 vartype_name(tv1->v_type));
1660 clear_tv(tv1);
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001661 return FAIL;
1662 }
1663 }
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01001664#ifdef FEAT_JOB_CHANNEL
1665 else if (tv1->v_type == tv2->v_type
1666 && (tv1->v_type == VAR_CHANNEL || tv1->v_type == VAR_JOB)
1667 && (type == EXPR_NEQUAL || type == EXPR_EQUAL))
1668 {
1669 if (tv1->v_type == VAR_CHANNEL)
1670 n1 = tv1->vval.v_channel == tv2->vval.v_channel;
1671 else
1672 n1 = tv1->vval.v_job == tv2->vval.v_job;
1673 if (type == EXPR_NEQUAL)
1674 n1 = !n1;
1675 }
1676#endif
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001677 else
1678 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001679 if (typval_compare_string(tv1, tv2, type, ic, &res) == FAIL)
Bram Moolenaar0c357522021-07-18 14:43:43 +02001680 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001681 clear_tv(tv1);
Bram Moolenaar0c357522021-07-18 14:43:43 +02001682 return FAIL;
1683 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001684 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001685 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001686 clear_tv(tv1);
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02001687 if (in_vim9script())
1688 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001689 tv1->v_type = VAR_BOOL;
1690 tv1->vval.v_number = n1 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02001691 }
1692 else
1693 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001694 tv1->v_type = VAR_NUMBER;
1695 tv1->vval.v_number = n1;
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02001696 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001697
1698 return OK;
1699}
1700
Bram Moolenaar34453202021-01-31 13:08:38 +01001701/*
dundargocc57b5bc2022-11-02 13:30:51 +00001702 * Compare "tv1" to "tv2" as lists according to "type" and "ic".
Bram Moolenaar265f8112021-12-19 12:33:05 +00001703 * Put the result, false or true, in "res".
1704 * Return FAIL and give an error message when the comparison can't be done.
1705 */
1706 int
1707typval_compare_list(
1708 typval_T *tv1,
1709 typval_T *tv2,
1710 exprtype_T type,
1711 int ic,
1712 int *res)
1713{
1714 int val = 0;
1715
1716 if (type == EXPR_IS || type == EXPR_ISNOT)
1717 {
1718 val = (tv1->v_type == tv2->v_type
1719 && tv1->vval.v_list == tv2->vval.v_list);
1720 if (type == EXPR_ISNOT)
1721 val = !val;
1722 }
1723 else if (tv1->v_type != tv2->v_type
1724 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
1725 {
1726 if (tv1->v_type != tv2->v_type)
Bram Moolenaara6f79292022-01-04 21:30:47 +00001727 emsg(_(e_can_only_compare_list_with_list));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001728 else
Bram Moolenaara6f79292022-01-04 21:30:47 +00001729 emsg(_(e_invalid_operation_for_list));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001730 return FAIL;
1731 }
1732 else
1733 {
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001734 val = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
Bram Moolenaar265f8112021-12-19 12:33:05 +00001735 if (type == EXPR_NEQUAL)
1736 val = !val;
1737 }
1738 *res = val;
1739 return OK;
1740}
1741
1742/*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001743 * Compare "tv1" to "tv2" as tuples according to "type" and "ic".
1744 * Put the result, false or true, in "res".
1745 * Return FAIL and give an error message when the comparison can't be done.
1746 */
1747 int
1748typval_compare_tuple(
1749 typval_T *tv1,
1750 typval_T *tv2,
1751 exprtype_T type,
1752 int ic,
1753 int *res)
1754{
1755 int val = 0;
1756
1757 if (type == EXPR_IS || type == EXPR_ISNOT)
1758 {
1759 val = (tv1->v_type == tv2->v_type
1760 && tv1->vval.v_tuple == tv2->vval.v_tuple);
1761 if (type == EXPR_ISNOT)
1762 val = !val;
1763 }
1764 else if (tv1->v_type != tv2->v_type
1765 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
1766 {
1767 if (tv1->v_type != tv2->v_type)
1768 emsg(_(e_can_only_compare_tuple_with_tuple));
1769 else
1770 emsg(_(e_invalid_operation_for_tuple));
1771 return FAIL;
1772 }
1773 else
1774 {
1775 val = tuple_equal(tv1->vval.v_tuple, tv2->vval.v_tuple, ic);
1776 if (type == EXPR_NEQUAL)
1777 val = !val;
1778 }
1779 *res = val;
1780 return OK;
1781}
1782
1783/*
Bram Moolenaarf3507a52022-03-09 11:56:21 +00001784 * Compare v:null with another type. Return TRUE if the value is NULL.
Bram Moolenaar7a222242022-03-01 19:23:24 +00001785 */
1786 int
1787typval_compare_null(typval_T *tv1, typval_T *tv2)
1788{
1789 if ((tv1->v_type == VAR_SPECIAL && tv1->vval.v_number == VVAL_NULL)
1790 || (tv2->v_type == VAR_SPECIAL && tv2->vval.v_number == VVAL_NULL))
1791 {
1792 typval_T *tv = tv1->v_type == VAR_SPECIAL ? tv2 : tv1;
1793
1794 switch (tv->v_type)
1795 {
1796 case VAR_BLOB: return tv->vval.v_blob == NULL;
Bram Moolenaarf6b0c792022-03-01 19:52:48 +00001797#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar7a222242022-03-01 19:23:24 +00001798 case VAR_CHANNEL: return tv->vval.v_channel == NULL;
Bram Moolenaarf6b0c792022-03-01 19:52:48 +00001799#endif
Ernie Rael5c018be2023-08-27 18:40:26 +02001800 // TODO: null_class handling
1801 // case VAR_CLASS: return tv->vval.v_class == NULL;
Bram Moolenaar7a222242022-03-01 19:23:24 +00001802 case VAR_DICT: return tv->vval.v_dict == NULL;
1803 case VAR_FUNC: return tv->vval.v_string == NULL;
Bram Moolenaarf6b0c792022-03-01 19:52:48 +00001804#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar7a222242022-03-01 19:23:24 +00001805 case VAR_JOB: return tv->vval.v_job == NULL;
Bram Moolenaarf6b0c792022-03-01 19:52:48 +00001806#endif
Bram Moolenaar7a222242022-03-01 19:23:24 +00001807 case VAR_LIST: return tv->vval.v_list == NULL;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001808 case VAR_TUPLE: return tv->vval.v_tuple == NULL;
Ernie Rael5c018be2023-08-27 18:40:26 +02001809 case VAR_OBJECT: return tv->vval.v_object == NULL;
Bram Moolenaar7a222242022-03-01 19:23:24 +00001810 case VAR_PARTIAL: return tv->vval.v_partial == NULL;
1811 case VAR_STRING: return tv->vval.v_string == NULL;
Bram Moolenaarc6e9d702022-03-02 13:13:30 +00001812
1813 case VAR_NUMBER: if (!in_vim9script())
1814 return tv->vval.v_number == 0;
1815 break;
Bram Moolenaarc6e9d702022-03-02 13:13:30 +00001816 case VAR_FLOAT: if (!in_vim9script())
1817 return tv->vval.v_float == 0.0;
1818 break;
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02001819 case VAR_TYPEALIAS: return tv->vval.v_typealias == NULL;
Bram Moolenaar7a222242022-03-01 19:23:24 +00001820 default: break;
1821 }
1822 }
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01001823 // although comparing null with number, float or bool is not very useful
Bram Moolenaar05667812022-03-15 20:21:33 +00001824 // we won't give an error
1825 return FALSE;
Bram Moolenaar7a222242022-03-01 19:23:24 +00001826}
1827
1828/*
dundargocc57b5bc2022-11-02 13:30:51 +00001829 * Compare "tv1" to "tv2" as blobs according to "type".
Bram Moolenaar265f8112021-12-19 12:33:05 +00001830 * Put the result, false or true, in "res".
1831 * Return FAIL and give an error message when the comparison can't be done.
1832 */
1833 int
1834typval_compare_blob(
1835 typval_T *tv1,
1836 typval_T *tv2,
1837 exprtype_T type,
1838 int *res)
1839{
1840 int val = 0;
1841
1842 if (type == EXPR_IS || type == EXPR_ISNOT)
1843 {
1844 val = (tv1->v_type == tv2->v_type
1845 && tv1->vval.v_blob == tv2->vval.v_blob);
1846 if (type == EXPR_ISNOT)
1847 val = !val;
1848 }
1849 else if (tv1->v_type != tv2->v_type
1850 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
1851 {
1852 if (tv1->v_type != tv2->v_type)
Bram Moolenaard82a47d2022-01-05 20:24:39 +00001853 emsg(_(e_can_only_compare_blob_with_blob));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001854 else
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00001855 emsg(_(e_invalid_operation_for_blob));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001856 return FAIL;
1857 }
1858 else
1859 {
1860 val = blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
1861 if (type == EXPR_NEQUAL)
1862 val = !val;
1863 }
1864 *res = val;
1865 return OK;
1866}
1867
1868/*
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001869 * Compare "tv1" to "tv2" as objects according to "type".
1870 * Put the result, false or true, in "res".
1871 * Return FAIL and give an error message when the comparison can't be done.
1872 */
1873 int
1874typval_compare_object(
1875 typval_T *tv1,
1876 typval_T *tv2,
1877 exprtype_T type,
1878 int ic,
1879 int *res)
1880{
1881 int res_match = type == EXPR_EQUAL || type == EXPR_IS ? TRUE : FALSE;
1882
1883 if (tv1->vval.v_object == NULL && tv2->vval.v_object == NULL)
1884 {
1885 *res = res_match;
1886 return OK;
1887 }
1888 if (tv1->vval.v_object == NULL || tv2->vval.v_object == NULL)
1889 {
1890 *res = !res_match;
1891 return OK;
1892 }
1893
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001894 object_T *obj1 = tv1->vval.v_object;
1895 object_T *obj2 = tv2->vval.v_object;
1896 if (type == EXPR_IS || type == EXPR_ISNOT)
1897 {
1898 *res = obj1 == obj2 ? res_match : !res_match;
1899 return OK;
1900 }
1901
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001902 *res = object_equal(obj1, obj2, ic) ? res_match : !res_match;
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001903 return OK;
1904}
1905
1906/*
dundargocc57b5bc2022-11-02 13:30:51 +00001907 * Compare "tv1" to "tv2" as dictionaries according to "type" and "ic".
Bram Moolenaar265f8112021-12-19 12:33:05 +00001908 * Put the result, false or true, in "res".
1909 * Return FAIL and give an error message when the comparison can't be done.
1910 */
1911 int
1912typval_compare_dict(
1913 typval_T *tv1,
1914 typval_T *tv2,
1915 exprtype_T type,
1916 int ic,
1917 int *res)
1918{
1919 int val;
1920
1921 if (type == EXPR_IS || type == EXPR_ISNOT)
1922 {
1923 val = (tv1->v_type == tv2->v_type
1924 && tv1->vval.v_dict == tv2->vval.v_dict);
1925 if (type == EXPR_ISNOT)
1926 val = !val;
1927 }
1928 else if (tv1->v_type != tv2->v_type
1929 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
1930 {
1931 if (tv1->v_type != tv2->v_type)
Bram Moolenaara6f79292022-01-04 21:30:47 +00001932 emsg(_(e_can_only_compare_dictionary_with_dictionary));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001933 else
Bram Moolenaara6f79292022-01-04 21:30:47 +00001934 emsg(_(e_invalid_operation_for_dictionary));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001935 return FAIL;
1936 }
1937 else
1938 {
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001939 val = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
Bram Moolenaar265f8112021-12-19 12:33:05 +00001940 if (type == EXPR_NEQUAL)
1941 val = !val;
1942 }
1943 *res = val;
1944 return OK;
1945}
1946
1947/*
dundargocc57b5bc2022-11-02 13:30:51 +00001948 * Compare "tv1" to "tv2" as funcrefs according to "type" and "ic".
Bram Moolenaar265f8112021-12-19 12:33:05 +00001949 * Put the result, false or true, in "res".
1950 * Return FAIL and give an error message when the comparison can't be done.
1951 */
1952 int
1953typval_compare_func(
1954 typval_T *tv1,
1955 typval_T *tv2,
1956 exprtype_T type,
1957 int ic,
1958 int *res)
1959{
1960 int val = 0;
1961
1962 if (type != EXPR_EQUAL && type != EXPR_NEQUAL
1963 && type != EXPR_IS && type != EXPR_ISNOT)
1964 {
Bram Moolenaara6f79292022-01-04 21:30:47 +00001965 emsg(_(e_invalid_operation_for_funcrefs));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001966 return FAIL;
1967 }
1968 if ((tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial == NULL)
1969 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial == NULL))
1970 // When both partials are NULL, then they are equal.
1971 // Otherwise they are not equal.
1972 val = (tv1->vval.v_partial == tv2->vval.v_partial);
1973 else if (type == EXPR_IS || type == EXPR_ISNOT)
1974 {
1975 if (tv1->v_type == VAR_FUNC && tv2->v_type == VAR_FUNC)
1976 // strings are considered the same if their value is
1977 // the same
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001978 val = tv_equal(tv1, tv2, ic);
Bram Moolenaar265f8112021-12-19 12:33:05 +00001979 else if (tv1->v_type == VAR_PARTIAL && tv2->v_type == VAR_PARTIAL)
1980 val = (tv1->vval.v_partial == tv2->vval.v_partial);
1981 else
1982 val = FALSE;
1983 }
1984 else
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001985 val = tv_equal(tv1, tv2, ic);
Bram Moolenaar265f8112021-12-19 12:33:05 +00001986 if (type == EXPR_NEQUAL || type == EXPR_ISNOT)
1987 val = !val;
1988 *res = val;
1989 return OK;
1990}
1991
1992/*
1993 * Compare "tv1" to "tv2" as strings according to "type" and "ic".
1994 * Put the result, false or true, in "res".
1995 * Return FAIL and give an error message when the comparison can't be done.
1996 */
1997 int
1998typval_compare_string(
1999 typval_T *tv1,
2000 typval_T *tv2,
2001 exprtype_T type,
2002 int ic,
2003 int *res)
2004{
2005 int i = 0;
2006 int val = FALSE;
2007 char_u *s1, *s2;
2008 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2009
2010 if (in_vim9script()
2011 && ((tv1->v_type != VAR_STRING && tv1->v_type != VAR_SPECIAL)
2012 || (tv2->v_type != VAR_STRING && tv2->v_type != VAR_SPECIAL)))
2013 {
2014 semsg(_(e_cannot_compare_str_with_str),
2015 vartype_name(tv1->v_type), vartype_name(tv2->v_type));
2016 return FAIL;
2017 }
2018 s1 = tv_get_string_buf(tv1, buf1);
2019 s2 = tv_get_string_buf(tv2, buf2);
2020 if (type != EXPR_MATCH && type != EXPR_NOMATCH)
2021 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
2022 switch (type)
2023 {
Bram Moolenaarf8691002022-03-10 12:20:53 +00002024 case EXPR_IS: if (in_vim9script())
2025 {
2026 // Really check it is the same string, not just
2027 // the same value.
2028 val = tv1->vval.v_string == tv2->vval.v_string;
2029 break;
2030 }
2031 // FALLTHROUGH
Bram Moolenaar265f8112021-12-19 12:33:05 +00002032 case EXPR_EQUAL: val = (i == 0); break;
Bram Moolenaarf8691002022-03-10 12:20:53 +00002033 case EXPR_ISNOT: if (in_vim9script())
2034 {
2035 // Really check it is not the same string, not
2036 // just a different value.
2037 val = tv1->vval.v_string != tv2->vval.v_string;
2038 break;
2039 }
2040 // FALLTHROUGH
Bram Moolenaar265f8112021-12-19 12:33:05 +00002041 case EXPR_NEQUAL: val = (i != 0); break;
2042 case EXPR_GREATER: val = (i > 0); break;
2043 case EXPR_GEQUAL: val = (i >= 0); break;
2044 case EXPR_SMALLER: val = (i < 0); break;
2045 case EXPR_SEQUAL: val = (i <= 0); break;
2046
2047 case EXPR_MATCH:
2048 case EXPR_NOMATCH:
2049 val = pattern_match(s2, s1, ic);
2050 if (type == EXPR_NOMATCH)
2051 val = !val;
2052 break;
2053
2054 default: break; // avoid gcc warning
2055 }
2056 *res = val;
2057 return OK;
2058}
2059/*
Bram Moolenaar34453202021-01-31 13:08:38 +01002060 * Convert any type to a string, never give an error.
2061 * When "quotes" is TRUE add quotes to a string.
2062 * Returns an allocated string.
2063 */
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002064 char_u *
Bram Moolenaar34453202021-01-31 13:08:38 +01002065typval_tostring(typval_T *arg, int quotes)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002066{
2067 char_u *tofree;
2068 char_u numbuf[NUMBUFLEN];
2069 char_u *ret = NULL;
2070
2071 if (arg == NULL)
2072 return vim_strsave((char_u *)"(does not exist)");
Bram Moolenaar34453202021-01-31 13:08:38 +01002073 if (!quotes && arg->v_type == VAR_STRING)
2074 {
2075 ret = vim_strsave(arg->vval.v_string == NULL ? (char_u *)""
2076 : arg->vval.v_string);
2077 }
2078 else
2079 {
2080 ret = tv2string(arg, &tofree, numbuf, 0);
2081 // Make a copy if we have a value but it's not in allocated memory.
2082 if (ret != NULL && tofree == NULL)
2083 ret = vim_strsave(ret);
2084 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002085 return ret;
2086}
2087
2088/*
2089 * Return TRUE if typeval "tv" is locked: Either that value is locked itself
2090 * or it refers to a List or Dictionary that is locked.
2091 */
2092 int
2093tv_islocked(typval_T *tv)
2094{
2095 return (tv->v_lock & VAR_LOCKED)
2096 || (tv->v_type == VAR_LIST
2097 && tv->vval.v_list != NULL
2098 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01002099 || (tv->v_type == VAR_TUPLE
2100 && tv->vval.v_tuple != NULL
2101 && (tv->vval.v_tuple->tv_lock & VAR_LOCKED))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002102 || (tv->v_type == VAR_DICT
2103 && tv->vval.v_dict != NULL
2104 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
2105}
2106
2107 static int
2108func_equal(
2109 typval_T *tv1,
2110 typval_T *tv2,
2111 int ic) // ignore case
2112{
2113 char_u *s1, *s2;
2114 dict_T *d1, *d2;
2115 int a1, a2;
2116 int i;
2117
2118 // empty and NULL function name considered the same
2119 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
2120 : partial_name(tv1->vval.v_partial);
2121 if (s1 != NULL && *s1 == NUL)
2122 s1 = NULL;
2123 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
2124 : partial_name(tv2->vval.v_partial);
2125 if (s2 != NULL && *s2 == NUL)
2126 s2 = NULL;
2127 if (s1 == NULL || s2 == NULL)
2128 {
2129 if (s1 != s2)
2130 return FALSE;
2131 }
2132 else if (STRCMP(s1, s2) != 0)
2133 return FALSE;
2134
2135 // empty dict and NULL dict is different
2136 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
2137 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
2138 if (d1 == NULL || d2 == NULL)
2139 {
2140 if (d1 != d2)
2141 return FALSE;
2142 }
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002143 else if (!dict_equal(d1, d2, ic))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002144 return FALSE;
2145
2146 // empty list and no list considered the same
2147 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
2148 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
2149 if (a1 != a2)
2150 return FALSE;
2151 for (i = 0; i < a1; ++i)
2152 if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002153 tv2->vval.v_partial->pt_argv + i, ic))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002154 return FALSE;
2155
2156 return TRUE;
2157}
2158
2159/*
2160 * Return TRUE if "tv1" and "tv2" have the same value.
2161 * Compares the items just like "==" would compare them, but strings and
2162 * numbers are different. Floats and numbers are also different.
2163 */
2164 int
2165tv_equal(
2166 typval_T *tv1,
2167 typval_T *tv2,
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002168 int ic) // ignore case
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002169{
2170 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2171 char_u *s1, *s2;
2172 static int recursive_cnt = 0; // catch recursive loops
2173 int r;
2174 static int tv_equal_recurse_limit;
2175
2176 // Catch lists and dicts that have an endless loop by limiting
2177 // recursiveness to a limit. We guess they are equal then.
2178 // A fixed limit has the problem of still taking an awful long time.
2179 // Reduce the limit every time running into it. That should work fine for
2180 // deeply linked structures that are not recursively linked and catch
2181 // recursiveness quickly.
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002182 if (recursive_cnt == 0)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002183 tv_equal_recurse_limit = 1000;
2184 if (recursive_cnt >= tv_equal_recurse_limit)
2185 {
2186 --tv_equal_recurse_limit;
2187 return TRUE;
2188 }
2189
2190 // For VAR_FUNC and VAR_PARTIAL compare the function name, bound dict and
2191 // arguments.
2192 if ((tv1->v_type == VAR_FUNC
2193 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
2194 && (tv2->v_type == VAR_FUNC
2195 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
2196 {
2197 ++recursive_cnt;
2198 r = func_equal(tv1, tv2, ic);
2199 --recursive_cnt;
2200 return r;
2201 }
2202
Bram Moolenaar418a29f2021-02-10 22:23:41 +01002203 if (tv1->v_type != tv2->v_type
2204 && ((tv1->v_type != VAR_BOOL && tv1->v_type != VAR_SPECIAL)
2205 || (tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL)))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002206 return FALSE;
2207
2208 switch (tv1->v_type)
2209 {
2210 case VAR_LIST:
2211 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002212 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002213 --recursive_cnt;
2214 return r;
2215
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01002216 case VAR_TUPLE:
2217 ++recursive_cnt;
2218 r = tuple_equal(tv1->vval.v_tuple, tv2->vval.v_tuple, ic);
2219 --recursive_cnt;
2220 return r;
2221
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002222 case VAR_DICT:
2223 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002224 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002225 --recursive_cnt;
2226 return r;
2227
2228 case VAR_BLOB:
2229 return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
2230
2231 case VAR_NUMBER:
2232 case VAR_BOOL:
2233 case VAR_SPECIAL:
2234 return tv1->vval.v_number == tv2->vval.v_number;
2235
2236 case VAR_STRING:
2237 s1 = tv_get_string_buf(tv1, buf1);
2238 s2 = tv_get_string_buf(tv2, buf2);
2239 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
2240
2241 case VAR_FLOAT:
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002242 return tv1->vval.v_float == tv2->vval.v_float;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002243 case VAR_JOB:
2244#ifdef FEAT_JOB_CHANNEL
2245 return tv1->vval.v_job == tv2->vval.v_job;
2246#endif
2247 case VAR_CHANNEL:
2248#ifdef FEAT_JOB_CHANNEL
2249 return tv1->vval.v_channel == tv2->vval.v_channel;
2250#endif
Bram Moolenaarf18332f2021-05-07 17:55:55 +02002251 case VAR_INSTR:
2252 return tv1->vval.v_instr == tv2->vval.v_instr;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002253
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002254 case VAR_CLASS:
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00002255 // A class only exists once, equality is identity.
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002256 return tv1->vval.v_class == tv2->vval.v_class;
2257
2258 case VAR_OBJECT:
Ernie Raelf0e69142024-06-22 11:12:00 +02002259 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002260 r = object_equal(tv1->vval.v_object, tv2->vval.v_object, ic);
Ernie Raelf0e69142024-06-22 11:12:00 +02002261 --recursive_cnt;
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00002262 return r;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002263
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002264 case VAR_PARTIAL:
2265 return tv1->vval.v_partial == tv2->vval.v_partial;
2266
2267 case VAR_FUNC:
2268 return tv1->vval.v_string == tv2->vval.v_string;
2269
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02002270 case VAR_TYPEALIAS:
2271 return tv1->vval.v_typealias == tv2->vval.v_typealias;
2272
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002273 case VAR_UNKNOWN:
2274 case VAR_ANY:
2275 case VAR_VOID:
2276 break;
2277 }
2278
2279 // VAR_UNKNOWN can be the result of a invalid expression, let's say it
2280 // does not equal anything, not even itself.
2281 return FALSE;
2282}
2283
2284/*
2285 * Get an option value.
2286 * "arg" points to the '&' or '+' before the option name.
2287 * "arg" is advanced to character after the option name.
2288 * Return OK or FAIL.
2289 */
2290 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002291eval_option(
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002292 char_u **arg,
2293 typval_T *rettv, // when NULL, only check if option exists
2294 int evaluate)
2295{
2296 char_u *option_end;
2297 long numval;
2298 char_u *stringval;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002299 getoption_T opt_type;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002300 int c;
2301 int working = (**arg == '+'); // has("+option")
2302 int ret = OK;
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002303 int scope;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002304
2305 // Isolate the option name and find its value.
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002306 option_end = find_option_end(arg, &scope);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002307 if (option_end == NULL)
2308 {
2309 if (rettv != NULL)
Bram Moolenaare1242042021-12-16 20:56:57 +00002310 semsg(_(e_option_name_missing_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002311 return FAIL;
2312 }
2313
2314 if (!evaluate)
2315 {
2316 *arg = option_end;
2317 return OK;
2318 }
2319
2320 c = *option_end;
2321 *option_end = NUL;
2322 opt_type = get_option_value(*arg, &numval,
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002323 rettv == NULL ? NULL : &stringval, NULL, scope);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002324
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002325 if (opt_type == gov_unknown)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002326 {
2327 if (rettv != NULL)
Bram Moolenaare1242042021-12-16 20:56:57 +00002328 semsg(_(e_unknown_option_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002329 ret = FAIL;
2330 }
2331 else if (rettv != NULL)
2332 {
Bram Moolenaara79925a2021-01-05 17:50:28 +01002333 rettv->v_lock = 0;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002334 if (opt_type == gov_hidden_string)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002335 {
2336 rettv->v_type = VAR_STRING;
2337 rettv->vval.v_string = NULL;
2338 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002339 else if (opt_type == gov_hidden_bool || opt_type == gov_hidden_number)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002340 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002341 rettv->v_type = in_vim9script() && opt_type == gov_hidden_bool
2342 ? VAR_BOOL : VAR_NUMBER;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002343 rettv->vval.v_number = 0;
2344 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002345 else if (opt_type == gov_bool || opt_type == gov_number)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002346 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002347 if (in_vim9script() && opt_type == gov_bool)
2348 {
2349 rettv->v_type = VAR_BOOL;
2350 rettv->vval.v_number = numval ? VVAL_TRUE : VVAL_FALSE;
2351 }
2352 else
2353 {
2354 rettv->v_type = VAR_NUMBER;
2355 rettv->vval.v_number = numval;
2356 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002357 }
2358 else // string option
2359 {
2360 rettv->v_type = VAR_STRING;
2361 rettv->vval.v_string = stringval;
2362 }
2363 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002364 else if (working && (opt_type == gov_hidden_bool
2365 || opt_type == gov_hidden_number
2366 || opt_type == gov_hidden_string))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002367 ret = FAIL;
2368
2369 *option_end = c; // put back for error messages
2370 *arg = option_end;
2371
2372 return ret;
2373}
2374
2375/*
2376 * Allocate a variable for a number constant. Also deals with "0z" for blob.
2377 * Return OK or FAIL.
2378 */
2379 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002380eval_number(
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002381 char_u **arg,
2382 typval_T *rettv,
2383 int evaluate,
Dominique Pellé0268ff32024-07-28 21:12:20 +02002384 int want_string)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002385{
2386 int len;
Bram Moolenaardd9de502021-08-15 13:49:42 +02002387 int skip_quotes = !in_old_script(4);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002388 char_u *p;
2389 int get_float = FALSE;
2390
2391 // We accept a float when the format matches
2392 // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
2393 // strict to avoid backwards compatibility problems.
2394 // With script version 2 and later the leading digit can be
2395 // omitted.
2396 // Don't look for a float after the "." operator, so that
2397 // ":let vers = 1.2.3" doesn't fail.
2398 if (**arg == '.')
2399 p = *arg;
2400 else
Bram Moolenaar29500652021-08-08 15:43:34 +02002401 {
2402 p = *arg + 1;
2403 if (skip_quotes)
2404 for (;;)
2405 {
2406 if (*p == '\'')
2407 ++p;
2408 if (!vim_isdigit(*p))
2409 break;
2410 p = skipdigits(p);
2411 }
2412 else
2413 p = skipdigits(p);
2414 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002415 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
2416 {
2417 get_float = TRUE;
2418 p = skipdigits(p + 2);
2419 if (*p == 'e' || *p == 'E')
2420 {
2421 ++p;
2422 if (*p == '-' || *p == '+')
2423 ++p;
2424 if (!vim_isdigit(*p))
2425 get_float = FALSE;
2426 else
2427 p = skipdigits(p + 1);
2428 }
2429 if (ASCII_ISALPHA(*p) || *p == '.')
2430 get_float = FALSE;
2431 }
2432 if (get_float)
2433 {
2434 float_T f;
2435
Bram Moolenaar29500652021-08-08 15:43:34 +02002436 *arg += string2float(*arg, &f, skip_quotes);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002437 if (evaluate)
2438 {
2439 rettv->v_type = VAR_FLOAT;
2440 rettv->vval.v_float = f;
2441 }
2442 }
2443 else
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002444 if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z'))
2445 {
2446 char_u *bp;
2447 blob_T *blob = NULL; // init for gcc
2448
2449 // Blob constant: 0z0123456789abcdef
2450 if (evaluate)
2451 blob = blob_alloc();
2452 for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2)
2453 {
2454 if (!vim_isxdigit(bp[1]))
2455 {
2456 if (blob != NULL)
2457 {
Bram Moolenaard82a47d2022-01-05 20:24:39 +00002458 emsg(_(e_blob_literal_should_have_an_even_number_of_hex_characters));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002459 ga_clear(&blob->bv_ga);
2460 VIM_CLEAR(blob);
2461 }
2462 return FAIL;
2463 }
2464 if (blob != NULL)
2465 ga_append(&blob->bv_ga,
2466 (hex2nr(*bp) << 4) + hex2nr(*(bp+1)));
2467 if (bp[2] == '.' && vim_isxdigit(bp[3]))
2468 ++bp;
2469 }
2470 if (blob != NULL)
2471 rettv_blob_set(rettv, blob);
2472 *arg = bp;
2473 }
2474 else
2475 {
2476 varnumber_T n;
2477
2478 // decimal, hex or octal number
Bram Moolenaar29500652021-08-08 15:43:34 +02002479 vim_str2nr(*arg, NULL, &len, skip_quotes
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002480 ? STR2NR_NO_OCT + STR2NR_QUOTE
Bram Moolenaar5fb78c32023-03-04 20:47:39 +00002481 : STR2NR_ALL, &n, NULL, 0, TRUE, NULL);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002482 if (len == 0)
2483 {
Bram Moolenaar98cb90e2021-11-30 11:56:22 +00002484 if (evaluate)
2485 semsg(_(e_invalid_expression_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002486 return FAIL;
2487 }
2488 *arg += len;
2489 if (evaluate)
2490 {
2491 rettv->v_type = VAR_NUMBER;
2492 rettv->vval.v_number = n;
2493 }
2494 }
2495 return OK;
2496}
2497
2498/*
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002499 * Evaluate a string constant and put the result in "rettv".
2500 * "*arg" points to the double quote or to after it when "interpolate" is TRUE.
2501 * When "interpolate" is TRUE reduce "{{" to "{", reduce "}}" to "}" and stop
2502 * at a single "{".
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002503 * Return OK or FAIL.
2504 */
2505 int
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002506eval_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002507{
2508 char_u *p;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002509 char_u *end;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002510 int extra = interpolate ? 1 : 0;
2511 int off = interpolate ? 0 : 1;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002512 int len;
2513
2514 // Find the end of the string, skipping backslashed characters.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002515 for (p = *arg + off; *p != NUL && *p != '"'; MB_PTR_ADV(p))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002516 {
2517 if (*p == '\\' && p[1] != NUL)
2518 {
2519 ++p;
2520 // A "\<x>" form occupies at least 4 characters, and produces up
zeertzjqdb088872022-05-02 22:53:45 +01002521 // to 9 characters (6 for the char and 3 for a modifier):
2522 // reserve space for 5 extra.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002523 if (*p == '<')
Bram Moolenaar1e56bda2022-07-29 15:28:27 +01002524 {
2525 int modifiers = 0;
2526 int flags = FSK_KEYCODE | FSK_IN_STRING;
2527
zeertzjqdb088872022-05-02 22:53:45 +01002528 extra += 5;
Bram Moolenaar1e56bda2022-07-29 15:28:27 +01002529
2530 // Skip to the '>' to avoid using '{' inside for string
2531 // interpolation.
2532 if (p[1] != '*')
2533 flags |= FSK_SIMPLIFY;
2534 if (find_special_key(&p, &modifiers, flags, NULL) != 0)
2535 --p; // leave "p" on the ">"
2536 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002537 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002538 else if (interpolate && (*p == '{' || *p == '}'))
2539 {
2540 if (*p == '{' && p[1] != '{') // start of expression
2541 break;
2542 ++p;
2543 if (p[-1] == '}' && *p != '}') // single '}' is an error
2544 {
2545 semsg(_(e_stray_closing_curly_str), *arg);
2546 return FAIL;
2547 }
2548 --extra; // "{{" becomes "{", "}}" becomes "}"
2549 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002550 }
2551
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002552 if (*p != '"' && !(interpolate && *p == '{'))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002553 {
Bram Moolenaare1242042021-12-16 20:56:57 +00002554 semsg(_(e_missing_double_quote_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002555 return FAIL;
2556 }
2557
2558 // If only parsing, set *arg and return here
2559 if (!evaluate)
2560 {
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002561 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002562 return OK;
2563 }
2564
2565 // Copy the string into allocated memory, handling backslashed
2566 // characters.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002567 rettv->v_type = VAR_STRING;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002568 len = (int)(p - *arg + extra);
2569 rettv->vval.v_string = alloc(len);
2570 if (rettv->vval.v_string == NULL)
2571 return FAIL;
2572 end = rettv->vval.v_string;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002573
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002574 for (p = *arg + off; *p != NUL && *p != '"'; )
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002575 {
2576 if (*p == '\\')
2577 {
2578 switch (*++p)
2579 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002580 case 'b': *end++ = BS; ++p; break;
2581 case 'e': *end++ = ESC; ++p; break;
2582 case 'f': *end++ = FF; ++p; break;
2583 case 'n': *end++ = NL; ++p; break;
2584 case 'r': *end++ = CAR; ++p; break;
2585 case 't': *end++ = TAB; ++p; break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002586
2587 case 'X': // hex: "\x1", "\x12"
2588 case 'x':
2589 case 'u': // Unicode: "\u0023"
2590 case 'U':
2591 if (vim_isxdigit(p[1]))
2592 {
2593 int n, nr;
Keith Thompson184f71c2024-01-04 21:19:04 +01002594 int c = SAFE_toupper(*p);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002595
2596 if (c == 'X')
2597 n = 2;
2598 else if (*p == 'u')
2599 n = 4;
2600 else
2601 n = 8;
2602 nr = 0;
2603 while (--n >= 0 && vim_isxdigit(p[1]))
2604 {
2605 ++p;
2606 nr = (nr << 4) + hex2nr(*p);
2607 }
2608 ++p;
2609 // For "\u" store the number according to
2610 // 'encoding'.
2611 if (c != 'X')
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002612 end += (*mb_char2bytes)(nr, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002613 else
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002614 *end++ = nr;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002615 }
2616 break;
2617
2618 // octal: "\1", "\12", "\123"
2619 case '0':
2620 case '1':
2621 case '2':
2622 case '3':
2623 case '4':
2624 case '5':
2625 case '6':
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002626 case '7': *end = *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002627 if (*p >= '0' && *p <= '7')
2628 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002629 *end = (*end << 3) + *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002630 if (*p >= '0' && *p <= '7')
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002631 *end = (*end << 3) + *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002632 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002633 ++end;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002634 break;
2635
Bram Moolenaarfccd93f2020-05-31 22:06:51 +02002636 // Special key, e.g.: "\<C-W>"
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002637 case '<':
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002638 {
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002639 int flags = FSK_KEYCODE | FSK_IN_STRING;
2640
Bram Moolenaarfccd93f2020-05-31 22:06:51 +02002641 if (p[1] != '*')
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002642 flags |= FSK_SIMPLIFY;
zeertzjqdb088872022-05-02 22:53:45 +01002643 extra = trans_special(&p, end, flags, FALSE, NULL);
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002644 if (extra != 0)
2645 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002646 end += extra;
2647 if (end >= rettv->vval.v_string + len)
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002648 iemsg("eval_string() used more space than allocated");
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002649 break;
2650 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002651 }
2652 // FALLTHROUGH
2653
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002654 default: MB_COPY_CHAR(p, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002655 break;
2656 }
2657 }
2658 else
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002659 {
2660 if (interpolate && (*p == '{' || *p == '}'))
2661 {
2662 if (*p == '{' && p[1] != '{') // start of expression
2663 break;
2664 ++p; // reduce "{{" to "{" and "}}" to "}"
2665 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002666 MB_COPY_CHAR(p, end);
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002667 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002668 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002669 *end = NUL;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002670 if (*p == '"' && !interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002671 ++p;
2672 *arg = p;
2673
2674 return OK;
2675}
2676
2677/*
2678 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002679 * When "interpolate" is TRUE reduce "{{" to "{" and stop at a single "{".
2680 * Return OK when a "rettv" was set to the string.
2681 * Return FAIL on error, "rettv" is not set.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002682 */
2683 int
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002684eval_lit_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002685{
2686 char_u *p;
2687 char_u *str;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002688 int reduce = interpolate ? -1 : 0;
2689 int off = interpolate ? 0 : 1;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002690
2691 // Find the end of the string, skipping ''.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002692 for (p = *arg + off; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002693 {
2694 if (*p == '\'')
2695 {
2696 if (p[1] != '\'')
2697 break;
2698 ++reduce;
2699 ++p;
2700 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002701 else if (interpolate)
2702 {
2703 if (*p == '{')
2704 {
2705 if (p[1] != '{')
2706 break;
2707 ++p;
2708 ++reduce;
2709 }
2710 else if (*p == '}')
2711 {
2712 ++p;
2713 if (*p != '}')
2714 {
2715 semsg(_(e_stray_closing_curly_str), *arg);
2716 return FAIL;
2717 }
2718 ++reduce;
2719 }
2720 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002721 }
2722
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002723 if (*p != '\'' && !(interpolate && *p == '{'))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002724 {
Bram Moolenaare1242042021-12-16 20:56:57 +00002725 semsg(_(e_missing_single_quote_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002726 return FAIL;
2727 }
2728
2729 // If only parsing return after setting "*arg"
2730 if (!evaluate)
2731 {
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002732 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002733 return OK;
2734 }
2735
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002736 // Copy the string into allocated memory, handling '' to ' reduction and
2737 // any expressions.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002738 str = alloc((p - *arg) - reduce);
2739 if (str == NULL)
2740 return FAIL;
2741 rettv->v_type = VAR_STRING;
2742 rettv->vval.v_string = str;
2743
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002744 for (p = *arg + off; *p != NUL; )
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002745 {
2746 if (*p == '\'')
2747 {
2748 if (p[1] != '\'')
2749 break;
2750 ++p;
2751 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002752 else if (interpolate && (*p == '{' || *p == '}'))
2753 {
2754 if (*p == '{' && p[1] != '{')
2755 break;
2756 ++p;
2757 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002758 MB_COPY_CHAR(p, str);
2759 }
2760 *str = NUL;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002761 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002762
2763 return OK;
2764}
2765
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002766/*
2767 * Evaluate a single or double quoted string possibly containing expressions.
2768 * "arg" points to the '$'. The result is put in "rettv".
2769 * Returns OK or FAIL.
2770 */
LemonBoy2eaef102022-05-06 13:14:50 +01002771 int
2772eval_interp_string(char_u **arg, typval_T *rettv, int evaluate)
2773{
2774 typval_T tv;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002775 int ret = OK;
2776 int quote;
2777 garray_T ga;
2778 char_u *p;
LemonBoy2eaef102022-05-06 13:14:50 +01002779
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002780 ga_init2(&ga, 1, 80);
2781
2782 // *arg is on the '$' character, move it to the first string character.
2783 ++*arg;
2784 quote = **arg;
2785 ++*arg;
2786
2787 for (;;)
2788 {
2789 // Get the string up to the matching quote or to a single '{'.
2790 // "arg" is advanced to either the quote or the '{'.
2791 if (quote == '"')
2792 ret = eval_string(arg, &tv, evaluate, TRUE);
2793 else
2794 ret = eval_lit_string(arg, &tv, evaluate, TRUE);
2795 if (ret == FAIL)
2796 break;
2797 if (evaluate)
2798 {
2799 ga_concat(&ga, tv.vval.v_string);
2800 clear_tv(&tv);
2801 }
2802
2803 if (**arg != '{')
2804 {
2805 // found terminating quote
2806 ++*arg;
2807 break;
2808 }
Bram Moolenaar70c41242022-05-10 18:11:43 +01002809 p = eval_one_expr_in_str(*arg, &ga, evaluate);
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002810 if (p == NULL)
2811 {
2812 ret = FAIL;
2813 break;
2814 }
2815 *arg = p;
2816 }
LemonBoy2eaef102022-05-06 13:14:50 +01002817
2818 rettv->v_type = VAR_STRING;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002819 if (ret == FAIL || !evaluate || ga_append(&ga, NUL) == FAIL)
2820 {
2821 ga_clear(&ga);
2822 rettv->vval.v_string = NULL;
LemonBoy2eaef102022-05-06 13:14:50 +01002823 return ret;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002824 }
LemonBoy2eaef102022-05-06 13:14:50 +01002825
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002826 rettv->vval.v_string = ga.ga_data;
2827 return OK;
LemonBoy2eaef102022-05-06 13:14:50 +01002828}
2829
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002830/*
2831 * Return a string with the string representation of a variable.
2832 * If the memory is allocated "tofree" is set to it, otherwise NULL.
2833 * "numbuf" is used for a number.
2834 * Puts quotes around strings, so that they can be parsed back by eval().
2835 * May return NULL.
2836 */
2837 char_u *
2838tv2string(
2839 typval_T *tv,
2840 char_u **tofree,
2841 char_u *numbuf,
2842 int copyID)
2843{
2844 return echo_string_core(tv, tofree, numbuf, copyID, FALSE, TRUE, FALSE);
2845}
2846
2847/*
2848 * Get the value of an environment variable.
2849 * "arg" is pointing to the '$'. It is advanced to after the name.
2850 * If the environment variable was not set, silently assume it is empty.
2851 * Return FAIL if the name is invalid.
2852 */
2853 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002854eval_env_var(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002855{
2856 char_u *string = NULL;
2857 int len;
2858 int cc;
2859 char_u *name;
2860 int mustfree = FALSE;
2861
2862 ++*arg;
2863 name = *arg;
2864 len = get_env_len(arg);
2865 if (evaluate)
2866 {
2867 if (len == 0)
2868 return FAIL; // invalid empty name
2869
2870 cc = name[len];
2871 name[len] = NUL;
2872 // first try vim_getenv(), fast for normal environment vars
2873 string = vim_getenv(name, &mustfree);
2874 if (string != NULL && *string != NUL)
2875 {
2876 if (!mustfree)
2877 string = vim_strsave(string);
2878 }
2879 else
2880 {
2881 if (mustfree)
2882 vim_free(string);
2883
2884 // next try expanding things like $VIM and ${HOME}
2885 string = expand_env_save(name - 1);
2886 if (string != NULL && *string == '$')
2887 VIM_CLEAR(string);
2888 }
2889 name[len] = cc;
2890
2891 rettv->v_type = VAR_STRING;
2892 rettv->vval.v_string = string;
Bram Moolenaar16e63e62021-08-11 16:47:26 +02002893 rettv->v_lock = 0;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002894 }
2895
2896 return OK;
2897}
2898
2899/*
2900 * Get the lnum from the first argument.
2901 * Also accepts ".", "$", etc., but that only works for the current buffer.
2902 * Returns -1 on error.
2903 */
2904 linenr_T
2905tv_get_lnum(typval_T *argvars)
2906{
Bram Moolenaar9a963372020-12-21 21:58:46 +01002907 linenr_T lnum = -1;
Bram Moolenaar801cd352022-10-10 16:08:16 +01002908 int did_emsg_before = did_emsg;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002909
Bram Moolenaar56acb092020-08-16 14:48:19 +02002910 if (argvars[0].v_type != VAR_STRING || !in_vim9script())
2911 lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL);
Bram Moolenaar801cd352022-10-10 16:08:16 +01002912 if (lnum <= 0 && did_emsg_before == did_emsg
2913 && argvars[0].v_type != VAR_NUMBER)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002914 {
2915 int fnum;
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002916 pos_T *fp;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002917
Bram Moolenaarf6bdd822021-03-28 16:26:41 +02002918 // no valid number, try using arg like line()
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002919 fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002920 if (fp != NULL)
2921 lnum = fp->lnum;
2922 }
2923 return lnum;
2924}
2925
2926/*
2927 * Get the lnum from the first argument.
2928 * Also accepts "$", then "buf" is used.
2929 * Returns 0 on error.
2930 */
2931 linenr_T
2932tv_get_lnum_buf(typval_T *argvars, buf_T *buf)
2933{
2934 if (argvars[0].v_type == VAR_STRING
2935 && argvars[0].vval.v_string != NULL
2936 && argvars[0].vval.v_string[0] == '$'
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002937 && argvars[0].vval.v_string[1] == NUL
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002938 && buf != NULL)
2939 return buf->b_ml.ml_line_count;
2940 return (linenr_T)tv_get_number_chk(&argvars[0], NULL);
2941}
2942
2943/*
2944 * Get buffer by number or pattern.
2945 */
2946 buf_T *
2947tv_get_buf(typval_T *tv, int curtab_only)
2948{
2949 char_u *name = tv->vval.v_string;
2950 buf_T *buf;
2951
2952 if (tv->v_type == VAR_NUMBER)
2953 return buflist_findnr((int)tv->vval.v_number);
2954 if (tv->v_type != VAR_STRING)
2955 return NULL;
2956 if (name == NULL || *name == NUL)
2957 return curbuf;
2958 if (name[0] == '$' && name[1] == NUL)
2959 return lastbuf;
2960
2961 buf = buflist_find_by_name(name, curtab_only);
2962
2963 // If not found, try expanding the name, like done for bufexists().
2964 if (buf == NULL)
2965 buf = find_buffer(tv);
2966
2967 return buf;
2968}
2969
Bram Moolenaar3767e3a2020-09-01 23:06:01 +02002970/*
2971 * Like tv_get_buf() but give an error message is the type is wrong.
2972 */
2973 buf_T *
2974tv_get_buf_from_arg(typval_T *tv)
2975{
2976 buf_T *buf;
2977
2978 ++emsg_off;
2979 buf = tv_get_buf(tv, FALSE);
2980 --emsg_off;
2981 if (buf == NULL
2982 && tv->v_type != VAR_NUMBER
2983 && tv->v_type != VAR_STRING)
2984 // issue errmsg for type error
2985 (void)tv_get_number(tv);
2986 return buf;
2987}
2988
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002989#endif // FEAT_EVAL