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