blob: c13e7a45f51de48a3cf58e1974831e1c2fff45f9 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaarcd524592016-07-17 14:57:05 +02002 *
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 * dict.c: Dictionary support
12 */
Bram Moolenaarcd524592016-07-17 14:57:05 +020013
14#include "vim.h"
15
16#if defined(FEAT_EVAL) || defined(PROTO)
17
18/* List head for garbage collection. Although there can be a reference loop
19 * from partial to dict to partial, we don't need to keep track of the partial,
20 * since it will get freed when the dict is unused and gets freed. */
21static dict_T *first_dict = NULL; /* list of all dicts */
22
23/*
24 * Allocate an empty header for a dictionary.
25 */
26 dict_T *
27dict_alloc(void)
28{
29 dict_T *d;
30
31 d = (dict_T *)alloc(sizeof(dict_T));
32 if (d != NULL)
33 {
34 /* Add the dict to the list of dicts for garbage collection. */
35 if (first_dict != NULL)
36 first_dict->dv_used_prev = d;
37 d->dv_used_next = first_dict;
38 d->dv_used_prev = NULL;
39 first_dict = d;
40
41 hash_init(&d->dv_hashtab);
42 d->dv_lock = 0;
43 d->dv_scope = 0;
44 d->dv_refcount = 0;
45 d->dv_copyID = 0;
46 }
47 return d;
48}
49
50/*
51 * Allocate an empty dict for a return value.
52 * Returns OK or FAIL.
53 */
54 int
55rettv_dict_alloc(typval_T *rettv)
56{
57 dict_T *d = dict_alloc();
58
59 if (d == NULL)
60 return FAIL;
61
Bram Moolenaar45cf6e92017-04-30 20:25:19 +020062 rettv_dict_set(rettv, d);
Bram Moolenaarcd524592016-07-17 14:57:05 +020063 rettv->v_lock = 0;
Bram Moolenaarcd524592016-07-17 14:57:05 +020064 return OK;
65}
66
67/*
Bram Moolenaar45cf6e92017-04-30 20:25:19 +020068 * Set a dictionary as the return value
69 */
70 void
71rettv_dict_set(typval_T *rettv, dict_T *d)
72{
73 rettv->v_type = VAR_DICT;
74 rettv->vval.v_dict = d;
75 if (d != NULL)
76 ++d->dv_refcount;
77}
78
79/*
Bram Moolenaarcd524592016-07-17 14:57:05 +020080 * Free a Dictionary, including all non-container items it contains.
81 * Ignores the reference count.
82 */
83 static void
84dict_free_contents(dict_T *d)
85{
86 int todo;
87 hashitem_T *hi;
88 dictitem_T *di;
89
90 /* Lock the hashtab, we don't want it to resize while freeing items. */
91 hash_lock(&d->dv_hashtab);
92 todo = (int)d->dv_hashtab.ht_used;
93 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
94 {
95 if (!HASHITEM_EMPTY(hi))
96 {
97 /* Remove the item before deleting it, just in case there is
98 * something recursive causing trouble. */
99 di = HI2DI(hi);
100 hash_remove(&d->dv_hashtab, hi);
Bram Moolenaar95c526e2017-02-25 14:59:34 +0100101 dictitem_free(di);
Bram Moolenaarcd524592016-07-17 14:57:05 +0200102 --todo;
103 }
104 }
105 hash_clear(&d->dv_hashtab);
106}
107
108 static void
109dict_free_dict(dict_T *d)
110{
111 /* Remove the dict from the list of dicts for garbage collection. */
112 if (d->dv_used_prev == NULL)
113 first_dict = d->dv_used_next;
114 else
115 d->dv_used_prev->dv_used_next = d->dv_used_next;
116 if (d->dv_used_next != NULL)
117 d->dv_used_next->dv_used_prev = d->dv_used_prev;
118 vim_free(d);
119}
120
121 static void
122dict_free(dict_T *d)
123{
124 if (!in_free_unref_items)
125 {
126 dict_free_contents(d);
127 dict_free_dict(d);
128 }
129}
130
131/*
132 * Unreference a Dictionary: decrement the reference count and free it when it
133 * becomes zero.
134 */
135 void
136dict_unref(dict_T *d)
137{
138 if (d != NULL && --d->dv_refcount <= 0)
139 dict_free(d);
140}
141
142/*
143 * Go through the list of dicts and free items without the copyID.
144 * Returns TRUE if something was freed.
145 */
146 int
147dict_free_nonref(int copyID)
148{
149 dict_T *dd;
150 int did_free = FALSE;
151
152 for (dd = first_dict; dd != NULL; dd = dd->dv_used_next)
153 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK))
154 {
155 /* Free the Dictionary and ordinary items it contains, but don't
156 * recurse into Lists and Dictionaries, they will be in the list
157 * of dicts or list of lists. */
158 dict_free_contents(dd);
159 did_free = TRUE;
160 }
161 return did_free;
162}
163
164 void
165dict_free_items(int copyID)
166{
167 dict_T *dd, *dd_next;
168
169 for (dd = first_dict; dd != NULL; dd = dd_next)
170 {
171 dd_next = dd->dv_used_next;
172 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK))
173 dict_free_dict(dd);
174 }
175}
176
177/*
178 * Allocate a Dictionary item.
179 * The "key" is copied to the new item.
180 * Note that the value of the item "di_tv" still needs to be initialized!
181 * Returns NULL when out of memory.
182 */
183 dictitem_T *
184dictitem_alloc(char_u *key)
185{
186 dictitem_T *di;
187
188 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) + STRLEN(key)));
189 if (di != NULL)
190 {
191 STRCPY(di->di_key, key);
192 di->di_flags = DI_FLAGS_ALLOC;
193 }
194 return di;
195}
196
197/*
198 * Make a copy of a Dictionary item.
199 */
200 static dictitem_T *
201dictitem_copy(dictitem_T *org)
202{
203 dictitem_T *di;
204
205 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
206 + STRLEN(org->di_key)));
207 if (di != NULL)
208 {
209 STRCPY(di->di_key, org->di_key);
210 di->di_flags = DI_FLAGS_ALLOC;
211 copy_tv(&org->di_tv, &di->di_tv);
212 }
213 return di;
214}
215
216/*
217 * Remove item "item" from Dictionary "dict" and free it.
218 */
219 void
220dictitem_remove(dict_T *dict, dictitem_T *item)
221{
222 hashitem_T *hi;
223
224 hi = hash_find(&dict->dv_hashtab, item->di_key);
225 if (HASHITEM_EMPTY(hi))
Bram Moolenaar95f09602016-11-10 20:01:45 +0100226 internal_error("dictitem_remove()");
Bram Moolenaarcd524592016-07-17 14:57:05 +0200227 else
228 hash_remove(&dict->dv_hashtab, hi);
229 dictitem_free(item);
230}
231
232/*
233 * Free a dict item. Also clears the value.
234 */
235 void
236dictitem_free(dictitem_T *item)
237{
238 clear_tv(&item->di_tv);
239 if (item->di_flags & DI_FLAGS_ALLOC)
240 vim_free(item);
241}
242
243/*
244 * Make a copy of dict "d". Shallow if "deep" is FALSE.
245 * The refcount of the new dict is set to 1.
246 * See item_copy() for "copyID".
247 * Returns NULL when out of memory.
248 */
249 dict_T *
250dict_copy(dict_T *orig, int deep, int copyID)
251{
252 dict_T *copy;
253 dictitem_T *di;
254 int todo;
255 hashitem_T *hi;
256
257 if (orig == NULL)
258 return NULL;
259
260 copy = dict_alloc();
261 if (copy != NULL)
262 {
263 if (copyID != 0)
264 {
265 orig->dv_copyID = copyID;
266 orig->dv_copydict = copy;
267 }
268 todo = (int)orig->dv_hashtab.ht_used;
269 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
270 {
271 if (!HASHITEM_EMPTY(hi))
272 {
273 --todo;
274
275 di = dictitem_alloc(hi->hi_key);
276 if (di == NULL)
277 break;
278 if (deep)
279 {
280 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
281 copyID) == FAIL)
282 {
283 vim_free(di);
284 break;
285 }
286 }
287 else
288 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
289 if (dict_add(copy, di) == FAIL)
290 {
291 dictitem_free(di);
292 break;
293 }
294 }
295 }
296
297 ++copy->dv_refcount;
298 if (todo > 0)
299 {
300 dict_unref(copy);
301 copy = NULL;
302 }
303 }
304
305 return copy;
306}
307
308/*
309 * Add item "item" to Dictionary "d".
310 * Returns FAIL when out of memory and when key already exists.
311 */
312 int
313dict_add(dict_T *d, dictitem_T *item)
314{
315 return hash_add(&d->dv_hashtab, item->di_key);
316}
317
318/*
319 * Add a number or string entry to dictionary "d".
320 * When "str" is NULL use number "nr", otherwise use "str".
321 * Returns FAIL when out of memory and when key already exists.
322 */
323 int
324dict_add_nr_str(
325 dict_T *d,
326 char *key,
327 varnumber_T nr,
328 char_u *str)
329{
330 dictitem_T *item;
331
332 item = dictitem_alloc((char_u *)key);
333 if (item == NULL)
334 return FAIL;
335 item->di_tv.v_lock = 0;
336 if (str == NULL)
337 {
338 item->di_tv.v_type = VAR_NUMBER;
339 item->di_tv.vval.v_number = nr;
340 }
341 else
342 {
343 item->di_tv.v_type = VAR_STRING;
344 item->di_tv.vval.v_string = vim_strsave(str);
345 }
346 if (dict_add(d, item) == FAIL)
347 {
348 dictitem_free(item);
349 return FAIL;
350 }
351 return OK;
352}
353
354/*
355 * Add a list entry to dictionary "d".
356 * Returns FAIL when out of memory and when key already exists.
357 */
358 int
359dict_add_list(dict_T *d, char *key, list_T *list)
360{
361 dictitem_T *item;
362
363 item = dictitem_alloc((char_u *)key);
364 if (item == NULL)
365 return FAIL;
366 item->di_tv.v_lock = 0;
367 item->di_tv.v_type = VAR_LIST;
368 item->di_tv.vval.v_list = list;
Bram Moolenaar42f45b82017-03-14 22:17:14 +0100369 ++list->lv_refcount;
Bram Moolenaarcd524592016-07-17 14:57:05 +0200370 if (dict_add(d, item) == FAIL)
371 {
372 dictitem_free(item);
373 return FAIL;
374 }
Bram Moolenaarcd524592016-07-17 14:57:05 +0200375 return OK;
376}
377
378/*
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +0200379 * Add a dict entry to dictionary "d".
380 * Returns FAIL when out of memory and when key already exists.
381 */
382 int
383dict_add_dict(dict_T *d, char *key, dict_T *dict)
384{
385 dictitem_T *item;
386
387 item = dictitem_alloc((char_u *)key);
388 if (item == NULL)
389 return FAIL;
390 item->di_tv.v_lock = 0;
391 item->di_tv.v_type = VAR_DICT;
392 item->di_tv.vval.v_dict = dict;
Bram Moolenaar42f45b82017-03-14 22:17:14 +0100393 ++dict->dv_refcount;
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +0200394 if (dict_add(d, item) == FAIL)
395 {
396 dictitem_free(item);
397 return FAIL;
398 }
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +0200399 return OK;
400}
401
402/*
Bram Moolenaarcd524592016-07-17 14:57:05 +0200403 * Get the number of items in a Dictionary.
404 */
405 long
406dict_len(dict_T *d)
407{
408 if (d == NULL)
409 return 0L;
410 return (long)d->dv_hashtab.ht_used;
411}
412
413/*
414 * Find item "key[len]" in Dictionary "d".
415 * If "len" is negative use strlen(key).
416 * Returns NULL when not found.
417 */
418 dictitem_T *
419dict_find(dict_T *d, char_u *key, int len)
420{
421#define AKEYLEN 200
422 char_u buf[AKEYLEN];
423 char_u *akey;
424 char_u *tofree = NULL;
425 hashitem_T *hi;
426
427 if (d == NULL)
428 return NULL;
429 if (len < 0)
430 akey = key;
431 else if (len >= AKEYLEN)
432 {
433 tofree = akey = vim_strnsave(key, len);
434 if (akey == NULL)
435 return NULL;
436 }
437 else
438 {
439 /* Avoid a malloc/free by using buf[]. */
440 vim_strncpy(buf, key, len);
441 akey = buf;
442 }
443
444 hi = hash_find(&d->dv_hashtab, akey);
445 vim_free(tofree);
446 if (HASHITEM_EMPTY(hi))
447 return NULL;
448 return HI2DI(hi);
449}
450
451/*
452 * Get a string item from a dictionary.
453 * When "save" is TRUE allocate memory for it.
Bram Moolenaar7dc5e2e2016-08-05 22:22:06 +0200454 * When FALSE a shared buffer is used, can only be used once!
Bram Moolenaarcd524592016-07-17 14:57:05 +0200455 * Returns NULL if the entry doesn't exist or out of memory.
456 */
457 char_u *
458get_dict_string(dict_T *d, char_u *key, int save)
459{
460 dictitem_T *di;
461 char_u *s;
462
463 di = dict_find(d, key, -1);
464 if (di == NULL)
465 return NULL;
466 s = get_tv_string(&di->di_tv);
467 if (save && s != NULL)
468 s = vim_strsave(s);
469 return s;
470}
471
472/*
473 * Get a number item from a dictionary.
474 * Returns 0 if the entry doesn't exist.
475 */
476 varnumber_T
477get_dict_number(dict_T *d, char_u *key)
478{
479 dictitem_T *di;
480
481 di = dict_find(d, key, -1);
482 if (di == NULL)
483 return 0;
484 return get_tv_number(&di->di_tv);
485}
486
487/*
488 * Return an allocated string with the string representation of a Dictionary.
489 * May return NULL.
490 */
491 char_u *
492dict2string(typval_T *tv, int copyID, int restore_copyID)
493{
494 garray_T ga;
495 int first = TRUE;
496 char_u *tofree;
497 char_u numbuf[NUMBUFLEN];
498 hashitem_T *hi;
499 char_u *s;
500 dict_T *d;
501 int todo;
502
503 if ((d = tv->vval.v_dict) == NULL)
504 return NULL;
505 ga_init2(&ga, (int)sizeof(char), 80);
506 ga_append(&ga, '{');
507
508 todo = (int)d->dv_hashtab.ht_used;
509 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
510 {
511 if (!HASHITEM_EMPTY(hi))
512 {
513 --todo;
514
515 if (first)
516 first = FALSE;
517 else
518 ga_concat(&ga, (char_u *)", ");
519
520 tofree = string_quote(hi->hi_key, FALSE);
521 if (tofree != NULL)
522 {
523 ga_concat(&ga, tofree);
524 vim_free(tofree);
525 }
526 ga_concat(&ga, (char_u *)": ");
527 s = echo_string_core(&HI2DI(hi)->di_tv, &tofree, numbuf, copyID,
528 FALSE, restore_copyID, TRUE);
529 if (s != NULL)
530 ga_concat(&ga, s);
531 vim_free(tofree);
532 if (s == NULL || did_echo_string_emsg)
533 break;
534 line_breakcheck();
535
536 }
537 }
538 if (todo > 0)
539 {
540 vim_free(ga.ga_data);
541 return NULL;
542 }
543
544 ga_append(&ga, '}');
545 ga_append(&ga, NUL);
546 return (char_u *)ga.ga_data;
547}
548
549/*
550 * Allocate a variable for a Dictionary and fill it from "*arg".
551 * Return OK or FAIL. Returns NOTDONE for {expr}.
552 */
553 int
554get_dict_tv(char_u **arg, typval_T *rettv, int evaluate)
555{
556 dict_T *d = NULL;
557 typval_T tvkey;
558 typval_T tv;
559 char_u *key = NULL;
560 dictitem_T *item;
561 char_u *start = skipwhite(*arg + 1);
562 char_u buf[NUMBUFLEN];
563
564 /*
565 * First check if it's not a curly-braces thing: {expr}.
566 * Must do this without evaluating, otherwise a function may be called
567 * twice. Unfortunately this means we need to call eval1() twice for the
568 * first item.
569 * But {} is an empty Dictionary.
570 */
571 if (*start != '}')
572 {
573 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
574 return FAIL;
575 if (*start == '}')
576 return NOTDONE;
577 }
578
579 if (evaluate)
580 {
581 d = dict_alloc();
582 if (d == NULL)
583 return FAIL;
584 }
585 tvkey.v_type = VAR_UNKNOWN;
586 tv.v_type = VAR_UNKNOWN;
587
588 *arg = skipwhite(*arg + 1);
589 while (**arg != '}' && **arg != NUL)
590 {
591 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
592 goto failret;
593 if (**arg != ':')
594 {
595 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
596 clear_tv(&tvkey);
597 goto failret;
598 }
599 if (evaluate)
600 {
601 key = get_tv_string_buf_chk(&tvkey, buf);
602 if (key == NULL)
603 {
604 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
605 clear_tv(&tvkey);
606 goto failret;
607 }
608 }
609
610 *arg = skipwhite(*arg + 1);
611 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
612 {
613 if (evaluate)
614 clear_tv(&tvkey);
615 goto failret;
616 }
617 if (evaluate)
618 {
619 item = dict_find(d, key, -1);
620 if (item != NULL)
621 {
622 EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key);
623 clear_tv(&tvkey);
624 clear_tv(&tv);
625 goto failret;
626 }
627 item = dictitem_alloc(key);
628 clear_tv(&tvkey);
629 if (item != NULL)
630 {
631 item->di_tv = tv;
632 item->di_tv.v_lock = 0;
633 if (dict_add(d, item) == FAIL)
634 dictitem_free(item);
635 }
636 }
637
638 if (**arg == '}')
639 break;
640 if (**arg != ',')
641 {
642 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
643 goto failret;
644 }
645 *arg = skipwhite(*arg + 1);
646 }
647
648 if (**arg != '}')
649 {
650 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
651failret:
652 if (evaluate)
653 dict_free(d);
654 return FAIL;
655 }
656
657 *arg = skipwhite(*arg + 1);
658 if (evaluate)
Bram Moolenaar45cf6e92017-04-30 20:25:19 +0200659 rettv_dict_set(rettv, d);
Bram Moolenaarcd524592016-07-17 14:57:05 +0200660
661 return OK;
662}
663
664/*
665 * Go over all entries in "d2" and add them to "d1".
666 * When "action" is "error" then a duplicate key is an error.
667 * When "action" is "force" then a duplicate key is overwritten.
668 * Otherwise duplicate keys are ignored ("action" is "keep").
669 */
670 void
671dict_extend(dict_T *d1, dict_T *d2, char_u *action)
672{
673 dictitem_T *di1;
674 hashitem_T *hi2;
675 int todo;
676 char_u *arg_errmsg = (char_u *)N_("extend() argument");
677
678 todo = (int)d2->dv_hashtab.ht_used;
679 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
680 {
681 if (!HASHITEM_EMPTY(hi2))
682 {
683 --todo;
684 di1 = dict_find(d1, hi2->hi_key, -1);
685 if (d1->dv_scope != 0)
686 {
687 /* Disallow replacing a builtin function in l: and g:.
688 * Check the key to be valid when adding to any scope. */
689 if (d1->dv_scope == VAR_DEF_SCOPE
690 && HI2DI(hi2)->di_tv.v_type == VAR_FUNC
691 && var_check_func_name(hi2->hi_key, di1 == NULL))
692 break;
693 if (!valid_varname(hi2->hi_key))
694 break;
695 }
696 if (di1 == NULL)
697 {
698 di1 = dictitem_copy(HI2DI(hi2));
699 if (di1 != NULL && dict_add(d1, di1) == FAIL)
700 dictitem_free(di1);
701 }
702 else if (*action == 'e')
703 {
704 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
705 break;
706 }
707 else if (*action == 'f' && HI2DI(hi2) != di1)
708 {
709 if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, TRUE)
710 || var_check_ro(di1->di_flags, arg_errmsg, TRUE))
711 break;
712 clear_tv(&di1->di_tv);
713 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
714 }
715 }
716 }
717}
718
719/*
720 * Return the dictitem that an entry in a hashtable points to.
721 */
722 dictitem_T *
723dict_lookup(hashitem_T *hi)
724{
725 return HI2DI(hi);
726}
727
728/*
729 * Return TRUE when two dictionaries have exactly the same key/values.
730 */
731 int
732dict_equal(
733 dict_T *d1,
734 dict_T *d2,
735 int ic, /* ignore case for strings */
736 int recursive) /* TRUE when used recursively */
737{
738 hashitem_T *hi;
739 dictitem_T *item2;
740 int todo;
741
742 if (d1 == NULL && d2 == NULL)
743 return TRUE;
744 if (d1 == NULL || d2 == NULL)
745 return FALSE;
746 if (d1 == d2)
747 return TRUE;
748 if (dict_len(d1) != dict_len(d2))
749 return FALSE;
750
751 todo = (int)d1->dv_hashtab.ht_used;
752 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
753 {
754 if (!HASHITEM_EMPTY(hi))
755 {
756 item2 = dict_find(d2, hi->hi_key, -1);
757 if (item2 == NULL)
758 return FALSE;
759 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive))
760 return FALSE;
761 --todo;
762 }
763 }
764 return TRUE;
765}
766
767/*
768 * Turn a dict into a list:
769 * "what" == 0: list of keys
770 * "what" == 1: list of values
771 * "what" == 2: list of items
772 */
773 void
774dict_list(typval_T *argvars, typval_T *rettv, int what)
775{
776 list_T *l2;
777 dictitem_T *di;
778 hashitem_T *hi;
779 listitem_T *li;
780 listitem_T *li2;
781 dict_T *d;
782 int todo;
783
784 if (argvars[0].v_type != VAR_DICT)
785 {
786 EMSG(_(e_dictreq));
787 return;
788 }
789 if ((d = argvars[0].vval.v_dict) == NULL)
790 return;
791
792 if (rettv_list_alloc(rettv) == FAIL)
793 return;
794
795 todo = (int)d->dv_hashtab.ht_used;
796 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
797 {
798 if (!HASHITEM_EMPTY(hi))
799 {
800 --todo;
801 di = HI2DI(hi);
802
803 li = listitem_alloc();
804 if (li == NULL)
805 break;
806 list_append(rettv->vval.v_list, li);
807
808 if (what == 0)
809 {
810 /* keys() */
811 li->li_tv.v_type = VAR_STRING;
812 li->li_tv.v_lock = 0;
813 li->li_tv.vval.v_string = vim_strsave(di->di_key);
814 }
815 else if (what == 1)
816 {
817 /* values() */
818 copy_tv(&di->di_tv, &li->li_tv);
819 }
820 else
821 {
822 /* items() */
823 l2 = list_alloc();
824 li->li_tv.v_type = VAR_LIST;
825 li->li_tv.v_lock = 0;
826 li->li_tv.vval.v_list = l2;
827 if (l2 == NULL)
828 break;
829 ++l2->lv_refcount;
830
831 li2 = listitem_alloc();
832 if (li2 == NULL)
833 break;
834 list_append(l2, li2);
835 li2->li_tv.v_type = VAR_STRING;
836 li2->li_tv.v_lock = 0;
837 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
838
839 li2 = listitem_alloc();
840 if (li2 == NULL)
841 break;
842 list_append(l2, li2);
843 copy_tv(&di->di_tv, &li2->li_tv);
844 }
845 }
846 }
847}
848
849#endif /* defined(FEAT_EVAL) */