xref: /vim-8.2.3635/src/list.c (revision ea2d8d25)
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  * list.c: List support and container (List, Dict, Blob) functions.
12  */
13 
14 #include "vim.h"
15 
16 #if defined(FEAT_EVAL) || defined(PROTO)
17 
18 static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
19 
20 // List heads for garbage collection.
21 static list_T		*first_list = NULL;	// list of all lists
22 
23 #define FOR_ALL_WATCHERS(l, lw) \
24     for ((lw) = (l)->lv_watch; (lw) != NULL; (lw) = (lw)->lw_next)
25 
26 static void list_free_item(list_T *l, listitem_T *item);
27 
28 /*
29  * Add a watcher to a list.
30  */
31     void
32 list_add_watch(list_T *l, listwatch_T *lw)
33 {
34     lw->lw_next = l->lv_watch;
35     l->lv_watch = lw;
36 }
37 
38 /*
39  * Remove a watcher from a list.
40  * No warning when it isn't found...
41  */
42     void
43 list_rem_watch(list_T *l, listwatch_T *lwrem)
44 {
45     listwatch_T	*lw, **lwp;
46 
47     lwp = &l->lv_watch;
48     FOR_ALL_WATCHERS(l, lw)
49     {
50 	if (lw == lwrem)
51 	{
52 	    *lwp = lw->lw_next;
53 	    break;
54 	}
55 	lwp = &lw->lw_next;
56     }
57 }
58 
59 /*
60  * Just before removing an item from a list: advance watchers to the next
61  * item.
62  */
63     static void
64 list_fix_watch(list_T *l, listitem_T *item)
65 {
66     listwatch_T	*lw;
67 
68     FOR_ALL_WATCHERS(l, lw)
69 	if (lw->lw_item == item)
70 	    lw->lw_item = item->li_next;
71 }
72 
73     static void
74 list_init(list_T *l)
75 {
76     // Prepend the list to the list of lists for garbage collection.
77     if (first_list != NULL)
78 	first_list->lv_used_prev = l;
79     l->lv_used_prev = NULL;
80     l->lv_used_next = first_list;
81     first_list = l;
82 }
83 
84 /*
85  * Allocate an empty header for a list.
86  * Caller should take care of the reference count.
87  */
88     list_T *
89 list_alloc(void)
90 {
91     list_T  *l;
92 
93     l = ALLOC_CLEAR_ONE(list_T);
94     if (l != NULL)
95 	list_init(l);
96     return l;
97 }
98 
99 /*
100  * list_alloc() with an ID for alloc_fail().
101  */
102     list_T *
103 list_alloc_id(alloc_id_T id UNUSED)
104 {
105 #ifdef FEAT_EVAL
106     if (alloc_fail_id == id && alloc_does_fail(sizeof(list_T)))
107 	return NULL;
108 #endif
109     return (list_alloc());
110 }
111 
112 /*
113  * Allocate space for a list, plus "count" items.
114  * Next list_set_item() must be called for each item.
115  */
116     list_T *
117 list_alloc_with_items(int count)
118 {
119     list_T	*l;
120 
121     l = (list_T *)alloc_clear(sizeof(list_T) + count * sizeof(listitem_T));
122     if (l != NULL)
123     {
124 	list_init(l);
125 
126 	if (count > 0)
127 	{
128 	    listitem_T	*li = (listitem_T *)(l + 1);
129 	    int		i;
130 
131 	    l->lv_len = count;
132 	    l->lv_with_items = count;
133 	    l->lv_first = li;
134 	    l->lv_u.mat.lv_last = li + count - 1;
135 	    for (i = 0; i < count; ++i)
136 	    {
137 		if (i == 0)
138 		    li->li_prev = NULL;
139 		else
140 		    li->li_prev = li - 1;
141 		if (i == count - 1)
142 		    li->li_next = NULL;
143 		else
144 		    li->li_next = li + 1;
145 		++li;
146 	    }
147 	}
148     }
149     return l;
150 }
151 
152 /*
153  * Set item "idx" for a list previously allocated with list_alloc_with_items().
154  * The contents of "tv" is moved into the list item.
155  * Each item must be set exactly once.
156  */
157     void
158 list_set_item(list_T *l, int idx, typval_T *tv)
159 {
160     listitem_T	*li = (listitem_T *)(l + 1) + idx;
161 
162     li->li_tv = *tv;
163 }
164 
165 /*
166  * Allocate an empty list for a return value, with reference count set.
167  * Returns OK or FAIL.
168  */
169     int
170 rettv_list_alloc(typval_T *rettv)
171 {
172     list_T	*l = list_alloc();
173 
174     if (l == NULL)
175 	return FAIL;
176 
177     rettv->v_lock = 0;
178     rettv_list_set(rettv, l);
179     return OK;
180 }
181 
182 /*
183  * Same as rettv_list_alloc() but uses an allocation id for testing.
184  */
185     int
186 rettv_list_alloc_id(typval_T *rettv, alloc_id_T id UNUSED)
187 {
188 #ifdef FEAT_EVAL
189     if (alloc_fail_id == id && alloc_does_fail(sizeof(list_T)))
190 	return FAIL;
191 #endif
192     return rettv_list_alloc(rettv);
193 }
194 
195 
196 /*
197  * Set a list as the return value.  Increments the reference count.
198  */
199     void
200 rettv_list_set(typval_T *rettv, list_T *l)
201 {
202     rettv->v_type = VAR_LIST;
203     rettv->vval.v_list = l;
204     if (l != NULL)
205 	++l->lv_refcount;
206 }
207 
208 /*
209  * Unreference a list: decrement the reference count and free it when it
210  * becomes zero.
211  */
212     void
213 list_unref(list_T *l)
214 {
215     if (l != NULL && --l->lv_refcount <= 0)
216 	list_free(l);
217 }
218 
219 /*
220  * Free a list, including all non-container items it points to.
221  * Ignores the reference count.
222  */
223     static void
224 list_free_contents(list_T *l)
225 {
226     listitem_T *item;
227 
228     if (l->lv_first != &range_list_item)
229 	for (item = l->lv_first; item != NULL; item = l->lv_first)
230 	{
231 	    // Remove the item before deleting it.
232 	    l->lv_first = item->li_next;
233 	    clear_tv(&item->li_tv);
234 	    list_free_item(l, item);
235 	}
236 }
237 
238 /*
239  * Go through the list of lists and free items without the copyID.
240  * But don't free a list that has a watcher (used in a for loop), these
241  * are not referenced anywhere.
242  */
243     int
244 list_free_nonref(int copyID)
245 {
246     list_T	*ll;
247     int		did_free = FALSE;
248 
249     for (ll = first_list; ll != NULL; ll = ll->lv_used_next)
250 	if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
251 						      && ll->lv_watch == NULL)
252 	{
253 	    // Free the List and ordinary items it contains, but don't recurse
254 	    // into Lists and Dictionaries, they will be in the list of dicts
255 	    // or list of lists.
256 	    list_free_contents(ll);
257 	    did_free = TRUE;
258 	}
259     return did_free;
260 }
261 
262     static void
263 list_free_list(list_T  *l)
264 {
265     // Remove the list from the list of lists for garbage collection.
266     if (l->lv_used_prev == NULL)
267 	first_list = l->lv_used_next;
268     else
269 	l->lv_used_prev->lv_used_next = l->lv_used_next;
270     if (l->lv_used_next != NULL)
271 	l->lv_used_next->lv_used_prev = l->lv_used_prev;
272 
273     vim_free(l);
274 }
275 
276     void
277 list_free_items(int copyID)
278 {
279     list_T	*ll, *ll_next;
280 
281     for (ll = first_list; ll != NULL; ll = ll_next)
282     {
283 	ll_next = ll->lv_used_next;
284 	if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
285 						      && ll->lv_watch == NULL)
286 	{
287 	    // Free the List and ordinary items it contains, but don't recurse
288 	    // into Lists and Dictionaries, they will be in the list of dicts
289 	    // or list of lists.
290 	    list_free_list(ll);
291 	}
292     }
293 }
294 
295     void
296 list_free(list_T *l)
297 {
298     if (!in_free_unref_items)
299     {
300 	list_free_contents(l);
301 	list_free_list(l);
302     }
303 }
304 
305 /*
306  * Allocate a list item.
307  * It is not initialized, don't forget to set v_lock.
308  */
309     listitem_T *
310 listitem_alloc(void)
311 {
312     return ALLOC_ONE(listitem_T);
313 }
314 
315 /*
316  * Free a list item, unless it was allocated together with the list itself.
317  * Does not clear the value.  Does not notify watchers.
318  */
319     static void
320 list_free_item(list_T *l, listitem_T *item)
321 {
322     if (l->lv_with_items == 0 || item < (listitem_T *)l
323 			   || item >= (listitem_T *)(l + 1) + l->lv_with_items)
324 	vim_free(item);
325 }
326 
327 /*
328  * Free a list item, unless it was allocated together with the list itself.
329  * Also clears the value.  Does not notify watchers.
330  */
331     void
332 listitem_free(list_T *l, listitem_T *item)
333 {
334     clear_tv(&item->li_tv);
335     list_free_item(l, item);
336 }
337 
338 /*
339  * Remove a list item from a List and free it.  Also clears the value.
340  */
341     void
342 listitem_remove(list_T *l, listitem_T *item)
343 {
344     vimlist_remove(l, item, item);
345     listitem_free(l, item);
346 }
347 
348 /*
349  * Get the number of items in a list.
350  */
351     long
352 list_len(list_T *l)
353 {
354     if (l == NULL)
355 	return 0L;
356     return l->lv_len;
357 }
358 
359 /*
360  * Return TRUE when two lists have exactly the same values.
361  */
362     int
363 list_equal(
364     list_T	*l1,
365     list_T	*l2,
366     int		ic,	// ignore case for strings
367     int		recursive)  // TRUE when used recursively
368 {
369     listitem_T	*item1, *item2;
370 
371     if (l1 == l2)
372 	return TRUE;
373     if (list_len(l1) != list_len(l2))
374 	return FALSE;
375     if (list_len(l1) == 0)
376 	// empty and NULL list are considered equal
377 	return TRUE;
378     if (l1 == NULL || l2 == NULL)
379 	return FALSE;
380 
381     CHECK_LIST_MATERIALIZE(l1);
382     CHECK_LIST_MATERIALIZE(l2);
383 
384     for (item1 = l1->lv_first, item2 = l2->lv_first;
385 	    item1 != NULL && item2 != NULL;
386 			       item1 = item1->li_next, item2 = item2->li_next)
387 	if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive))
388 	    return FALSE;
389     return item1 == NULL && item2 == NULL;
390 }
391 
392 /*
393  * Locate item with index "n" in list "l" and return it.
394  * A negative index is counted from the end; -1 is the last item.
395  * Returns NULL when "n" is out of range.
396  */
397     listitem_T *
398 list_find(list_T *l, long n)
399 {
400     listitem_T	*item;
401     long	idx;
402 
403     if (l == NULL)
404 	return NULL;
405 
406     // Negative index is relative to the end.
407     if (n < 0)
408 	n = l->lv_len + n;
409 
410     // Check for index out of range.
411     if (n < 0 || n >= l->lv_len)
412 	return NULL;
413 
414     CHECK_LIST_MATERIALIZE(l);
415 
416     // When there is a cached index may start search from there.
417     if (l->lv_u.mat.lv_idx_item != NULL)
418     {
419 	if (n < l->lv_u.mat.lv_idx / 2)
420 	{
421 	    // closest to the start of the list
422 	    item = l->lv_first;
423 	    idx = 0;
424 	}
425 	else if (n > (l->lv_u.mat.lv_idx + l->lv_len) / 2)
426 	{
427 	    // closest to the end of the list
428 	    item = l->lv_u.mat.lv_last;
429 	    idx = l->lv_len - 1;
430 	}
431 	else
432 	{
433 	    // closest to the cached index
434 	    item = l->lv_u.mat.lv_idx_item;
435 	    idx = l->lv_u.mat.lv_idx;
436 	}
437     }
438     else
439     {
440 	if (n < l->lv_len / 2)
441 	{
442 	    // closest to the start of the list
443 	    item = l->lv_first;
444 	    idx = 0;
445 	}
446 	else
447 	{
448 	    // closest to the end of the list
449 	    item = l->lv_u.mat.lv_last;
450 	    idx = l->lv_len - 1;
451 	}
452     }
453 
454     while (n > idx)
455     {
456 	// search forward
457 	item = item->li_next;
458 	++idx;
459     }
460     while (n < idx)
461     {
462 	// search backward
463 	item = item->li_prev;
464 	--idx;
465     }
466 
467     // cache the used index
468     l->lv_u.mat.lv_idx = idx;
469     l->lv_u.mat.lv_idx_item = item;
470 
471     return item;
472 }
473 
474 /*
475  * Get list item "l[idx]" as a number.
476  */
477     long
478 list_find_nr(
479     list_T	*l,
480     long	idx,
481     int		*errorp)	// set to TRUE when something wrong
482 {
483     listitem_T	*li;
484 
485     if (l != NULL && l->lv_first == &range_list_item)
486     {
487 	long	    n = idx;
488 
489 	// not materialized range() list: compute the value.
490 	// Negative index is relative to the end.
491 	if (n < 0)
492 	    n = l->lv_len + n;
493 
494 	// Check for index out of range.
495 	if (n < 0 || n >= l->lv_len)
496 	{
497 	    if (errorp != NULL)
498 		*errorp = TRUE;
499 	    return -1L;
500 	}
501 
502 	return l->lv_u.nonmat.lv_start + n * l->lv_u.nonmat.lv_stride;
503     }
504 
505     li = list_find(l, idx);
506     if (li == NULL)
507     {
508 	if (errorp != NULL)
509 	    *errorp = TRUE;
510 	return -1L;
511     }
512     return (long)tv_get_number_chk(&li->li_tv, errorp);
513 }
514 
515 /*
516  * Get list item "l[idx - 1]" as a string.  Returns NULL for failure.
517  */
518     char_u *
519 list_find_str(list_T *l, long idx)
520 {
521     listitem_T	*li;
522 
523     li = list_find(l, idx - 1);
524     if (li == NULL)
525     {
526 	semsg(_(e_listidx), idx);
527 	return NULL;
528     }
529     return tv_get_string(&li->li_tv);
530 }
531 
532 /*
533  * Locate "item" list "l" and return its index.
534  * Returns -1 when "item" is not in the list.
535  */
536     long
537 list_idx_of_item(list_T *l, listitem_T *item)
538 {
539     long	idx = 0;
540     listitem_T	*li;
541 
542     if (l == NULL)
543 	return -1;
544     CHECK_LIST_MATERIALIZE(l);
545     idx = 0;
546     for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
547 	++idx;
548     if (li == NULL)
549 	return -1;
550     return idx;
551 }
552 
553 /*
554  * Append item "item" to the end of list "l".
555  */
556     void
557 list_append(list_T *l, listitem_T *item)
558 {
559     CHECK_LIST_MATERIALIZE(l);
560     if (l->lv_u.mat.lv_last == NULL)
561     {
562 	// empty list
563 	l->lv_first = item;
564 	l->lv_u.mat.lv_last = item;
565 	item->li_prev = NULL;
566     }
567     else
568     {
569 	l->lv_u.mat.lv_last->li_next = item;
570 	item->li_prev = l->lv_u.mat.lv_last;
571 	l->lv_u.mat.lv_last = item;
572     }
573     ++l->lv_len;
574     item->li_next = NULL;
575 }
576 
577 /*
578  * Append typval_T "tv" to the end of list "l".  "tv" is copied.
579  * Return FAIL when out of memory.
580  */
581     int
582 list_append_tv(list_T *l, typval_T *tv)
583 {
584     listitem_T	*li = listitem_alloc();
585 
586     if (li == NULL)
587 	return FAIL;
588     copy_tv(tv, &li->li_tv);
589     list_append(l, li);
590     return OK;
591 }
592 
593 /*
594  * As list_append_tv() but move the value instead of copying it.
595  * Return FAIL when out of memory.
596  */
597     int
598 list_append_tv_move(list_T *l, typval_T *tv)
599 {
600     listitem_T	*li = listitem_alloc();
601 
602     if (li == NULL)
603 	return FAIL;
604     li->li_tv = *tv;
605     list_append(l, li);
606     return OK;
607 }
608 
609 /*
610  * Add a dictionary to a list.  Used by getqflist().
611  * Return FAIL when out of memory.
612  */
613     int
614 list_append_dict(list_T *list, dict_T *dict)
615 {
616     listitem_T	*li = listitem_alloc();
617 
618     if (li == NULL)
619 	return FAIL;
620     li->li_tv.v_type = VAR_DICT;
621     li->li_tv.v_lock = 0;
622     li->li_tv.vval.v_dict = dict;
623     list_append(list, li);
624     ++dict->dv_refcount;
625     return OK;
626 }
627 
628 /*
629  * Append list2 to list1.
630  * Return FAIL when out of memory.
631  */
632     int
633 list_append_list(list_T *list1, list_T *list2)
634 {
635     listitem_T	*li = listitem_alloc();
636 
637     if (li == NULL)
638 	return FAIL;
639     li->li_tv.v_type = VAR_LIST;
640     li->li_tv.v_lock = 0;
641     li->li_tv.vval.v_list = list2;
642     list_append(list1, li);
643     ++list2->lv_refcount;
644     return OK;
645 }
646 
647 /*
648  * Make a copy of "str" and append it as an item to list "l".
649  * When "len" >= 0 use "str[len]".
650  * Returns FAIL when out of memory.
651  */
652     int
653 list_append_string(list_T *l, char_u *str, int len)
654 {
655     listitem_T *li = listitem_alloc();
656 
657     if (li == NULL)
658 	return FAIL;
659     list_append(l, li);
660     li->li_tv.v_type = VAR_STRING;
661     li->li_tv.v_lock = 0;
662     if (str == NULL)
663 	li->li_tv.vval.v_string = NULL;
664     else if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len)
665 						 : vim_strsave(str))) == NULL)
666 	return FAIL;
667     return OK;
668 }
669 
670 /*
671  * Append "n" to list "l".
672  * Returns FAIL when out of memory.
673  */
674     int
675 list_append_number(list_T *l, varnumber_T n)
676 {
677     listitem_T	*li;
678 
679     li = listitem_alloc();
680     if (li == NULL)
681 	return FAIL;
682     li->li_tv.v_type = VAR_NUMBER;
683     li->li_tv.v_lock = 0;
684     li->li_tv.vval.v_number = n;
685     list_append(l, li);
686     return OK;
687 }
688 
689 /*
690  * Insert typval_T "tv" in list "l" before "item".
691  * If "item" is NULL append at the end.
692  * Return FAIL when out of memory.
693  */
694     int
695 list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
696 {
697     listitem_T	*ni = listitem_alloc();
698 
699     if (ni == NULL)
700 	return FAIL;
701     copy_tv(tv, &ni->li_tv);
702     list_insert(l, ni, item);
703     return OK;
704 }
705 
706     void
707 list_insert(list_T *l, listitem_T *ni, listitem_T *item)
708 {
709     CHECK_LIST_MATERIALIZE(l);
710     if (item == NULL)
711 	// Append new item at end of list.
712 	list_append(l, ni);
713     else
714     {
715 	// Insert new item before existing item.
716 	ni->li_prev = item->li_prev;
717 	ni->li_next = item;
718 	if (item->li_prev == NULL)
719 	{
720 	    l->lv_first = ni;
721 	    ++l->lv_u.mat.lv_idx;
722 	}
723 	else
724 	{
725 	    item->li_prev->li_next = ni;
726 	    l->lv_u.mat.lv_idx_item = NULL;
727 	}
728 	item->li_prev = ni;
729 	++l->lv_len;
730     }
731 }
732 
733 /*
734  * Flatten "list" to depth "maxdepth".
735  * It does nothing if "maxdepth" is 0.
736  * Returns FAIL when out of memory.
737  */
738     static int
739 list_flatten(list_T *list, long maxdepth)
740 {
741     listitem_T	*item;
742     listitem_T	*tofree;
743     int		n;
744 
745     if (maxdepth == 0)
746 	return OK;
747     CHECK_LIST_MATERIALIZE(list);
748 
749     n = 0;
750     item = list->lv_first;
751     while (item != NULL)
752     {
753 	fast_breakcheck();
754 	if (got_int)
755 	    return FAIL;
756 
757 	if (item->li_tv.v_type == VAR_LIST)
758 	{
759 	    listitem_T *next = item->li_next;
760 
761 	    vimlist_remove(list, item, item);
762 	    if (list_extend(list, item->li_tv.vval.v_list, next) == FAIL)
763 		return FAIL;
764 	    clear_tv(&item->li_tv);
765 	    tofree = item;
766 
767 	    if (item->li_prev == NULL)
768 		item = list->lv_first;
769 	    else
770 		item = item->li_prev->li_next;
771 	    list_free_item(list, tofree);
772 
773 	    if (++n >= maxdepth)
774 	    {
775 		n = 0;
776 		item = next;
777 	    }
778 	}
779 	else
780 	{
781 	    n = 0;
782 	    item = item->li_next;
783 	}
784     }
785 
786     return OK;
787 }
788 
789 /*
790  * "flatten(list[, {maxdepth}])" function
791  */
792     void
793 f_flatten(typval_T *argvars, typval_T *rettv)
794 {
795     list_T  *l;
796     long    maxdepth;
797     int	    error = FALSE;
798 
799     if (argvars[0].v_type != VAR_LIST)
800     {
801 	semsg(_(e_listarg), "flatten()");
802 	return;
803     }
804 
805     if (argvars[1].v_type == VAR_UNKNOWN)
806 	maxdepth = 999999;
807     else
808     {
809 	maxdepth = (long)tv_get_number_chk(&argvars[1], &error);
810 	if (error)
811 	    return;
812 	if (maxdepth < 0)
813 	{
814 	    emsg(_("E900: maxdepth must be non-negative number"));
815 	    return;
816 	}
817     }
818 
819     l = argvars[0].vval.v_list;
820     if (l != NULL && !var_check_lock(l->lv_lock,
821 				      (char_u *)N_("flatten() argument"), TRUE)
822 		 && list_flatten(l, maxdepth) == OK)
823 	copy_tv(&argvars[0], rettv);
824 }
825 
826 /*
827  * Extend "l1" with "l2".
828  * If "bef" is NULL append at the end, otherwise insert before this item.
829  * Returns FAIL when out of memory.
830  */
831     int
832 list_extend(list_T *l1, list_T *l2, listitem_T *bef)
833 {
834     listitem_T	*item;
835     int		todo = l2->lv_len;
836 
837     CHECK_LIST_MATERIALIZE(l1);
838     CHECK_LIST_MATERIALIZE(l2);
839 
840     // We also quit the loop when we have inserted the original item count of
841     // the list, avoid a hang when we extend a list with itself.
842     for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next)
843 	if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
844 	    return FAIL;
845     return OK;
846 }
847 
848 /*
849  * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
850  * Return FAIL when out of memory.
851  */
852     int
853 list_concat(list_T *l1, list_T *l2, typval_T *tv)
854 {
855     list_T	*l;
856 
857     if (l1 == NULL || l2 == NULL)
858 	return FAIL;
859 
860     // make a copy of the first list.
861     l = list_copy(l1, FALSE, 0);
862     if (l == NULL)
863 	return FAIL;
864     tv->v_type = VAR_LIST;
865     tv->vval.v_list = l;
866 
867     // append all items from the second list
868     return list_extend(l, l2, NULL);
869 }
870 
871     list_T *
872 list_slice(list_T *ol, long n1, long n2)
873 {
874     listitem_T	*item;
875     list_T	*l = list_alloc();
876 
877     if (l == NULL)
878 	return NULL;
879     for (item = list_find(ol, n1); n1 <= n2; ++n1)
880     {
881 	if (list_append_tv(l, &item->li_tv) == FAIL)
882 	{
883 	    list_free(l);
884 	    return NULL;
885 	}
886 	item = item->li_next;
887     }
888     return l;
889 }
890 
891 /*
892  * Make a copy of list "orig".  Shallow if "deep" is FALSE.
893  * The refcount of the new list is set to 1.
894  * See item_copy() for "copyID".
895  * Returns NULL when out of memory.
896  */
897     list_T *
898 list_copy(list_T *orig, int deep, int copyID)
899 {
900     list_T	*copy;
901     listitem_T	*item;
902     listitem_T	*ni;
903 
904     if (orig == NULL)
905 	return NULL;
906 
907     copy = list_alloc();
908     if (copy != NULL)
909     {
910 	if (copyID != 0)
911 	{
912 	    // Do this before adding the items, because one of the items may
913 	    // refer back to this list.
914 	    orig->lv_copyID = copyID;
915 	    orig->lv_copylist = copy;
916 	}
917 	CHECK_LIST_MATERIALIZE(orig);
918 	for (item = orig->lv_first; item != NULL && !got_int;
919 							 item = item->li_next)
920 	{
921 	    ni = listitem_alloc();
922 	    if (ni == NULL)
923 		break;
924 	    if (deep)
925 	    {
926 		if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
927 		{
928 		    vim_free(ni);
929 		    break;
930 		}
931 	    }
932 	    else
933 		copy_tv(&item->li_tv, &ni->li_tv);
934 	    list_append(copy, ni);
935 	}
936 	++copy->lv_refcount;
937 	if (item != NULL)
938 	{
939 	    list_unref(copy);
940 	    copy = NULL;
941 	}
942     }
943 
944     return copy;
945 }
946 
947 /*
948  * Remove items "item" to "item2" from list "l".
949  * Does not free the listitem or the value!
950  * This used to be called list_remove, but that conflicts with a Sun header
951  * file.
952  */
953     void
954 vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2)
955 {
956     listitem_T	*ip;
957 
958     CHECK_LIST_MATERIALIZE(l);
959 
960     // notify watchers
961     for (ip = item; ip != NULL; ip = ip->li_next)
962     {
963 	--l->lv_len;
964 	list_fix_watch(l, ip);
965 	if (ip == item2)
966 	    break;
967     }
968 
969     if (item2->li_next == NULL)
970 	l->lv_u.mat.lv_last = item->li_prev;
971     else
972 	item2->li_next->li_prev = item->li_prev;
973     if (item->li_prev == NULL)
974 	l->lv_first = item2->li_next;
975     else
976 	item->li_prev->li_next = item2->li_next;
977     l->lv_u.mat.lv_idx_item = NULL;
978 }
979 
980 /*
981  * Return an allocated string with the string representation of a list.
982  * May return NULL.
983  */
984     char_u *
985 list2string(typval_T *tv, int copyID, int restore_copyID)
986 {
987     garray_T	ga;
988 
989     if (tv->vval.v_list == NULL)
990 	return NULL;
991     ga_init2(&ga, (int)sizeof(char), 80);
992     ga_append(&ga, '[');
993     CHECK_LIST_MATERIALIZE(tv->vval.v_list);
994     if (list_join(&ga, tv->vval.v_list, (char_u *)", ",
995 				       FALSE, restore_copyID, copyID) == FAIL)
996     {
997 	vim_free(ga.ga_data);
998 	return NULL;
999     }
1000     ga_append(&ga, ']');
1001     ga_append(&ga, NUL);
1002     return (char_u *)ga.ga_data;
1003 }
1004 
1005 typedef struct join_S {
1006     char_u	*s;
1007     char_u	*tofree;
1008 } join_T;
1009 
1010     static int
1011 list_join_inner(
1012     garray_T	*gap,		// to store the result in
1013     list_T	*l,
1014     char_u	*sep,
1015     int		echo_style,
1016     int		restore_copyID,
1017     int		copyID,
1018     garray_T	*join_gap)	// to keep each list item string
1019 {
1020     int		i;
1021     join_T	*p;
1022     int		len;
1023     int		sumlen = 0;
1024     int		first = TRUE;
1025     char_u	*tofree;
1026     char_u	numbuf[NUMBUFLEN];
1027     listitem_T	*item;
1028     char_u	*s;
1029 
1030     // Stringify each item in the list.
1031     CHECK_LIST_MATERIALIZE(l);
1032     for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
1033     {
1034 	s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID,
1035 				      echo_style, restore_copyID, !echo_style);
1036 	if (s == NULL)
1037 	    return FAIL;
1038 
1039 	len = (int)STRLEN(s);
1040 	sumlen += len;
1041 
1042 	(void)ga_grow(join_gap, 1);
1043 	p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++);
1044 	if (tofree != NULL || s != numbuf)
1045 	{
1046 	    p->s = s;
1047 	    p->tofree = tofree;
1048 	}
1049 	else
1050 	{
1051 	    p->s = vim_strnsave(s, len);
1052 	    p->tofree = p->s;
1053 	}
1054 
1055 	line_breakcheck();
1056 	if (did_echo_string_emsg)  // recursion error, bail out
1057 	    break;
1058     }
1059 
1060     // Allocate result buffer with its total size, avoid re-allocation and
1061     // multiple copy operations.  Add 2 for a tailing ']' and NUL.
1062     if (join_gap->ga_len >= 2)
1063 	sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1);
1064     if (ga_grow(gap, sumlen + 2) == FAIL)
1065 	return FAIL;
1066 
1067     for (i = 0; i < join_gap->ga_len && !got_int; ++i)
1068     {
1069 	if (first)
1070 	    first = FALSE;
1071 	else
1072 	    ga_concat(gap, sep);
1073 	p = ((join_T *)join_gap->ga_data) + i;
1074 
1075 	if (p->s != NULL)
1076 	    ga_concat(gap, p->s);
1077 	line_breakcheck();
1078     }
1079 
1080     return OK;
1081 }
1082 
1083 /*
1084  * Join list "l" into a string in "*gap", using separator "sep".
1085  * When "echo_style" is TRUE use String as echoed, otherwise as inside a List.
1086  * Return FAIL or OK.
1087  */
1088     int
1089 list_join(
1090     garray_T	*gap,
1091     list_T	*l,
1092     char_u	*sep,
1093     int		echo_style,
1094     int		restore_copyID,
1095     int		copyID)
1096 {
1097     garray_T	join_ga;
1098     int		retval;
1099     join_T	*p;
1100     int		i;
1101 
1102     if (l->lv_len < 1)
1103 	return OK; // nothing to do
1104     ga_init2(&join_ga, (int)sizeof(join_T), l->lv_len);
1105     retval = list_join_inner(gap, l, sep, echo_style, restore_copyID,
1106 							    copyID, &join_ga);
1107 
1108     // Dispose each item in join_ga.
1109     if (join_ga.ga_data != NULL)
1110     {
1111 	p = (join_T *)join_ga.ga_data;
1112 	for (i = 0; i < join_ga.ga_len; ++i)
1113 	{
1114 	    vim_free(p->tofree);
1115 	    ++p;
1116 	}
1117 	ga_clear(&join_ga);
1118     }
1119 
1120     return retval;
1121 }
1122 
1123 /*
1124  * "join()" function
1125  */
1126     void
1127 f_join(typval_T *argvars, typval_T *rettv)
1128 {
1129     garray_T	ga;
1130     char_u	*sep;
1131 
1132     if (argvars[0].v_type != VAR_LIST)
1133     {
1134 	emsg(_(e_listreq));
1135 	return;
1136     }
1137     if (argvars[0].vval.v_list == NULL)
1138 	return;
1139     if (argvars[1].v_type == VAR_UNKNOWN)
1140 	sep = (char_u *)" ";
1141     else
1142 	sep = tv_get_string_chk(&argvars[1]);
1143 
1144     rettv->v_type = VAR_STRING;
1145 
1146     if (sep != NULL)
1147     {
1148 	ga_init2(&ga, (int)sizeof(char), 80);
1149 	list_join(&ga, argvars[0].vval.v_list, sep, TRUE, FALSE, 0);
1150 	ga_append(&ga, NUL);
1151 	rettv->vval.v_string = (char_u *)ga.ga_data;
1152     }
1153     else
1154 	rettv->vval.v_string = NULL;
1155 }
1156 
1157 /*
1158  * Allocate a variable for a List and fill it from "*arg".
1159  * "*arg" points to the "[".
1160  * Return OK or FAIL.
1161  */
1162     int
1163 eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error)
1164 {
1165     int		evaluate = evalarg == NULL ? FALSE
1166 					 : evalarg->eval_flags & EVAL_EVALUATE;
1167     list_T	*l = NULL;
1168     typval_T	tv;
1169     listitem_T	*item;
1170     int		vim9script = in_vim9script();
1171     int		had_comma;
1172 
1173     if (evaluate)
1174     {
1175 	l = list_alloc();
1176 	if (l == NULL)
1177 	    return FAIL;
1178     }
1179 
1180     *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
1181     while (**arg != ']' && **arg != NUL)
1182     {
1183 	if (eval1(arg, &tv, evalarg) == FAIL)	// recursive!
1184 	    goto failret;
1185 	if (evaluate)
1186 	{
1187 	    item = listitem_alloc();
1188 	    if (item != NULL)
1189 	    {
1190 		item->li_tv = tv;
1191 		item->li_tv.v_lock = 0;
1192 		list_append(l, item);
1193 	    }
1194 	    else
1195 		clear_tv(&tv);
1196 	}
1197 
1198 	// the comma must come after the value
1199 	had_comma = **arg == ',';
1200 	if (had_comma)
1201 	{
1202 	    if (vim9script && (*arg)[1] != NUL && !VIM_ISWHITE((*arg)[1]))
1203 	    {
1204 		semsg(_(e_white_after), ",");
1205 		goto failret;
1206 	    }
1207 	    *arg = skipwhite(*arg + 1);
1208 	}
1209 
1210 	// The "]" can be on the next line.  But a double quoted string may
1211 	// follow, not a comment.
1212 	*arg = skipwhite_and_linebreak(*arg, evalarg);
1213 	if (**arg == ']')
1214 	    break;
1215 
1216 	if (!had_comma)
1217 	{
1218 	    if (do_error)
1219 		semsg(_("E696: Missing comma in List: %s"), *arg);
1220 	    goto failret;
1221 	}
1222     }
1223 
1224     if (**arg != ']')
1225     {
1226 	if (do_error)
1227 	    semsg(_(e_list_end), *arg);
1228 failret:
1229 	if (evaluate)
1230 	    list_free(l);
1231 	return FAIL;
1232     }
1233 
1234     *arg = skipwhite(*arg + 1);
1235     if (evaluate)
1236 	rettv_list_set(rettv, l);
1237 
1238     return OK;
1239 }
1240 
1241 /*
1242  * Write "list" of strings to file "fd".
1243  */
1244     int
1245 write_list(FILE *fd, list_T *list, int binary)
1246 {
1247     listitem_T	*li;
1248     int		c;
1249     int		ret = OK;
1250     char_u	*s;
1251 
1252     CHECK_LIST_MATERIALIZE(list);
1253     FOR_ALL_LIST_ITEMS(list, li)
1254     {
1255 	for (s = tv_get_string(&li->li_tv); *s != NUL; ++s)
1256 	{
1257 	    if (*s == '\n')
1258 		c = putc(NUL, fd);
1259 	    else
1260 		c = putc(*s, fd);
1261 	    if (c == EOF)
1262 	    {
1263 		ret = FAIL;
1264 		break;
1265 	    }
1266 	}
1267 	if (!binary || li->li_next != NULL)
1268 	    if (putc('\n', fd) == EOF)
1269 	    {
1270 		ret = FAIL;
1271 		break;
1272 	    }
1273 	if (ret == FAIL)
1274 	{
1275 	    emsg(_(e_write));
1276 	    break;
1277 	}
1278     }
1279     return ret;
1280 }
1281 
1282 /*
1283  * Initialize a static list with 10 items.
1284  */
1285     void
1286 init_static_list(staticList10_T *sl)
1287 {
1288     list_T  *l = &sl->sl_list;
1289     int	    i;
1290 
1291     memset(sl, 0, sizeof(staticList10_T));
1292     l->lv_first = &sl->sl_items[0];
1293     l->lv_u.mat.lv_last = &sl->sl_items[9];
1294     l->lv_refcount = DO_NOT_FREE_CNT;
1295     l->lv_lock = VAR_FIXED;
1296     sl->sl_list.lv_len = 10;
1297 
1298     for (i = 0; i < 10; ++i)
1299     {
1300 	listitem_T *li = &sl->sl_items[i];
1301 
1302 	if (i == 0)
1303 	    li->li_prev = NULL;
1304 	else
1305 	    li->li_prev = li - 1;
1306 	if (i == 9)
1307 	    li->li_next = NULL;
1308 	else
1309 	    li->li_next = li + 1;
1310     }
1311 }
1312 
1313 /*
1314  * "list2str()" function
1315  */
1316     void
1317 f_list2str(typval_T *argvars, typval_T *rettv)
1318 {
1319     list_T	*l;
1320     listitem_T	*li;
1321     garray_T	ga;
1322     int		utf8 = FALSE;
1323 
1324     rettv->v_type = VAR_STRING;
1325     rettv->vval.v_string = NULL;
1326     if (argvars[0].v_type != VAR_LIST)
1327     {
1328 	emsg(_(e_invarg));
1329 	return;
1330     }
1331 
1332     l = argvars[0].vval.v_list;
1333     if (l == NULL)
1334 	return;  // empty list results in empty string
1335 
1336     if (argvars[1].v_type != VAR_UNKNOWN)
1337 	utf8 = (int)tv_get_number_chk(&argvars[1], NULL);
1338 
1339     CHECK_LIST_MATERIALIZE(l);
1340     ga_init2(&ga, 1, 80);
1341     if (has_mbyte || utf8)
1342     {
1343 	char_u	buf[MB_MAXBYTES + 1];
1344 	int	(*char2bytes)(int, char_u *);
1345 
1346 	if (utf8 || enc_utf8)
1347 	    char2bytes = utf_char2bytes;
1348 	else
1349 	    char2bytes = mb_char2bytes;
1350 
1351 	FOR_ALL_LIST_ITEMS(l, li)
1352 	{
1353 	    buf[(*char2bytes)(tv_get_number(&li->li_tv), buf)] = NUL;
1354 	    ga_concat(&ga, buf);
1355 	}
1356 	ga_append(&ga, NUL);
1357     }
1358     else if (ga_grow(&ga, list_len(l) + 1) == OK)
1359     {
1360 	FOR_ALL_LIST_ITEMS(l, li)
1361 	    ga_append(&ga, tv_get_number(&li->li_tv));
1362 	ga_append(&ga, NUL);
1363     }
1364 
1365     rettv->v_type = VAR_STRING;
1366     rettv->vval.v_string = ga.ga_data;
1367 }
1368 
1369     static void
1370 list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg)
1371 {
1372     list_T	*l;
1373     listitem_T	*item, *item2;
1374     listitem_T	*li;
1375     int		error = FALSE;
1376     int		idx;
1377 
1378     if ((l = argvars[0].vval.v_list) == NULL
1379 			      || var_check_lock(l->lv_lock, arg_errmsg, TRUE))
1380 	return;
1381 
1382     idx = (long)tv_get_number_chk(&argvars[1], &error);
1383     if (error)
1384 	;		// type error: do nothing, errmsg already given
1385     else if ((item = list_find(l, idx)) == NULL)
1386 	semsg(_(e_listidx), idx);
1387     else
1388     {
1389 	if (argvars[2].v_type == VAR_UNKNOWN)
1390 	{
1391 	    // Remove one item, return its value.
1392 	    vimlist_remove(l, item, item);
1393 	    *rettv = item->li_tv;
1394 	    list_free_item(l, item);
1395 	}
1396 	else
1397 	{
1398 	    // Remove range of items, return list with values.
1399 	    int end = (long)tv_get_number_chk(&argvars[2], &error);
1400 
1401 	    if (error)
1402 		;		// type error: do nothing
1403 	    else if ((item2 = list_find(l, end)) == NULL)
1404 		semsg(_(e_listidx), end);
1405 	    else
1406 	    {
1407 		int	    cnt = 0;
1408 
1409 		for (li = item; li != NULL; li = li->li_next)
1410 		{
1411 		    ++cnt;
1412 		    if (li == item2)
1413 			break;
1414 		}
1415 		if (li == NULL)  // didn't find "item2" after "item"
1416 		    emsg(_(e_invrange));
1417 		else
1418 		{
1419 		    vimlist_remove(l, item, item2);
1420 		    if (rettv_list_alloc(rettv) == OK)
1421 		    {
1422 			l = rettv->vval.v_list;
1423 			l->lv_first = item;
1424 			l->lv_u.mat.lv_last = item2;
1425 			item->li_prev = NULL;
1426 			item2->li_next = NULL;
1427 			l->lv_len = cnt;
1428 		    }
1429 		}
1430 	    }
1431 	}
1432     }
1433 }
1434 
1435 static int item_compare(const void *s1, const void *s2);
1436 static int item_compare2(const void *s1, const void *s2);
1437 
1438 // struct used in the array that's given to qsort()
1439 typedef struct
1440 {
1441     listitem_T	*item;
1442     int		idx;
1443 } sortItem_T;
1444 
1445 // struct storing information about current sort
1446 typedef struct
1447 {
1448     int		item_compare_ic;
1449     int		item_compare_numeric;
1450     int		item_compare_numbers;
1451 #ifdef FEAT_FLOAT
1452     int		item_compare_float;
1453 #endif
1454     char_u	*item_compare_func;
1455     partial_T	*item_compare_partial;
1456     dict_T	*item_compare_selfdict;
1457     int		item_compare_func_err;
1458     int		item_compare_keep_zero;
1459 } sortinfo_T;
1460 static sortinfo_T	*sortinfo = NULL;
1461 #define ITEM_COMPARE_FAIL 999
1462 
1463 /*
1464  * Compare functions for f_sort() and f_uniq() below.
1465  */
1466     static int
1467 item_compare(const void *s1, const void *s2)
1468 {
1469     sortItem_T  *si1, *si2;
1470     typval_T	*tv1, *tv2;
1471     char_u	*p1, *p2;
1472     char_u	*tofree1 = NULL, *tofree2 = NULL;
1473     int		res;
1474     char_u	numbuf1[NUMBUFLEN];
1475     char_u	numbuf2[NUMBUFLEN];
1476 
1477     si1 = (sortItem_T *)s1;
1478     si2 = (sortItem_T *)s2;
1479     tv1 = &si1->item->li_tv;
1480     tv2 = &si2->item->li_tv;
1481 
1482     if (sortinfo->item_compare_numbers)
1483     {
1484 	varnumber_T	v1 = tv_get_number(tv1);
1485 	varnumber_T	v2 = tv_get_number(tv2);
1486 
1487 	return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
1488     }
1489 
1490 #ifdef FEAT_FLOAT
1491     if (sortinfo->item_compare_float)
1492     {
1493 	float_T	v1 = tv_get_float(tv1);
1494 	float_T	v2 = tv_get_float(tv2);
1495 
1496 	return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
1497     }
1498 #endif
1499 
1500     // tv2string() puts quotes around a string and allocates memory.  Don't do
1501     // that for string variables. Use a single quote when comparing with a
1502     // non-string to do what the docs promise.
1503     if (tv1->v_type == VAR_STRING)
1504     {
1505 	if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric)
1506 	    p1 = (char_u *)"'";
1507 	else
1508 	    p1 = tv1->vval.v_string;
1509     }
1510     else
1511 	p1 = tv2string(tv1, &tofree1, numbuf1, 0);
1512     if (tv2->v_type == VAR_STRING)
1513     {
1514 	if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric)
1515 	    p2 = (char_u *)"'";
1516 	else
1517 	    p2 = tv2->vval.v_string;
1518     }
1519     else
1520 	p2 = tv2string(tv2, &tofree2, numbuf2, 0);
1521     if (p1 == NULL)
1522 	p1 = (char_u *)"";
1523     if (p2 == NULL)
1524 	p2 = (char_u *)"";
1525     if (!sortinfo->item_compare_numeric)
1526     {
1527 	if (sortinfo->item_compare_ic)
1528 	    res = STRICMP(p1, p2);
1529 	else
1530 	    res = STRCMP(p1, p2);
1531     }
1532     else
1533     {
1534 	double n1, n2;
1535 	n1 = strtod((char *)p1, (char **)&p1);
1536 	n2 = strtod((char *)p2, (char **)&p2);
1537 	res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1;
1538     }
1539 
1540     // When the result would be zero, compare the item indexes.  Makes the
1541     // sort stable.
1542     if (res == 0 && !sortinfo->item_compare_keep_zero)
1543 	res = si1->idx > si2->idx ? 1 : -1;
1544 
1545     vim_free(tofree1);
1546     vim_free(tofree2);
1547     return res;
1548 }
1549 
1550     static int
1551 item_compare2(const void *s1, const void *s2)
1552 {
1553     sortItem_T  *si1, *si2;
1554     int		res;
1555     typval_T	rettv;
1556     typval_T	argv[3];
1557     char_u	*func_name;
1558     partial_T	*partial = sortinfo->item_compare_partial;
1559     funcexe_T	funcexe;
1560 
1561     // shortcut after failure in previous call; compare all items equal
1562     if (sortinfo->item_compare_func_err)
1563 	return 0;
1564 
1565     si1 = (sortItem_T *)s1;
1566     si2 = (sortItem_T *)s2;
1567 
1568     if (partial == NULL)
1569 	func_name = sortinfo->item_compare_func;
1570     else
1571 	func_name = partial_name(partial);
1572 
1573     // Copy the values.  This is needed to be able to set v_lock to VAR_FIXED
1574     // in the copy without changing the original list items.
1575     copy_tv(&si1->item->li_tv, &argv[0]);
1576     copy_tv(&si2->item->li_tv, &argv[1]);
1577 
1578     rettv.v_type = VAR_UNKNOWN;		// clear_tv() uses this
1579     CLEAR_FIELD(funcexe);
1580     funcexe.evaluate = TRUE;
1581     funcexe.partial = partial;
1582     funcexe.selfdict = sortinfo->item_compare_selfdict;
1583     res = call_func(func_name, -1, &rettv, 2, argv, &funcexe);
1584     clear_tv(&argv[0]);
1585     clear_tv(&argv[1]);
1586 
1587     if (res == FAIL)
1588 	res = ITEM_COMPARE_FAIL;
1589     else
1590 	res = (int)tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err);
1591     if (sortinfo->item_compare_func_err)
1592 	res = ITEM_COMPARE_FAIL;  // return value has wrong type
1593     clear_tv(&rettv);
1594 
1595     // When the result would be zero, compare the pointers themselves.  Makes
1596     // the sort stable.
1597     if (res == 0 && !sortinfo->item_compare_keep_zero)
1598 	res = si1->idx > si2->idx ? 1 : -1;
1599 
1600     return res;
1601 }
1602 
1603 /*
1604  * "sort()" or "uniq()" function
1605  */
1606     static void
1607 do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1608 {
1609     list_T	*l;
1610     listitem_T	*li;
1611     sortItem_T	*ptrs;
1612     sortinfo_T	*old_sortinfo;
1613     sortinfo_T	info;
1614     long	len;
1615     long	i;
1616 
1617     // Pointer to current info struct used in compare function. Save and
1618     // restore the current one for nested calls.
1619     old_sortinfo = sortinfo;
1620     sortinfo = &info;
1621 
1622     if (argvars[0].v_type != VAR_LIST)
1623 	semsg(_(e_listarg), sort ? "sort()" : "uniq()");
1624     else
1625     {
1626 	l = argvars[0].vval.v_list;
1627 	if (l == NULL || var_check_lock(l->lv_lock,
1628 	     (char_u *)(sort ? N_("sort() argument") : N_("uniq() argument")),
1629 									TRUE))
1630 	    goto theend;
1631 	rettv_list_set(rettv, l);
1632 	CHECK_LIST_MATERIALIZE(l);
1633 
1634 	len = list_len(l);
1635 	if (len <= 1)
1636 	    goto theend;	// short list sorts pretty quickly
1637 
1638 	info.item_compare_ic = FALSE;
1639 	info.item_compare_numeric = FALSE;
1640 	info.item_compare_numbers = FALSE;
1641 #ifdef FEAT_FLOAT
1642 	info.item_compare_float = FALSE;
1643 #endif
1644 	info.item_compare_func = NULL;
1645 	info.item_compare_partial = NULL;
1646 	info.item_compare_selfdict = NULL;
1647 	if (argvars[1].v_type != VAR_UNKNOWN)
1648 	{
1649 	    // optional second argument: {func}
1650 	    if (argvars[1].v_type == VAR_FUNC)
1651 		info.item_compare_func = argvars[1].vval.v_string;
1652 	    else if (argvars[1].v_type == VAR_PARTIAL)
1653 		info.item_compare_partial = argvars[1].vval.v_partial;
1654 	    else
1655 	    {
1656 		int	    error = FALSE;
1657 
1658 		i = (long)tv_get_number_chk(&argvars[1], &error);
1659 		if (error)
1660 		    goto theend;	// type error; errmsg already given
1661 		if (i == 1)
1662 		    info.item_compare_ic = TRUE;
1663 		else if (argvars[1].v_type != VAR_NUMBER)
1664 		    info.item_compare_func = tv_get_string(&argvars[1]);
1665 		else if (i != 0)
1666 		{
1667 		    emsg(_(e_invarg));
1668 		    goto theend;
1669 		}
1670 		if (info.item_compare_func != NULL)
1671 		{
1672 		    if (*info.item_compare_func == NUL)
1673 		    {
1674 			// empty string means default sort
1675 			info.item_compare_func = NULL;
1676 		    }
1677 		    else if (STRCMP(info.item_compare_func, "n") == 0)
1678 		    {
1679 			info.item_compare_func = NULL;
1680 			info.item_compare_numeric = TRUE;
1681 		    }
1682 		    else if (STRCMP(info.item_compare_func, "N") == 0)
1683 		    {
1684 			info.item_compare_func = NULL;
1685 			info.item_compare_numbers = TRUE;
1686 		    }
1687 #ifdef FEAT_FLOAT
1688 		    else if (STRCMP(info.item_compare_func, "f") == 0)
1689 		    {
1690 			info.item_compare_func = NULL;
1691 			info.item_compare_float = TRUE;
1692 		    }
1693 #endif
1694 		    else if (STRCMP(info.item_compare_func, "i") == 0)
1695 		    {
1696 			info.item_compare_func = NULL;
1697 			info.item_compare_ic = TRUE;
1698 		    }
1699 		}
1700 	    }
1701 
1702 	    if (argvars[2].v_type != VAR_UNKNOWN)
1703 	    {
1704 		// optional third argument: {dict}
1705 		if (argvars[2].v_type != VAR_DICT)
1706 		{
1707 		    emsg(_(e_dictreq));
1708 		    goto theend;
1709 		}
1710 		info.item_compare_selfdict = argvars[2].vval.v_dict;
1711 	    }
1712 	}
1713 
1714 	// Make an array with each entry pointing to an item in the List.
1715 	ptrs = ALLOC_MULT(sortItem_T, len);
1716 	if (ptrs == NULL)
1717 	    goto theend;
1718 
1719 	i = 0;
1720 	if (sort)
1721 	{
1722 	    // sort(): ptrs will be the list to sort
1723 	    FOR_ALL_LIST_ITEMS(l, li)
1724 	    {
1725 		ptrs[i].item = li;
1726 		ptrs[i].idx = i;
1727 		++i;
1728 	    }
1729 
1730 	    info.item_compare_func_err = FALSE;
1731 	    info.item_compare_keep_zero = FALSE;
1732 	    // test the compare function
1733 	    if ((info.item_compare_func != NULL
1734 					 || info.item_compare_partial != NULL)
1735 		    && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
1736 							 == ITEM_COMPARE_FAIL)
1737 		emsg(_("E702: Sort compare function failed"));
1738 	    else
1739 	    {
1740 		// Sort the array with item pointers.
1741 		qsort((void *)ptrs, (size_t)len, sizeof(sortItem_T),
1742 		    info.item_compare_func == NULL
1743 					  && info.item_compare_partial == NULL
1744 					       ? item_compare : item_compare2);
1745 
1746 		if (!info.item_compare_func_err)
1747 		{
1748 		    // Clear the List and append the items in sorted order.
1749 		    l->lv_first = l->lv_u.mat.lv_last
1750 					      = l->lv_u.mat.lv_idx_item = NULL;
1751 		    l->lv_len = 0;
1752 		    for (i = 0; i < len; ++i)
1753 			list_append(l, ptrs[i].item);
1754 		}
1755 	    }
1756 	}
1757 	else
1758 	{
1759 	    int	(*item_compare_func_ptr)(const void *, const void *);
1760 
1761 	    // f_uniq(): ptrs will be a stack of items to remove
1762 	    info.item_compare_func_err = FALSE;
1763 	    info.item_compare_keep_zero = TRUE;
1764 	    item_compare_func_ptr = info.item_compare_func != NULL
1765 					  || info.item_compare_partial != NULL
1766 					       ? item_compare2 : item_compare;
1767 
1768 	    for (li = l->lv_first; li != NULL && li->li_next != NULL;
1769 							     li = li->li_next)
1770 	    {
1771 		if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
1772 									 == 0)
1773 		    ptrs[i++].item = li;
1774 		if (info.item_compare_func_err)
1775 		{
1776 		    emsg(_("E882: Uniq compare function failed"));
1777 		    break;
1778 		}
1779 	    }
1780 
1781 	    if (!info.item_compare_func_err)
1782 	    {
1783 		while (--i >= 0)
1784 		{
1785 		    li = ptrs[i].item->li_next;
1786 		    ptrs[i].item->li_next = li->li_next;
1787 		    if (li->li_next != NULL)
1788 			li->li_next->li_prev = ptrs[i].item;
1789 		    else
1790 			l->lv_u.mat.lv_last = ptrs[i].item;
1791 		    list_fix_watch(l, li);
1792 		    listitem_free(l, li);
1793 		    l->lv_len--;
1794 		}
1795 	    }
1796 	}
1797 
1798 	vim_free(ptrs);
1799     }
1800 theend:
1801     sortinfo = old_sortinfo;
1802 }
1803 
1804 /*
1805  * "sort({list})" function
1806  */
1807     void
1808 f_sort(typval_T *argvars, typval_T *rettv)
1809 {
1810     do_sort_uniq(argvars, rettv, TRUE);
1811 }
1812 
1813 /*
1814  * "uniq({list})" function
1815  */
1816     void
1817 f_uniq(typval_T *argvars, typval_T *rettv)
1818 {
1819     do_sort_uniq(argvars, rettv, FALSE);
1820 }
1821 
1822 /*
1823  * Handle one item for map() and filter().
1824  */
1825     static int
1826 filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
1827 {
1828     typval_T	rettv;
1829     typval_T	argv[3];
1830     int		retval = FAIL;
1831 
1832     copy_tv(tv, get_vim_var_tv(VV_VAL));
1833     argv[0] = *get_vim_var_tv(VV_KEY);
1834     argv[1] = *get_vim_var_tv(VV_VAL);
1835     if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL)
1836 	goto theend;
1837     if (map)
1838     {
1839 	// map(): replace the list item value
1840 	clear_tv(tv);
1841 	rettv.v_lock = 0;
1842 	*tv = rettv;
1843     }
1844     else
1845     {
1846 	int	    error = FALSE;
1847 
1848 	// filter(): when expr is zero remove the item
1849 	*remp = (tv_get_number_chk(&rettv, &error) == 0);
1850 	clear_tv(&rettv);
1851 	// On type error, nothing has been removed; return FAIL to stop the
1852 	// loop.  The error message was given by tv_get_number_chk().
1853 	if (error)
1854 	    goto theend;
1855     }
1856     retval = OK;
1857 theend:
1858     clear_tv(get_vim_var_tv(VV_VAL));
1859     return retval;
1860 }
1861 
1862 /*
1863  * Implementation of map() and filter().
1864  */
1865     static void
1866 filter_map(typval_T *argvars, typval_T *rettv, int map)
1867 {
1868     typval_T	*expr;
1869     listitem_T	*li, *nli;
1870     list_T	*l = NULL;
1871     dictitem_T	*di;
1872     hashtab_T	*ht;
1873     hashitem_T	*hi;
1874     dict_T	*d = NULL;
1875     blob_T	*b = NULL;
1876     int		rem;
1877     int		todo;
1878     char_u	*ermsg = (char_u *)(map ? "map()" : "filter()");
1879     char_u	*arg_errmsg = (char_u *)(map ? N_("map() argument")
1880 				   : N_("filter() argument"));
1881     int		save_did_emsg;
1882     int		idx = 0;
1883 
1884     if (argvars[0].v_type == VAR_BLOB)
1885     {
1886 	if ((b = argvars[0].vval.v_blob) == NULL)
1887 	    return;
1888     }
1889     else if (argvars[0].v_type == VAR_LIST)
1890     {
1891 	if ((l = argvars[0].vval.v_list) == NULL
1892 	      || (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE)))
1893 	    return;
1894     }
1895     else if (argvars[0].v_type == VAR_DICT)
1896     {
1897 	if ((d = argvars[0].vval.v_dict) == NULL
1898 	      || (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE)))
1899 	    return;
1900     }
1901     else
1902     {
1903 	semsg(_(e_listdictblobarg), ermsg);
1904 	return;
1905     }
1906 
1907     expr = &argvars[1];
1908     // On type errors, the preceding call has already displayed an error
1909     // message.  Avoid a misleading error message for an empty string that
1910     // was not passed as argument.
1911     if (expr->v_type != VAR_UNKNOWN)
1912     {
1913 	typval_T	save_val;
1914 	typval_T	save_key;
1915 
1916 	prepare_vimvar(VV_VAL, &save_val);
1917 	prepare_vimvar(VV_KEY, &save_key);
1918 
1919 	// We reset "did_emsg" to be able to detect whether an error
1920 	// occurred during evaluation of the expression.
1921 	save_did_emsg = did_emsg;
1922 	did_emsg = FALSE;
1923 
1924 	if (argvars[0].v_type == VAR_DICT)
1925 	{
1926 	    int	    prev_lock = d->dv_lock;
1927 
1928 	    if (map && d->dv_lock == 0)
1929 		d->dv_lock = VAR_LOCKED;
1930 	    ht = &d->dv_hashtab;
1931 	    hash_lock(ht);
1932 	    todo = (int)ht->ht_used;
1933 	    for (hi = ht->ht_array; todo > 0; ++hi)
1934 	    {
1935 		if (!HASHITEM_EMPTY(hi))
1936 		{
1937 		    int r;
1938 
1939 		    --todo;
1940 		    di = HI2DI(hi);
1941 		    if (map && (var_check_lock(di->di_tv.v_lock,
1942 							   arg_errmsg, TRUE)
1943 				|| var_check_ro(di->di_flags,
1944 							   arg_errmsg, TRUE)))
1945 			break;
1946 		    set_vim_var_string(VV_KEY, di->di_key, -1);
1947 		    r = filter_map_one(&di->di_tv, expr, map, &rem);
1948 		    clear_tv(get_vim_var_tv(VV_KEY));
1949 		    if (r == FAIL || did_emsg)
1950 			break;
1951 		    if (!map && rem)
1952 		    {
1953 			if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
1954 			    || var_check_ro(di->di_flags, arg_errmsg, TRUE))
1955 			    break;
1956 			dictitem_remove(d, di);
1957 		    }
1958 		}
1959 	    }
1960 	    hash_unlock(ht);
1961 	    d->dv_lock = prev_lock;
1962 	}
1963 	else if (argvars[0].v_type == VAR_BLOB)
1964 	{
1965 	    int		i;
1966 	    typval_T	tv;
1967 	    varnumber_T	val;
1968 
1969 	    // set_vim_var_nr() doesn't set the type
1970 	    set_vim_var_type(VV_KEY, VAR_NUMBER);
1971 
1972 	    for (i = 0; i < b->bv_ga.ga_len; i++)
1973 	    {
1974 		tv.v_type = VAR_NUMBER;
1975 		val = blob_get(b, i);
1976 		tv.vval.v_number = val;
1977 		set_vim_var_nr(VV_KEY, idx);
1978 		if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg)
1979 		    break;
1980 		if (tv.v_type != VAR_NUMBER)
1981 		{
1982 		    emsg(_(e_invalblob));
1983 		    break;
1984 		}
1985 		if (map)
1986 		{
1987 		    if (tv.vval.v_number != val)
1988 			blob_set(b, i, tv.vval.v_number);
1989 		}
1990 		else if (rem)
1991 		{
1992 		    char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
1993 
1994 		    mch_memmove(p + i, p + i + 1,
1995 					      (size_t)b->bv_ga.ga_len - i - 1);
1996 		    --b->bv_ga.ga_len;
1997 		    --i;
1998 		}
1999 		++idx;
2000 	    }
2001 	}
2002 	else // argvars[0].v_type == VAR_LIST
2003 	{
2004 	    int prev_lock = l->lv_lock;
2005 
2006 	    // set_vim_var_nr() doesn't set the type
2007 	    set_vim_var_type(VV_KEY, VAR_NUMBER);
2008 
2009 	    CHECK_LIST_MATERIALIZE(l);
2010 	    if (map && l->lv_lock == 0)
2011 		l->lv_lock = VAR_LOCKED;
2012 	    for (li = l->lv_first; li != NULL; li = nli)
2013 	    {
2014 		if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
2015 		    break;
2016 		nli = li->li_next;
2017 		set_vim_var_nr(VV_KEY, idx);
2018 		if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
2019 								  || did_emsg)
2020 		    break;
2021 		if (!map && rem)
2022 		    listitem_remove(l, li);
2023 		++idx;
2024 	    }
2025 	    l->lv_lock = prev_lock;
2026 	}
2027 
2028 	restore_vimvar(VV_KEY, &save_key);
2029 	restore_vimvar(VV_VAL, &save_val);
2030 
2031 	did_emsg |= save_did_emsg;
2032     }
2033 
2034     copy_tv(&argvars[0], rettv);
2035 }
2036 
2037 /*
2038  * "filter()" function
2039  */
2040     void
2041 f_filter(typval_T *argvars, typval_T *rettv)
2042 {
2043     filter_map(argvars, rettv, FALSE);
2044 }
2045 
2046 /*
2047  * "map()" function
2048  */
2049     void
2050 f_map(typval_T *argvars, typval_T *rettv)
2051 {
2052     filter_map(argvars, rettv, TRUE);
2053 }
2054 
2055 /*
2056  * "add(list, item)" function
2057  */
2058     void
2059 f_add(typval_T *argvars, typval_T *rettv)
2060 {
2061     list_T	*l;
2062     blob_T	*b;
2063 
2064     rettv->vval.v_number = 1; // Default: Failed
2065     if (argvars[0].v_type == VAR_LIST)
2066     {
2067 	if ((l = argvars[0].vval.v_list) != NULL
2068 		&& !var_check_lock(l->lv_lock,
2069 					 (char_u *)N_("add() argument"), TRUE)
2070 		&& list_append_tv(l, &argvars[1]) == OK)
2071 	    copy_tv(&argvars[0], rettv);
2072     }
2073     else if (argvars[0].v_type == VAR_BLOB)
2074     {
2075 	if ((b = argvars[0].vval.v_blob) != NULL
2076 		&& !var_check_lock(b->bv_lock,
2077 					 (char_u *)N_("add() argument"), TRUE))
2078 	{
2079 	    int		error = FALSE;
2080 	    varnumber_T n = tv_get_number_chk(&argvars[1], &error);
2081 
2082 	    if (!error)
2083 	    {
2084 		ga_append(&b->bv_ga, (int)n);
2085 		copy_tv(&argvars[0], rettv);
2086 	    }
2087 	}
2088     }
2089     else
2090 	emsg(_(e_listblobreq));
2091 }
2092 
2093 /*
2094  * "count()" function
2095  */
2096     void
2097 f_count(typval_T *argvars, typval_T *rettv)
2098 {
2099     long	n = 0;
2100     int		ic = FALSE;
2101     int		error = FALSE;
2102 
2103     if (argvars[2].v_type != VAR_UNKNOWN)
2104 	ic = (int)tv_get_number_chk(&argvars[2], &error);
2105 
2106     if (argvars[0].v_type == VAR_STRING)
2107     {
2108 	char_u *expr = tv_get_string_chk(&argvars[1]);
2109 	char_u *p = argvars[0].vval.v_string;
2110 	char_u *next;
2111 
2112 	if (!error && expr != NULL && *expr != NUL && p != NULL)
2113 	{
2114 	    if (ic)
2115 	    {
2116 		size_t len = STRLEN(expr);
2117 
2118 		while (*p != NUL)
2119 		{
2120 		    if (MB_STRNICMP(p, expr, len) == 0)
2121 		    {
2122 			++n;
2123 			p += len;
2124 		    }
2125 		    else
2126 			MB_PTR_ADV(p);
2127 		}
2128 	    }
2129 	    else
2130 		while ((next = (char_u *)strstr((char *)p, (char *)expr))
2131 								       != NULL)
2132 		{
2133 		    ++n;
2134 		    p = next + STRLEN(expr);
2135 		}
2136 	}
2137 
2138     }
2139     else if (argvars[0].v_type == VAR_LIST)
2140     {
2141 	listitem_T	*li;
2142 	list_T		*l;
2143 	long		idx;
2144 
2145 	if ((l = argvars[0].vval.v_list) != NULL)
2146 	{
2147 	    CHECK_LIST_MATERIALIZE(l);
2148 	    li = l->lv_first;
2149 	    if (argvars[2].v_type != VAR_UNKNOWN)
2150 	    {
2151 		if (argvars[3].v_type != VAR_UNKNOWN)
2152 		{
2153 		    idx = (long)tv_get_number_chk(&argvars[3], &error);
2154 		    if (!error)
2155 		    {
2156 			li = list_find(l, idx);
2157 			if (li == NULL)
2158 			    semsg(_(e_listidx), idx);
2159 		    }
2160 		}
2161 		if (error)
2162 		    li = NULL;
2163 	    }
2164 
2165 	    for ( ; li != NULL; li = li->li_next)
2166 		if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE))
2167 		    ++n;
2168 	}
2169     }
2170     else if (argvars[0].v_type == VAR_DICT)
2171     {
2172 	int		todo;
2173 	dict_T		*d;
2174 	hashitem_T	*hi;
2175 
2176 	if ((d = argvars[0].vval.v_dict) != NULL)
2177 	{
2178 	    if (argvars[2].v_type != VAR_UNKNOWN)
2179 	    {
2180 		if (argvars[3].v_type != VAR_UNKNOWN)
2181 		    emsg(_(e_invarg));
2182 	    }
2183 
2184 	    todo = error ? 0 : (int)d->dv_hashtab.ht_used;
2185 	    for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
2186 	    {
2187 		if (!HASHITEM_EMPTY(hi))
2188 		{
2189 		    --todo;
2190 		    if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE))
2191 			++n;
2192 		}
2193 	    }
2194 	}
2195     }
2196     else
2197 	semsg(_(e_listdictarg), "count()");
2198     rettv->vval.v_number = n;
2199 }
2200 
2201 /*
2202  * "extend(list, list [, idx])" function
2203  * "extend(dict, dict [, action])" function
2204  */
2205     void
2206 f_extend(typval_T *argvars, typval_T *rettv)
2207 {
2208     char_u      *arg_errmsg = (char_u *)N_("extend() argument");
2209 
2210     if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
2211     {
2212 	list_T		*l1, *l2;
2213 	listitem_T	*item;
2214 	long		before;
2215 	int		error = FALSE;
2216 
2217 	l1 = argvars[0].vval.v_list;
2218 	l2 = argvars[1].vval.v_list;
2219 	if (l1 != NULL && !var_check_lock(l1->lv_lock, arg_errmsg, TRUE)
2220 		&& l2 != NULL)
2221 	{
2222 	    if (argvars[2].v_type != VAR_UNKNOWN)
2223 	    {
2224 		before = (long)tv_get_number_chk(&argvars[2], &error);
2225 		if (error)
2226 		    return;		// type error; errmsg already given
2227 
2228 		if (before == l1->lv_len)
2229 		    item = NULL;
2230 		else
2231 		{
2232 		    item = list_find(l1, before);
2233 		    if (item == NULL)
2234 		    {
2235 			semsg(_(e_listidx), before);
2236 			return;
2237 		    }
2238 		}
2239 	    }
2240 	    else
2241 		item = NULL;
2242 	    list_extend(l1, l2, item);
2243 
2244 	    copy_tv(&argvars[0], rettv);
2245 	}
2246     }
2247     else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
2248     {
2249 	dict_T	*d1, *d2;
2250 	char_u	*action;
2251 	int	i;
2252 
2253 	d1 = argvars[0].vval.v_dict;
2254 	d2 = argvars[1].vval.v_dict;
2255 	if (d1 != NULL && !var_check_lock(d1->dv_lock, arg_errmsg, TRUE)
2256 		&& d2 != NULL)
2257 	{
2258 	    // Check the third argument.
2259 	    if (argvars[2].v_type != VAR_UNKNOWN)
2260 	    {
2261 		static char *(av[]) = {"keep", "force", "error"};
2262 
2263 		action = tv_get_string_chk(&argvars[2]);
2264 		if (action == NULL)
2265 		    return;		// type error; errmsg already given
2266 		for (i = 0; i < 3; ++i)
2267 		    if (STRCMP(action, av[i]) == 0)
2268 			break;
2269 		if (i == 3)
2270 		{
2271 		    semsg(_(e_invarg2), action);
2272 		    return;
2273 		}
2274 	    }
2275 	    else
2276 		action = (char_u *)"force";
2277 
2278 	    dict_extend(d1, d2, action);
2279 
2280 	    copy_tv(&argvars[0], rettv);
2281 	}
2282     }
2283     else
2284 	semsg(_(e_listdictarg), "extend()");
2285 }
2286 
2287 /*
2288  * "insert()" function
2289  */
2290     void
2291 f_insert(typval_T *argvars, typval_T *rettv)
2292 {
2293     long	before = 0;
2294     listitem_T	*item;
2295     list_T	*l;
2296     int		error = FALSE;
2297 
2298     if (argvars[0].v_type == VAR_BLOB)
2299     {
2300 	int	    val, len;
2301 	char_u	    *p;
2302 
2303 	if (argvars[0].vval.v_blob == NULL)
2304 	    return;
2305 
2306 	len = blob_len(argvars[0].vval.v_blob);
2307 	if (argvars[2].v_type != VAR_UNKNOWN)
2308 	{
2309 	    before = (long)tv_get_number_chk(&argvars[2], &error);
2310 	    if (error)
2311 		return;		// type error; errmsg already given
2312 	    if (before < 0 || before > len)
2313 	    {
2314 		semsg(_(e_invarg2), tv_get_string(&argvars[2]));
2315 		return;
2316 	    }
2317 	}
2318 	val = tv_get_number_chk(&argvars[1], &error);
2319 	if (error)
2320 	    return;
2321 	if (val < 0 || val > 255)
2322 	{
2323 	    semsg(_(e_invarg2), tv_get_string(&argvars[1]));
2324 	    return;
2325 	}
2326 
2327 	if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL)
2328 	    return;
2329 	p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
2330 	mch_memmove(p + before + 1, p + before, (size_t)len - before);
2331 	*(p + before) = val;
2332 	++argvars[0].vval.v_blob->bv_ga.ga_len;
2333 
2334 	copy_tv(&argvars[0], rettv);
2335     }
2336     else if (argvars[0].v_type != VAR_LIST)
2337 	semsg(_(e_listblobarg), "insert()");
2338     else if ((l = argvars[0].vval.v_list) != NULL
2339 	    && !var_check_lock(l->lv_lock,
2340 				     (char_u *)N_("insert() argument"), TRUE))
2341     {
2342 	if (argvars[2].v_type != VAR_UNKNOWN)
2343 	    before = (long)tv_get_number_chk(&argvars[2], &error);
2344 	if (error)
2345 	    return;		// type error; errmsg already given
2346 
2347 	if (before == l->lv_len)
2348 	    item = NULL;
2349 	else
2350 	{
2351 	    item = list_find(l, before);
2352 	    if (item == NULL)
2353 	    {
2354 		semsg(_(e_listidx), before);
2355 		l = NULL;
2356 	    }
2357 	}
2358 	if (l != NULL)
2359 	{
2360 	    (void)list_insert_tv(l, &argvars[1], item);
2361 	    copy_tv(&argvars[0], rettv);
2362 	}
2363     }
2364 }
2365 
2366 /*
2367  * "remove()" function
2368  */
2369     void
2370 f_remove(typval_T *argvars, typval_T *rettv)
2371 {
2372     char_u	*arg_errmsg = (char_u *)N_("remove() argument");
2373 
2374     if (argvars[0].v_type == VAR_DICT)
2375 	dict_remove(argvars, rettv, arg_errmsg);
2376     else if (argvars[0].v_type == VAR_BLOB)
2377 	blob_remove(argvars, rettv);
2378     else if (argvars[0].v_type == VAR_LIST)
2379 	list_remove(argvars, rettv, arg_errmsg);
2380     else
2381 	semsg(_(e_listdictblobarg), "remove()");
2382 }
2383 
2384 /*
2385  * "reverse({list})" function
2386  */
2387     void
2388 f_reverse(typval_T *argvars, typval_T *rettv)
2389 {
2390     list_T	*l;
2391     listitem_T	*li, *ni;
2392 
2393     if (argvars[0].v_type == VAR_BLOB)
2394     {
2395 	blob_T	*b = argvars[0].vval.v_blob;
2396 	int	i, len = blob_len(b);
2397 
2398 	for (i = 0; i < len / 2; i++)
2399 	{
2400 	    int tmp = blob_get(b, i);
2401 
2402 	    blob_set(b, i, blob_get(b, len - i - 1));
2403 	    blob_set(b, len - i - 1, tmp);
2404 	}
2405 	rettv_blob_set(rettv, b);
2406 	return;
2407     }
2408 
2409     if (argvars[0].v_type != VAR_LIST)
2410 	semsg(_(e_listblobarg), "reverse()");
2411     else if ((l = argvars[0].vval.v_list) != NULL
2412 	    && !var_check_lock(l->lv_lock,
2413 				    (char_u *)N_("reverse() argument"), TRUE))
2414     {
2415 	if (l->lv_first == &range_list_item)
2416 	{
2417 	    varnumber_T new_start = l->lv_u.nonmat.lv_start
2418 				  + (l->lv_len - 1) * l->lv_u.nonmat.lv_stride;
2419 	    l->lv_u.nonmat.lv_end = new_start
2420 			   - (l->lv_u.nonmat.lv_end - l->lv_u.nonmat.lv_start);
2421 	    l->lv_u.nonmat.lv_start = new_start;
2422 	    l->lv_u.nonmat.lv_stride = -l->lv_u.nonmat.lv_stride;
2423 	    rettv_list_set(rettv, l);
2424 	    return;
2425 	}
2426 	li = l->lv_u.mat.lv_last;
2427 	l->lv_first = l->lv_u.mat.lv_last = NULL;
2428 	l->lv_len = 0;
2429 	while (li != NULL)
2430 	{
2431 	    ni = li->li_prev;
2432 	    list_append(l, li);
2433 	    li = ni;
2434 	}
2435 	rettv_list_set(rettv, l);
2436 	l->lv_u.mat.lv_idx = l->lv_len - l->lv_u.mat.lv_idx - 1;
2437     }
2438 }
2439 
2440 /*
2441  * "reduce(list, { accumlator, element -> value } [, initial])" function
2442  */
2443     void
2444 f_reduce(typval_T *argvars, typval_T *rettv)
2445 {
2446     typval_T	initial;
2447     char_u	*func_name;
2448     partial_T   *partial = NULL;
2449     funcexe_T	funcexe;
2450     typval_T	argv[3];
2451 
2452     if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB)
2453     {
2454 	emsg(_(e_listblobreq));
2455 	return;
2456     }
2457 
2458     if (argvars[1].v_type == VAR_FUNC)
2459 	func_name = argvars[1].vval.v_string;
2460     else if (argvars[1].v_type == VAR_PARTIAL)
2461     {
2462 	partial = argvars[1].vval.v_partial;
2463 	func_name = partial_name(partial);
2464     }
2465     else
2466 	func_name = tv_get_string(&argvars[1]);
2467     if (*func_name == NUL)
2468 	return;		// type error or empty name
2469 
2470     vim_memset(&funcexe, 0, sizeof(funcexe));
2471     funcexe.evaluate = TRUE;
2472     funcexe.partial = partial;
2473 
2474     if (argvars[0].v_type == VAR_LIST)
2475     {
2476 	list_T	    *l = argvars[0].vval.v_list;
2477 	listitem_T  *li = NULL;
2478 	int	    r;
2479 	int	    called_emsg_start = called_emsg;
2480 
2481 	if (l != NULL)
2482 	    CHECK_LIST_MATERIALIZE(l);
2483 	if (argvars[2].v_type == VAR_UNKNOWN)
2484 	{
2485 	    if (l == NULL || l->lv_first == NULL)
2486 	    {
2487 		semsg(_(e_reduceempty), "List");
2488 		return;
2489 	    }
2490 	    initial = l->lv_first->li_tv;
2491 	    li = l->lv_first->li_next;
2492 	}
2493 	else
2494 	{
2495 	    initial = argvars[2];
2496 	    if (l != NULL)
2497 		li = l->lv_first;
2498 	}
2499 	copy_tv(&initial, rettv);
2500 
2501 	if (l != NULL)
2502 	{
2503 	    int	    prev_locked = l->lv_lock;
2504 
2505 	    l->lv_lock = VAR_FIXED;  // disallow the list changing here
2506 	    for ( ; li != NULL; li = li->li_next)
2507 	    {
2508 		argv[0] = *rettv;
2509 		argv[1] = li->li_tv;
2510 		rettv->v_type = VAR_UNKNOWN;
2511 		r = call_func(func_name, -1, rettv, 2, argv, &funcexe);
2512 		clear_tv(&argv[0]);
2513 		if (r == FAIL || called_emsg != called_emsg_start)
2514 		    break;
2515 	    }
2516 	    l->lv_lock = prev_locked;
2517 	}
2518     }
2519     else
2520     {
2521 	blob_T	*b = argvars[0].vval.v_blob;
2522 	int	i;
2523 
2524 	if (argvars[2].v_type == VAR_UNKNOWN)
2525 	{
2526 	    if (b == NULL || b->bv_ga.ga_len == 0)
2527 	    {
2528 		semsg(_(e_reduceempty), "Blob");
2529 		return;
2530 	    }
2531 	    initial.v_type = VAR_NUMBER;
2532 	    initial.vval.v_number = blob_get(b, 0);
2533 	    i = 1;
2534 	}
2535 	else if (argvars[2].v_type != VAR_NUMBER)
2536 	{
2537 	    emsg(_(e_number_exp));
2538 	    return;
2539 	}
2540 	else
2541 	{
2542 	    initial = argvars[2];
2543 	    i = 0;
2544 	}
2545 
2546 	copy_tv(&initial, rettv);
2547 	if (b != NULL)
2548 	{
2549 	    for ( ; i < b->bv_ga.ga_len; i++)
2550 	    {
2551 		argv[0] = *rettv;
2552 		argv[1].v_type = VAR_NUMBER;
2553 		argv[1].vval.v_number = blob_get(b, i);
2554 		if (call_func(func_name, -1, rettv, 2, argv, &funcexe) == FAIL)
2555 		    return;
2556 	    }
2557 	}
2558     }
2559 }
2560 
2561 #endif // defined(FEAT_EVAL)
2562