blob: b9f8f1c1609106028963a365e84cb476c5800da8 [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
1308 f_string(varp, &tmp);
1309 tv_get_string_buf(&tmp, buf);
1310 clear_tv(varp);
1311 *varp = tmp;
1312 return tmp.vval.v_string;
1313 }
1314 return tv_get_string_buf(varp, buf);
1315}
1316
1317/*
1318 * Return TRUE if typeval "tv" and its value are set to be locked (immutable).
1319 * Also give an error message, using "name" or _("name") when use_gettext is
1320 * TRUE.
1321 */
1322 int
1323tv_check_lock(typval_T *tv, char_u *name, int use_gettext)
1324{
1325 int lock = 0;
1326
1327 switch (tv->v_type)
1328 {
1329 case VAR_BLOB:
1330 if (tv->vval.v_blob != NULL)
1331 lock = tv->vval.v_blob->bv_lock;
1332 break;
1333 case VAR_LIST:
1334 if (tv->vval.v_list != NULL)
1335 lock = tv->vval.v_list->lv_lock;
1336 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001337 case VAR_TUPLE:
1338 if (tv->vval.v_tuple != NULL)
1339 lock = tv->vval.v_tuple->tv_lock;
1340 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001341 case VAR_DICT:
1342 if (tv->vval.v_dict != NULL)
1343 lock = tv->vval.v_dict->dv_lock;
1344 break;
1345 default:
1346 break;
1347 }
Bram Moolenaara187c432020-09-16 21:08:28 +02001348 return value_check_lock(tv->v_lock, name, use_gettext)
1349 || (lock != 0 && value_check_lock(lock, name, use_gettext));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001350}
1351
1352/*
1353 * Copy the values from typval_T "from" to typval_T "to".
1354 * When needed allocates string or increases reference count.
1355 * Does not make a copy of a list, blob or dict but copies the reference!
1356 * It is OK for "from" and "to" to point to the same item. This is used to
1357 * make a copy later.
1358 */
1359 void
1360copy_tv(typval_T *from, typval_T *to)
1361{
1362 to->v_type = from->v_type;
1363 to->v_lock = 0;
1364 switch (from->v_type)
1365 {
1366 case VAR_NUMBER:
1367 case VAR_BOOL:
1368 case VAR_SPECIAL:
1369 to->vval.v_number = from->vval.v_number;
1370 break;
1371 case VAR_FLOAT:
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001372 to->vval.v_float = from->vval.v_float;
1373 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001374 case VAR_JOB:
1375#ifdef FEAT_JOB_CHANNEL
1376 to->vval.v_job = from->vval.v_job;
1377 if (to->vval.v_job != NULL)
1378 ++to->vval.v_job->jv_refcount;
1379 break;
1380#endif
1381 case VAR_CHANNEL:
1382#ifdef FEAT_JOB_CHANNEL
1383 to->vval.v_channel = from->vval.v_channel;
1384 if (to->vval.v_channel != NULL)
1385 ++to->vval.v_channel->ch_refcount;
1386 break;
1387#endif
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001388 case VAR_INSTR:
1389 to->vval.v_instr = from->vval.v_instr;
1390 break;
1391
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001392 case VAR_CLASS:
1393 copy_class(from, to);
1394 break;
1395
1396 case VAR_OBJECT:
1397 copy_object(from, to);
1398 break;
1399
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001400 case VAR_STRING:
1401 case VAR_FUNC:
1402 if (from->vval.v_string == NULL)
1403 to->vval.v_string = NULL;
1404 else
1405 {
1406 to->vval.v_string = vim_strsave(from->vval.v_string);
1407 if (from->v_type == VAR_FUNC)
1408 func_ref(to->vval.v_string);
1409 }
1410 break;
1411 case VAR_PARTIAL:
1412 if (from->vval.v_partial == NULL)
1413 to->vval.v_partial = NULL;
1414 else
1415 {
1416 to->vval.v_partial = from->vval.v_partial;
1417 ++to->vval.v_partial->pt_refcount;
1418 }
1419 break;
1420 case VAR_BLOB:
1421 if (from->vval.v_blob == NULL)
1422 to->vval.v_blob = NULL;
1423 else
1424 {
1425 to->vval.v_blob = from->vval.v_blob;
1426 ++to->vval.v_blob->bv_refcount;
1427 }
1428 break;
1429 case VAR_LIST:
1430 if (from->vval.v_list == NULL)
1431 to->vval.v_list = NULL;
1432 else
1433 {
1434 to->vval.v_list = from->vval.v_list;
1435 ++to->vval.v_list->lv_refcount;
1436 }
1437 break;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001438 case VAR_TUPLE:
1439 if (from->vval.v_tuple == NULL)
1440 to->vval.v_tuple = NULL;
1441 else
1442 {
1443 to->vval.v_tuple = from->vval.v_tuple;
1444 ++to->vval.v_tuple->tv_refcount;
1445 }
1446 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001447 case VAR_DICT:
1448 if (from->vval.v_dict == NULL)
1449 to->vval.v_dict = NULL;
1450 else
1451 {
1452 to->vval.v_dict = from->vval.v_dict;
1453 ++to->vval.v_dict->dv_refcount;
1454 }
1455 break;
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02001456 case VAR_TYPEALIAS:
1457 if (from->vval.v_typealias == NULL)
1458 to->vval.v_typealias = NULL;
1459 else
1460 {
1461 to->vval.v_typealias = from->vval.v_typealias;
1462 ++to->vval.v_typealias->ta_refcount;
1463 }
1464 break;
Bram Moolenaar61a417b2021-06-15 22:54:28 +02001465 case VAR_VOID:
1466 emsg(_(e_cannot_use_void_value));
1467 break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001468 case VAR_UNKNOWN:
1469 case VAR_ANY:
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001470 internal_error_no_abort("copy_tv(UNKNOWN)");
1471 break;
1472 }
1473}
1474
1475/*
Bram Moolenaar265f8112021-12-19 12:33:05 +00001476 * Compare "tv1" and "tv2".
1477 * Put the result in "tv1". Caller should clear "tv2".
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001478 */
1479 int
1480typval_compare(
Bram Moolenaar265f8112021-12-19 12:33:05 +00001481 typval_T *tv1, // first operand
1482 typval_T *tv2, // second operand
1483 exprtype_T type, // operator
1484 int ic) // ignore case
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001485{
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001486 varnumber_T n1, n2;
Bram Moolenaar265f8112021-12-19 12:33:05 +00001487 int res = 0;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001488 int type_is = type == EXPR_IS || type == EXPR_ISNOT;
1489
Ernie Raele75fde62023-12-21 17:18:54 +01001490 if (check_typval_is_value(tv1) == FAIL
1491 || check_typval_is_value(tv2) == FAIL)
1492 {
1493 clear_tv(tv1);
1494 return FAIL;
1495 }
1496 else if (type_is && tv1->v_type != tv2->v_type)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001497 {
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001498 // For "is" a different type always means FALSE, for "isnot"
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001499 // it means TRUE.
1500 n1 = (type == EXPR_ISNOT);
1501 }
Bram Moolenaar7a222242022-03-01 19:23:24 +00001502 else if (((tv1->v_type == VAR_SPECIAL && tv1->vval.v_number == VVAL_NULL)
1503 || (tv2->v_type == VAR_SPECIAL
1504 && tv2->vval.v_number == VVAL_NULL))
1505 && tv1->v_type != tv2->v_type
1506 && (type == EXPR_EQUAL || type == EXPR_NEQUAL))
1507 {
1508 n1 = typval_compare_null(tv1, tv2);
1509 if (n1 == MAYBE)
1510 {
1511 clear_tv(tv1);
1512 return FAIL;
1513 }
1514 if (type == EXPR_NEQUAL)
1515 n1 = !n1;
1516 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001517 else if (tv1->v_type == VAR_BLOB || tv2->v_type == VAR_BLOB)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001518 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001519 if (typval_compare_blob(tv1, tv2, type, &res) == FAIL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001520 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001521 clear_tv(tv1);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001522 return FAIL;
1523 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001524 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001525 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001526 else if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001527 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001528 if (typval_compare_list(tv1, tv2, type, ic, &res) == FAIL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001529 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001530 clear_tv(tv1);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001531 return FAIL;
1532 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001533 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001534 }
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001535 else if (tv1->v_type == VAR_TUPLE || tv2->v_type == VAR_TUPLE)
1536 {
1537 if (typval_compare_tuple(tv1, tv2, type, ic, &res) == FAIL)
1538 {
1539 clear_tv(tv1);
1540 return FAIL;
1541 }
1542 n1 = res;
1543 }
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001544 else if (tv1->v_type == VAR_OBJECT || tv2->v_type == VAR_OBJECT)
1545 {
1546 if (typval_compare_object(tv1, tv2, type, ic, &res) == FAIL)
1547 {
1548 clear_tv(tv1);
1549 return FAIL;
1550 }
1551 n1 = res;
1552 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001553 else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001554 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001555 if (typval_compare_dict(tv1, tv2, type, ic, &res) == FAIL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001556 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001557 clear_tv(tv1);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001558 return FAIL;
1559 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001560 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001561 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001562 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC
1563 || tv1->v_type == VAR_PARTIAL || tv2->v_type == VAR_PARTIAL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001564 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001565 if (typval_compare_func(tv1, tv2, type, ic, &res) == FAIL)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001566 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001567 clear_tv(tv1);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001568 return FAIL;
1569 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001570 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001571 }
1572
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001573 // If one of the two variables is a float, compare as a float.
1574 // When using "=~" or "!~", always compare as string.
Bram Moolenaar265f8112021-12-19 12:33:05 +00001575 else if ((tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001576 && type != EXPR_MATCH && type != EXPR_NOMATCH)
1577 {
1578 float_T f1, f2;
Bram Moolenaar28fbbea2021-12-22 21:40:33 +00001579 int error = FALSE;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001580
Bram Moolenaar28fbbea2021-12-22 21:40:33 +00001581 f1 = tv_get_float_chk(tv1, &error);
1582 if (!error)
1583 f2 = tv_get_float_chk(tv2, &error);
1584 if (error)
1585 {
1586 clear_tv(tv1);
1587 return FAIL;
1588 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001589 n1 = FALSE;
1590 switch (type)
1591 {
1592 case EXPR_IS:
1593 case EXPR_EQUAL: n1 = (f1 == f2); break;
1594 case EXPR_ISNOT:
1595 case EXPR_NEQUAL: n1 = (f1 != f2); break;
1596 case EXPR_GREATER: n1 = (f1 > f2); break;
1597 case EXPR_GEQUAL: n1 = (f1 >= f2); break;
1598 case EXPR_SMALLER: n1 = (f1 < f2); break;
1599 case EXPR_SEQUAL: n1 = (f1 <= f2); break;
1600 case EXPR_UNKNOWN:
1601 case EXPR_MATCH:
1602 default: break; // avoid gcc warning
1603 }
1604 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001605
1606 // If one of the two variables is a number, compare as a number.
1607 // When using "=~" or "!~", always compare as string.
Bram Moolenaar265f8112021-12-19 12:33:05 +00001608 else if ((tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001609 && type != EXPR_MATCH && type != EXPR_NOMATCH)
1610 {
Bram Moolenaar28fbbea2021-12-22 21:40:33 +00001611 int error = FALSE;
1612
1613 n1 = tv_get_number_chk(tv1, &error);
1614 if (!error)
1615 n2 = tv_get_number_chk(tv2, &error);
1616 if (error)
1617 {
1618 clear_tv(tv1);
1619 return FAIL;
1620 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001621 switch (type)
1622 {
1623 case EXPR_IS:
1624 case EXPR_EQUAL: n1 = (n1 == n2); break;
1625 case EXPR_ISNOT:
1626 case EXPR_NEQUAL: n1 = (n1 != n2); break;
1627 case EXPR_GREATER: n1 = (n1 > n2); break;
1628 case EXPR_GEQUAL: n1 = (n1 >= n2); break;
1629 case EXPR_SMALLER: n1 = (n1 < n2); break;
1630 case EXPR_SEQUAL: n1 = (n1 <= n2); break;
1631 case EXPR_UNKNOWN:
1632 case EXPR_MATCH:
1633 default: break; // avoid gcc warning
1634 }
1635 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001636 else if (in_vim9script() && (tv1->v_type == VAR_BOOL
1637 || tv2->v_type == VAR_BOOL
1638 || (tv1->v_type == VAR_SPECIAL
1639 && tv2->v_type == VAR_SPECIAL)))
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001640 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001641 if (tv1->v_type != tv2->v_type)
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001642 {
1643 semsg(_(e_cannot_compare_str_with_str),
Bram Moolenaar265f8112021-12-19 12:33:05 +00001644 vartype_name(tv1->v_type), vartype_name(tv2->v_type));
1645 clear_tv(tv1);
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001646 return FAIL;
1647 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001648 n1 = tv1->vval.v_number;
1649 n2 = tv2->vval.v_number;
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001650 switch (type)
1651 {
1652 case EXPR_IS:
1653 case EXPR_EQUAL: n1 = (n1 == n2); break;
1654 case EXPR_ISNOT:
1655 case EXPR_NEQUAL: n1 = (n1 != n2); break;
1656 default:
Bram Moolenaar0c357522021-07-18 14:43:43 +02001657 semsg(_(e_invalid_operation_for_str),
Bram Moolenaar265f8112021-12-19 12:33:05 +00001658 vartype_name(tv1->v_type));
1659 clear_tv(tv1);
Bram Moolenaarcff40ff2021-01-09 16:21:37 +01001660 return FAIL;
1661 }
1662 }
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01001663#ifdef FEAT_JOB_CHANNEL
1664 else if (tv1->v_type == tv2->v_type
1665 && (tv1->v_type == VAR_CHANNEL || tv1->v_type == VAR_JOB)
1666 && (type == EXPR_NEQUAL || type == EXPR_EQUAL))
1667 {
1668 if (tv1->v_type == VAR_CHANNEL)
1669 n1 = tv1->vval.v_channel == tv2->vval.v_channel;
1670 else
1671 n1 = tv1->vval.v_job == tv2->vval.v_job;
1672 if (type == EXPR_NEQUAL)
1673 n1 = !n1;
1674 }
1675#endif
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001676 else
1677 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001678 if (typval_compare_string(tv1, tv2, type, ic, &res) == FAIL)
Bram Moolenaar0c357522021-07-18 14:43:43 +02001679 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001680 clear_tv(tv1);
Bram Moolenaar0c357522021-07-18 14:43:43 +02001681 return FAIL;
1682 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001683 n1 = res;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001684 }
Bram Moolenaar265f8112021-12-19 12:33:05 +00001685 clear_tv(tv1);
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02001686 if (in_vim9script())
1687 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001688 tv1->v_type = VAR_BOOL;
1689 tv1->vval.v_number = n1 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02001690 }
1691 else
1692 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00001693 tv1->v_type = VAR_NUMBER;
1694 tv1->vval.v_number = n1;
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02001695 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001696
1697 return OK;
1698}
1699
Bram Moolenaar34453202021-01-31 13:08:38 +01001700/*
dundargocc57b5bc2022-11-02 13:30:51 +00001701 * Compare "tv1" to "tv2" as lists according to "type" and "ic".
Bram Moolenaar265f8112021-12-19 12:33:05 +00001702 * Put the result, false or true, in "res".
1703 * Return FAIL and give an error message when the comparison can't be done.
1704 */
1705 int
1706typval_compare_list(
1707 typval_T *tv1,
1708 typval_T *tv2,
1709 exprtype_T type,
1710 int ic,
1711 int *res)
1712{
1713 int val = 0;
1714
1715 if (type == EXPR_IS || type == EXPR_ISNOT)
1716 {
1717 val = (tv1->v_type == tv2->v_type
1718 && tv1->vval.v_list == tv2->vval.v_list);
1719 if (type == EXPR_ISNOT)
1720 val = !val;
1721 }
1722 else if (tv1->v_type != tv2->v_type
1723 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
1724 {
1725 if (tv1->v_type != tv2->v_type)
Bram Moolenaara6f79292022-01-04 21:30:47 +00001726 emsg(_(e_can_only_compare_list_with_list));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001727 else
Bram Moolenaara6f79292022-01-04 21:30:47 +00001728 emsg(_(e_invalid_operation_for_list));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001729 return FAIL;
1730 }
1731 else
1732 {
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001733 val = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
Bram Moolenaar265f8112021-12-19 12:33:05 +00001734 if (type == EXPR_NEQUAL)
1735 val = !val;
1736 }
1737 *res = val;
1738 return OK;
1739}
1740
1741/*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001742 * Compare "tv1" to "tv2" as tuples according to "type" and "ic".
1743 * Put the result, false or true, in "res".
1744 * Return FAIL and give an error message when the comparison can't be done.
1745 */
1746 int
1747typval_compare_tuple(
1748 typval_T *tv1,
1749 typval_T *tv2,
1750 exprtype_T type,
1751 int ic,
1752 int *res)
1753{
1754 int val = 0;
1755
1756 if (type == EXPR_IS || type == EXPR_ISNOT)
1757 {
1758 val = (tv1->v_type == tv2->v_type
1759 && tv1->vval.v_tuple == tv2->vval.v_tuple);
1760 if (type == EXPR_ISNOT)
1761 val = !val;
1762 }
1763 else if (tv1->v_type != tv2->v_type
1764 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
1765 {
1766 if (tv1->v_type != tv2->v_type)
1767 emsg(_(e_can_only_compare_tuple_with_tuple));
1768 else
1769 emsg(_(e_invalid_operation_for_tuple));
1770 return FAIL;
1771 }
1772 else
1773 {
1774 val = tuple_equal(tv1->vval.v_tuple, tv2->vval.v_tuple, ic);
1775 if (type == EXPR_NEQUAL)
1776 val = !val;
1777 }
1778 *res = val;
1779 return OK;
1780}
1781
1782/*
Bram Moolenaarf3507a52022-03-09 11:56:21 +00001783 * Compare v:null with another type. Return TRUE if the value is NULL.
Bram Moolenaar7a222242022-03-01 19:23:24 +00001784 */
1785 int
1786typval_compare_null(typval_T *tv1, typval_T *tv2)
1787{
1788 if ((tv1->v_type == VAR_SPECIAL && tv1->vval.v_number == VVAL_NULL)
1789 || (tv2->v_type == VAR_SPECIAL && tv2->vval.v_number == VVAL_NULL))
1790 {
1791 typval_T *tv = tv1->v_type == VAR_SPECIAL ? tv2 : tv1;
1792
1793 switch (tv->v_type)
1794 {
1795 case VAR_BLOB: return tv->vval.v_blob == NULL;
Bram Moolenaarf6b0c792022-03-01 19:52:48 +00001796#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar7a222242022-03-01 19:23:24 +00001797 case VAR_CHANNEL: return tv->vval.v_channel == NULL;
Bram Moolenaarf6b0c792022-03-01 19:52:48 +00001798#endif
Ernie Rael5c018be2023-08-27 18:40:26 +02001799 // TODO: null_class handling
1800 // case VAR_CLASS: return tv->vval.v_class == NULL;
Bram Moolenaar7a222242022-03-01 19:23:24 +00001801 case VAR_DICT: return tv->vval.v_dict == NULL;
1802 case VAR_FUNC: return tv->vval.v_string == NULL;
Bram Moolenaarf6b0c792022-03-01 19:52:48 +00001803#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar7a222242022-03-01 19:23:24 +00001804 case VAR_JOB: return tv->vval.v_job == NULL;
Bram Moolenaarf6b0c792022-03-01 19:52:48 +00001805#endif
Bram Moolenaar7a222242022-03-01 19:23:24 +00001806 case VAR_LIST: return tv->vval.v_list == NULL;
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001807 case VAR_TUPLE: return tv->vval.v_tuple == NULL;
Ernie Rael5c018be2023-08-27 18:40:26 +02001808 case VAR_OBJECT: return tv->vval.v_object == NULL;
Bram Moolenaar7a222242022-03-01 19:23:24 +00001809 case VAR_PARTIAL: return tv->vval.v_partial == NULL;
1810 case VAR_STRING: return tv->vval.v_string == NULL;
Bram Moolenaarc6e9d702022-03-02 13:13:30 +00001811
1812 case VAR_NUMBER: if (!in_vim9script())
1813 return tv->vval.v_number == 0;
1814 break;
Bram Moolenaarc6e9d702022-03-02 13:13:30 +00001815 case VAR_FLOAT: if (!in_vim9script())
1816 return tv->vval.v_float == 0.0;
1817 break;
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02001818 case VAR_TYPEALIAS: return tv->vval.v_typealias == NULL;
Bram Moolenaar7a222242022-03-01 19:23:24 +00001819 default: break;
1820 }
1821 }
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01001822 // although comparing null with number, float or bool is not very useful
Bram Moolenaar05667812022-03-15 20:21:33 +00001823 // we won't give an error
1824 return FALSE;
Bram Moolenaar7a222242022-03-01 19:23:24 +00001825}
1826
1827/*
dundargocc57b5bc2022-11-02 13:30:51 +00001828 * Compare "tv1" to "tv2" as blobs according to "type".
Bram Moolenaar265f8112021-12-19 12:33:05 +00001829 * Put the result, false or true, in "res".
1830 * Return FAIL and give an error message when the comparison can't be done.
1831 */
1832 int
1833typval_compare_blob(
1834 typval_T *tv1,
1835 typval_T *tv2,
1836 exprtype_T type,
1837 int *res)
1838{
1839 int val = 0;
1840
1841 if (type == EXPR_IS || type == EXPR_ISNOT)
1842 {
1843 val = (tv1->v_type == tv2->v_type
1844 && tv1->vval.v_blob == tv2->vval.v_blob);
1845 if (type == EXPR_ISNOT)
1846 val = !val;
1847 }
1848 else if (tv1->v_type != tv2->v_type
1849 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
1850 {
1851 if (tv1->v_type != tv2->v_type)
Bram Moolenaard82a47d2022-01-05 20:24:39 +00001852 emsg(_(e_can_only_compare_blob_with_blob));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001853 else
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00001854 emsg(_(e_invalid_operation_for_blob));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001855 return FAIL;
1856 }
1857 else
1858 {
1859 val = blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
1860 if (type == EXPR_NEQUAL)
1861 val = !val;
1862 }
1863 *res = val;
1864 return OK;
1865}
1866
1867/*
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001868 * Compare "tv1" to "tv2" as objects according to "type".
1869 * Put the result, false or true, in "res".
1870 * Return FAIL and give an error message when the comparison can't be done.
1871 */
1872 int
1873typval_compare_object(
1874 typval_T *tv1,
1875 typval_T *tv2,
1876 exprtype_T type,
1877 int ic,
1878 int *res)
1879{
1880 int res_match = type == EXPR_EQUAL || type == EXPR_IS ? TRUE : FALSE;
1881
1882 if (tv1->vval.v_object == NULL && tv2->vval.v_object == NULL)
1883 {
1884 *res = res_match;
1885 return OK;
1886 }
1887 if (tv1->vval.v_object == NULL || tv2->vval.v_object == NULL)
1888 {
1889 *res = !res_match;
1890 return OK;
1891 }
1892
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001893 object_T *obj1 = tv1->vval.v_object;
1894 object_T *obj2 = tv2->vval.v_object;
1895 if (type == EXPR_IS || type == EXPR_ISNOT)
1896 {
1897 *res = obj1 == obj2 ? res_match : !res_match;
1898 return OK;
1899 }
1900
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001901 *res = object_equal(obj1, obj2, ic) ? res_match : !res_match;
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001902 return OK;
1903}
1904
1905/*
dundargocc57b5bc2022-11-02 13:30:51 +00001906 * Compare "tv1" to "tv2" as dictionaries according to "type" and "ic".
Bram Moolenaar265f8112021-12-19 12:33:05 +00001907 * Put the result, false or true, in "res".
1908 * Return FAIL and give an error message when the comparison can't be done.
1909 */
1910 int
1911typval_compare_dict(
1912 typval_T *tv1,
1913 typval_T *tv2,
1914 exprtype_T type,
1915 int ic,
1916 int *res)
1917{
1918 int val;
1919
1920 if (type == EXPR_IS || type == EXPR_ISNOT)
1921 {
1922 val = (tv1->v_type == tv2->v_type
1923 && tv1->vval.v_dict == tv2->vval.v_dict);
1924 if (type == EXPR_ISNOT)
1925 val = !val;
1926 }
1927 else if (tv1->v_type != tv2->v_type
1928 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
1929 {
1930 if (tv1->v_type != tv2->v_type)
Bram Moolenaara6f79292022-01-04 21:30:47 +00001931 emsg(_(e_can_only_compare_dictionary_with_dictionary));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001932 else
Bram Moolenaara6f79292022-01-04 21:30:47 +00001933 emsg(_(e_invalid_operation_for_dictionary));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001934 return FAIL;
1935 }
1936 else
1937 {
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001938 val = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
Bram Moolenaar265f8112021-12-19 12:33:05 +00001939 if (type == EXPR_NEQUAL)
1940 val = !val;
1941 }
1942 *res = val;
1943 return OK;
1944}
1945
1946/*
dundargocc57b5bc2022-11-02 13:30:51 +00001947 * Compare "tv1" to "tv2" as funcrefs according to "type" and "ic".
Bram Moolenaar265f8112021-12-19 12:33:05 +00001948 * Put the result, false or true, in "res".
1949 * Return FAIL and give an error message when the comparison can't be done.
1950 */
1951 int
1952typval_compare_func(
1953 typval_T *tv1,
1954 typval_T *tv2,
1955 exprtype_T type,
1956 int ic,
1957 int *res)
1958{
1959 int val = 0;
1960
1961 if (type != EXPR_EQUAL && type != EXPR_NEQUAL
1962 && type != EXPR_IS && type != EXPR_ISNOT)
1963 {
Bram Moolenaara6f79292022-01-04 21:30:47 +00001964 emsg(_(e_invalid_operation_for_funcrefs));
Bram Moolenaar265f8112021-12-19 12:33:05 +00001965 return FAIL;
1966 }
1967 if ((tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial == NULL)
1968 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial == NULL))
1969 // When both partials are NULL, then they are equal.
1970 // Otherwise they are not equal.
1971 val = (tv1->vval.v_partial == tv2->vval.v_partial);
1972 else if (type == EXPR_IS || type == EXPR_ISNOT)
1973 {
1974 if (tv1->v_type == VAR_FUNC && tv2->v_type == VAR_FUNC)
1975 // strings are considered the same if their value is
1976 // the same
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001977 val = tv_equal(tv1, tv2, ic);
Bram Moolenaar265f8112021-12-19 12:33:05 +00001978 else if (tv1->v_type == VAR_PARTIAL && tv2->v_type == VAR_PARTIAL)
1979 val = (tv1->vval.v_partial == tv2->vval.v_partial);
1980 else
1981 val = FALSE;
1982 }
1983 else
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02001984 val = tv_equal(tv1, tv2, ic);
Bram Moolenaar265f8112021-12-19 12:33:05 +00001985 if (type == EXPR_NEQUAL || type == EXPR_ISNOT)
1986 val = !val;
1987 *res = val;
1988 return OK;
1989}
1990
1991/*
1992 * Compare "tv1" to "tv2" as strings according to "type" and "ic".
1993 * Put the result, false or true, in "res".
1994 * Return FAIL and give an error message when the comparison can't be done.
1995 */
1996 int
1997typval_compare_string(
1998 typval_T *tv1,
1999 typval_T *tv2,
2000 exprtype_T type,
2001 int ic,
2002 int *res)
2003{
2004 int i = 0;
2005 int val = FALSE;
2006 char_u *s1, *s2;
2007 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2008
2009 if (in_vim9script()
2010 && ((tv1->v_type != VAR_STRING && tv1->v_type != VAR_SPECIAL)
2011 || (tv2->v_type != VAR_STRING && tv2->v_type != VAR_SPECIAL)))
2012 {
2013 semsg(_(e_cannot_compare_str_with_str),
2014 vartype_name(tv1->v_type), vartype_name(tv2->v_type));
2015 return FAIL;
2016 }
2017 s1 = tv_get_string_buf(tv1, buf1);
2018 s2 = tv_get_string_buf(tv2, buf2);
2019 if (type != EXPR_MATCH && type != EXPR_NOMATCH)
2020 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
2021 switch (type)
2022 {
Bram Moolenaarf8691002022-03-10 12:20:53 +00002023 case EXPR_IS: if (in_vim9script())
2024 {
2025 // Really check it is the same string, not just
2026 // the same value.
2027 val = tv1->vval.v_string == tv2->vval.v_string;
2028 break;
2029 }
2030 // FALLTHROUGH
Bram Moolenaar265f8112021-12-19 12:33:05 +00002031 case EXPR_EQUAL: val = (i == 0); break;
Bram Moolenaarf8691002022-03-10 12:20:53 +00002032 case EXPR_ISNOT: if (in_vim9script())
2033 {
2034 // Really check it is not the same string, not
2035 // just a different value.
2036 val = tv1->vval.v_string != tv2->vval.v_string;
2037 break;
2038 }
2039 // FALLTHROUGH
Bram Moolenaar265f8112021-12-19 12:33:05 +00002040 case EXPR_NEQUAL: val = (i != 0); break;
2041 case EXPR_GREATER: val = (i > 0); break;
2042 case EXPR_GEQUAL: val = (i >= 0); break;
2043 case EXPR_SMALLER: val = (i < 0); break;
2044 case EXPR_SEQUAL: val = (i <= 0); break;
2045
2046 case EXPR_MATCH:
2047 case EXPR_NOMATCH:
2048 val = pattern_match(s2, s1, ic);
2049 if (type == EXPR_NOMATCH)
2050 val = !val;
2051 break;
2052
2053 default: break; // avoid gcc warning
2054 }
2055 *res = val;
2056 return OK;
2057}
2058/*
Bram Moolenaar34453202021-01-31 13:08:38 +01002059 * Convert any type to a string, never give an error.
2060 * When "quotes" is TRUE add quotes to a string.
2061 * Returns an allocated string.
2062 */
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002063 char_u *
Bram Moolenaar34453202021-01-31 13:08:38 +01002064typval_tostring(typval_T *arg, int quotes)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002065{
2066 char_u *tofree;
2067 char_u numbuf[NUMBUFLEN];
2068 char_u *ret = NULL;
2069
2070 if (arg == NULL)
2071 return vim_strsave((char_u *)"(does not exist)");
Bram Moolenaar34453202021-01-31 13:08:38 +01002072 if (!quotes && arg->v_type == VAR_STRING)
2073 {
2074 ret = vim_strsave(arg->vval.v_string == NULL ? (char_u *)""
2075 : arg->vval.v_string);
2076 }
2077 else
2078 {
2079 ret = tv2string(arg, &tofree, numbuf, 0);
2080 // Make a copy if we have a value but it's not in allocated memory.
2081 if (ret != NULL && tofree == NULL)
2082 ret = vim_strsave(ret);
2083 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002084 return ret;
2085}
2086
2087/*
2088 * Return TRUE if typeval "tv" is locked: Either that value is locked itself
2089 * or it refers to a List or Dictionary that is locked.
2090 */
2091 int
2092tv_islocked(typval_T *tv)
2093{
2094 return (tv->v_lock & VAR_LOCKED)
2095 || (tv->v_type == VAR_LIST
2096 && tv->vval.v_list != NULL
2097 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01002098 || (tv->v_type == VAR_TUPLE
2099 && tv->vval.v_tuple != NULL
2100 && (tv->vval.v_tuple->tv_lock & VAR_LOCKED))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002101 || (tv->v_type == VAR_DICT
2102 && tv->vval.v_dict != NULL
2103 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
2104}
2105
2106 static int
2107func_equal(
2108 typval_T *tv1,
2109 typval_T *tv2,
2110 int ic) // ignore case
2111{
2112 char_u *s1, *s2;
2113 dict_T *d1, *d2;
2114 int a1, a2;
2115 int i;
2116
2117 // empty and NULL function name considered the same
2118 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
2119 : partial_name(tv1->vval.v_partial);
2120 if (s1 != NULL && *s1 == NUL)
2121 s1 = NULL;
2122 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
2123 : partial_name(tv2->vval.v_partial);
2124 if (s2 != NULL && *s2 == NUL)
2125 s2 = NULL;
2126 if (s1 == NULL || s2 == NULL)
2127 {
2128 if (s1 != s2)
2129 return FALSE;
2130 }
2131 else if (STRCMP(s1, s2) != 0)
2132 return FALSE;
2133
2134 // empty dict and NULL dict is different
2135 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
2136 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
2137 if (d1 == NULL || d2 == NULL)
2138 {
2139 if (d1 != d2)
2140 return FALSE;
2141 }
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002142 else if (!dict_equal(d1, d2, ic))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002143 return FALSE;
2144
2145 // empty list and no list considered the same
2146 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
2147 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
2148 if (a1 != a2)
2149 return FALSE;
2150 for (i = 0; i < a1; ++i)
2151 if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002152 tv2->vval.v_partial->pt_argv + i, ic))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002153 return FALSE;
2154
2155 return TRUE;
2156}
2157
2158/*
2159 * Return TRUE if "tv1" and "tv2" have the same value.
2160 * Compares the items just like "==" would compare them, but strings and
2161 * numbers are different. Floats and numbers are also different.
2162 */
2163 int
2164tv_equal(
2165 typval_T *tv1,
2166 typval_T *tv2,
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002167 int ic) // ignore case
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002168{
2169 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2170 char_u *s1, *s2;
2171 static int recursive_cnt = 0; // catch recursive loops
2172 int r;
2173 static int tv_equal_recurse_limit;
2174
2175 // Catch lists and dicts that have an endless loop by limiting
2176 // recursiveness to a limit. We guess they are equal then.
2177 // A fixed limit has the problem of still taking an awful long time.
2178 // Reduce the limit every time running into it. That should work fine for
2179 // deeply linked structures that are not recursively linked and catch
2180 // recursiveness quickly.
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002181 if (recursive_cnt == 0)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002182 tv_equal_recurse_limit = 1000;
2183 if (recursive_cnt >= tv_equal_recurse_limit)
2184 {
2185 --tv_equal_recurse_limit;
2186 return TRUE;
2187 }
2188
2189 // For VAR_FUNC and VAR_PARTIAL compare the function name, bound dict and
2190 // arguments.
2191 if ((tv1->v_type == VAR_FUNC
2192 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
2193 && (tv2->v_type == VAR_FUNC
2194 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
2195 {
2196 ++recursive_cnt;
2197 r = func_equal(tv1, tv2, ic);
2198 --recursive_cnt;
2199 return r;
2200 }
2201
Bram Moolenaar418a29f2021-02-10 22:23:41 +01002202 if (tv1->v_type != tv2->v_type
2203 && ((tv1->v_type != VAR_BOOL && tv1->v_type != VAR_SPECIAL)
2204 || (tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL)))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002205 return FALSE;
2206
2207 switch (tv1->v_type)
2208 {
2209 case VAR_LIST:
2210 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002211 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002212 --recursive_cnt;
2213 return r;
2214
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01002215 case VAR_TUPLE:
2216 ++recursive_cnt;
2217 r = tuple_equal(tv1->vval.v_tuple, tv2->vval.v_tuple, ic);
2218 --recursive_cnt;
2219 return r;
2220
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002221 case VAR_DICT:
2222 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002223 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002224 --recursive_cnt;
2225 return r;
2226
2227 case VAR_BLOB:
2228 return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
2229
2230 case VAR_NUMBER:
2231 case VAR_BOOL:
2232 case VAR_SPECIAL:
2233 return tv1->vval.v_number == tv2->vval.v_number;
2234
2235 case VAR_STRING:
2236 s1 = tv_get_string_buf(tv1, buf1);
2237 s2 = tv_get_string_buf(tv2, buf2);
2238 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
2239
2240 case VAR_FLOAT:
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002241 return tv1->vval.v_float == tv2->vval.v_float;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002242 case VAR_JOB:
2243#ifdef FEAT_JOB_CHANNEL
2244 return tv1->vval.v_job == tv2->vval.v_job;
2245#endif
2246 case VAR_CHANNEL:
2247#ifdef FEAT_JOB_CHANNEL
2248 return tv1->vval.v_channel == tv2->vval.v_channel;
2249#endif
Bram Moolenaarf18332f2021-05-07 17:55:55 +02002250 case VAR_INSTR:
2251 return tv1->vval.v_instr == tv2->vval.v_instr;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002252
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002253 case VAR_CLASS:
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00002254 // A class only exists once, equality is identity.
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002255 return tv1->vval.v_class == tv2->vval.v_class;
2256
2257 case VAR_OBJECT:
Ernie Raelf0e69142024-06-22 11:12:00 +02002258 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002259 r = object_equal(tv1->vval.v_object, tv2->vval.v_object, ic);
Ernie Raelf0e69142024-06-22 11:12:00 +02002260 --recursive_cnt;
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00002261 return r;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002262
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002263 case VAR_PARTIAL:
2264 return tv1->vval.v_partial == tv2->vval.v_partial;
2265
2266 case VAR_FUNC:
2267 return tv1->vval.v_string == tv2->vval.v_string;
2268
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02002269 case VAR_TYPEALIAS:
2270 return tv1->vval.v_typealias == tv2->vval.v_typealias;
2271
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002272 case VAR_UNKNOWN:
2273 case VAR_ANY:
2274 case VAR_VOID:
2275 break;
2276 }
2277
2278 // VAR_UNKNOWN can be the result of a invalid expression, let's say it
2279 // does not equal anything, not even itself.
2280 return FALSE;
2281}
2282
2283/*
2284 * Get an option value.
2285 * "arg" points to the '&' or '+' before the option name.
2286 * "arg" is advanced to character after the option name.
2287 * Return OK or FAIL.
2288 */
2289 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002290eval_option(
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002291 char_u **arg,
2292 typval_T *rettv, // when NULL, only check if option exists
2293 int evaluate)
2294{
2295 char_u *option_end;
2296 long numval;
2297 char_u *stringval;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002298 getoption_T opt_type;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002299 int c;
2300 int working = (**arg == '+'); // has("+option")
2301 int ret = OK;
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002302 int scope;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002303
2304 // Isolate the option name and find its value.
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002305 option_end = find_option_end(arg, &scope);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002306 if (option_end == NULL)
2307 {
2308 if (rettv != NULL)
Bram Moolenaare1242042021-12-16 20:56:57 +00002309 semsg(_(e_option_name_missing_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002310 return FAIL;
2311 }
2312
2313 if (!evaluate)
2314 {
2315 *arg = option_end;
2316 return OK;
2317 }
2318
2319 c = *option_end;
2320 *option_end = NUL;
2321 opt_type = get_option_value(*arg, &numval,
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002322 rettv == NULL ? NULL : &stringval, NULL, scope);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002323
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002324 if (opt_type == gov_unknown)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002325 {
2326 if (rettv != NULL)
Bram Moolenaare1242042021-12-16 20:56:57 +00002327 semsg(_(e_unknown_option_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002328 ret = FAIL;
2329 }
2330 else if (rettv != NULL)
2331 {
Bram Moolenaara79925a2021-01-05 17:50:28 +01002332 rettv->v_lock = 0;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002333 if (opt_type == gov_hidden_string)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002334 {
2335 rettv->v_type = VAR_STRING;
2336 rettv->vval.v_string = NULL;
2337 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002338 else if (opt_type == gov_hidden_bool || opt_type == gov_hidden_number)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002339 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002340 rettv->v_type = in_vim9script() && opt_type == gov_hidden_bool
2341 ? VAR_BOOL : VAR_NUMBER;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002342 rettv->vval.v_number = 0;
2343 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002344 else if (opt_type == gov_bool || opt_type == gov_number)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002345 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002346 if (in_vim9script() && opt_type == gov_bool)
2347 {
2348 rettv->v_type = VAR_BOOL;
2349 rettv->vval.v_number = numval ? VVAL_TRUE : VVAL_FALSE;
2350 }
2351 else
2352 {
2353 rettv->v_type = VAR_NUMBER;
2354 rettv->vval.v_number = numval;
2355 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002356 }
2357 else // string option
2358 {
2359 rettv->v_type = VAR_STRING;
2360 rettv->vval.v_string = stringval;
2361 }
2362 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002363 else if (working && (opt_type == gov_hidden_bool
2364 || opt_type == gov_hidden_number
2365 || opt_type == gov_hidden_string))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002366 ret = FAIL;
2367
2368 *option_end = c; // put back for error messages
2369 *arg = option_end;
2370
2371 return ret;
2372}
2373
2374/*
2375 * Allocate a variable for a number constant. Also deals with "0z" for blob.
2376 * Return OK or FAIL.
2377 */
2378 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002379eval_number(
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002380 char_u **arg,
2381 typval_T *rettv,
2382 int evaluate,
Dominique Pellé0268ff32024-07-28 21:12:20 +02002383 int want_string)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002384{
2385 int len;
Bram Moolenaardd9de502021-08-15 13:49:42 +02002386 int skip_quotes = !in_old_script(4);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002387 char_u *p;
2388 int get_float = FALSE;
2389
2390 // We accept a float when the format matches
2391 // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
2392 // strict to avoid backwards compatibility problems.
2393 // With script version 2 and later the leading digit can be
2394 // omitted.
2395 // Don't look for a float after the "." operator, so that
2396 // ":let vers = 1.2.3" doesn't fail.
2397 if (**arg == '.')
2398 p = *arg;
2399 else
Bram Moolenaar29500652021-08-08 15:43:34 +02002400 {
2401 p = *arg + 1;
2402 if (skip_quotes)
2403 for (;;)
2404 {
2405 if (*p == '\'')
2406 ++p;
2407 if (!vim_isdigit(*p))
2408 break;
2409 p = skipdigits(p);
2410 }
2411 else
2412 p = skipdigits(p);
2413 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002414 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
2415 {
2416 get_float = TRUE;
2417 p = skipdigits(p + 2);
2418 if (*p == 'e' || *p == 'E')
2419 {
2420 ++p;
2421 if (*p == '-' || *p == '+')
2422 ++p;
2423 if (!vim_isdigit(*p))
2424 get_float = FALSE;
2425 else
2426 p = skipdigits(p + 1);
2427 }
2428 if (ASCII_ISALPHA(*p) || *p == '.')
2429 get_float = FALSE;
2430 }
2431 if (get_float)
2432 {
2433 float_T f;
2434
Bram Moolenaar29500652021-08-08 15:43:34 +02002435 *arg += string2float(*arg, &f, skip_quotes);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002436 if (evaluate)
2437 {
2438 rettv->v_type = VAR_FLOAT;
2439 rettv->vval.v_float = f;
2440 }
2441 }
2442 else
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002443 if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z'))
2444 {
2445 char_u *bp;
2446 blob_T *blob = NULL; // init for gcc
2447
2448 // Blob constant: 0z0123456789abcdef
2449 if (evaluate)
2450 blob = blob_alloc();
2451 for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2)
2452 {
2453 if (!vim_isxdigit(bp[1]))
2454 {
2455 if (blob != NULL)
2456 {
Bram Moolenaard82a47d2022-01-05 20:24:39 +00002457 emsg(_(e_blob_literal_should_have_an_even_number_of_hex_characters));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002458 ga_clear(&blob->bv_ga);
2459 VIM_CLEAR(blob);
2460 }
2461 return FAIL;
2462 }
2463 if (blob != NULL)
2464 ga_append(&blob->bv_ga,
2465 (hex2nr(*bp) << 4) + hex2nr(*(bp+1)));
2466 if (bp[2] == '.' && vim_isxdigit(bp[3]))
2467 ++bp;
2468 }
2469 if (blob != NULL)
2470 rettv_blob_set(rettv, blob);
2471 *arg = bp;
2472 }
2473 else
2474 {
2475 varnumber_T n;
2476
2477 // decimal, hex or octal number
Bram Moolenaar29500652021-08-08 15:43:34 +02002478 vim_str2nr(*arg, NULL, &len, skip_quotes
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002479 ? STR2NR_NO_OCT + STR2NR_QUOTE
Bram Moolenaar5fb78c32023-03-04 20:47:39 +00002480 : STR2NR_ALL, &n, NULL, 0, TRUE, NULL);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002481 if (len == 0)
2482 {
Bram Moolenaar98cb90e2021-11-30 11:56:22 +00002483 if (evaluate)
2484 semsg(_(e_invalid_expression_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002485 return FAIL;
2486 }
2487 *arg += len;
2488 if (evaluate)
2489 {
2490 rettv->v_type = VAR_NUMBER;
2491 rettv->vval.v_number = n;
2492 }
2493 }
2494 return OK;
2495}
2496
2497/*
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002498 * Evaluate a string constant and put the result in "rettv".
2499 * "*arg" points to the double quote or to after it when "interpolate" is TRUE.
2500 * When "interpolate" is TRUE reduce "{{" to "{", reduce "}}" to "}" and stop
2501 * at a single "{".
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002502 * Return OK or FAIL.
2503 */
2504 int
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002505eval_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002506{
2507 char_u *p;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002508 char_u *end;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002509 int extra = interpolate ? 1 : 0;
2510 int off = interpolate ? 0 : 1;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002511 int len;
2512
2513 // Find the end of the string, skipping backslashed characters.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002514 for (p = *arg + off; *p != NUL && *p != '"'; MB_PTR_ADV(p))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002515 {
2516 if (*p == '\\' && p[1] != NUL)
2517 {
2518 ++p;
2519 // A "\<x>" form occupies at least 4 characters, and produces up
zeertzjqdb088872022-05-02 22:53:45 +01002520 // to 9 characters (6 for the char and 3 for a modifier):
2521 // reserve space for 5 extra.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002522 if (*p == '<')
Bram Moolenaar1e56bda2022-07-29 15:28:27 +01002523 {
2524 int modifiers = 0;
2525 int flags = FSK_KEYCODE | FSK_IN_STRING;
2526
zeertzjqdb088872022-05-02 22:53:45 +01002527 extra += 5;
Bram Moolenaar1e56bda2022-07-29 15:28:27 +01002528
2529 // Skip to the '>' to avoid using '{' inside for string
2530 // interpolation.
2531 if (p[1] != '*')
2532 flags |= FSK_SIMPLIFY;
2533 if (find_special_key(&p, &modifiers, flags, NULL) != 0)
2534 --p; // leave "p" on the ">"
2535 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002536 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002537 else if (interpolate && (*p == '{' || *p == '}'))
2538 {
2539 if (*p == '{' && p[1] != '{') // start of expression
2540 break;
2541 ++p;
2542 if (p[-1] == '}' && *p != '}') // single '}' is an error
2543 {
2544 semsg(_(e_stray_closing_curly_str), *arg);
2545 return FAIL;
2546 }
2547 --extra; // "{{" becomes "{", "}}" becomes "}"
2548 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002549 }
2550
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002551 if (*p != '"' && !(interpolate && *p == '{'))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002552 {
Bram Moolenaare1242042021-12-16 20:56:57 +00002553 semsg(_(e_missing_double_quote_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002554 return FAIL;
2555 }
2556
2557 // If only parsing, set *arg and return here
2558 if (!evaluate)
2559 {
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002560 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002561 return OK;
2562 }
2563
2564 // Copy the string into allocated memory, handling backslashed
2565 // characters.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002566 rettv->v_type = VAR_STRING;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002567 len = (int)(p - *arg + extra);
2568 rettv->vval.v_string = alloc(len);
2569 if (rettv->vval.v_string == NULL)
2570 return FAIL;
2571 end = rettv->vval.v_string;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002572
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002573 for (p = *arg + off; *p != NUL && *p != '"'; )
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002574 {
2575 if (*p == '\\')
2576 {
2577 switch (*++p)
2578 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002579 case 'b': *end++ = BS; ++p; break;
2580 case 'e': *end++ = ESC; ++p; break;
2581 case 'f': *end++ = FF; ++p; break;
2582 case 'n': *end++ = NL; ++p; break;
2583 case 'r': *end++ = CAR; ++p; break;
2584 case 't': *end++ = TAB; ++p; break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002585
2586 case 'X': // hex: "\x1", "\x12"
2587 case 'x':
2588 case 'u': // Unicode: "\u0023"
2589 case 'U':
2590 if (vim_isxdigit(p[1]))
2591 {
2592 int n, nr;
Keith Thompson184f71c2024-01-04 21:19:04 +01002593 int c = SAFE_toupper(*p);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002594
2595 if (c == 'X')
2596 n = 2;
2597 else if (*p == 'u')
2598 n = 4;
2599 else
2600 n = 8;
2601 nr = 0;
2602 while (--n >= 0 && vim_isxdigit(p[1]))
2603 {
2604 ++p;
2605 nr = (nr << 4) + hex2nr(*p);
2606 }
2607 ++p;
2608 // For "\u" store the number according to
2609 // 'encoding'.
2610 if (c != 'X')
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002611 end += (*mb_char2bytes)(nr, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002612 else
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002613 *end++ = nr;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002614 }
2615 break;
2616
2617 // octal: "\1", "\12", "\123"
2618 case '0':
2619 case '1':
2620 case '2':
2621 case '3':
2622 case '4':
2623 case '5':
2624 case '6':
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002625 case '7': *end = *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002626 if (*p >= '0' && *p <= '7')
2627 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002628 *end = (*end << 3) + *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002629 if (*p >= '0' && *p <= '7')
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002630 *end = (*end << 3) + *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002631 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002632 ++end;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002633 break;
2634
Bram Moolenaarfccd93f2020-05-31 22:06:51 +02002635 // Special key, e.g.: "\<C-W>"
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002636 case '<':
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002637 {
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002638 int flags = FSK_KEYCODE | FSK_IN_STRING;
2639
Bram Moolenaarfccd93f2020-05-31 22:06:51 +02002640 if (p[1] != '*')
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002641 flags |= FSK_SIMPLIFY;
zeertzjqdb088872022-05-02 22:53:45 +01002642 extra = trans_special(&p, end, flags, FALSE, NULL);
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002643 if (extra != 0)
2644 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002645 end += extra;
2646 if (end >= rettv->vval.v_string + len)
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002647 iemsg("eval_string() used more space than allocated");
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002648 break;
2649 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002650 }
2651 // FALLTHROUGH
2652
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002653 default: MB_COPY_CHAR(p, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002654 break;
2655 }
2656 }
2657 else
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002658 {
2659 if (interpolate && (*p == '{' || *p == '}'))
2660 {
2661 if (*p == '{' && p[1] != '{') // start of expression
2662 break;
2663 ++p; // reduce "{{" to "{" and "}}" to "}"
2664 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002665 MB_COPY_CHAR(p, end);
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002666 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002667 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002668 *end = NUL;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002669 if (*p == '"' && !interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002670 ++p;
2671 *arg = p;
2672
2673 return OK;
2674}
2675
2676/*
2677 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002678 * When "interpolate" is TRUE reduce "{{" to "{" and stop at a single "{".
2679 * Return OK when a "rettv" was set to the string.
2680 * Return FAIL on error, "rettv" is not set.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002681 */
2682 int
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002683eval_lit_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002684{
2685 char_u *p;
2686 char_u *str;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002687 int reduce = interpolate ? -1 : 0;
2688 int off = interpolate ? 0 : 1;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002689
2690 // Find the end of the string, skipping ''.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002691 for (p = *arg + off; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002692 {
2693 if (*p == '\'')
2694 {
2695 if (p[1] != '\'')
2696 break;
2697 ++reduce;
2698 ++p;
2699 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002700 else if (interpolate)
2701 {
2702 if (*p == '{')
2703 {
2704 if (p[1] != '{')
2705 break;
2706 ++p;
2707 ++reduce;
2708 }
2709 else if (*p == '}')
2710 {
2711 ++p;
2712 if (*p != '}')
2713 {
2714 semsg(_(e_stray_closing_curly_str), *arg);
2715 return FAIL;
2716 }
2717 ++reduce;
2718 }
2719 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002720 }
2721
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002722 if (*p != '\'' && !(interpolate && *p == '{'))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002723 {
Bram Moolenaare1242042021-12-16 20:56:57 +00002724 semsg(_(e_missing_single_quote_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002725 return FAIL;
2726 }
2727
2728 // If only parsing return after setting "*arg"
2729 if (!evaluate)
2730 {
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002731 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002732 return OK;
2733 }
2734
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002735 // Copy the string into allocated memory, handling '' to ' reduction and
2736 // any expressions.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002737 str = alloc((p - *arg) - reduce);
2738 if (str == NULL)
2739 return FAIL;
2740 rettv->v_type = VAR_STRING;
2741 rettv->vval.v_string = str;
2742
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002743 for (p = *arg + off; *p != NUL; )
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002744 {
2745 if (*p == '\'')
2746 {
2747 if (p[1] != '\'')
2748 break;
2749 ++p;
2750 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002751 else if (interpolate && (*p == '{' || *p == '}'))
2752 {
2753 if (*p == '{' && p[1] != '{')
2754 break;
2755 ++p;
2756 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002757 MB_COPY_CHAR(p, str);
2758 }
2759 *str = NUL;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002760 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002761
2762 return OK;
2763}
2764
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002765/*
2766 * Evaluate a single or double quoted string possibly containing expressions.
2767 * "arg" points to the '$'. The result is put in "rettv".
2768 * Returns OK or FAIL.
2769 */
LemonBoy2eaef102022-05-06 13:14:50 +01002770 int
2771eval_interp_string(char_u **arg, typval_T *rettv, int evaluate)
2772{
2773 typval_T tv;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002774 int ret = OK;
2775 int quote;
2776 garray_T ga;
2777 char_u *p;
LemonBoy2eaef102022-05-06 13:14:50 +01002778
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002779 ga_init2(&ga, 1, 80);
2780
2781 // *arg is on the '$' character, move it to the first string character.
2782 ++*arg;
2783 quote = **arg;
2784 ++*arg;
2785
2786 for (;;)
2787 {
2788 // Get the string up to the matching quote or to a single '{'.
2789 // "arg" is advanced to either the quote or the '{'.
2790 if (quote == '"')
2791 ret = eval_string(arg, &tv, evaluate, TRUE);
2792 else
2793 ret = eval_lit_string(arg, &tv, evaluate, TRUE);
2794 if (ret == FAIL)
2795 break;
2796 if (evaluate)
2797 {
2798 ga_concat(&ga, tv.vval.v_string);
2799 clear_tv(&tv);
2800 }
2801
2802 if (**arg != '{')
2803 {
2804 // found terminating quote
2805 ++*arg;
2806 break;
2807 }
Bram Moolenaar70c41242022-05-10 18:11:43 +01002808 p = eval_one_expr_in_str(*arg, &ga, evaluate);
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002809 if (p == NULL)
2810 {
2811 ret = FAIL;
2812 break;
2813 }
2814 *arg = p;
2815 }
LemonBoy2eaef102022-05-06 13:14:50 +01002816
2817 rettv->v_type = VAR_STRING;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002818 if (ret == FAIL || !evaluate || ga_append(&ga, NUL) == FAIL)
2819 {
2820 ga_clear(&ga);
2821 rettv->vval.v_string = NULL;
LemonBoy2eaef102022-05-06 13:14:50 +01002822 return ret;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002823 }
LemonBoy2eaef102022-05-06 13:14:50 +01002824
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002825 rettv->vval.v_string = ga.ga_data;
2826 return OK;
LemonBoy2eaef102022-05-06 13:14:50 +01002827}
2828
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002829/*
2830 * Return a string with the string representation of a variable.
2831 * If the memory is allocated "tofree" is set to it, otherwise NULL.
2832 * "numbuf" is used for a number.
2833 * Puts quotes around strings, so that they can be parsed back by eval().
2834 * May return NULL.
2835 */
2836 char_u *
2837tv2string(
2838 typval_T *tv,
2839 char_u **tofree,
2840 char_u *numbuf,
2841 int copyID)
2842{
2843 return echo_string_core(tv, tofree, numbuf, copyID, FALSE, TRUE, FALSE);
2844}
2845
2846/*
2847 * Get the value of an environment variable.
2848 * "arg" is pointing to the '$'. It is advanced to after the name.
2849 * If the environment variable was not set, silently assume it is empty.
2850 * Return FAIL if the name is invalid.
2851 */
2852 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002853eval_env_var(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002854{
2855 char_u *string = NULL;
2856 int len;
2857 int cc;
2858 char_u *name;
2859 int mustfree = FALSE;
2860
2861 ++*arg;
2862 name = *arg;
2863 len = get_env_len(arg);
2864 if (evaluate)
2865 {
2866 if (len == 0)
2867 return FAIL; // invalid empty name
2868
2869 cc = name[len];
2870 name[len] = NUL;
2871 // first try vim_getenv(), fast for normal environment vars
2872 string = vim_getenv(name, &mustfree);
2873 if (string != NULL && *string != NUL)
2874 {
2875 if (!mustfree)
2876 string = vim_strsave(string);
2877 }
2878 else
2879 {
2880 if (mustfree)
2881 vim_free(string);
2882
2883 // next try expanding things like $VIM and ${HOME}
2884 string = expand_env_save(name - 1);
2885 if (string != NULL && *string == '$')
2886 VIM_CLEAR(string);
2887 }
2888 name[len] = cc;
2889
2890 rettv->v_type = VAR_STRING;
2891 rettv->vval.v_string = string;
Bram Moolenaar16e63e62021-08-11 16:47:26 +02002892 rettv->v_lock = 0;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002893 }
2894
2895 return OK;
2896}
2897
2898/*
2899 * Get the lnum from the first argument.
2900 * Also accepts ".", "$", etc., but that only works for the current buffer.
2901 * Returns -1 on error.
2902 */
2903 linenr_T
2904tv_get_lnum(typval_T *argvars)
2905{
Bram Moolenaar9a963372020-12-21 21:58:46 +01002906 linenr_T lnum = -1;
Bram Moolenaar801cd352022-10-10 16:08:16 +01002907 int did_emsg_before = did_emsg;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002908
Bram Moolenaar56acb092020-08-16 14:48:19 +02002909 if (argvars[0].v_type != VAR_STRING || !in_vim9script())
2910 lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL);
Bram Moolenaar801cd352022-10-10 16:08:16 +01002911 if (lnum <= 0 && did_emsg_before == did_emsg
2912 && argvars[0].v_type != VAR_NUMBER)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002913 {
2914 int fnum;
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002915 pos_T *fp;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002916
Bram Moolenaarf6bdd822021-03-28 16:26:41 +02002917 // no valid number, try using arg like line()
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002918 fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002919 if (fp != NULL)
2920 lnum = fp->lnum;
2921 }
2922 return lnum;
2923}
2924
2925/*
2926 * Get the lnum from the first argument.
2927 * Also accepts "$", then "buf" is used.
2928 * Returns 0 on error.
2929 */
2930 linenr_T
2931tv_get_lnum_buf(typval_T *argvars, buf_T *buf)
2932{
2933 if (argvars[0].v_type == VAR_STRING
2934 && argvars[0].vval.v_string != NULL
2935 && argvars[0].vval.v_string[0] == '$'
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002936 && argvars[0].vval.v_string[1] == NUL
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002937 && buf != NULL)
2938 return buf->b_ml.ml_line_count;
2939 return (linenr_T)tv_get_number_chk(&argvars[0], NULL);
2940}
2941
2942/*
2943 * Get buffer by number or pattern.
2944 */
2945 buf_T *
2946tv_get_buf(typval_T *tv, int curtab_only)
2947{
2948 char_u *name = tv->vval.v_string;
2949 buf_T *buf;
2950
2951 if (tv->v_type == VAR_NUMBER)
2952 return buflist_findnr((int)tv->vval.v_number);
2953 if (tv->v_type != VAR_STRING)
2954 return NULL;
2955 if (name == NULL || *name == NUL)
2956 return curbuf;
2957 if (name[0] == '$' && name[1] == NUL)
2958 return lastbuf;
2959
2960 buf = buflist_find_by_name(name, curtab_only);
2961
2962 // If not found, try expanding the name, like done for bufexists().
2963 if (buf == NULL)
2964 buf = find_buffer(tv);
2965
2966 return buf;
2967}
2968
Bram Moolenaar3767e3a2020-09-01 23:06:01 +02002969/*
2970 * Like tv_get_buf() but give an error message is the type is wrong.
2971 */
2972 buf_T *
2973tv_get_buf_from_arg(typval_T *tv)
2974{
2975 buf_T *buf;
2976
2977 ++emsg_off;
2978 buf = tv_get_buf(tv, FALSE);
2979 --emsg_off;
2980 if (buf == NULL
2981 && tv->v_type != VAR_NUMBER
2982 && tv->v_type != VAR_STRING)
2983 // issue errmsg for type error
2984 (void)tv_get_number(tv);
2985 return buf;
2986}
2987
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002988#endif // FEAT_EVAL