blob: 3cf6dff76ab8a031500ea659dd4b2da38b404123 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaarda861d62016-07-17 15:46:27 +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 * list.c: List support
12 */
13
14#include "vim.h"
15
16#if defined(FEAT_EVAL) || defined(PROTO)
17
18/* List heads for garbage collection. */
19static list_T *first_list = NULL; /* list of all lists */
20
21/*
22 * Add a watcher to a list.
23 */
24 void
25list_add_watch(list_T *l, listwatch_T *lw)
26{
27 lw->lw_next = l->lv_watch;
28 l->lv_watch = lw;
29}
30
31/*
32 * Remove a watcher from a list.
33 * No warning when it isn't found...
34 */
35 void
36list_rem_watch(list_T *l, listwatch_T *lwrem)
37{
38 listwatch_T *lw, **lwp;
39
40 lwp = &l->lv_watch;
41 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
42 {
43 if (lw == lwrem)
44 {
45 *lwp = lw->lw_next;
46 break;
47 }
48 lwp = &lw->lw_next;
49 }
50}
51
52/*
53 * Just before removing an item from a list: advance watchers to the next
54 * item.
55 */
56 void
57list_fix_watch(list_T *l, listitem_T *item)
58{
59 listwatch_T *lw;
60
61 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
62 if (lw->lw_item == item)
63 lw->lw_item = item->li_next;
64}
65
66/*
67 * Allocate an empty header for a list.
68 * Caller should take care of the reference count.
69 */
70 list_T *
71list_alloc(void)
72{
73 list_T *l;
74
75 l = (list_T *)alloc_clear(sizeof(list_T));
76 if (l != NULL)
77 {
78 /* Prepend the list to the list of lists for garbage collection. */
79 if (first_list != NULL)
80 first_list->lv_used_prev = l;
81 l->lv_used_prev = NULL;
82 l->lv_used_next = first_list;
83 first_list = l;
84 }
85 return l;
86}
87
88/*
Bram Moolenaarf49cc602018-11-11 15:21:05 +010089 * list_alloc() with an ID for alloc_fail().
90 */
91 list_T *
92list_alloc_id(alloc_id_T id UNUSED)
93{
94#ifdef FEAT_EVAL
95 if (alloc_fail_id == id && alloc_does_fail((long_u)sizeof(list_T)))
96 return NULL;
97#endif
98 return (list_alloc());
99}
100
101/*
Bram Moolenaarda861d62016-07-17 15:46:27 +0200102 * Allocate an empty list for a return value, with reference count set.
103 * Returns OK or FAIL.
104 */
105 int
106rettv_list_alloc(typval_T *rettv)
107{
108 list_T *l = list_alloc();
109
110 if (l == NULL)
111 return FAIL;
112
Bram Moolenaarda861d62016-07-17 15:46:27 +0200113 rettv->v_lock = 0;
Bram Moolenaar45cf6e92017-04-30 20:25:19 +0200114 rettv_list_set(rettv, l);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200115 return OK;
116}
117
118/*
Bram Moolenaar45cf6e92017-04-30 20:25:19 +0200119 * Set a list as the return value
120 */
121 void
122rettv_list_set(typval_T *rettv, list_T *l)
123{
124 rettv->v_type = VAR_LIST;
125 rettv->vval.v_list = l;
126 if (l != NULL)
127 ++l->lv_refcount;
128}
129
130/*
Bram Moolenaarda861d62016-07-17 15:46:27 +0200131 * Unreference a list: decrement the reference count and free it when it
132 * becomes zero.
133 */
134 void
135list_unref(list_T *l)
136{
137 if (l != NULL && --l->lv_refcount <= 0)
138 list_free(l);
139}
140
141/*
142 * Free a list, including all non-container items it points to.
143 * Ignores the reference count.
144 */
145 static void
146list_free_contents(list_T *l)
147{
148 listitem_T *item;
149
150 for (item = l->lv_first; item != NULL; item = l->lv_first)
151 {
152 /* Remove the item before deleting it. */
153 l->lv_first = item->li_next;
154 clear_tv(&item->li_tv);
155 vim_free(item);
156 }
157}
158
159/*
160 * Go through the list of lists and free items without the copyID.
161 * But don't free a list that has a watcher (used in a for loop), these
162 * are not referenced anywhere.
163 */
164 int
165list_free_nonref(int copyID)
166{
167 list_T *ll;
168 int did_free = FALSE;
169
170 for (ll = first_list; ll != NULL; ll = ll->lv_used_next)
171 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
172 && ll->lv_watch == NULL)
173 {
174 /* Free the List and ordinary items it contains, but don't recurse
175 * into Lists and Dictionaries, they will be in the list of dicts
176 * or list of lists. */
177 list_free_contents(ll);
178 did_free = TRUE;
179 }
180 return did_free;
181}
182
183 static void
184list_free_list(list_T *l)
185{
186 /* Remove the list from the list of lists for garbage collection. */
187 if (l->lv_used_prev == NULL)
188 first_list = l->lv_used_next;
189 else
190 l->lv_used_prev->lv_used_next = l->lv_used_next;
191 if (l->lv_used_next != NULL)
192 l->lv_used_next->lv_used_prev = l->lv_used_prev;
193
194 vim_free(l);
195}
196
197 void
198list_free_items(int copyID)
199{
200 list_T *ll, *ll_next;
201
202 for (ll = first_list; ll != NULL; ll = ll_next)
203 {
204 ll_next = ll->lv_used_next;
205 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
206 && ll->lv_watch == NULL)
207 {
208 /* Free the List and ordinary items it contains, but don't recurse
209 * into Lists and Dictionaries, they will be in the list of dicts
210 * or list of lists. */
211 list_free_list(ll);
212 }
213 }
214}
215
216 void
217list_free(list_T *l)
218{
219 if (!in_free_unref_items)
220 {
221 list_free_contents(l);
222 list_free_list(l);
223 }
224}
225
226/*
227 * Allocate a list item.
228 * It is not initialized, don't forget to set v_lock.
229 */
230 listitem_T *
231listitem_alloc(void)
232{
233 return (listitem_T *)alloc(sizeof(listitem_T));
234}
235
236/*
237 * Free a list item. Also clears the value. Does not notify watchers.
238 */
239 void
240listitem_free(listitem_T *item)
241{
242 clear_tv(&item->li_tv);
243 vim_free(item);
244}
245
246/*
247 * Remove a list item from a List and free it. Also clears the value.
248 */
249 void
250listitem_remove(list_T *l, listitem_T *item)
251{
252 vimlist_remove(l, item, item);
253 listitem_free(item);
254}
255
256/*
257 * Get the number of items in a list.
258 */
259 long
260list_len(list_T *l)
261{
262 if (l == NULL)
263 return 0L;
264 return l->lv_len;
265}
266
267/*
268 * Return TRUE when two lists have exactly the same values.
269 */
270 int
271list_equal(
272 list_T *l1,
273 list_T *l2,
274 int ic, /* ignore case for strings */
275 int recursive) /* TRUE when used recursively */
276{
277 listitem_T *item1, *item2;
278
279 if (l1 == NULL || l2 == NULL)
280 return FALSE;
281 if (l1 == l2)
282 return TRUE;
283 if (list_len(l1) != list_len(l2))
284 return FALSE;
285
286 for (item1 = l1->lv_first, item2 = l2->lv_first;
287 item1 != NULL && item2 != NULL;
288 item1 = item1->li_next, item2 = item2->li_next)
289 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive))
290 return FALSE;
291 return item1 == NULL && item2 == NULL;
292}
293
294/*
295 * Locate item with index "n" in list "l" and return it.
296 * A negative index is counted from the end; -1 is the last item.
297 * Returns NULL when "n" is out of range.
298 */
299 listitem_T *
300list_find(list_T *l, long n)
301{
302 listitem_T *item;
303 long idx;
304
305 if (l == NULL)
306 return NULL;
307
308 /* Negative index is relative to the end. */
309 if (n < 0)
310 n = l->lv_len + n;
311
312 /* Check for index out of range. */
313 if (n < 0 || n >= l->lv_len)
314 return NULL;
315
316 /* When there is a cached index may start search from there. */
317 if (l->lv_idx_item != NULL)
318 {
319 if (n < l->lv_idx / 2)
320 {
321 /* closest to the start of the list */
322 item = l->lv_first;
323 idx = 0;
324 }
325 else if (n > (l->lv_idx + l->lv_len) / 2)
326 {
327 /* closest to the end of the list */
328 item = l->lv_last;
329 idx = l->lv_len - 1;
330 }
331 else
332 {
333 /* closest to the cached index */
334 item = l->lv_idx_item;
335 idx = l->lv_idx;
336 }
337 }
338 else
339 {
340 if (n < l->lv_len / 2)
341 {
342 /* closest to the start of the list */
343 item = l->lv_first;
344 idx = 0;
345 }
346 else
347 {
348 /* closest to the end of the list */
349 item = l->lv_last;
350 idx = l->lv_len - 1;
351 }
352 }
353
354 while (n > idx)
355 {
356 /* search forward */
357 item = item->li_next;
358 ++idx;
359 }
360 while (n < idx)
361 {
362 /* search backward */
363 item = item->li_prev;
364 --idx;
365 }
366
367 /* cache the used index */
368 l->lv_idx = idx;
369 l->lv_idx_item = item;
370
371 return item;
372}
373
374/*
375 * Get list item "l[idx]" as a number.
376 */
377 long
378list_find_nr(
379 list_T *l,
380 long idx,
381 int *errorp) /* set to TRUE when something wrong */
382{
383 listitem_T *li;
384
385 li = list_find(l, idx);
386 if (li == NULL)
387 {
388 if (errorp != NULL)
389 *errorp = TRUE;
390 return -1L;
391 }
392 return (long)get_tv_number_chk(&li->li_tv, errorp);
393}
394
395/*
396 * Get list item "l[idx - 1]" as a string. Returns NULL for failure.
397 */
398 char_u *
399list_find_str(list_T *l, long idx)
400{
401 listitem_T *li;
402
403 li = list_find(l, idx - 1);
404 if (li == NULL)
405 {
406 EMSGN(_(e_listidx), idx);
407 return NULL;
408 }
409 return get_tv_string(&li->li_tv);
410}
411
412/*
413 * Locate "item" list "l" and return its index.
414 * Returns -1 when "item" is not in the list.
415 */
416 long
417list_idx_of_item(list_T *l, listitem_T *item)
418{
419 long idx = 0;
420 listitem_T *li;
421
422 if (l == NULL)
423 return -1;
424 idx = 0;
425 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
426 ++idx;
427 if (li == NULL)
428 return -1;
429 return idx;
430}
431
432/*
433 * Append item "item" to the end of list "l".
434 */
435 void
436list_append(list_T *l, listitem_T *item)
437{
438 if (l->lv_last == NULL)
439 {
440 /* empty list */
441 l->lv_first = item;
442 l->lv_last = item;
443 item->li_prev = NULL;
444 }
445 else
446 {
447 l->lv_last->li_next = item;
448 item->li_prev = l->lv_last;
449 l->lv_last = item;
450 }
451 ++l->lv_len;
452 item->li_next = NULL;
453}
454
455/*
456 * Append typval_T "tv" to the end of list "l".
457 * Return FAIL when out of memory.
458 */
459 int
460list_append_tv(list_T *l, typval_T *tv)
461{
462 listitem_T *li = listitem_alloc();
463
464 if (li == NULL)
465 return FAIL;
466 copy_tv(tv, &li->li_tv);
467 list_append(l, li);
468 return OK;
469}
470
471/*
472 * Add a dictionary to a list. Used by getqflist().
473 * Return FAIL when out of memory.
474 */
475 int
476list_append_dict(list_T *list, dict_T *dict)
477{
478 listitem_T *li = listitem_alloc();
479
480 if (li == NULL)
481 return FAIL;
482 li->li_tv.v_type = VAR_DICT;
483 li->li_tv.v_lock = 0;
484 li->li_tv.vval.v_dict = dict;
485 list_append(list, li);
486 ++dict->dv_refcount;
487 return OK;
488}
489
490/*
Bram Moolenaar4f505882018-02-10 21:06:32 +0100491 * Append list2 to list1.
492 * Return FAIL when out of memory.
493 */
494 int
Bram Moolenaar6f8d2ac2018-07-25 19:49:45 +0200495list_append_list(list_T *list1, list_T *list2)
Bram Moolenaar4f505882018-02-10 21:06:32 +0100496{
497 listitem_T *li = listitem_alloc();
498
499 if (li == NULL)
500 return FAIL;
501 li->li_tv.v_type = VAR_LIST;
502 li->li_tv.v_lock = 0;
503 li->li_tv.vval.v_list = list2;
504 list_append(list1, li);
505 ++list2->lv_refcount;
506 return OK;
507}
508
509/*
Bram Moolenaarda861d62016-07-17 15:46:27 +0200510 * Make a copy of "str" and append it as an item to list "l".
511 * When "len" >= 0 use "str[len]".
512 * Returns FAIL when out of memory.
513 */
514 int
515list_append_string(list_T *l, char_u *str, int len)
516{
517 listitem_T *li = listitem_alloc();
518
519 if (li == NULL)
520 return FAIL;
521 list_append(l, li);
522 li->li_tv.v_type = VAR_STRING;
523 li->li_tv.v_lock = 0;
524 if (str == NULL)
525 li->li_tv.vval.v_string = NULL;
526 else if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len)
527 : vim_strsave(str))) == NULL)
528 return FAIL;
529 return OK;
530}
531
532/*
533 * Append "n" to list "l".
534 * Returns FAIL when out of memory.
535 */
536 int
537list_append_number(list_T *l, varnumber_T n)
538{
539 listitem_T *li;
540
541 li = listitem_alloc();
542 if (li == NULL)
543 return FAIL;
544 li->li_tv.v_type = VAR_NUMBER;
545 li->li_tv.v_lock = 0;
546 li->li_tv.vval.v_number = n;
547 list_append(l, li);
548 return OK;
549}
550
551/*
552 * Insert typval_T "tv" in list "l" before "item".
553 * If "item" is NULL append at the end.
554 * Return FAIL when out of memory.
555 */
556 int
557list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
558{
559 listitem_T *ni = listitem_alloc();
560
561 if (ni == NULL)
562 return FAIL;
563 copy_tv(tv, &ni->li_tv);
564 list_insert(l, ni, item);
565 return OK;
566}
567
568 void
569list_insert(list_T *l, listitem_T *ni, listitem_T *item)
570{
571 if (item == NULL)
572 /* Append new item at end of list. */
573 list_append(l, ni);
574 else
575 {
576 /* Insert new item before existing item. */
577 ni->li_prev = item->li_prev;
578 ni->li_next = item;
579 if (item->li_prev == NULL)
580 {
581 l->lv_first = ni;
582 ++l->lv_idx;
583 }
584 else
585 {
586 item->li_prev->li_next = ni;
587 l->lv_idx_item = NULL;
588 }
589 item->li_prev = ni;
590 ++l->lv_len;
591 }
592}
593
594/*
595 * Extend "l1" with "l2".
596 * If "bef" is NULL append at the end, otherwise insert before this item.
597 * Returns FAIL when out of memory.
598 */
599 int
600list_extend(list_T *l1, list_T *l2, listitem_T *bef)
601{
602 listitem_T *item;
603 int todo = l2->lv_len;
604
605 /* We also quit the loop when we have inserted the original item count of
606 * the list, avoid a hang when we extend a list with itself. */
607 for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next)
608 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
609 return FAIL;
610 return OK;
611}
612
613/*
614 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
615 * Return FAIL when out of memory.
616 */
617 int
618list_concat(list_T *l1, list_T *l2, typval_T *tv)
619{
620 list_T *l;
621
622 if (l1 == NULL || l2 == NULL)
623 return FAIL;
624
625 /* make a copy of the first list. */
626 l = list_copy(l1, FALSE, 0);
627 if (l == NULL)
628 return FAIL;
629 tv->v_type = VAR_LIST;
630 tv->vval.v_list = l;
631
632 /* append all items from the second list */
633 return list_extend(l, l2, NULL);
634}
635
636/*
637 * Make a copy of list "orig". Shallow if "deep" is FALSE.
638 * The refcount of the new list is set to 1.
639 * See item_copy() for "copyID".
640 * Returns NULL when out of memory.
641 */
642 list_T *
643list_copy(list_T *orig, int deep, int copyID)
644{
645 list_T *copy;
646 listitem_T *item;
647 listitem_T *ni;
648
649 if (orig == NULL)
650 return NULL;
651
652 copy = list_alloc();
653 if (copy != NULL)
654 {
655 if (copyID != 0)
656 {
657 /* Do this before adding the items, because one of the items may
658 * refer back to this list. */
659 orig->lv_copyID = copyID;
660 orig->lv_copylist = copy;
661 }
662 for (item = orig->lv_first; item != NULL && !got_int;
663 item = item->li_next)
664 {
665 ni = listitem_alloc();
666 if (ni == NULL)
667 break;
668 if (deep)
669 {
670 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
671 {
672 vim_free(ni);
673 break;
674 }
675 }
676 else
677 copy_tv(&item->li_tv, &ni->li_tv);
678 list_append(copy, ni);
679 }
680 ++copy->lv_refcount;
681 if (item != NULL)
682 {
683 list_unref(copy);
684 copy = NULL;
685 }
686 }
687
688 return copy;
689}
690
691/*
692 * Remove items "item" to "item2" from list "l".
693 * Does not free the listitem or the value!
694 * This used to be called list_remove, but that conflicts with a Sun header
695 * file.
696 */
697 void
698vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2)
699{
700 listitem_T *ip;
701
702 /* notify watchers */
703 for (ip = item; ip != NULL; ip = ip->li_next)
704 {
705 --l->lv_len;
706 list_fix_watch(l, ip);
707 if (ip == item2)
708 break;
709 }
710
711 if (item2->li_next == NULL)
712 l->lv_last = item->li_prev;
713 else
714 item2->li_next->li_prev = item->li_prev;
715 if (item->li_prev == NULL)
716 l->lv_first = item2->li_next;
717 else
718 item->li_prev->li_next = item2->li_next;
719 l->lv_idx_item = NULL;
720}
721
722/*
723 * Return an allocated string with the string representation of a list.
724 * May return NULL.
725 */
726 char_u *
727list2string(typval_T *tv, int copyID, int restore_copyID)
728{
729 garray_T ga;
730
731 if (tv->vval.v_list == NULL)
732 return NULL;
733 ga_init2(&ga, (int)sizeof(char), 80);
734 ga_append(&ga, '[');
735 if (list_join(&ga, tv->vval.v_list, (char_u *)", ",
736 FALSE, restore_copyID, copyID) == FAIL)
737 {
738 vim_free(ga.ga_data);
739 return NULL;
740 }
741 ga_append(&ga, ']');
742 ga_append(&ga, NUL);
743 return (char_u *)ga.ga_data;
744}
745
746typedef struct join_S {
747 char_u *s;
748 char_u *tofree;
749} join_T;
750
751 static int
752list_join_inner(
753 garray_T *gap, /* to store the result in */
754 list_T *l,
755 char_u *sep,
756 int echo_style,
757 int restore_copyID,
758 int copyID,
759 garray_T *join_gap) /* to keep each list item string */
760{
761 int i;
762 join_T *p;
763 int len;
764 int sumlen = 0;
765 int first = TRUE;
766 char_u *tofree;
767 char_u numbuf[NUMBUFLEN];
768 listitem_T *item;
769 char_u *s;
770
771 /* Stringify each item in the list. */
772 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
773 {
774 s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID,
Bram Moolenaar35422f42017-08-05 16:33:56 +0200775 echo_style, restore_copyID, !echo_style);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200776 if (s == NULL)
777 return FAIL;
778
779 len = (int)STRLEN(s);
780 sumlen += len;
781
782 (void)ga_grow(join_gap, 1);
783 p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++);
784 if (tofree != NULL || s != numbuf)
785 {
786 p->s = s;
787 p->tofree = tofree;
788 }
789 else
790 {
791 p->s = vim_strnsave(s, len);
792 p->tofree = p->s;
793 }
794
795 line_breakcheck();
796 if (did_echo_string_emsg) /* recursion error, bail out */
797 break;
798 }
799
800 /* Allocate result buffer with its total size, avoid re-allocation and
801 * multiple copy operations. Add 2 for a tailing ']' and NUL. */
802 if (join_gap->ga_len >= 2)
803 sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1);
804 if (ga_grow(gap, sumlen + 2) == FAIL)
805 return FAIL;
806
807 for (i = 0; i < join_gap->ga_len && !got_int; ++i)
808 {
809 if (first)
810 first = FALSE;
811 else
812 ga_concat(gap, sep);
813 p = ((join_T *)join_gap->ga_data) + i;
814
815 if (p->s != NULL)
816 ga_concat(gap, p->s);
817 line_breakcheck();
818 }
819
820 return OK;
821}
822
823/*
824 * Join list "l" into a string in "*gap", using separator "sep".
825 * When "echo_style" is TRUE use String as echoed, otherwise as inside a List.
826 * Return FAIL or OK.
827 */
828 int
829list_join(
830 garray_T *gap,
831 list_T *l,
832 char_u *sep,
833 int echo_style,
834 int restore_copyID,
835 int copyID)
836{
837 garray_T join_ga;
838 int retval;
839 join_T *p;
840 int i;
841
842 if (l->lv_len < 1)
843 return OK; /* nothing to do */
844 ga_init2(&join_ga, (int)sizeof(join_T), l->lv_len);
845 retval = list_join_inner(gap, l, sep, echo_style, restore_copyID,
846 copyID, &join_ga);
847
848 /* Dispose each item in join_ga. */
849 if (join_ga.ga_data != NULL)
850 {
851 p = (join_T *)join_ga.ga_data;
852 for (i = 0; i < join_ga.ga_len; ++i)
853 {
854 vim_free(p->tofree);
855 ++p;
856 }
857 ga_clear(&join_ga);
858 }
859
860 return retval;
861}
862
863/*
864 * Allocate a variable for a List and fill it from "*arg".
865 * Return OK or FAIL.
866 */
867 int
868get_list_tv(char_u **arg, typval_T *rettv, int evaluate)
869{
870 list_T *l = NULL;
871 typval_T tv;
872 listitem_T *item;
873
874 if (evaluate)
875 {
876 l = list_alloc();
877 if (l == NULL)
878 return FAIL;
879 }
880
881 *arg = skipwhite(*arg + 1);
882 while (**arg != ']' && **arg != NUL)
883 {
884 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
885 goto failret;
886 if (evaluate)
887 {
888 item = listitem_alloc();
889 if (item != NULL)
890 {
891 item->li_tv = tv;
892 item->li_tv.v_lock = 0;
893 list_append(l, item);
894 }
895 else
896 clear_tv(&tv);
897 }
898
899 if (**arg == ']')
900 break;
901 if (**arg != ',')
902 {
903 EMSG2(_("E696: Missing comma in List: %s"), *arg);
904 goto failret;
905 }
906 *arg = skipwhite(*arg + 1);
907 }
908
909 if (**arg != ']')
910 {
911 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
912failret:
913 if (evaluate)
914 list_free(l);
915 return FAIL;
916 }
917
918 *arg = skipwhite(*arg + 1);
919 if (evaluate)
Bram Moolenaar45cf6e92017-04-30 20:25:19 +0200920 rettv_list_set(rettv, l);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200921
922 return OK;
923}
924
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200925/*
Bram Moolenaarcaa55b62017-01-10 13:51:09 +0100926 * Write "list" of strings to file "fd".
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200927 */
928 int
929write_list(FILE *fd, list_T *list, int binary)
930{
931 listitem_T *li;
932 int c;
933 int ret = OK;
934 char_u *s;
935
936 for (li = list->lv_first; li != NULL; li = li->li_next)
937 {
938 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
939 {
940 if (*s == '\n')
941 c = putc(NUL, fd);
942 else
943 c = putc(*s, fd);
944 if (c == EOF)
945 {
946 ret = FAIL;
947 break;
948 }
949 }
950 if (!binary || li->li_next != NULL)
951 if (putc('\n', fd) == EOF)
952 {
953 ret = FAIL;
954 break;
955 }
956 if (ret == FAIL)
957 {
958 EMSG(_(e_write));
959 break;
960 }
961 }
962 return ret;
963}
964
Bram Moolenaardf48fb42016-07-22 21:50:18 +0200965/*
966 * Initialize a static list with 10 items.
967 */
968 void
969init_static_list(staticList10_T *sl)
970{
971 list_T *l = &sl->sl_list;
972 int i;
973
974 memset(sl, 0, sizeof(staticList10_T));
975 l->lv_first = &sl->sl_items[0];
976 l->lv_last = &sl->sl_items[9];
977 l->lv_refcount = DO_NOT_FREE_CNT;
978 l->lv_lock = VAR_FIXED;
979 sl->sl_list.lv_len = 10;
980
981 for (i = 0; i < 10; ++i)
982 {
983 listitem_T *li = &sl->sl_items[i];
984
985 if (i == 0)
986 li->li_prev = NULL;
987 else
988 li->li_prev = li - 1;
989 if (i == 9)
990 li->li_next = NULL;
991 else
992 li->li_next = li + 1;
993 }
994}
995
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200996#endif /* defined(FEAT_EVAL) */