comparison src/list.c @ 19181:94eda51ba9ba v8.2.0149

patch 8.2.0149: maintaining a Vim9 branch separately is more work Commit: https://github.com/vim/vim/commit/8a7d6542b33e5d2b352262305c3bfdb2d14e1cf8 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jan 26 15:56:19 2020 +0100 patch 8.2.0149: maintaining a Vim9 branch separately is more work Problem: Maintaining a Vim9 branch separately is more work. Solution: Merge the Vim9 script changes.
author Bram Moolenaar <Bram@vim.org>
date Sun, 26 Jan 2020 16:00:05 +0100
parents 09f28c17ac58
children 09f01421a356
comparison
equal deleted inserted replaced
19180:8edf0aeb71b9 19181:94eda51ba9ba
63 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) 63 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
64 if (lw->lw_item == item) 64 if (lw->lw_item == item)
65 lw->lw_item = item->li_next; 65 lw->lw_item = item->li_next;
66 } 66 }
67 67
68 static void
69 list_init(list_T *l)
70 {
71 // Prepend the list to the list of lists for garbage collection.
72 if (first_list != NULL)
73 first_list->lv_used_prev = l;
74 l->lv_used_prev = NULL;
75 l->lv_used_next = first_list;
76 first_list = l;
77 }
78
68 /* 79 /*
69 * Allocate an empty header for a list. 80 * Allocate an empty header for a list.
70 * Caller should take care of the reference count. 81 * Caller should take care of the reference count.
71 */ 82 */
72 list_T * 83 list_T *
74 { 85 {
75 list_T *l; 86 list_T *l;
76 87
77 l = ALLOC_CLEAR_ONE(list_T); 88 l = ALLOC_CLEAR_ONE(list_T);
78 if (l != NULL) 89 if (l != NULL)
79 { 90 list_init(l);
80 // Prepend the list to the list of lists for garbage collection.
81 if (first_list != NULL)
82 first_list->lv_used_prev = l;
83 l->lv_used_prev = NULL;
84 l->lv_used_next = first_list;
85 first_list = l;
86 }
87 return l; 91 return l;
88 } 92 }
89 93
90 /* 94 /*
91 * list_alloc() with an ID for alloc_fail(). 95 * list_alloc() with an ID for alloc_fail().
99 #endif 103 #endif
100 return (list_alloc()); 104 return (list_alloc());
101 } 105 }
102 106
103 /* 107 /*
108 * Allocate space for a list, plus "count" items.
109 * Next list_set_item() must be called for each item.
110 */
111 list_T *
112 list_alloc_with_items(int count)
113 {
114 list_T *l;
115
116 l = (list_T *)alloc_clear(sizeof(list_T) + count * sizeof(listitem_T));
117 if (l != NULL)
118 {
119 list_init(l);
120
121 if (count > 0)
122 {
123 listitem_T *li = (listitem_T *)(l + 1);
124 int i;
125
126 l->lv_len = count;
127 l->lv_with_items = count;
128 l->lv_first = li;
129 l->lv_last = li + count - 1;
130 for (i = 0; i < count; ++i)
131 {
132 if (i == 0)
133 li->li_prev = NULL;
134 else
135 li->li_prev = li - 1;
136 if (i == count - 1)
137 li->li_next = NULL;
138 else
139 li->li_next = li + 1;
140 ++li;
141 }
142 }
143 }
144 return l;
145 }
146
147 /*
148 * Set item "idx" for a list previously allocated with list_alloc_with_items().
149 * The contents of "tv" is moved into the list item.
150 * Each item must be set exactly once.
151 */
152 void
153 list_set_item(list_T *l, int idx, typval_T *tv)
154 {
155 listitem_T *li = (listitem_T *)(l + 1) + idx;
156
157 li->li_tv = *tv;
158 }
159
160 /*
104 * Allocate an empty list for a return value, with reference count set. 161 * Allocate an empty list for a return value, with reference count set.
105 * Returns OK or FAIL. 162 * Returns OK or FAIL.
106 */ 163 */
107 int 164 int
108 rettv_list_alloc(typval_T *rettv) 165 rettv_list_alloc(typval_T *rettv)
161 static void 218 static void
162 list_free_contents(list_T *l) 219 list_free_contents(list_T *l)
163 { 220 {
164 listitem_T *item; 221 listitem_T *item;
165 222
166 for (item = l->lv_first; item != NULL; item = l->lv_first) 223 if (l->lv_first != &range_list_item)
167 { 224 for (item = l->lv_first; item != NULL; item = l->lv_first)
168 // Remove the item before deleting it. 225 {
169 l->lv_first = item->li_next; 226 // Remove the item before deleting it.
170 clear_tv(&item->li_tv); 227 l->lv_first = item->li_next;
171 vim_free(item); 228 clear_tv(&item->li_tv);
172 } 229 list_free_item(l, item);
230 }
173 } 231 }
174 232
175 /* 233 /*
176 * Go through the list of lists and free items without the copyID. 234 * Go through the list of lists and free items without the copyID.
177 * But don't free a list that has a watcher (used in a for loop), these 235 * But don't free a list that has a watcher (used in a for loop), these
248 { 306 {
249 return ALLOC_ONE(listitem_T); 307 return ALLOC_ONE(listitem_T);
250 } 308 }
251 309
252 /* 310 /*
253 * Free a list item. Also clears the value. Does not notify watchers. 311 * Free a list item, unless it was allocated together with the list itself.
254 */ 312 * Does not clear the value. Does not notify watchers.
255 void 313 */
256 listitem_free(listitem_T *item) 314 void
315 list_free_item(list_T *l, listitem_T *item)
316 {
317 if (l->lv_with_items == 0 || item < (listitem_T *)l
318 || item >= (listitem_T *)(l + 1) + l->lv_with_items)
319 vim_free(item);
320 }
321
322 /*
323 * Free a list item, unless it was allocated together with the list itself.
324 * Also clears the value. Does not notify watchers.
325 */
326 void
327 listitem_free(list_T *l, listitem_T *item)
257 { 328 {
258 clear_tv(&item->li_tv); 329 clear_tv(&item->li_tv);
259 vim_free(item); 330 list_free_item(l, item);
260 } 331 }
261 332
262 /* 333 /*
263 * Remove a list item from a List and free it. Also clears the value. 334 * Remove a list item from a List and free it. Also clears the value.
264 */ 335 */
265 void 336 void
266 listitem_remove(list_T *l, listitem_T *item) 337 listitem_remove(list_T *l, listitem_T *item)
267 { 338 {
268 vimlist_remove(l, item, item); 339 vimlist_remove(l, item, item);
269 listitem_free(item); 340 listitem_free(l, item);
270 } 341 }
271 342
272 /* 343 /*
273 * Get the number of items in a list. 344 * Get the number of items in a list.
274 */ 345 */
297 if (l1 == l2) 368 if (l1 == l2)
298 return TRUE; 369 return TRUE;
299 if (list_len(l1) != list_len(l2)) 370 if (list_len(l1) != list_len(l2))
300 return FALSE; 371 return FALSE;
301 372
373 range_list_materialize(l1);
374 range_list_materialize(l2);
375
302 for (item1 = l1->lv_first, item2 = l2->lv_first; 376 for (item1 = l1->lv_first, item2 = l2->lv_first;
303 item1 != NULL && item2 != NULL; 377 item1 != NULL && item2 != NULL;
304 item1 = item1->li_next, item2 = item2->li_next) 378 item1 = item1->li_next, item2 = item2->li_next)
305 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) 379 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive))
306 return FALSE; 380 return FALSE;
327 401
328 // Check for index out of range. 402 // Check for index out of range.
329 if (n < 0 || n >= l->lv_len) 403 if (n < 0 || n >= l->lv_len)
330 return NULL; 404 return NULL;
331 405
406 range_list_materialize(l);
407
332 // When there is a cached index may start search from there. 408 // When there is a cached index may start search from there.
333 if (l->lv_idx_item != NULL) 409 if (l->lv_idx_item != NULL)
334 { 410 {
335 if (n < l->lv_idx / 2) 411 if (n < l->lv_idx / 2)
336 { 412 {
396 long idx, 472 long idx,
397 int *errorp) // set to TRUE when something wrong 473 int *errorp) // set to TRUE when something wrong
398 { 474 {
399 listitem_T *li; 475 listitem_T *li;
400 476
477 if (l != NULL && l->lv_first == &range_list_item)
478 {
479 long n = idx;
480
481 // not materialized range() list: compute the value.
482 // Negative index is relative to the end.
483 if (n < 0)
484 n = l->lv_len + n;
485
486 // Check for index out of range.
487 if (n < 0 || n >= l->lv_len)
488 {
489 if (errorp != NULL)
490 *errorp = TRUE;
491 return -1L;
492 }
493
494 return l->lv_start + n * l->lv_stride;
495 }
496
401 li = list_find(l, idx); 497 li = list_find(l, idx);
402 if (li == NULL) 498 if (li == NULL)
403 { 499 {
404 if (errorp != NULL) 500 if (errorp != NULL)
405 *errorp = TRUE; 501 *errorp = TRUE;
435 long idx = 0; 531 long idx = 0;
436 listitem_T *li; 532 listitem_T *li;
437 533
438 if (l == NULL) 534 if (l == NULL)
439 return -1; 535 return -1;
536 range_list_materialize(l);
440 idx = 0; 537 idx = 0;
441 for (li = l->lv_first; li != NULL && li != item; li = li->li_next) 538 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
442 ++idx; 539 ++idx;
443 if (li == NULL) 540 if (li == NULL)
444 return -1; 541 return -1;
449 * Append item "item" to the end of list "l". 546 * Append item "item" to the end of list "l".
450 */ 547 */
451 void 548 void
452 list_append(list_T *l, listitem_T *item) 549 list_append(list_T *l, listitem_T *item)
453 { 550 {
551 range_list_materialize(l);
454 if (l->lv_last == NULL) 552 if (l->lv_last == NULL)
455 { 553 {
456 // empty list 554 // empty list
457 l->lv_first = item; 555 l->lv_first = item;
458 l->lv_last = item; 556 l->lv_last = item;
467 ++l->lv_len; 565 ++l->lv_len;
468 item->li_next = NULL; 566 item->li_next = NULL;
469 } 567 }
470 568
471 /* 569 /*
472 * Append typval_T "tv" to the end of list "l". 570 * Append typval_T "tv" to the end of list "l". "tv" is copied.
473 * Return FAIL when out of memory. 571 * Return FAIL when out of memory.
474 */ 572 */
475 int 573 int
476 list_append_tv(list_T *l, typval_T *tv) 574 list_append_tv(list_T *l, typval_T *tv)
477 { 575 {
478 listitem_T *li = listitem_alloc(); 576 listitem_T *li = listitem_alloc();
479 577
480 if (li == NULL) 578 if (li == NULL)
481 return FAIL; 579 return FAIL;
482 copy_tv(tv, &li->li_tv); 580 copy_tv(tv, &li->li_tv);
581 list_append(l, li);
582 return OK;
583 }
584
585 /*
586 * As list_append_tv() but move the value instead of copying it.
587 * Return FAIL when out of memory.
588 */
589 int
590 list_append_tv_move(list_T *l, typval_T *tv)
591 {
592 listitem_T *li = listitem_alloc();
593
594 if (li == NULL)
595 return FAIL;
596 li->li_tv = *tv;
483 list_append(l, li); 597 list_append(l, li);
484 return OK; 598 return OK;
485 } 599 }
486 600
487 /* 601 /*
582 } 696 }
583 697
584 void 698 void
585 list_insert(list_T *l, listitem_T *ni, listitem_T *item) 699 list_insert(list_T *l, listitem_T *ni, listitem_T *item)
586 { 700 {
701 range_list_materialize(l);
587 if (item == NULL) 702 if (item == NULL)
588 // Append new item at end of list. 703 // Append new item at end of list.
589 list_append(l, ni); 704 list_append(l, ni);
590 else 705 else
591 { 706 {
615 int 730 int
616 list_extend(list_T *l1, list_T *l2, listitem_T *bef) 731 list_extend(list_T *l1, list_T *l2, listitem_T *bef)
617 { 732 {
618 listitem_T *item; 733 listitem_T *item;
619 int todo = l2->lv_len; 734 int todo = l2->lv_len;
735
736 range_list_materialize(l1);
737 range_list_materialize(l2);
620 738
621 // We also quit the loop when we have inserted the original item count of 739 // We also quit the loop when we have inserted the original item count of
622 // the list, avoid a hang when we extend a list with itself. 740 // the list, avoid a hang when we extend a list with itself.
623 for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next) 741 for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next)
624 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL) 742 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
673 // Do this before adding the items, because one of the items may 791 // Do this before adding the items, because one of the items may
674 // refer back to this list. 792 // refer back to this list.
675 orig->lv_copyID = copyID; 793 orig->lv_copyID = copyID;
676 orig->lv_copylist = copy; 794 orig->lv_copylist = copy;
677 } 795 }
796 range_list_materialize(orig);
678 for (item = orig->lv_first; item != NULL && !got_int; 797 for (item = orig->lv_first; item != NULL && !got_int;
679 item = item->li_next) 798 item = item->li_next)
680 { 799 {
681 ni = listitem_alloc(); 800 ni = listitem_alloc();
682 if (ni == NULL) 801 if (ni == NULL)
712 */ 831 */
713 void 832 void
714 vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2) 833 vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2)
715 { 834 {
716 listitem_T *ip; 835 listitem_T *ip;
836
837 range_list_materialize(l);
717 838
718 // notify watchers 839 // notify watchers
719 for (ip = item; ip != NULL; ip = ip->li_next) 840 for (ip = item; ip != NULL; ip = ip->li_next)
720 { 841 {
721 --l->lv_len; 842 --l->lv_len;
746 867
747 if (tv->vval.v_list == NULL) 868 if (tv->vval.v_list == NULL)
748 return NULL; 869 return NULL;
749 ga_init2(&ga, (int)sizeof(char), 80); 870 ga_init2(&ga, (int)sizeof(char), 80);
750 ga_append(&ga, '['); 871 ga_append(&ga, '[');
872 range_list_materialize(tv->vval.v_list);
751 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", 873 if (list_join(&ga, tv->vval.v_list, (char_u *)", ",
752 FALSE, restore_copyID, copyID) == FAIL) 874 FALSE, restore_copyID, copyID) == FAIL)
753 { 875 {
754 vim_free(ga.ga_data); 876 vim_free(ga.ga_data);
755 return NULL; 877 return NULL;
783 char_u numbuf[NUMBUFLEN]; 905 char_u numbuf[NUMBUFLEN];
784 listitem_T *item; 906 listitem_T *item;
785 char_u *s; 907 char_u *s;
786 908
787 // Stringify each item in the list. 909 // Stringify each item in the list.
910 range_list_materialize(l);
788 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) 911 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
789 { 912 {
790 s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID, 913 s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID,
791 echo_style, restore_copyID, !echo_style); 914 echo_style, restore_copyID, !echo_style);
792 if (s == NULL) 915 if (s == NULL)
913 /* 1036 /*
914 * Allocate a variable for a List and fill it from "*arg". 1037 * Allocate a variable for a List and fill it from "*arg".
915 * Return OK or FAIL. 1038 * Return OK or FAIL.
916 */ 1039 */
917 int 1040 int
918 get_list_tv(char_u **arg, typval_T *rettv, int evaluate) 1041 get_list_tv(char_u **arg, typval_T *rettv, int evaluate, int do_error)
919 { 1042 {
920 list_T *l = NULL; 1043 list_T *l = NULL;
921 typval_T tv; 1044 typval_T tv;
922 listitem_T *item; 1045 listitem_T *item;
923 1046
948 1071
949 if (**arg == ']') 1072 if (**arg == ']')
950 break; 1073 break;
951 if (**arg != ',') 1074 if (**arg != ',')
952 { 1075 {
953 semsg(_("E696: Missing comma in List: %s"), *arg); 1076 if (do_error)
1077 semsg(_("E696: Missing comma in List: %s"), *arg);
954 goto failret; 1078 goto failret;
955 } 1079 }
956 *arg = skipwhite(*arg + 1); 1080 *arg = skipwhite(*arg + 1);
957 } 1081 }
958 1082
959 if (**arg != ']') 1083 if (**arg != ']')
960 { 1084 {
961 semsg(_("E697: Missing end of List ']': %s"), *arg); 1085 if (do_error)
1086 semsg(_("E697: Missing end of List ']': %s"), *arg);
962 failret: 1087 failret:
963 if (evaluate) 1088 if (evaluate)
964 list_free(l); 1089 list_free(l);
965 return FAIL; 1090 return FAIL;
966 } 1091 }
981 listitem_T *li; 1106 listitem_T *li;
982 int c; 1107 int c;
983 int ret = OK; 1108 int ret = OK;
984 char_u *s; 1109 char_u *s;
985 1110
1111 range_list_materialize(list);
986 for (li = list->lv_first; li != NULL; li = li->li_next) 1112 for (li = list->lv_first; li != NULL; li = li->li_next)
987 { 1113 {
988 for (s = tv_get_string(&li->li_tv); *s != NUL; ++s) 1114 for (s = tv_get_string(&li->li_tv); *s != NUL; ++s)
989 { 1115 {
990 if (*s == '\n') 1116 if (*s == '\n')
1067 return; // empty list results in empty string 1193 return; // empty list results in empty string
1068 1194
1069 if (argvars[1].v_type != VAR_UNKNOWN) 1195 if (argvars[1].v_type != VAR_UNKNOWN)
1070 utf8 = (int)tv_get_number_chk(&argvars[1], NULL); 1196 utf8 = (int)tv_get_number_chk(&argvars[1], NULL);
1071 1197
1198 range_list_materialize(l);
1072 ga_init2(&ga, 1, 80); 1199 ga_init2(&ga, 1, 80);
1073 if (has_mbyte || utf8) 1200 if (has_mbyte || utf8)
1074 { 1201 {
1075 char_u buf[MB_MAXBYTES + 1]; 1202 char_u buf[MB_MAXBYTES + 1];
1076 int (*char2bytes)(int, char_u *); 1203 int (*char2bytes)(int, char_u *);
1121 if (argvars[2].v_type == VAR_UNKNOWN) 1248 if (argvars[2].v_type == VAR_UNKNOWN)
1122 { 1249 {
1123 // Remove one item, return its value. 1250 // Remove one item, return its value.
1124 vimlist_remove(l, item, item); 1251 vimlist_remove(l, item, item);
1125 *rettv = item->li_tv; 1252 *rettv = item->li_tv;
1126 vim_free(item); 1253 list_free_item(l, item);
1127 } 1254 }
1128 else 1255 else
1129 { 1256 {
1130 // Remove range of items, return list with values. 1257 // Remove range of items, return list with values.
1131 int end = (long)tv_get_number_chk(&argvars[2], &error); 1258 int end = (long)tv_get_number_chk(&argvars[2], &error);
1359 if (l == NULL || var_check_lock(l->lv_lock, 1486 if (l == NULL || var_check_lock(l->lv_lock,
1360 (char_u *)(sort ? N_("sort() argument") : N_("uniq() argument")), 1487 (char_u *)(sort ? N_("sort() argument") : N_("uniq() argument")),
1361 TRUE)) 1488 TRUE))
1362 goto theend; 1489 goto theend;
1363 rettv_list_set(rettv, l); 1490 rettv_list_set(rettv, l);
1491 range_list_materialize(l);
1364 1492
1365 len = list_len(l); 1493 len = list_len(l);
1366 if (len <= 1) 1494 if (len <= 1)
1367 goto theend; // short list sorts pretty quickly 1495 goto theend; // short list sorts pretty quickly
1368 1496
1517 if (li->li_next != NULL) 1645 if (li->li_next != NULL)
1518 li->li_next->li_prev = ptrs[i].item; 1646 li->li_next->li_prev = ptrs[i].item;
1519 else 1647 else
1520 l->lv_last = ptrs[i].item; 1648 l->lv_last = ptrs[i].item;
1521 list_fix_watch(l, li); 1649 list_fix_watch(l, li);
1522 listitem_free(li); 1650 listitem_free(l, li);
1523 l->lv_len--; 1651 l->lv_len--;
1524 } 1652 }
1525 } 1653 }
1526 } 1654 }
1527 1655
1727 else // argvars[0].v_type == VAR_LIST 1855 else // argvars[0].v_type == VAR_LIST
1728 { 1856 {
1729 // set_vim_var_nr() doesn't set the type 1857 // set_vim_var_nr() doesn't set the type
1730 set_vim_var_type(VV_KEY, VAR_NUMBER); 1858 set_vim_var_type(VV_KEY, VAR_NUMBER);
1731 1859
1860 range_list_materialize(l);
1732 for (li = l->lv_first; li != NULL; li = nli) 1861 for (li = l->lv_first; li != NULL; li = nli)
1733 { 1862 {
1734 if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE)) 1863 if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
1735 break; 1864 break;
1736 nli = li->li_next; 1865 nli = li->li_next;