blob: 406a193be33a0bb3ad68e4aeb2ffb9b59ea51d37 [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{
55 if (varp != NULL)
56 {
57 switch (varp->v_type)
58 {
59 case VAR_FUNC:
60 func_unref(varp->vval.v_string);
61 // FALLTHROUGH
62 case VAR_STRING:
63 vim_free(varp->vval.v_string);
64 break;
65 case VAR_PARTIAL:
66 partial_unref(varp->vval.v_partial);
67 break;
68 case VAR_BLOB:
69 blob_unref(varp->vval.v_blob);
70 break;
71 case VAR_LIST:
72 list_unref(varp->vval.v_list);
73 break;
74 case VAR_DICT:
75 dict_unref(varp->vval.v_dict);
76 break;
77 case VAR_JOB:
78#ifdef FEAT_JOB_CHANNEL
79 job_unref(varp->vval.v_job);
80 break;
81#endif
82 case VAR_CHANNEL:
83#ifdef FEAT_JOB_CHANNEL
84 channel_unref(varp->vval.v_channel);
85 break;
86#endif
87 case VAR_NUMBER:
88 case VAR_FLOAT:
89 case VAR_ANY:
90 case VAR_UNKNOWN:
91 case VAR_VOID:
92 case VAR_BOOL:
93 case VAR_SPECIAL:
94 break;
95 }
96 vim_free(varp);
97 }
98}
99
100/*
101 * Free the memory for a variable value and set the value to NULL or 0.
102 */
103 void
104clear_tv(typval_T *varp)
105{
106 if (varp != NULL)
107 {
108 switch (varp->v_type)
109 {
110 case VAR_FUNC:
111 func_unref(varp->vval.v_string);
112 // FALLTHROUGH
113 case VAR_STRING:
114 VIM_CLEAR(varp->vval.v_string);
115 break;
116 case VAR_PARTIAL:
117 partial_unref(varp->vval.v_partial);
118 varp->vval.v_partial = NULL;
119 break;
120 case VAR_BLOB:
121 blob_unref(varp->vval.v_blob);
122 varp->vval.v_blob = NULL;
123 break;
124 case VAR_LIST:
125 list_unref(varp->vval.v_list);
126 varp->vval.v_list = NULL;
127 break;
128 case VAR_DICT:
129 dict_unref(varp->vval.v_dict);
130 varp->vval.v_dict = NULL;
131 break;
132 case VAR_NUMBER:
133 case VAR_BOOL:
134 case VAR_SPECIAL:
135 varp->vval.v_number = 0;
136 break;
137 case VAR_FLOAT:
138#ifdef FEAT_FLOAT
139 varp->vval.v_float = 0.0;
140 break;
141#endif
142 case VAR_JOB:
143#ifdef FEAT_JOB_CHANNEL
144 job_unref(varp->vval.v_job);
145 varp->vval.v_job = NULL;
146#endif
147 break;
148 case VAR_CHANNEL:
149#ifdef FEAT_JOB_CHANNEL
150 channel_unref(varp->vval.v_channel);
151 varp->vval.v_channel = NULL;
152#endif
153 case VAR_UNKNOWN:
154 case VAR_ANY:
155 case VAR_VOID:
156 break;
157 }
158 varp->v_lock = 0;
159 }
160}
161
162/*
163 * Set the value of a variable to NULL without freeing items.
164 */
165 void
166init_tv(typval_T *varp)
167{
168 if (varp != NULL)
169 CLEAR_POINTER(varp);
170}
171
172/*
173 * Get the number value of a variable.
174 * If it is a String variable, uses vim_str2nr().
175 * For incompatible types, return 0.
176 * tv_get_number_chk() is similar to tv_get_number(), but informs the
177 * caller of incompatible types: it sets *denote to TRUE if "denote"
178 * is not NULL or returns -1 otherwise.
179 */
180 varnumber_T
181tv_get_number(typval_T *varp)
182{
183 int error = FALSE;
184
185 return tv_get_number_chk(varp, &error); // return 0L on error
186}
187
188 varnumber_T
189tv_get_number_chk(typval_T *varp, int *denote)
190{
191 varnumber_T n = 0L;
192
193 switch (varp->v_type)
194 {
195 case VAR_NUMBER:
196 return varp->vval.v_number;
197 case VAR_FLOAT:
198#ifdef FEAT_FLOAT
199 emsg(_("E805: Using a Float as a Number"));
200 break;
201#endif
202 case VAR_FUNC:
203 case VAR_PARTIAL:
204 emsg(_("E703: Using a Funcref as a Number"));
205 break;
206 case VAR_STRING:
Bram Moolenaar56acb092020-08-16 14:48:19 +0200207 if (in_vim9script())
208 {
209 emsg(_(e_using_string_as_number));
210 break;
211 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200212 if (varp->vval.v_string != NULL)
213 vim_str2nr(varp->vval.v_string, NULL, NULL,
214 STR2NR_ALL, &n, NULL, 0, FALSE);
215 return n;
216 case VAR_LIST:
217 emsg(_("E745: Using a List as a Number"));
218 break;
219 case VAR_DICT:
220 emsg(_("E728: Using a Dictionary as a Number"));
221 break;
222 case VAR_BOOL:
223 case VAR_SPECIAL:
Bram Moolenaar56acb092020-08-16 14:48:19 +0200224 if (in_vim9script())
225 {
226 emsg(_("E611: Using a Special as a Number"));
227 break;
228 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200229 return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
230 case VAR_JOB:
231#ifdef FEAT_JOB_CHANNEL
232 emsg(_("E910: Using a Job as a Number"));
233 break;
234#endif
235 case VAR_CHANNEL:
236#ifdef FEAT_JOB_CHANNEL
237 emsg(_("E913: Using a Channel as a Number"));
238 break;
239#endif
240 case VAR_BLOB:
241 emsg(_("E974: Using a Blob as a Number"));
242 break;
243 case VAR_UNKNOWN:
244 case VAR_ANY:
245 case VAR_VOID:
246 internal_error_no_abort("tv_get_number(UNKNOWN)");
247 break;
248 }
249 if (denote == NULL) // useful for values that must be unsigned
250 n = -1;
251 else
252 *denote = TRUE;
253 return n;
254}
255
256#ifdef FEAT_FLOAT
257 float_T
258tv_get_float(typval_T *varp)
259{
260 switch (varp->v_type)
261 {
262 case VAR_NUMBER:
263 return (float_T)(varp->vval.v_number);
264 case VAR_FLOAT:
265 return varp->vval.v_float;
266 case VAR_FUNC:
267 case VAR_PARTIAL:
268 emsg(_("E891: Using a Funcref as a Float"));
269 break;
270 case VAR_STRING:
271 emsg(_("E892: Using a String as a Float"));
272 break;
273 case VAR_LIST:
274 emsg(_("E893: Using a List as a Float"));
275 break;
276 case VAR_DICT:
277 emsg(_("E894: Using a Dictionary as a Float"));
278 break;
279 case VAR_BOOL:
280 emsg(_("E362: Using a boolean value as a Float"));
281 break;
282 case VAR_SPECIAL:
283 emsg(_("E907: Using a special value as a Float"));
284 break;
285 case VAR_JOB:
286# ifdef FEAT_JOB_CHANNEL
287 emsg(_("E911: Using a Job as a Float"));
288 break;
289# endif
290 case VAR_CHANNEL:
291# ifdef FEAT_JOB_CHANNEL
292 emsg(_("E914: Using a Channel as a Float"));
293 break;
294# endif
295 case VAR_BLOB:
296 emsg(_("E975: Using a Blob as a Float"));
297 break;
298 case VAR_UNKNOWN:
299 case VAR_ANY:
300 case VAR_VOID:
301 internal_error_no_abort("tv_get_float(UNKNOWN)");
302 break;
303 }
304 return 0;
305}
306#endif
307
308/*
309 * Get the string value of a variable.
310 * If it is a Number variable, the number is converted into a string.
311 * tv_get_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
312 * tv_get_string_buf() uses a given buffer.
313 * If the String variable has never been set, return an empty string.
314 * Never returns NULL;
315 * tv_get_string_chk() and tv_get_string_buf_chk() are similar, but return
316 * NULL on error.
317 */
318 char_u *
319tv_get_string(typval_T *varp)
320{
321 static char_u mybuf[NUMBUFLEN];
322
323 return tv_get_string_buf(varp, mybuf);
324}
325
326 char_u *
327tv_get_string_buf(typval_T *varp, char_u *buf)
328{
329 char_u *res = tv_get_string_buf_chk(varp, buf);
330
331 return res != NULL ? res : (char_u *)"";
332}
333
334/*
335 * Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
336 */
337 char_u *
338tv_get_string_chk(typval_T *varp)
339{
340 static char_u mybuf[NUMBUFLEN];
341
342 return tv_get_string_buf_chk(varp, mybuf);
343}
344
345 char_u *
346tv_get_string_buf_chk(typval_T *varp, char_u *buf)
347{
348 switch (varp->v_type)
349 {
350 case VAR_NUMBER:
351 vim_snprintf((char *)buf, NUMBUFLEN, "%lld",
352 (varnumber_T)varp->vval.v_number);
353 return buf;
354 case VAR_FUNC:
355 case VAR_PARTIAL:
356 emsg(_("E729: using Funcref as a String"));
357 break;
358 case VAR_LIST:
359 emsg(_("E730: using List as a String"));
360 break;
361 case VAR_DICT:
362 emsg(_("E731: using Dictionary as a String"));
363 break;
364 case VAR_FLOAT:
365#ifdef FEAT_FLOAT
366 emsg(_(e_float_as_string));
367 break;
368#endif
369 case VAR_STRING:
370 if (varp->vval.v_string != NULL)
371 return varp->vval.v_string;
372 return (char_u *)"";
373 case VAR_BOOL:
374 case VAR_SPECIAL:
375 STRCPY(buf, get_var_special_name(varp->vval.v_number));
376 return buf;
377 case VAR_BLOB:
378 emsg(_("E976: using Blob as a String"));
379 break;
380 case VAR_JOB:
381#ifdef FEAT_JOB_CHANNEL
382 {
383 job_T *job = varp->vval.v_job;
384 char *status;
385
386 if (job == NULL)
387 return (char_u *)"no process";
388 status = job->jv_status == JOB_FAILED ? "fail"
389 : job->jv_status >= JOB_ENDED ? "dead"
390 : "run";
391# ifdef UNIX
392 vim_snprintf((char *)buf, NUMBUFLEN,
393 "process %ld %s", (long)job->jv_pid, status);
394# elif defined(MSWIN)
395 vim_snprintf((char *)buf, NUMBUFLEN,
396 "process %ld %s",
397 (long)job->jv_proc_info.dwProcessId,
398 status);
399# else
400 // fall-back
401 vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status);
402# endif
403 return buf;
404 }
405#endif
406 break;
407 case VAR_CHANNEL:
408#ifdef FEAT_JOB_CHANNEL
409 {
410 channel_T *channel = varp->vval.v_channel;
411 char *status = channel_status(channel, -1);
412
413 if (channel == NULL)
414 vim_snprintf((char *)buf, NUMBUFLEN, "channel %s", status);
415 else
416 vim_snprintf((char *)buf, NUMBUFLEN,
417 "channel %d %s", channel->ch_id, status);
418 return buf;
419 }
420#endif
421 break;
422 case VAR_UNKNOWN:
423 case VAR_ANY:
424 case VAR_VOID:
425 emsg(_(e_inval_string));
426 break;
427 }
428 return NULL;
429}
430
431/*
432 * Turn a typeval into a string. Similar to tv_get_string_buf() but uses
433 * string() on Dict, List, etc.
434 */
435 char_u *
436tv_stringify(typval_T *varp, char_u *buf)
437{
438 if (varp->v_type == VAR_LIST
439 || varp->v_type == VAR_DICT
440 || varp->v_type == VAR_BLOB
441 || varp->v_type == VAR_FUNC
442 || varp->v_type == VAR_PARTIAL
443 || varp->v_type == VAR_FLOAT)
444 {
445 typval_T tmp;
446
447 f_string(varp, &tmp);
448 tv_get_string_buf(&tmp, buf);
449 clear_tv(varp);
450 *varp = tmp;
451 return tmp.vval.v_string;
452 }
453 return tv_get_string_buf(varp, buf);
454}
455
456/*
457 * Return TRUE if typeval "tv" and its value are set to be locked (immutable).
458 * Also give an error message, using "name" or _("name") when use_gettext is
459 * TRUE.
460 */
461 int
462tv_check_lock(typval_T *tv, char_u *name, int use_gettext)
463{
464 int lock = 0;
465
466 switch (tv->v_type)
467 {
468 case VAR_BLOB:
469 if (tv->vval.v_blob != NULL)
470 lock = tv->vval.v_blob->bv_lock;
471 break;
472 case VAR_LIST:
473 if (tv->vval.v_list != NULL)
474 lock = tv->vval.v_list->lv_lock;
475 break;
476 case VAR_DICT:
477 if (tv->vval.v_dict != NULL)
478 lock = tv->vval.v_dict->dv_lock;
479 break;
480 default:
481 break;
482 }
483 return var_check_lock(tv->v_lock, name, use_gettext)
484 || (lock != 0 && var_check_lock(lock, name, use_gettext));
485}
486
487/*
488 * Copy the values from typval_T "from" to typval_T "to".
489 * When needed allocates string or increases reference count.
490 * Does not make a copy of a list, blob or dict but copies the reference!
491 * It is OK for "from" and "to" to point to the same item. This is used to
492 * make a copy later.
493 */
494 void
495copy_tv(typval_T *from, typval_T *to)
496{
497 to->v_type = from->v_type;
498 to->v_lock = 0;
499 switch (from->v_type)
500 {
501 case VAR_NUMBER:
502 case VAR_BOOL:
503 case VAR_SPECIAL:
504 to->vval.v_number = from->vval.v_number;
505 break;
506 case VAR_FLOAT:
507#ifdef FEAT_FLOAT
508 to->vval.v_float = from->vval.v_float;
509 break;
510#endif
511 case VAR_JOB:
512#ifdef FEAT_JOB_CHANNEL
513 to->vval.v_job = from->vval.v_job;
514 if (to->vval.v_job != NULL)
515 ++to->vval.v_job->jv_refcount;
516 break;
517#endif
518 case VAR_CHANNEL:
519#ifdef FEAT_JOB_CHANNEL
520 to->vval.v_channel = from->vval.v_channel;
521 if (to->vval.v_channel != NULL)
522 ++to->vval.v_channel->ch_refcount;
523 break;
524#endif
525 case VAR_STRING:
526 case VAR_FUNC:
527 if (from->vval.v_string == NULL)
528 to->vval.v_string = NULL;
529 else
530 {
531 to->vval.v_string = vim_strsave(from->vval.v_string);
532 if (from->v_type == VAR_FUNC)
533 func_ref(to->vval.v_string);
534 }
535 break;
536 case VAR_PARTIAL:
537 if (from->vval.v_partial == NULL)
538 to->vval.v_partial = NULL;
539 else
540 {
541 to->vval.v_partial = from->vval.v_partial;
542 ++to->vval.v_partial->pt_refcount;
543 }
544 break;
545 case VAR_BLOB:
546 if (from->vval.v_blob == NULL)
547 to->vval.v_blob = NULL;
548 else
549 {
550 to->vval.v_blob = from->vval.v_blob;
551 ++to->vval.v_blob->bv_refcount;
552 }
553 break;
554 case VAR_LIST:
555 if (from->vval.v_list == NULL)
556 to->vval.v_list = NULL;
557 else
558 {
559 to->vval.v_list = from->vval.v_list;
560 ++to->vval.v_list->lv_refcount;
561 }
562 break;
563 case VAR_DICT:
564 if (from->vval.v_dict == NULL)
565 to->vval.v_dict = NULL;
566 else
567 {
568 to->vval.v_dict = from->vval.v_dict;
569 ++to->vval.v_dict->dv_refcount;
570 }
571 break;
572 case VAR_UNKNOWN:
573 case VAR_ANY:
574 case VAR_VOID:
575 internal_error_no_abort("copy_tv(UNKNOWN)");
576 break;
577 }
578}
579
580/*
581 * Compare "typ1" and "typ2". Put the result in "typ1".
582 */
583 int
584typval_compare(
585 typval_T *typ1, // first operand
586 typval_T *typ2, // second operand
587 exptype_T type, // operator
588 int ic) // ignore case
589{
590 int i;
591 varnumber_T n1, n2;
592 char_u *s1, *s2;
593 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
594 int type_is = type == EXPR_IS || type == EXPR_ISNOT;
595
596 if (type_is && typ1->v_type != typ2->v_type)
597 {
598 // For "is" a different type always means FALSE, for "notis"
599 // it means TRUE.
600 n1 = (type == EXPR_ISNOT);
601 }
602 else if (typ1->v_type == VAR_BLOB || typ2->v_type == VAR_BLOB)
603 {
604 if (type_is)
605 {
606 n1 = (typ1->v_type == typ2->v_type
607 && typ1->vval.v_blob == typ2->vval.v_blob);
608 if (type == EXPR_ISNOT)
609 n1 = !n1;
610 }
611 else if (typ1->v_type != typ2->v_type
612 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
613 {
614 if (typ1->v_type != typ2->v_type)
615 emsg(_("E977: Can only compare Blob with Blob"));
616 else
617 emsg(_(e_invalblob));
618 clear_tv(typ1);
619 return FAIL;
620 }
621 else
622 {
623 // Compare two Blobs for being equal or unequal.
624 n1 = blob_equal(typ1->vval.v_blob, typ2->vval.v_blob);
625 if (type == EXPR_NEQUAL)
626 n1 = !n1;
627 }
628 }
629 else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST)
630 {
631 if (type_is)
632 {
633 n1 = (typ1->v_type == typ2->v_type
634 && typ1->vval.v_list == typ2->vval.v_list);
635 if (type == EXPR_ISNOT)
636 n1 = !n1;
637 }
638 else if (typ1->v_type != typ2->v_type
639 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
640 {
641 if (typ1->v_type != typ2->v_type)
642 emsg(_("E691: Can only compare List with List"));
643 else
644 emsg(_("E692: Invalid operation for List"));
645 clear_tv(typ1);
646 return FAIL;
647 }
648 else
649 {
650 // Compare two Lists for being equal or unequal.
651 n1 = list_equal(typ1->vval.v_list, typ2->vval.v_list,
652 ic, FALSE);
653 if (type == EXPR_NEQUAL)
654 n1 = !n1;
655 }
656 }
657
658 else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT)
659 {
660 if (type_is)
661 {
662 n1 = (typ1->v_type == typ2->v_type
663 && typ1->vval.v_dict == typ2->vval.v_dict);
664 if (type == EXPR_ISNOT)
665 n1 = !n1;
666 }
667 else if (typ1->v_type != typ2->v_type
668 || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
669 {
670 if (typ1->v_type != typ2->v_type)
671 emsg(_("E735: Can only compare Dictionary with Dictionary"));
672 else
673 emsg(_("E736: Invalid operation for Dictionary"));
674 clear_tv(typ1);
675 return FAIL;
676 }
677 else
678 {
679 // Compare two Dictionaries for being equal or unequal.
680 n1 = dict_equal(typ1->vval.v_dict, typ2->vval.v_dict,
681 ic, FALSE);
682 if (type == EXPR_NEQUAL)
683 n1 = !n1;
684 }
685 }
686
687 else if (typ1->v_type == VAR_FUNC || typ2->v_type == VAR_FUNC
688 || typ1->v_type == VAR_PARTIAL || typ2->v_type == VAR_PARTIAL)
689 {
690 if (type != EXPR_EQUAL && type != EXPR_NEQUAL
691 && type != EXPR_IS && type != EXPR_ISNOT)
692 {
693 emsg(_("E694: Invalid operation for Funcrefs"));
694 clear_tv(typ1);
695 return FAIL;
696 }
697 if ((typ1->v_type == VAR_PARTIAL
698 && typ1->vval.v_partial == NULL)
699 || (typ2->v_type == VAR_PARTIAL
700 && typ2->vval.v_partial == NULL))
701 // When both partials are NULL, then they are equal.
702 // Otherwise they are not equal.
703 n1 = (typ1->vval.v_partial == typ2->vval.v_partial);
704 else if (type_is)
705 {
706 if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC)
707 // strings are considered the same if their value is
708 // the same
709 n1 = tv_equal(typ1, typ2, ic, FALSE);
710 else if (typ1->v_type == VAR_PARTIAL
711 && typ2->v_type == VAR_PARTIAL)
712 n1 = (typ1->vval.v_partial == typ2->vval.v_partial);
713 else
714 n1 = FALSE;
715 }
716 else
717 n1 = tv_equal(typ1, typ2, ic, FALSE);
718 if (type == EXPR_NEQUAL || type == EXPR_ISNOT)
719 n1 = !n1;
720 }
721
722#ifdef FEAT_FLOAT
723 // If one of the two variables is a float, compare as a float.
724 // When using "=~" or "!~", always compare as string.
725 else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT)
726 && type != EXPR_MATCH && type != EXPR_NOMATCH)
727 {
728 float_T f1, f2;
729
730 f1 = tv_get_float(typ1);
731 f2 = tv_get_float(typ2);
732 n1 = FALSE;
733 switch (type)
734 {
735 case EXPR_IS:
736 case EXPR_EQUAL: n1 = (f1 == f2); break;
737 case EXPR_ISNOT:
738 case EXPR_NEQUAL: n1 = (f1 != f2); break;
739 case EXPR_GREATER: n1 = (f1 > f2); break;
740 case EXPR_GEQUAL: n1 = (f1 >= f2); break;
741 case EXPR_SMALLER: n1 = (f1 < f2); break;
742 case EXPR_SEQUAL: n1 = (f1 <= f2); break;
743 case EXPR_UNKNOWN:
744 case EXPR_MATCH:
745 default: break; // avoid gcc warning
746 }
747 }
748#endif
749
750 // If one of the two variables is a number, compare as a number.
751 // When using "=~" or "!~", always compare as string.
752 else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER)
753 && type != EXPR_MATCH && type != EXPR_NOMATCH)
754 {
755 n1 = tv_get_number(typ1);
756 n2 = tv_get_number(typ2);
757 switch (type)
758 {
759 case EXPR_IS:
760 case EXPR_EQUAL: n1 = (n1 == n2); break;
761 case EXPR_ISNOT:
762 case EXPR_NEQUAL: n1 = (n1 != n2); break;
763 case EXPR_GREATER: n1 = (n1 > n2); break;
764 case EXPR_GEQUAL: n1 = (n1 >= n2); break;
765 case EXPR_SMALLER: n1 = (n1 < n2); break;
766 case EXPR_SEQUAL: n1 = (n1 <= n2); break;
767 case EXPR_UNKNOWN:
768 case EXPR_MATCH:
769 default: break; // avoid gcc warning
770 }
771 }
772 else
773 {
774 s1 = tv_get_string_buf(typ1, buf1);
775 s2 = tv_get_string_buf(typ2, buf2);
776 if (type != EXPR_MATCH && type != EXPR_NOMATCH)
777 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
778 else
779 i = 0;
780 n1 = FALSE;
781 switch (type)
782 {
783 case EXPR_IS:
784 case EXPR_EQUAL: n1 = (i == 0); break;
785 case EXPR_ISNOT:
786 case EXPR_NEQUAL: n1 = (i != 0); break;
787 case EXPR_GREATER: n1 = (i > 0); break;
788 case EXPR_GEQUAL: n1 = (i >= 0); break;
789 case EXPR_SMALLER: n1 = (i < 0); break;
790 case EXPR_SEQUAL: n1 = (i <= 0); break;
791
792 case EXPR_MATCH:
793 case EXPR_NOMATCH:
794 n1 = pattern_match(s2, s1, ic);
795 if (type == EXPR_NOMATCH)
796 n1 = !n1;
797 break;
798
799 default: break; // avoid gcc warning
800 }
801 }
802 clear_tv(typ1);
Bram Moolenaarc71f36a2020-07-21 21:31:00 +0200803 if (in_vim9script())
804 {
805 typ1->v_type = VAR_BOOL;
806 typ1->vval.v_number = n1 ? VVAL_TRUE : VVAL_FALSE;
807 }
808 else
809 {
810 typ1->v_type = VAR_NUMBER;
811 typ1->vval.v_number = n1;
812 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +0200813
814 return OK;
815}
816
817 char_u *
818typval_tostring(typval_T *arg)
819{
820 char_u *tofree;
821 char_u numbuf[NUMBUFLEN];
822 char_u *ret = NULL;
823
824 if (arg == NULL)
825 return vim_strsave((char_u *)"(does not exist)");
826 ret = tv2string(arg, &tofree, numbuf, 0);
827 // Make a copy if we have a value but it's not in allocated memory.
828 if (ret != NULL && tofree == NULL)
829 ret = vim_strsave(ret);
830 return ret;
831}
832
833/*
834 * Return TRUE if typeval "tv" is locked: Either that value is locked itself
835 * or it refers to a List or Dictionary that is locked.
836 */
837 int
838tv_islocked(typval_T *tv)
839{
840 return (tv->v_lock & VAR_LOCKED)
841 || (tv->v_type == VAR_LIST
842 && tv->vval.v_list != NULL
843 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
844 || (tv->v_type == VAR_DICT
845 && tv->vval.v_dict != NULL
846 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
847}
848
849 static int
850func_equal(
851 typval_T *tv1,
852 typval_T *tv2,
853 int ic) // ignore case
854{
855 char_u *s1, *s2;
856 dict_T *d1, *d2;
857 int a1, a2;
858 int i;
859
860 // empty and NULL function name considered the same
861 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
862 : partial_name(tv1->vval.v_partial);
863 if (s1 != NULL && *s1 == NUL)
864 s1 = NULL;
865 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
866 : partial_name(tv2->vval.v_partial);
867 if (s2 != NULL && *s2 == NUL)
868 s2 = NULL;
869 if (s1 == NULL || s2 == NULL)
870 {
871 if (s1 != s2)
872 return FALSE;
873 }
874 else if (STRCMP(s1, s2) != 0)
875 return FALSE;
876
877 // empty dict and NULL dict is different
878 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
879 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
880 if (d1 == NULL || d2 == NULL)
881 {
882 if (d1 != d2)
883 return FALSE;
884 }
885 else if (!dict_equal(d1, d2, ic, TRUE))
886 return FALSE;
887
888 // empty list and no list considered the same
889 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
890 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
891 if (a1 != a2)
892 return FALSE;
893 for (i = 0; i < a1; ++i)
894 if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
895 tv2->vval.v_partial->pt_argv + i, ic, TRUE))
896 return FALSE;
897
898 return TRUE;
899}
900
901/*
902 * Return TRUE if "tv1" and "tv2" have the same value.
903 * Compares the items just like "==" would compare them, but strings and
904 * numbers are different. Floats and numbers are also different.
905 */
906 int
907tv_equal(
908 typval_T *tv1,
909 typval_T *tv2,
910 int ic, // ignore case
911 int recursive) // TRUE when used recursively
912{
913 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
914 char_u *s1, *s2;
915 static int recursive_cnt = 0; // catch recursive loops
916 int r;
917 static int tv_equal_recurse_limit;
918
919 // Catch lists and dicts that have an endless loop by limiting
920 // recursiveness to a limit. We guess they are equal then.
921 // A fixed limit has the problem of still taking an awful long time.
922 // Reduce the limit every time running into it. That should work fine for
923 // deeply linked structures that are not recursively linked and catch
924 // recursiveness quickly.
925 if (!recursive)
926 tv_equal_recurse_limit = 1000;
927 if (recursive_cnt >= tv_equal_recurse_limit)
928 {
929 --tv_equal_recurse_limit;
930 return TRUE;
931 }
932
933 // For VAR_FUNC and VAR_PARTIAL compare the function name, bound dict and
934 // arguments.
935 if ((tv1->v_type == VAR_FUNC
936 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
937 && (tv2->v_type == VAR_FUNC
938 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
939 {
940 ++recursive_cnt;
941 r = func_equal(tv1, tv2, ic);
942 --recursive_cnt;
943 return r;
944 }
945
946 if (tv1->v_type != tv2->v_type)
947 return FALSE;
948
949 switch (tv1->v_type)
950 {
951 case VAR_LIST:
952 ++recursive_cnt;
953 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
954 --recursive_cnt;
955 return r;
956
957 case VAR_DICT:
958 ++recursive_cnt;
959 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE);
960 --recursive_cnt;
961 return r;
962
963 case VAR_BLOB:
964 return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
965
966 case VAR_NUMBER:
967 case VAR_BOOL:
968 case VAR_SPECIAL:
969 return tv1->vval.v_number == tv2->vval.v_number;
970
971 case VAR_STRING:
972 s1 = tv_get_string_buf(tv1, buf1);
973 s2 = tv_get_string_buf(tv2, buf2);
974 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
975
976 case VAR_FLOAT:
977#ifdef FEAT_FLOAT
978 return tv1->vval.v_float == tv2->vval.v_float;
979#endif
980 case VAR_JOB:
981#ifdef FEAT_JOB_CHANNEL
982 return tv1->vval.v_job == tv2->vval.v_job;
983#endif
984 case VAR_CHANNEL:
985#ifdef FEAT_JOB_CHANNEL
986 return tv1->vval.v_channel == tv2->vval.v_channel;
987#endif
988
989 case VAR_PARTIAL:
990 return tv1->vval.v_partial == tv2->vval.v_partial;
991
992 case VAR_FUNC:
993 return tv1->vval.v_string == tv2->vval.v_string;
994
995 case VAR_UNKNOWN:
996 case VAR_ANY:
997 case VAR_VOID:
998 break;
999 }
1000
1001 // VAR_UNKNOWN can be the result of a invalid expression, let's say it
1002 // does not equal anything, not even itself.
1003 return FALSE;
1004}
1005
1006/*
1007 * Get an option value.
1008 * "arg" points to the '&' or '+' before the option name.
1009 * "arg" is advanced to character after the option name.
1010 * Return OK or FAIL.
1011 */
1012 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02001013eval_option(
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001014 char_u **arg,
1015 typval_T *rettv, // when NULL, only check if option exists
1016 int evaluate)
1017{
1018 char_u *option_end;
1019 long numval;
1020 char_u *stringval;
1021 int opt_type;
1022 int c;
1023 int working = (**arg == '+'); // has("+option")
1024 int ret = OK;
1025 int opt_flags;
1026
1027 // Isolate the option name and find its value.
1028 option_end = find_option_end(arg, &opt_flags);
1029 if (option_end == NULL)
1030 {
1031 if (rettv != NULL)
1032 semsg(_("E112: Option name missing: %s"), *arg);
1033 return FAIL;
1034 }
1035
1036 if (!evaluate)
1037 {
1038 *arg = option_end;
1039 return OK;
1040 }
1041
1042 c = *option_end;
1043 *option_end = NUL;
1044 opt_type = get_option_value(*arg, &numval,
1045 rettv == NULL ? NULL : &stringval, opt_flags);
1046
1047 if (opt_type == -3) // invalid name
1048 {
1049 if (rettv != NULL)
1050 semsg(_(e_unknown_option), *arg);
1051 ret = FAIL;
1052 }
1053 else if (rettv != NULL)
1054 {
1055 if (opt_type == -2) // hidden string option
1056 {
1057 rettv->v_type = VAR_STRING;
1058 rettv->vval.v_string = NULL;
1059 }
1060 else if (opt_type == -1) // hidden number option
1061 {
1062 rettv->v_type = VAR_NUMBER;
1063 rettv->vval.v_number = 0;
1064 }
1065 else if (opt_type == 1) // number option
1066 {
1067 rettv->v_type = VAR_NUMBER;
1068 rettv->vval.v_number = numval;
1069 }
1070 else // string option
1071 {
1072 rettv->v_type = VAR_STRING;
1073 rettv->vval.v_string = stringval;
1074 }
1075 }
1076 else if (working && (opt_type == -2 || opt_type == -1))
1077 ret = FAIL;
1078
1079 *option_end = c; // put back for error messages
1080 *arg = option_end;
1081
1082 return ret;
1083}
1084
1085/*
1086 * Allocate a variable for a number constant. Also deals with "0z" for blob.
1087 * Return OK or FAIL.
1088 */
1089 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02001090eval_number(
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001091 char_u **arg,
1092 typval_T *rettv,
1093 int evaluate,
1094 int want_string UNUSED)
1095{
1096 int len;
1097#ifdef FEAT_FLOAT
1098 char_u *p;
1099 int get_float = FALSE;
1100
1101 // We accept a float when the format matches
1102 // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
1103 // strict to avoid backwards compatibility problems.
1104 // With script version 2 and later the leading digit can be
1105 // omitted.
1106 // Don't look for a float after the "." operator, so that
1107 // ":let vers = 1.2.3" doesn't fail.
1108 if (**arg == '.')
1109 p = *arg;
1110 else
1111 p = skipdigits(*arg + 1);
1112 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
1113 {
1114 get_float = TRUE;
1115 p = skipdigits(p + 2);
1116 if (*p == 'e' || *p == 'E')
1117 {
1118 ++p;
1119 if (*p == '-' || *p == '+')
1120 ++p;
1121 if (!vim_isdigit(*p))
1122 get_float = FALSE;
1123 else
1124 p = skipdigits(p + 1);
1125 }
1126 if (ASCII_ISALPHA(*p) || *p == '.')
1127 get_float = FALSE;
1128 }
1129 if (get_float)
1130 {
1131 float_T f;
1132
1133 *arg += string2float(*arg, &f);
1134 if (evaluate)
1135 {
1136 rettv->v_type = VAR_FLOAT;
1137 rettv->vval.v_float = f;
1138 }
1139 }
1140 else
1141#endif
1142 if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z'))
1143 {
1144 char_u *bp;
1145 blob_T *blob = NULL; // init for gcc
1146
1147 // Blob constant: 0z0123456789abcdef
1148 if (evaluate)
1149 blob = blob_alloc();
1150 for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2)
1151 {
1152 if (!vim_isxdigit(bp[1]))
1153 {
1154 if (blob != NULL)
1155 {
1156 emsg(_("E973: Blob literal should have an even number of hex characters"));
1157 ga_clear(&blob->bv_ga);
1158 VIM_CLEAR(blob);
1159 }
1160 return FAIL;
1161 }
1162 if (blob != NULL)
1163 ga_append(&blob->bv_ga,
1164 (hex2nr(*bp) << 4) + hex2nr(*(bp+1)));
1165 if (bp[2] == '.' && vim_isxdigit(bp[3]))
1166 ++bp;
1167 }
1168 if (blob != NULL)
1169 rettv_blob_set(rettv, blob);
1170 *arg = bp;
1171 }
1172 else
1173 {
1174 varnumber_T n;
1175
1176 // decimal, hex or octal number
1177 vim_str2nr(*arg, NULL, &len, current_sctx.sc_version >= 4
1178 ? STR2NR_NO_OCT + STR2NR_QUOTE
1179 : STR2NR_ALL, &n, NULL, 0, TRUE);
1180 if (len == 0)
1181 {
1182 semsg(_(e_invexpr2), *arg);
1183 return FAIL;
1184 }
1185 *arg += len;
1186 if (evaluate)
1187 {
1188 rettv->v_type = VAR_NUMBER;
1189 rettv->vval.v_number = n;
1190 }
1191 }
1192 return OK;
1193}
1194
1195/*
1196 * Allocate a variable for a string constant.
1197 * Return OK or FAIL.
1198 */
1199 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02001200eval_string(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001201{
1202 char_u *p;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001203 char_u *end;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001204 int extra = 0;
1205 int len;
1206
1207 // Find the end of the string, skipping backslashed characters.
1208 for (p = *arg + 1; *p != NUL && *p != '"'; MB_PTR_ADV(p))
1209 {
1210 if (*p == '\\' && p[1] != NUL)
1211 {
1212 ++p;
1213 // A "\<x>" form occupies at least 4 characters, and produces up
1214 // to 21 characters (3 * 6 for the char and 3 for a modifier):
1215 // reserve space for 18 extra.
1216 // Each byte in the char could be encoded as K_SPECIAL K_EXTRA x.
1217 if (*p == '<')
1218 extra += 18;
1219 }
1220 }
1221
1222 if (*p != '"')
1223 {
1224 semsg(_("E114: Missing quote: %s"), *arg);
1225 return FAIL;
1226 }
1227
1228 // If only parsing, set *arg and return here
1229 if (!evaluate)
1230 {
1231 *arg = p + 1;
1232 return OK;
1233 }
1234
1235 // Copy the string into allocated memory, handling backslashed
1236 // characters.
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001237 rettv->v_type = VAR_STRING;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001238 len = (int)(p - *arg + extra);
1239 rettv->vval.v_string = alloc(len);
1240 if (rettv->vval.v_string == NULL)
1241 return FAIL;
1242 end = rettv->vval.v_string;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001243
1244 for (p = *arg + 1; *p != NUL && *p != '"'; )
1245 {
1246 if (*p == '\\')
1247 {
1248 switch (*++p)
1249 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001250 case 'b': *end++ = BS; ++p; break;
1251 case 'e': *end++ = ESC; ++p; break;
1252 case 'f': *end++ = FF; ++p; break;
1253 case 'n': *end++ = NL; ++p; break;
1254 case 'r': *end++ = CAR; ++p; break;
1255 case 't': *end++ = TAB; ++p; break;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001256
1257 case 'X': // hex: "\x1", "\x12"
1258 case 'x':
1259 case 'u': // Unicode: "\u0023"
1260 case 'U':
1261 if (vim_isxdigit(p[1]))
1262 {
1263 int n, nr;
1264 int c = toupper(*p);
1265
1266 if (c == 'X')
1267 n = 2;
1268 else if (*p == 'u')
1269 n = 4;
1270 else
1271 n = 8;
1272 nr = 0;
1273 while (--n >= 0 && vim_isxdigit(p[1]))
1274 {
1275 ++p;
1276 nr = (nr << 4) + hex2nr(*p);
1277 }
1278 ++p;
1279 // For "\u" store the number according to
1280 // 'encoding'.
1281 if (c != 'X')
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001282 end += (*mb_char2bytes)(nr, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001283 else
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001284 *end++ = nr;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001285 }
1286 break;
1287
1288 // octal: "\1", "\12", "\123"
1289 case '0':
1290 case '1':
1291 case '2':
1292 case '3':
1293 case '4':
1294 case '5':
1295 case '6':
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001296 case '7': *end = *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001297 if (*p >= '0' && *p <= '7')
1298 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001299 *end = (*end << 3) + *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001300 if (*p >= '0' && *p <= '7')
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001301 *end = (*end << 3) + *p++ - '0';
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001302 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001303 ++end;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001304 break;
1305
Bram Moolenaarfccd93f2020-05-31 22:06:51 +02001306 // Special key, e.g.: "\<C-W>"
Bram Moolenaarebe9d342020-05-30 21:52:54 +02001307 case '<':
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001308 {
Bram Moolenaarebe9d342020-05-30 21:52:54 +02001309 int flags = FSK_KEYCODE | FSK_IN_STRING;
1310
Bram Moolenaarfccd93f2020-05-31 22:06:51 +02001311 if (p[1] != '*')
Bram Moolenaarebe9d342020-05-30 21:52:54 +02001312 flags |= FSK_SIMPLIFY;
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001313 extra = trans_special(&p, end, flags, NULL);
Bram Moolenaarebe9d342020-05-30 21:52:54 +02001314 if (extra != 0)
1315 {
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001316 end += extra;
1317 if (end >= rettv->vval.v_string + len)
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02001318 iemsg("eval_string() used more space than allocated");
Bram Moolenaarebe9d342020-05-30 21:52:54 +02001319 break;
1320 }
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001321 }
1322 // FALLTHROUGH
1323
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001324 default: MB_COPY_CHAR(p, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001325 break;
1326 }
1327 }
1328 else
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001329 MB_COPY_CHAR(p, end);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001330 }
Bram Moolenaar1e0b7b12020-06-19 19:30:53 +02001331 *end = NUL;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001332 if (*p != NUL) // just in case
1333 ++p;
1334 *arg = p;
1335
1336 return OK;
1337}
1338
1339/*
1340 * Allocate a variable for a 'str''ing' constant.
1341 * Return OK or FAIL.
1342 */
1343 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02001344eval_lit_string(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001345{
1346 char_u *p;
1347 char_u *str;
1348 int reduce = 0;
1349
1350 // Find the end of the string, skipping ''.
1351 for (p = *arg + 1; *p != NUL; MB_PTR_ADV(p))
1352 {
1353 if (*p == '\'')
1354 {
1355 if (p[1] != '\'')
1356 break;
1357 ++reduce;
1358 ++p;
1359 }
1360 }
1361
1362 if (*p != '\'')
1363 {
1364 semsg(_("E115: Missing quote: %s"), *arg);
1365 return FAIL;
1366 }
1367
1368 // If only parsing return after setting "*arg"
1369 if (!evaluate)
1370 {
1371 *arg = p + 1;
1372 return OK;
1373 }
1374
1375 // Copy the string into allocated memory, handling '' to ' reduction.
1376 str = alloc((p - *arg) - reduce);
1377 if (str == NULL)
1378 return FAIL;
1379 rettv->v_type = VAR_STRING;
1380 rettv->vval.v_string = str;
1381
1382 for (p = *arg + 1; *p != NUL; )
1383 {
1384 if (*p == '\'')
1385 {
1386 if (p[1] != '\'')
1387 break;
1388 ++p;
1389 }
1390 MB_COPY_CHAR(p, str);
1391 }
1392 *str = NUL;
1393 *arg = p + 1;
1394
1395 return OK;
1396}
1397
1398/*
1399 * Return a string with the string representation of a variable.
1400 * If the memory is allocated "tofree" is set to it, otherwise NULL.
1401 * "numbuf" is used for a number.
1402 * Puts quotes around strings, so that they can be parsed back by eval().
1403 * May return NULL.
1404 */
1405 char_u *
1406tv2string(
1407 typval_T *tv,
1408 char_u **tofree,
1409 char_u *numbuf,
1410 int copyID)
1411{
1412 return echo_string_core(tv, tofree, numbuf, copyID, FALSE, TRUE, FALSE);
1413}
1414
1415/*
1416 * Get the value of an environment variable.
1417 * "arg" is pointing to the '$'. It is advanced to after the name.
1418 * If the environment variable was not set, silently assume it is empty.
1419 * Return FAIL if the name is invalid.
1420 */
1421 int
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02001422eval_env_var(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001423{
1424 char_u *string = NULL;
1425 int len;
1426 int cc;
1427 char_u *name;
1428 int mustfree = FALSE;
1429
1430 ++*arg;
1431 name = *arg;
1432 len = get_env_len(arg);
1433 if (evaluate)
1434 {
1435 if (len == 0)
1436 return FAIL; // invalid empty name
1437
1438 cc = name[len];
1439 name[len] = NUL;
1440 // first try vim_getenv(), fast for normal environment vars
1441 string = vim_getenv(name, &mustfree);
1442 if (string != NULL && *string != NUL)
1443 {
1444 if (!mustfree)
1445 string = vim_strsave(string);
1446 }
1447 else
1448 {
1449 if (mustfree)
1450 vim_free(string);
1451
1452 // next try expanding things like $VIM and ${HOME}
1453 string = expand_env_save(name - 1);
1454 if (string != NULL && *string == '$')
1455 VIM_CLEAR(string);
1456 }
1457 name[len] = cc;
1458
1459 rettv->v_type = VAR_STRING;
1460 rettv->vval.v_string = string;
1461 }
1462
1463 return OK;
1464}
1465
1466/*
1467 * Get the lnum from the first argument.
1468 * Also accepts ".", "$", etc., but that only works for the current buffer.
1469 * Returns -1 on error.
1470 */
1471 linenr_T
1472tv_get_lnum(typval_T *argvars)
1473{
Bram Moolenaar56acb092020-08-16 14:48:19 +02001474 linenr_T lnum = 0;
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001475
Bram Moolenaar56acb092020-08-16 14:48:19 +02001476 if (argvars[0].v_type != VAR_STRING || !in_vim9script())
1477 lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL);
Bram Moolenaar367d59e2020-05-30 17:06:14 +02001478 if (lnum == 0) // no valid number, try using arg like line()
1479 {
1480 int fnum;
1481 pos_T *fp = var2fpos(&argvars[0], TRUE, &fnum);
1482
1483 if (fp != NULL)
1484 lnum = fp->lnum;
1485 }
1486 return lnum;
1487}
1488
1489/*
1490 * Get the lnum from the first argument.
1491 * Also accepts "$", then "buf" is used.
1492 * Returns 0 on error.
1493 */
1494 linenr_T
1495tv_get_lnum_buf(typval_T *argvars, buf_T *buf)
1496{
1497 if (argvars[0].v_type == VAR_STRING
1498 && argvars[0].vval.v_string != NULL
1499 && argvars[0].vval.v_string[0] == '$'
1500 && buf != NULL)
1501 return buf->b_ml.ml_line_count;
1502 return (linenr_T)tv_get_number_chk(&argvars[0], NULL);
1503}
1504
1505/*
1506 * Get buffer by number or pattern.
1507 */
1508 buf_T *
1509tv_get_buf(typval_T *tv, int curtab_only)
1510{
1511 char_u *name = tv->vval.v_string;
1512 buf_T *buf;
1513
1514 if (tv->v_type == VAR_NUMBER)
1515 return buflist_findnr((int)tv->vval.v_number);
1516 if (tv->v_type != VAR_STRING)
1517 return NULL;
1518 if (name == NULL || *name == NUL)
1519 return curbuf;
1520 if (name[0] == '$' && name[1] == NUL)
1521 return lastbuf;
1522
1523 buf = buflist_find_by_name(name, curtab_only);
1524
1525 // If not found, try expanding the name, like done for bufexists().
1526 if (buf == NULL)
1527 buf = find_buffer(tv);
1528
1529 return buf;
1530}
1531
1532#endif // FEAT_EVAL