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