blob: 59ac61133e1560c3bd208354aba72f6efebd5865 [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))
2098 || (tv->v_type == VAR_DICT
2099 && tv->vval.v_dict != NULL
2100 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
2101}
2102
2103 static int
2104func_equal(
2105 typval_T *tv1,
2106 typval_T *tv2,
2107 int ic) // ignore case
2108{
2109 char_u *s1, *s2;
2110 dict_T *d1, *d2;
2111 int a1, a2;
2112 int i;
2113
2114 // empty and NULL function name considered the same
2115 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
2116 : partial_name(tv1->vval.v_partial);
2117 if (s1 != NULL && *s1 == NUL)
2118 s1 = NULL;
2119 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
2120 : partial_name(tv2->vval.v_partial);
2121 if (s2 != NULL && *s2 == NUL)
2122 s2 = NULL;
2123 if (s1 == NULL || s2 == NULL)
2124 {
2125 if (s1 != s2)
2126 return FALSE;
2127 }
2128 else if (STRCMP(s1, s2) != 0)
2129 return FALSE;
2130
2131 // empty dict and NULL dict is different
2132 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
2133 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
2134 if (d1 == NULL || d2 == NULL)
2135 {
2136 if (d1 != d2)
2137 return FALSE;
2138 }
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002139 else if (!dict_equal(d1, d2, ic))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002140 return FALSE;
2141
2142 // empty list and no list considered the same
2143 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
2144 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
2145 if (a1 != a2)
2146 return FALSE;
2147 for (i = 0; i < a1; ++i)
2148 if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002149 tv2->vval.v_partial->pt_argv + i, ic))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002150 return FALSE;
2151
2152 return TRUE;
2153}
2154
2155/*
2156 * Return TRUE if "tv1" and "tv2" have the same value.
2157 * Compares the items just like "==" would compare them, but strings and
2158 * numbers are different. Floats and numbers are also different.
2159 */
2160 int
2161tv_equal(
2162 typval_T *tv1,
2163 typval_T *tv2,
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002164 int ic) // ignore case
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002165{
2166 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2167 char_u *s1, *s2;
2168 static int recursive_cnt = 0; // catch recursive loops
2169 int r;
2170 static int tv_equal_recurse_limit;
2171
2172 // Catch lists and dicts that have an endless loop by limiting
2173 // recursiveness to a limit. We guess they are equal then.
2174 // A fixed limit has the problem of still taking an awful long time.
2175 // Reduce the limit every time running into it. That should work fine for
2176 // deeply linked structures that are not recursively linked and catch
2177 // recursiveness quickly.
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002178 if (recursive_cnt == 0)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002179 tv_equal_recurse_limit = 1000;
2180 if (recursive_cnt >= tv_equal_recurse_limit)
2181 {
2182 --tv_equal_recurse_limit;
2183 return TRUE;
2184 }
2185
2186 // For VAR_FUNC and VAR_PARTIAL compare the function name, bound dict and
2187 // arguments.
2188 if ((tv1->v_type == VAR_FUNC
2189 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
2190 && (tv2->v_type == VAR_FUNC
2191 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
2192 {
2193 ++recursive_cnt;
2194 r = func_equal(tv1, tv2, ic);
2195 --recursive_cnt;
2196 return r;
2197 }
2198
Bram Moolenaar418a29f2021-02-10 22:23:41 +01002199 if (tv1->v_type != tv2->v_type
2200 && ((tv1->v_type != VAR_BOOL && tv1->v_type != VAR_SPECIAL)
2201 || (tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL)))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002202 return FALSE;
2203
2204 switch (tv1->v_type)
2205 {
2206 case VAR_LIST:
2207 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002208 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002209 --recursive_cnt;
2210 return r;
2211
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01002212 case VAR_TUPLE:
2213 ++recursive_cnt;
2214 r = tuple_equal(tv1->vval.v_tuple, tv2->vval.v_tuple, ic);
2215 --recursive_cnt;
2216 return r;
2217
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002218 case VAR_DICT:
2219 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002220 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002221 --recursive_cnt;
2222 return r;
2223
2224 case VAR_BLOB:
2225 return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
2226
2227 case VAR_NUMBER:
2228 case VAR_BOOL:
2229 case VAR_SPECIAL:
2230 return tv1->vval.v_number == tv2->vval.v_number;
2231
2232 case VAR_STRING:
2233 s1 = tv_get_string_buf(tv1, buf1);
2234 s2 = tv_get_string_buf(tv2, buf2);
2235 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
2236
2237 case VAR_FLOAT:
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002238 return tv1->vval.v_float == tv2->vval.v_float;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002239 case VAR_JOB:
2240#ifdef FEAT_JOB_CHANNEL
2241 return tv1->vval.v_job == tv2->vval.v_job;
2242#endif
2243 case VAR_CHANNEL:
2244#ifdef FEAT_JOB_CHANNEL
2245 return tv1->vval.v_channel == tv2->vval.v_channel;
2246#endif
Bram Moolenaarf18332f2021-05-07 17:55:55 +02002247 case VAR_INSTR:
2248 return tv1->vval.v_instr == tv2->vval.v_instr;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002249
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002250 case VAR_CLASS:
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00002251 // A class only exists once, equality is identity.
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002252 return tv1->vval.v_class == tv2->vval.v_class;
2253
2254 case VAR_OBJECT:
Ernie Raelf0e69142024-06-22 11:12:00 +02002255 ++recursive_cnt;
Yinzuo Jiang7ccd1a22024-07-04 17:20:53 +02002256 r = object_equal(tv1->vval.v_object, tv2->vval.v_object, ic);
Ernie Raelf0e69142024-06-22 11:12:00 +02002257 --recursive_cnt;
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00002258 return r;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002259
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002260 case VAR_PARTIAL:
2261 return tv1->vval.v_partial == tv2->vval.v_partial;
2262
2263 case VAR_FUNC:
2264 return tv1->vval.v_string == tv2->vval.v_string;
2265
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02002266 case VAR_TYPEALIAS:
2267 return tv1->vval.v_typealias == tv2->vval.v_typealias;
2268
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002269 case VAR_UNKNOWN:
2270 case VAR_ANY:
2271 case VAR_VOID:
2272 break;
2273 }
2274
2275 // VAR_UNKNOWN can be the result of a invalid expression, let's say it
2276 // does not equal anything, not even itself.
2277 return FALSE;
2278}
2279
2280/*
2281 * Get an option value.
2282 * "arg" points to the '&' or '+' before the option name.
2283 * "arg" is advanced to character after the option name.
2284 * Return OK or FAIL.
2285 */
2286 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002287eval_option(
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002288 char_u **arg,
2289 typval_T *rettv, // when NULL, only check if option exists
2290 int evaluate)
2291{
2292 char_u *option_end;
2293 long numval;
2294 char_u *stringval;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002295 getoption_T opt_type;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002296 int c;
2297 int working = (**arg == '+'); // has("+option")
2298 int ret = OK;
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002299 int scope;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002300
2301 // Isolate the option name and find its value.
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002302 option_end = find_option_end(arg, &scope);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002303 if (option_end == NULL)
2304 {
2305 if (rettv != NULL)
Bram Moolenaare1242042021-12-16 20:56:57 +00002306 semsg(_(e_option_name_missing_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002307 return FAIL;
2308 }
2309
2310 if (!evaluate)
2311 {
2312 *arg = option_end;
2313 return OK;
2314 }
2315
2316 c = *option_end;
2317 *option_end = NUL;
2318 opt_type = get_option_value(*arg, &numval,
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002319 rettv == NULL ? NULL : &stringval, NULL, scope);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002320
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002321 if (opt_type == gov_unknown)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002322 {
2323 if (rettv != NULL)
Bram Moolenaare1242042021-12-16 20:56:57 +00002324 semsg(_(e_unknown_option_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002325 ret = FAIL;
2326 }
2327 else if (rettv != NULL)
2328 {
Bram Moolenaara79925a2021-01-05 17:50:28 +01002329 rettv->v_lock = 0;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002330 if (opt_type == gov_hidden_string)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002331 {
2332 rettv->v_type = VAR_STRING;
2333 rettv->vval.v_string = NULL;
2334 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002335 else if (opt_type == gov_hidden_bool || opt_type == gov_hidden_number)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002336 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002337 rettv->v_type = in_vim9script() && opt_type == gov_hidden_bool
2338 ? VAR_BOOL : VAR_NUMBER;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002339 rettv->vval.v_number = 0;
2340 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002341 else if (opt_type == gov_bool || opt_type == gov_number)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002342 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002343 if (in_vim9script() && opt_type == gov_bool)
2344 {
2345 rettv->v_type = VAR_BOOL;
2346 rettv->vval.v_number = numval ? VVAL_TRUE : VVAL_FALSE;
2347 }
2348 else
2349 {
2350 rettv->v_type = VAR_NUMBER;
2351 rettv->vval.v_number = numval;
2352 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002353 }
2354 else // string option
2355 {
2356 rettv->v_type = VAR_STRING;
2357 rettv->vval.v_string = stringval;
2358 }
2359 }
Bram Moolenaardd1f4262020-12-31 17:41:01 +01002360 else if (working && (opt_type == gov_hidden_bool
2361 || opt_type == gov_hidden_number
2362 || opt_type == gov_hidden_string))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002363 ret = FAIL;
2364
2365 *option_end = c; // put back for error messages
2366 *arg = option_end;
2367
2368 return ret;
2369}
2370
2371/*
2372 * Allocate a variable for a number constant. Also deals with "0z" for blob.
2373 * Return OK or FAIL.
2374 */
2375 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002376eval_number(
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002377 char_u **arg,
2378 typval_T *rettv,
2379 int evaluate,
Dominique Pellé0268ff32024-07-28 21:12:20 +02002380 int want_string)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002381{
2382 int len;
Bram Moolenaardd9de502021-08-15 13:49:42 +02002383 int skip_quotes = !in_old_script(4);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002384 char_u *p;
2385 int get_float = FALSE;
2386
2387 // We accept a float when the format matches
2388 // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
2389 // strict to avoid backwards compatibility problems.
2390 // With script version 2 and later the leading digit can be
2391 // omitted.
2392 // Don't look for a float after the "." operator, so that
2393 // ":let vers = 1.2.3" doesn't fail.
2394 if (**arg == '.')
2395 p = *arg;
2396 else
Bram Moolenaar29500652021-08-08 15:43:34 +02002397 {
2398 p = *arg + 1;
2399 if (skip_quotes)
2400 for (;;)
2401 {
2402 if (*p == '\'')
2403 ++p;
2404 if (!vim_isdigit(*p))
2405 break;
2406 p = skipdigits(p);
2407 }
2408 else
2409 p = skipdigits(p);
2410 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002411 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
2412 {
2413 get_float = TRUE;
2414 p = skipdigits(p + 2);
2415 if (*p == 'e' || *p == 'E')
2416 {
2417 ++p;
2418 if (*p == '-' || *p == '+')
2419 ++p;
2420 if (!vim_isdigit(*p))
2421 get_float = FALSE;
2422 else
2423 p = skipdigits(p + 1);
2424 }
2425 if (ASCII_ISALPHA(*p) || *p == '.')
2426 get_float = FALSE;
2427 }
2428 if (get_float)
2429 {
2430 float_T f;
2431
Bram Moolenaar29500652021-08-08 15:43:34 +02002432 *arg += string2float(*arg, &f, skip_quotes);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002433 if (evaluate)
2434 {
2435 rettv->v_type = VAR_FLOAT;
2436 rettv->vval.v_float = f;
2437 }
2438 }
2439 else
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002440 if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z'))
2441 {
2442 char_u *bp;
2443 blob_T *blob = NULL; // init for gcc
2444
2445 // Blob constant: 0z0123456789abcdef
2446 if (evaluate)
2447 blob = blob_alloc();
2448 for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2)
2449 {
2450 if (!vim_isxdigit(bp[1]))
2451 {
2452 if (blob != NULL)
2453 {
Bram Moolenaard82a47d2022-01-05 20:24:39 +00002454 emsg(_(e_blob_literal_should_have_an_even_number_of_hex_characters));
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002455 ga_clear(&blob->bv_ga);
2456 VIM_CLEAR(blob);
2457 }
2458 return FAIL;
2459 }
2460 if (blob != NULL)
2461 ga_append(&blob->bv_ga,
2462 (hex2nr(*bp) << 4) + hex2nr(*(bp+1)));
2463 if (bp[2] == '.' && vim_isxdigit(bp[3]))
2464 ++bp;
2465 }
2466 if (blob != NULL)
2467 rettv_blob_set(rettv, blob);
2468 *arg = bp;
2469 }
2470 else
2471 {
2472 varnumber_T n;
2473
2474 // decimal, hex or octal number
Bram Moolenaar29500652021-08-08 15:43:34 +02002475 vim_str2nr(*arg, NULL, &len, skip_quotes
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002476 ? STR2NR_NO_OCT + STR2NR_QUOTE
Bram Moolenaar5fb78c32023-03-04 20:47:39 +00002477 : STR2NR_ALL, &n, NULL, 0, TRUE, NULL);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002478 if (len == 0)
2479 {
Bram Moolenaar98cb90e2021-11-30 11:56:22 +00002480 if (evaluate)
2481 semsg(_(e_invalid_expression_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002482 return FAIL;
2483 }
2484 *arg += len;
2485 if (evaluate)
2486 {
2487 rettv->v_type = VAR_NUMBER;
2488 rettv->vval.v_number = n;
2489 }
2490 }
2491 return OK;
2492}
2493
2494/*
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002495 * Evaluate a string constant and put the result in "rettv".
2496 * "*arg" points to the double quote or to after it when "interpolate" is TRUE.
2497 * When "interpolate" is TRUE reduce "{{" to "{", reduce "}}" to "}" and stop
2498 * at a single "{".
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002499 * Return OK or FAIL.
2500 */
2501 int
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002502eval_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002503{
2504 char_u *p;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002505 char_u *end;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002506 int extra = interpolate ? 1 : 0;
2507 int off = interpolate ? 0 : 1;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002508 int len;
2509
2510 // Find the end of the string, skipping backslashed characters.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002511 for (p = *arg + off; *p != NUL && *p != '"'; MB_PTR_ADV(p))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002512 {
2513 if (*p == '\\' && p[1] != NUL)
2514 {
2515 ++p;
2516 // A "\<x>" form occupies at least 4 characters, and produces up
zeertzjqdb088872022-05-02 22:53:45 +01002517 // to 9 characters (6 for the char and 3 for a modifier):
2518 // reserve space for 5 extra.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002519 if (*p == '<')
Bram Moolenaar1e56bda2022-07-29 15:28:27 +01002520 {
2521 int modifiers = 0;
2522 int flags = FSK_KEYCODE | FSK_IN_STRING;
2523
zeertzjqdb088872022-05-02 22:53:45 +01002524 extra += 5;
Bram Moolenaar1e56bda2022-07-29 15:28:27 +01002525
2526 // Skip to the '>' to avoid using '{' inside for string
2527 // interpolation.
2528 if (p[1] != '*')
2529 flags |= FSK_SIMPLIFY;
2530 if (find_special_key(&p, &modifiers, flags, NULL) != 0)
2531 --p; // leave "p" on the ">"
2532 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002533 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002534 else if (interpolate && (*p == '{' || *p == '}'))
2535 {
2536 if (*p == '{' && p[1] != '{') // start of expression
2537 break;
2538 ++p;
2539 if (p[-1] == '}' && *p != '}') // single '}' is an error
2540 {
2541 semsg(_(e_stray_closing_curly_str), *arg);
2542 return FAIL;
2543 }
2544 --extra; // "{{" becomes "{", "}}" becomes "}"
2545 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002546 }
2547
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002548 if (*p != '"' && !(interpolate && *p == '{'))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002549 {
Bram Moolenaare1242042021-12-16 20:56:57 +00002550 semsg(_(e_missing_double_quote_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002551 return FAIL;
2552 }
2553
2554 // If only parsing, set *arg and return here
2555 if (!evaluate)
2556 {
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002557 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002558 return OK;
2559 }
2560
2561 // Copy the string into allocated memory, handling backslashed
2562 // characters.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002563 rettv->v_type = VAR_STRING;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002564 len = (int)(p - *arg + extra);
2565 rettv->vval.v_string = alloc(len);
2566 if (rettv->vval.v_string == NULL)
2567 return FAIL;
2568 end = rettv->vval.v_string;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002569
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002570 for (p = *arg + off; *p != NUL && *p != '"'; )
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002571 {
2572 if (*p == '\\')
2573 {
2574 switch (*++p)
2575 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002576 case 'b': *end++ = BS; ++p; break;
2577 case 'e': *end++ = ESC; ++p; break;
2578 case 'f': *end++ = FF; ++p; break;
2579 case 'n': *end++ = NL; ++p; break;
2580 case 'r': *end++ = CAR; ++p; break;
2581 case 't': *end++ = TAB; ++p; break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002582
2583 case 'X': // hex: "\x1", "\x12"
2584 case 'x':
2585 case 'u': // Unicode: "\u0023"
2586 case 'U':
2587 if (vim_isxdigit(p[1]))
2588 {
2589 int n, nr;
Keith Thompson184f71c2024-01-04 21:19:04 +01002590 int c = SAFE_toupper(*p);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002591
2592 if (c == 'X')
2593 n = 2;
2594 else if (*p == 'u')
2595 n = 4;
2596 else
2597 n = 8;
2598 nr = 0;
2599 while (--n >= 0 && vim_isxdigit(p[1]))
2600 {
2601 ++p;
2602 nr = (nr << 4) + hex2nr(*p);
2603 }
2604 ++p;
2605 // For "\u" store the number according to
2606 // 'encoding'.
2607 if (c != 'X')
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002608 end += (*mb_char2bytes)(nr, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002609 else
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002610 *end++ = nr;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002611 }
2612 break;
2613
2614 // octal: "\1", "\12", "\123"
2615 case '0':
2616 case '1':
2617 case '2':
2618 case '3':
2619 case '4':
2620 case '5':
2621 case '6':
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002622 case '7': *end = *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002623 if (*p >= '0' && *p <= '7')
2624 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002625 *end = (*end << 3) + *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002626 if (*p >= '0' && *p <= '7')
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002627 *end = (*end << 3) + *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002628 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002629 ++end;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002630 break;
2631
Bram Moolenaarfccd93f2020-05-31 22:06:51 +02002632 // Special key, e.g.: "\<C-W>"
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002633 case '<':
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002634 {
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002635 int flags = FSK_KEYCODE | FSK_IN_STRING;
2636
Bram Moolenaarfccd93f2020-05-31 22:06:51 +02002637 if (p[1] != '*')
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002638 flags |= FSK_SIMPLIFY;
zeertzjqdb088872022-05-02 22:53:45 +01002639 extra = trans_special(&p, end, flags, FALSE, NULL);
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002640 if (extra != 0)
2641 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002642 end += extra;
2643 if (end >= rettv->vval.v_string + len)
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002644 iemsg("eval_string() used more space than allocated");
Bram Moolenaarebe9d342020-05-30 21:52:54 +02002645 break;
2646 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002647 }
2648 // FALLTHROUGH
2649
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002650 default: MB_COPY_CHAR(p, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002651 break;
2652 }
2653 }
2654 else
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002655 {
2656 if (interpolate && (*p == '{' || *p == '}'))
2657 {
2658 if (*p == '{' && p[1] != '{') // start of expression
2659 break;
2660 ++p; // reduce "{{" to "{" and "}}" to "}"
2661 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002662 MB_COPY_CHAR(p, end);
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002663 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002664 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02002665 *end = NUL;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002666 if (*p == '"' && !interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002667 ++p;
2668 *arg = p;
2669
2670 return OK;
2671}
2672
2673/*
2674 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002675 * When "interpolate" is TRUE reduce "{{" to "{" and stop at a single "{".
2676 * Return OK when a "rettv" was set to the string.
2677 * Return FAIL on error, "rettv" is not set.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002678 */
2679 int
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002680eval_lit_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002681{
2682 char_u *p;
2683 char_u *str;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002684 int reduce = interpolate ? -1 : 0;
2685 int off = interpolate ? 0 : 1;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002686
2687 // Find the end of the string, skipping ''.
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002688 for (p = *arg + off; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002689 {
2690 if (*p == '\'')
2691 {
2692 if (p[1] != '\'')
2693 break;
2694 ++reduce;
2695 ++p;
2696 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002697 else if (interpolate)
2698 {
2699 if (*p == '{')
2700 {
2701 if (p[1] != '{')
2702 break;
2703 ++p;
2704 ++reduce;
2705 }
2706 else if (*p == '}')
2707 {
2708 ++p;
2709 if (*p != '}')
2710 {
2711 semsg(_(e_stray_closing_curly_str), *arg);
2712 return FAIL;
2713 }
2714 ++reduce;
2715 }
2716 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002717 }
2718
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002719 if (*p != '\'' && !(interpolate && *p == '{'))
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002720 {
Bram Moolenaare1242042021-12-16 20:56:57 +00002721 semsg(_(e_missing_single_quote_str), *arg);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002722 return FAIL;
2723 }
2724
2725 // If only parsing return after setting "*arg"
2726 if (!evaluate)
2727 {
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002728 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002729 return OK;
2730 }
2731
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002732 // Copy the string into allocated memory, handling '' to ' reduction and
2733 // any expressions.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002734 str = alloc((p - *arg) - reduce);
2735 if (str == NULL)
2736 return FAIL;
2737 rettv->v_type = VAR_STRING;
2738 rettv->vval.v_string = str;
2739
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002740 for (p = *arg + off; *p != NUL; )
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002741 {
2742 if (*p == '\'')
2743 {
2744 if (p[1] != '\'')
2745 break;
2746 ++p;
2747 }
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002748 else if (interpolate && (*p == '{' || *p == '}'))
2749 {
2750 if (*p == '{' && p[1] != '{')
2751 break;
2752 ++p;
2753 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002754 MB_COPY_CHAR(p, str);
2755 }
2756 *str = NUL;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002757 *arg = p + off;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002758
2759 return OK;
2760}
2761
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002762/*
2763 * Evaluate a single or double quoted string possibly containing expressions.
2764 * "arg" points to the '$'. The result is put in "rettv".
2765 * Returns OK or FAIL.
2766 */
LemonBoy2eaef102022-05-06 13:14:50 +01002767 int
2768eval_interp_string(char_u **arg, typval_T *rettv, int evaluate)
2769{
2770 typval_T tv;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002771 int ret = OK;
2772 int quote;
2773 garray_T ga;
2774 char_u *p;
LemonBoy2eaef102022-05-06 13:14:50 +01002775
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002776 ga_init2(&ga, 1, 80);
2777
2778 // *arg is on the '$' character, move it to the first string character.
2779 ++*arg;
2780 quote = **arg;
2781 ++*arg;
2782
2783 for (;;)
2784 {
2785 // Get the string up to the matching quote or to a single '{'.
2786 // "arg" is advanced to either the quote or the '{'.
2787 if (quote == '"')
2788 ret = eval_string(arg, &tv, evaluate, TRUE);
2789 else
2790 ret = eval_lit_string(arg, &tv, evaluate, TRUE);
2791 if (ret == FAIL)
2792 break;
2793 if (evaluate)
2794 {
2795 ga_concat(&ga, tv.vval.v_string);
2796 clear_tv(&tv);
2797 }
2798
2799 if (**arg != '{')
2800 {
2801 // found terminating quote
2802 ++*arg;
2803 break;
2804 }
Bram Moolenaar70c41242022-05-10 18:11:43 +01002805 p = eval_one_expr_in_str(*arg, &ga, evaluate);
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002806 if (p == NULL)
2807 {
2808 ret = FAIL;
2809 break;
2810 }
2811 *arg = p;
2812 }
LemonBoy2eaef102022-05-06 13:14:50 +01002813
2814 rettv->v_type = VAR_STRING;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002815 if (ret == FAIL || !evaluate || ga_append(&ga, NUL) == FAIL)
2816 {
2817 ga_clear(&ga);
2818 rettv->vval.v_string = NULL;
LemonBoy2eaef102022-05-06 13:14:50 +01002819 return ret;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002820 }
LemonBoy2eaef102022-05-06 13:14:50 +01002821
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002822 rettv->vval.v_string = ga.ga_data;
2823 return OK;
LemonBoy2eaef102022-05-06 13:14:50 +01002824}
2825
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002826/*
2827 * Return a string with the string representation of a variable.
2828 * If the memory is allocated "tofree" is set to it, otherwise NULL.
2829 * "numbuf" is used for a number.
2830 * Puts quotes around strings, so that they can be parsed back by eval().
2831 * May return NULL.
2832 */
2833 char_u *
2834tv2string(
2835 typval_T *tv,
2836 char_u **tofree,
2837 char_u *numbuf,
2838 int copyID)
2839{
2840 return echo_string_core(tv, tofree, numbuf, copyID, FALSE, TRUE, FALSE);
2841}
2842
2843/*
2844 * Get the value of an environment variable.
2845 * "arg" is pointing to the '$'. It is advanced to after the name.
2846 * If the environment variable was not set, silently assume it is empty.
2847 * Return FAIL if the name is invalid.
2848 */
2849 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002850eval_env_var(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002851{
2852 char_u *string = NULL;
2853 int len;
2854 int cc;
2855 char_u *name;
2856 int mustfree = FALSE;
2857
2858 ++*arg;
2859 name = *arg;
2860 len = get_env_len(arg);
2861 if (evaluate)
2862 {
2863 if (len == 0)
2864 return FAIL; // invalid empty name
2865
2866 cc = name[len];
2867 name[len] = NUL;
2868 // first try vim_getenv(), fast for normal environment vars
2869 string = vim_getenv(name, &mustfree);
2870 if (string != NULL && *string != NUL)
2871 {
2872 if (!mustfree)
2873 string = vim_strsave(string);
2874 }
2875 else
2876 {
2877 if (mustfree)
2878 vim_free(string);
2879
2880 // next try expanding things like $VIM and ${HOME}
2881 string = expand_env_save(name - 1);
2882 if (string != NULL && *string == '$')
2883 VIM_CLEAR(string);
2884 }
2885 name[len] = cc;
2886
2887 rettv->v_type = VAR_STRING;
2888 rettv->vval.v_string = string;
Bram Moolenaar16e63e62021-08-11 16:47:26 +02002889 rettv->v_lock = 0;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002890 }
2891
2892 return OK;
2893}
2894
2895/*
2896 * Get the lnum from the first argument.
2897 * Also accepts ".", "$", etc., but that only works for the current buffer.
2898 * Returns -1 on error.
2899 */
2900 linenr_T
2901tv_get_lnum(typval_T *argvars)
2902{
Bram Moolenaar9a963372020-12-21 21:58:46 +01002903 linenr_T lnum = -1;
Bram Moolenaar801cd352022-10-10 16:08:16 +01002904 int did_emsg_before = did_emsg;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002905
Bram Moolenaar56acb092020-08-16 14:48:19 +02002906 if (argvars[0].v_type != VAR_STRING || !in_vim9script())
2907 lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL);
Bram Moolenaar801cd352022-10-10 16:08:16 +01002908 if (lnum <= 0 && did_emsg_before == did_emsg
2909 && argvars[0].v_type != VAR_NUMBER)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002910 {
2911 int fnum;
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002912 pos_T *fp;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002913
Bram Moolenaarf6bdd822021-03-28 16:26:41 +02002914 // no valid number, try using arg like line()
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002915 fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002916 if (fp != NULL)
2917 lnum = fp->lnum;
2918 }
2919 return lnum;
2920}
2921
2922/*
2923 * Get the lnum from the first argument.
2924 * Also accepts "$", then "buf" is used.
2925 * Returns 0 on error.
2926 */
2927 linenr_T
2928tv_get_lnum_buf(typval_T *argvars, buf_T *buf)
2929{
2930 if (argvars[0].v_type == VAR_STRING
2931 && argvars[0].vval.v_string != NULL
2932 && argvars[0].vval.v_string[0] == '$'
Bram Moolenaar8b6256f2021-12-28 11:24:49 +00002933 && argvars[0].vval.v_string[1] == NUL
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002934 && buf != NULL)
2935 return buf->b_ml.ml_line_count;
2936 return (linenr_T)tv_get_number_chk(&argvars[0], NULL);
2937}
2938
2939/*
2940 * Get buffer by number or pattern.
2941 */
2942 buf_T *
2943tv_get_buf(typval_T *tv, int curtab_only)
2944{
2945 char_u *name = tv->vval.v_string;
2946 buf_T *buf;
2947
2948 if (tv->v_type == VAR_NUMBER)
2949 return buflist_findnr((int)tv->vval.v_number);
2950 if (tv->v_type != VAR_STRING)
2951 return NULL;
2952 if (name == NULL || *name == NUL)
2953 return curbuf;
2954 if (name[0] == '$' && name[1] == NUL)
2955 return lastbuf;
2956
2957 buf = buflist_find_by_name(name, curtab_only);
2958
2959 // If not found, try expanding the name, like done for bufexists().
2960 if (buf == NULL)
2961 buf = find_buffer(tv);
2962
2963 return buf;
2964}
2965
Bram Moolenaar3767e3a2020-09-01 23:06:01 +02002966/*
2967 * Like tv_get_buf() but give an error message is the type is wrong.
2968 */
2969 buf_T *
2970tv_get_buf_from_arg(typval_T *tv)
2971{
2972 buf_T *buf;
2973
2974 ++emsg_off;
2975 buf = tv_get_buf(tv, FALSE);
2976 --emsg_off;
2977 if (buf == NULL
2978 && tv->v_type != VAR_NUMBER
2979 && tv->v_type != VAR_STRING)
2980 // issue errmsg for type error
2981 (void)tv_get_number(tv);
2982 return buf;
2983}
2984
Bram Moolenaar367d59e2020-05-30 17:06:14 +02002985#endif // FEAT_EVAL