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