neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

typval.c (134556B)


      1 #include <assert.h>
      2 #include <lauxlib.h>
      3 #include <stdbool.h>
      4 #include <stddef.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <uv.h>
      9 
     10 #include "nvim/ascii_defs.h"
     11 #include "nvim/assert_defs.h"
     12 #include "nvim/buffer_defs.h"
     13 #include "nvim/charset.h"
     14 #include "nvim/errors.h"
     15 #include "nvim/eval.h"
     16 #include "nvim/eval/encode.h"
     17 #include "nvim/eval/executor.h"
     18 #include "nvim/eval/gc.h"
     19 #include "nvim/eval/typval.h"
     20 #include "nvim/eval/typval_defs.h"
     21 #include "nvim/eval/typval_encode.h"
     22 #include "nvim/eval/userfunc.h"
     23 #include "nvim/eval/vars.h"
     24 #include "nvim/garray.h"
     25 #include "nvim/garray_defs.h"
     26 #include "nvim/gettext_defs.h"
     27 #include "nvim/globals.h"
     28 #include "nvim/hashtab.h"
     29 #include "nvim/hashtab_defs.h"
     30 #include "nvim/lib/queue_defs.h"
     31 #include "nvim/lua/executor.h"
     32 #include "nvim/macros_defs.h"
     33 #include "nvim/mbyte.h"
     34 #include "nvim/mbyte_defs.h"
     35 #include "nvim/memory.h"
     36 #include "nvim/memory_defs.h"
     37 #include "nvim/message.h"
     38 #include "nvim/os/input.h"
     39 #include "nvim/pos_defs.h"
     40 #include "nvim/strings.h"
     41 #include "nvim/types_defs.h"
     42 #include "nvim/vim_defs.h"
     43 
     44 /// struct storing information about current sort
     45 typedef struct {
     46  int item_compare_ic;
     47  bool item_compare_lc;
     48  bool item_compare_numeric;
     49  bool item_compare_numbers;
     50  bool item_compare_float;
     51  const char *item_compare_func;
     52  partial_T *item_compare_partial;
     53  dict_T *item_compare_selfdict;
     54  bool item_compare_func_err;
     55 } sortinfo_T;
     56 
     57 /// Structure representing one list item, used for sort array.
     58 typedef struct {
     59  listitem_T *item;  ///< Sorted list item.
     60  int idx;  ///< Sorted list item index.
     61 } ListSortItem;
     62 
     63 typedef int (*ListSorter)(const void *, const void *);
     64 
     65 /// Type for tv_dict2list() function
     66 typedef enum {
     67  kDict2ListKeys,    ///< List dictionary keys.
     68  kDict2ListValues,  ///< List dictionary values.
     69  kDict2ListItems,   ///< List dictionary contents: [keys, values].
     70 } DictListType;
     71 
     72 #include "eval/typval.c.generated.h"
     73 
     74 static const char e_variable_nested_too_deep_for_unlock[]
     75  = N_("E743: Variable nested too deep for (un)lock");
     76 static const char e_using_invalid_value_as_string[]
     77  = N_("E908: Using an invalid value as a String");
     78 static const char e_string_required_for_argument_nr[]
     79  = N_("E1174: String required for argument %d");
     80 static const char e_non_empty_string_required_for_argument_nr[]
     81  = N_("E1175: Non-empty string required for argument %d");
     82 static const char e_dict_required_for_argument_nr[]
     83  = N_("E1206: Dictionary required for argument %d");
     84 static const char e_number_required_for_argument_nr[]
     85  = N_("E1210: Number required for argument %d");
     86 static const char e_list_required_for_argument_nr[]
     87  = N_("E1211: List required for argument %d");
     88 static const char e_bool_required_for_argument_nr[]
     89  = N_("E1212: Bool required for argument %d");
     90 static const char e_float_or_number_required_for_argument_nr[]
     91  = N_("E1219: Float or Number required for argument %d");
     92 static const char e_string_or_number_required_for_argument_nr[]
     93  = N_("E1220: String or Number required for argument %d");
     94 static const char e_string_or_list_required_for_argument_nr[]
     95  = N_("E1222: String or List required for argument %d");
     96 static const char e_list_dict_blob_or_string_required_for_argument_nr[]
     97  = N_("E1225: List, Dictionary, Blob or String required for argument %d");
     98 static const char e_list_or_blob_required_for_argument_nr[]
     99  = N_("E1226: List or Blob required for argument %d");
    100 static const char e_blob_required_for_argument_nr[]
    101  = N_("E1238: Blob required for argument %d");
    102 static const char e_string_list_or_blob_required_for_argument_nr[]
    103  = N_("E1252: String, List or Blob required for argument %d");
    104 static const char e_string_or_function_required_for_argument_nr[]
    105  = N_("E1256: String or function required for argument %d");
    106 static const char e_non_null_dict_required_for_argument_nr[]
    107  = N_("E1297: Non-NULL Dictionary required for argument %d");
    108 
    109 bool tv_in_free_unref_items = false;
    110 
    111 // TODO(ZyX-I): Remove DICT_MAXNEST, make users be non-recursive instead
    112 
    113 #define DICT_MAXNEST 100
    114 
    115 const char *const tv_empty_string = "";
    116 
    117 // Lists:
    118 // List item:
    119 
    120 /// Allocate a list item
    121 ///
    122 /// @warning Allocated item is not initialized, do not forget to initialize it
    123 ///          and specifically set lv_lock.
    124 ///
    125 /// @return [allocated] new list item.
    126 static listitem_T *tv_list_item_alloc(void)
    127  FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC
    128 {
    129  return xmalloc(sizeof(listitem_T));
    130 }
    131 
    132 /// Remove a list item from a List and free it
    133 ///
    134 /// Also clears the value.
    135 ///
    136 /// @param[out]  l  List to remove item from.
    137 /// @param[in,out]  item  Item to remove.
    138 ///
    139 /// @return Pointer to the list item just after removed one, NULL if removed
    140 ///         item was the last one.
    141 listitem_T *tv_list_item_remove(list_T *const l, listitem_T *const item)
    142  FUNC_ATTR_NONNULL_ALL
    143 {
    144  listitem_T *const next_item = TV_LIST_ITEM_NEXT(l, item);
    145  tv_list_drop_items(l, item, item);
    146  tv_clear(TV_LIST_ITEM_TV(item));
    147  xfree(item);
    148  return next_item;
    149 }
    150 
    151 // List watchers:
    152 
    153 /// Add a watcher to a list
    154 ///
    155 /// @param[out]  l  List to add watcher to.
    156 /// @param[in]  lw  Watcher to add.
    157 void tv_list_watch_add(list_T *const l, listwatch_T *const lw)
    158  FUNC_ATTR_NONNULL_ALL
    159 {
    160  lw->lw_next = l->lv_watch;
    161  l->lv_watch = lw;
    162 }
    163 
    164 /// Remove a watcher from a list
    165 ///
    166 /// Does not give a warning if watcher was not found.
    167 ///
    168 /// @param[out]  l  List to remove watcher from.
    169 /// @param[in]  lwrem  Watcher to remove.
    170 void tv_list_watch_remove(list_T *const l, listwatch_T *const lwrem)
    171  FUNC_ATTR_NONNULL_ALL
    172 {
    173  listwatch_T **lwp = &l->lv_watch;
    174  for (listwatch_T *lw = l->lv_watch; lw != NULL; lw = lw->lw_next) {
    175    if (lw == lwrem) {
    176      *lwp = lw->lw_next;
    177      break;
    178    }
    179    lwp = &lw->lw_next;
    180  }
    181 }
    182 
    183 /// Advance watchers to the next item
    184 ///
    185 /// Used just before removing an item from a list.
    186 ///
    187 /// @param[out]  l  List from which item is removed.
    188 /// @param[in]  item  List item being removed.
    189 static void tv_list_watch_fix(list_T *const l, const listitem_T *const item)
    190  FUNC_ATTR_NONNULL_ALL
    191 {
    192  for (listwatch_T *lw = l->lv_watch; lw != NULL; lw = lw->lw_next) {
    193    if (lw->lw_item == item) {
    194      lw->lw_item = item->li_next;
    195    }
    196  }
    197 }
    198 
    199 // Alloc/free:
    200 
    201 /// Allocate an empty list
    202 ///
    203 /// Caller should take care of the reference count.
    204 ///
    205 /// @param[in]  len  Expected number of items to be populated before list
    206 ///                  becomes accessible from Vimscript. It is still valid to
    207 ///                  underpopulate a list, value only controls how many elements
    208 ///                  will be allocated in advance. Currently does nothing.
    209 ///                  @see ListLenSpecials.
    210 ///
    211 /// @return [allocated] new list.
    212 list_T *tv_list_alloc(const ptrdiff_t len)
    213  FUNC_ATTR_NONNULL_RET
    214 {
    215  list_T *const list = xcalloc(1, sizeof(list_T));
    216 
    217  // Prepend the list to the list of lists for garbage collection.
    218  if (gc_first_list != NULL) {
    219    gc_first_list->lv_used_prev = list;
    220  }
    221  list->lv_used_prev = NULL;
    222  list->lv_used_next = gc_first_list;
    223  gc_first_list = list;
    224  list->lua_table_ref = LUA_NOREF;
    225  return list;
    226 }
    227 
    228 /// Initialize a static list with 10 items
    229 ///
    230 /// @param[out]  sl  Static list to initialize.
    231 void tv_list_init_static10(staticList10_T *const sl)
    232  FUNC_ATTR_NONNULL_ALL
    233 {
    234 #define SL_SIZE ARRAY_SIZE(sl->sl_items)
    235  list_T *const l = &sl->sl_list;
    236 
    237  CLEAR_POINTER(sl);
    238  l->lv_first = &sl->sl_items[0];
    239  l->lv_last = &sl->sl_items[SL_SIZE - 1];
    240  l->lv_refcount = DO_NOT_FREE_CNT;
    241  tv_list_set_lock(l, VAR_FIXED);
    242  sl->sl_list.lv_len = 10;
    243 
    244  sl->sl_items[0].li_prev = NULL;
    245  sl->sl_items[0].li_next = &sl->sl_items[1];
    246  sl->sl_items[SL_SIZE - 1].li_prev = &sl->sl_items[SL_SIZE - 2];
    247  sl->sl_items[SL_SIZE - 1].li_next = NULL;
    248 
    249  for (size_t i = 1; i < SL_SIZE - 1; i++) {
    250    listitem_T *const li = &sl->sl_items[i];
    251    li->li_prev = li - 1;
    252    li->li_next = li + 1;
    253  }
    254 #undef SL_SIZE
    255 }
    256 
    257 /// Initialize static list with undefined number of elements
    258 ///
    259 /// @param[out]  l  List to initialize.
    260 void tv_list_init_static(list_T *const l)
    261  FUNC_ATTR_NONNULL_ALL
    262 {
    263  CLEAR_POINTER(l);
    264  l->lv_refcount = DO_NOT_FREE_CNT;
    265 }
    266 
    267 /// Free items contained in a list
    268 ///
    269 /// @param[in,out]  l  List to clear.
    270 void tv_list_free_contents(list_T *const l)
    271  FUNC_ATTR_NONNULL_ALL
    272 {
    273  for (listitem_T *item = l->lv_first; item != NULL; item = l->lv_first) {
    274    // Remove the item before deleting it.
    275    l->lv_first = item->li_next;
    276    tv_clear(&item->li_tv);
    277    xfree(item);
    278  }
    279  l->lv_len = 0;
    280  l->lv_idx_item = NULL;
    281  l->lv_last = NULL;
    282  assert(l->lv_watch == NULL);
    283 }
    284 
    285 /// Free a list itself, ignoring items it contains
    286 ///
    287 /// Ignores the reference count.
    288 ///
    289 /// @param[in,out]  l  List to free.
    290 void tv_list_free_list(list_T *const l)
    291  FUNC_ATTR_NONNULL_ALL
    292 {
    293  // Remove the list from the list of lists for garbage collection.
    294  if (l->lv_used_prev == NULL) {
    295    gc_first_list = l->lv_used_next;
    296  } else {
    297    l->lv_used_prev->lv_used_next = l->lv_used_next;
    298  }
    299  if (l->lv_used_next != NULL) {
    300    l->lv_used_next->lv_used_prev = l->lv_used_prev;
    301  }
    302 
    303  NLUA_CLEAR_REF(l->lua_table_ref);
    304  xfree(l);
    305 }
    306 
    307 /// Free a list, including all items it points to
    308 ///
    309 /// Ignores the reference count. Does not do anything if
    310 /// tv_in_free_unref_items is true.
    311 ///
    312 /// @param[in,out]  l  List to free.
    313 void tv_list_free(list_T *const l)
    314  FUNC_ATTR_NONNULL_ALL
    315 {
    316  if (tv_in_free_unref_items) {
    317    return;
    318  }
    319 
    320  tv_list_free_contents(l);
    321  tv_list_free_list(l);
    322 }
    323 
    324 /// Unreference a list
    325 ///
    326 /// Decrements the reference count and frees when it becomes zero or less.
    327 ///
    328 /// @param[in,out]  l  List to unreference.
    329 void tv_list_unref(list_T *const l)
    330 {
    331  if (l != NULL && --l->lv_refcount <= 0) {
    332    tv_list_free(l);
    333  }
    334 }
    335 
    336 // Add/remove:
    337 
    338 /// Remove items "item" to "item2" from list "l"
    339 ///
    340 /// @warning Does not free the listitem or the value!
    341 ///
    342 /// @param[out]  l  List to remove from.
    343 /// @param[in]  item  First item to remove.
    344 /// @param[in]  item2  Last item to remove.
    345 void tv_list_drop_items(list_T *const l, listitem_T *const item, listitem_T *const item2)
    346  FUNC_ATTR_NONNULL_ALL
    347 {
    348  // Notify watchers.
    349  for (listitem_T *ip = item; ip != item2->li_next; ip = ip->li_next) {
    350    l->lv_len--;
    351    tv_list_watch_fix(l, ip);
    352  }
    353 
    354  if (item2->li_next == NULL) {
    355    l->lv_last = item->li_prev;
    356  } else {
    357    item2->li_next->li_prev = item->li_prev;
    358  }
    359  if (item->li_prev == NULL) {
    360    l->lv_first = item2->li_next;
    361  } else {
    362    item->li_prev->li_next = item2->li_next;
    363  }
    364  l->lv_idx_item = NULL;
    365 }
    366 
    367 /// Like tv_list_drop_items, but also frees all removed items
    368 void tv_list_remove_items(list_T *const l, listitem_T *const item, listitem_T *const item2)
    369  FUNC_ATTR_NONNULL_ALL
    370 {
    371  tv_list_drop_items(l, item, item2);
    372  for (listitem_T *li = item;;) {
    373    tv_clear(TV_LIST_ITEM_TV(li));
    374    listitem_T *const nli = li->li_next;
    375    xfree(li);
    376    if (li == item2) {
    377      break;
    378    }
    379    li = nli;
    380  }
    381 }
    382 
    383 /// Move items "item" to "item2" from list "l" to the end of the list "tgt_l"
    384 ///
    385 /// @param[out]  l  List to move from.
    386 /// @param[in]  item  First item to move.
    387 /// @param[in]  item2  Last item to move.
    388 /// @param[out]  tgt_l  List to move to.
    389 /// @param[in]  cnt  Number of items moved.
    390 void tv_list_move_items(list_T *const l, listitem_T *const item, listitem_T *const item2,
    391                        list_T *const tgt_l, const int cnt)
    392  FUNC_ATTR_NONNULL_ALL
    393 {
    394  tv_list_drop_items(l, item, item2);
    395  item->li_prev = tgt_l->lv_last;
    396  item2->li_next = NULL;
    397  if (tgt_l->lv_last == NULL) {
    398    tgt_l->lv_first = item;
    399  } else {
    400    tgt_l->lv_last->li_next = item;
    401  }
    402  tgt_l->lv_last = item2;
    403  tgt_l->lv_len += cnt;
    404 }
    405 
    406 /// Insert list item
    407 ///
    408 /// @param[out]  l  List to insert to.
    409 /// @param[in,out]  ni  Item to insert.
    410 /// @param[in]  item  Item to insert before. If NULL, inserts at the end of the
    411 ///                   list.
    412 void tv_list_insert(list_T *const l, listitem_T *const ni, listitem_T *const item)
    413  FUNC_ATTR_NONNULL_ARG(1, 2)
    414 {
    415  if (item == NULL) {
    416    // Append new item at end of list.
    417    tv_list_append(l, ni);
    418  } else {
    419    // Insert new item before existing item.
    420    ni->li_prev = item->li_prev;
    421    ni->li_next = item;
    422    if (item->li_prev == NULL) {
    423      l->lv_first = ni;
    424      l->lv_idx++;
    425    } else {
    426      item->li_prev->li_next = ni;
    427      l->lv_idx_item = NULL;
    428    }
    429    item->li_prev = ni;
    430    l->lv_len++;
    431  }
    432 }
    433 
    434 /// Insert Vimscript value into a list
    435 ///
    436 /// @param[out]  l  List to insert to.
    437 /// @param[in,out]  tv  Value to insert. Is copied (@see tv_copy()) to an
    438 ///                     allocated listitem_T and inserted.
    439 /// @param[in]  item  Item to insert before. If NULL, inserts at the end of the
    440 ///                   list.
    441 void tv_list_insert_tv(list_T *const l, typval_T *const tv, listitem_T *const item)
    442 {
    443  listitem_T *const ni = tv_list_item_alloc();
    444 
    445  tv_copy(tv, &ni->li_tv);
    446  tv_list_insert(l, ni, item);
    447 }
    448 
    449 /// Append item to the end of list
    450 ///
    451 /// @param[out]  l  List to append to.
    452 /// @param[in,out]  item  Item to append.
    453 void tv_list_append(list_T *const l, listitem_T *const item)
    454  FUNC_ATTR_NONNULL_ALL
    455 {
    456  if (l->lv_last == NULL) {
    457    // empty list
    458    l->lv_first = item;
    459    l->lv_last = item;
    460    item->li_prev = NULL;
    461  } else {
    462    l->lv_last->li_next = item;
    463    item->li_prev = l->lv_last;
    464    l->lv_last = item;
    465  }
    466  l->lv_len++;
    467  item->li_next = NULL;
    468 }
    469 
    470 /// Append Vimscript value to the end of list
    471 ///
    472 /// @param[out]  l  List to append to.
    473 /// @param[in,out]  tv  Value to append. Is copied (@see tv_copy()) to an
    474 ///                     allocated listitem_T.
    475 void tv_list_append_tv(list_T *const l, typval_T *const tv)
    476  FUNC_ATTR_NONNULL_ALL
    477 {
    478  listitem_T *const li = tv_list_item_alloc();
    479  tv_copy(tv, TV_LIST_ITEM_TV(li));
    480  tv_list_append(l, li);
    481 }
    482 
    483 /// Like tv_list_append_tv(), but tv is moved to a list
    484 ///
    485 /// This means that it is no longer valid to use contents of the typval_T after
    486 /// function exits. A pointer is returned to the allocated typval which can be used
    487 typval_T *tv_list_append_owned_tv(list_T *const l, typval_T tv)
    488  FUNC_ATTR_NONNULL_ALL
    489 {
    490  listitem_T *const li = tv_list_item_alloc();
    491  *TV_LIST_ITEM_TV(li) = tv;
    492  tv_list_append(l, li);
    493  return TV_LIST_ITEM_TV(li);
    494 }
    495 
    496 /// Append a list to a list as one item
    497 ///
    498 /// @param[out]  l  List to append to.
    499 /// @param[in,out]  itemlist  List to append. Reference count is increased.
    500 void tv_list_append_list(list_T *const l, list_T *const itemlist)
    501  FUNC_ATTR_NONNULL_ARG(1)
    502 {
    503  tv_list_append_owned_tv(l, (typval_T) {
    504    .v_type = VAR_LIST,
    505    .v_lock = VAR_UNLOCKED,
    506    .vval.v_list = itemlist,
    507  });
    508  tv_list_ref(itemlist);
    509 }
    510 
    511 /// Append a dictionary to a list
    512 ///
    513 /// @param[out]  l  List to append to.
    514 /// @param[in,out]  dict  Dictionary to append. Reference count is increased.
    515 void tv_list_append_dict(list_T *const l, dict_T *const dict)
    516  FUNC_ATTR_NONNULL_ARG(1)
    517 {
    518  tv_list_append_owned_tv(l, (typval_T) {
    519    .v_type = VAR_DICT,
    520    .v_lock = VAR_UNLOCKED,
    521    .vval.v_dict = dict,
    522  });
    523  if (dict != NULL) {
    524    dict->dv_refcount++;
    525  }
    526 }
    527 
    528 /// Make a copy of "str" and append it as an item to list "l"
    529 ///
    530 /// @param[out]  l  List to append to.
    531 /// @param[in]  str  String to append.
    532 /// @param[in]  len  Length of the appended string. May be -1, in this
    533 ///                  case string is considered to be usual zero-terminated
    534 ///                  string or NULL “empty” string.
    535 void tv_list_append_string(list_T *const l, const char *const str, const ssize_t len)
    536  FUNC_ATTR_NONNULL_ARG(1)
    537 {
    538  tv_list_append_owned_tv(l, (typval_T) {
    539    .v_type = VAR_STRING,
    540    .v_lock = VAR_UNLOCKED,
    541    .vval.v_string = (str == NULL
    542                      ? NULL
    543                      : (len >= 0
    544                         ? xmemdupz(str, (size_t)len)
    545                         : xstrdup(str))),
    546  });
    547 }
    548 
    549 /// Append given string to the list
    550 ///
    551 /// Unlike list_append_string this function does not copy the string.
    552 ///
    553 /// @param[out]  l    List to append to.
    554 /// @param[in]   str  String to append.
    555 void tv_list_append_allocated_string(list_T *const l, char *const str)
    556  FUNC_ATTR_NONNULL_ARG(1)
    557 {
    558  tv_list_append_owned_tv(l, (typval_T) {
    559    .v_type = VAR_STRING,
    560    .v_lock = VAR_UNLOCKED,
    561    .vval.v_string = str,
    562  });
    563 }
    564 
    565 /// Append number to the list
    566 ///
    567 /// @param[out]  l  List to append to.
    568 /// @param[in]  n  Number to append. Will be recorded in the allocated
    569 ///                listitem_T.
    570 void tv_list_append_number(list_T *const l, const varnumber_T n)
    571 {
    572  tv_list_append_owned_tv(l, (typval_T) {
    573    .v_type = VAR_NUMBER,
    574    .v_lock = VAR_UNLOCKED,
    575    .vval.v_number = n,
    576  });
    577 }
    578 
    579 // Operations on the whole list:
    580 
    581 /// Make a copy of list
    582 ///
    583 /// @param[in]  conv  If non-NULL, then all internal strings will be converted.
    584 ///                   Only used when `deep` is true.
    585 /// @param[in]  orig  Original list to copy.
    586 /// @param[in]  deep  If false, then shallow copy will be done.
    587 /// @param[in]  copyID  See var_item_copy().
    588 ///
    589 /// @return Copied list. May be NULL in case original list is NULL or some
    590 ///         failure happens. The refcount of the new list is set to 1.
    591 list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig, const bool deep,
    592                     const int copyID)
    593  FUNC_ATTR_WARN_UNUSED_RESULT
    594 {
    595  if (orig == NULL) {
    596    return NULL;
    597  }
    598 
    599  list_T *copy = tv_list_alloc(tv_list_len(orig));
    600  tv_list_ref(copy);
    601  if (copyID != 0) {
    602    // Do this before adding the items, because one of the items may
    603    // refer back to this list.
    604    orig->lv_copyID = copyID;
    605    orig->lv_copylist = copy;
    606  }
    607  TV_LIST_ITER(orig, item, {
    608    if (got_int) {
    609      break;
    610    }
    611    listitem_T *const ni = tv_list_item_alloc();
    612    if (deep) {
    613      if (var_item_copy(conv, TV_LIST_ITEM_TV(item), TV_LIST_ITEM_TV(ni),
    614                        deep, copyID) == FAIL) {
    615        xfree(ni);
    616        goto tv_list_copy_error;
    617      }
    618    } else {
    619      tv_copy(TV_LIST_ITEM_TV(item), TV_LIST_ITEM_TV(ni));
    620    }
    621    tv_list_append(copy, ni);
    622  });
    623 
    624  return copy;
    625 
    626 tv_list_copy_error:
    627  tv_list_unref(copy);
    628  return NULL;
    629 }
    630 
    631 /// Get the list item in "l" with index "n1".  "n1" is adjusted if needed.
    632 /// Return NULL if there is no such item.
    633 listitem_T *tv_list_check_range_index_one(list_T *const l, int *const n1, const bool quiet)
    634 {
    635  listitem_T *li = tv_list_find_index(l, n1);
    636  if (li != NULL) {
    637    return li;
    638  }
    639 
    640  if (!quiet) {
    641    semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n1));
    642  }
    643  return NULL;
    644 }
    645 
    646 /// Check that "n2" can be used as the second index in a range of list "l".
    647 /// If "n1" or "n2" is negative it is changed to the positive index.
    648 /// "li1" is the item for item "n1".
    649 /// Return OK or FAIL.
    650 int tv_list_check_range_index_two(list_T *const l, int *const n1, const listitem_T *const li1,
    651                                  int *const n2, const bool quiet)
    652 {
    653  if (*n2 < 0) {
    654    listitem_T *ni = tv_list_find(l, *n2);
    655    if (ni == NULL) {
    656      if (!quiet) {
    657        semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n2));
    658      }
    659      return FAIL;
    660    }
    661    *n2 = tv_list_idx_of_item(l, ni);
    662  }
    663 
    664  // Check that n2 isn't before n1.
    665  if (*n1 < 0) {
    666    *n1 = tv_list_idx_of_item(l, li1);
    667  }
    668  if (*n2 < *n1) {
    669    if (!quiet) {
    670      semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n2));
    671    }
    672    return FAIL;
    673  }
    674  return OK;
    675 }
    676 
    677 /// Assign values from list "src" into a range of "dest".
    678 /// "idx1_arg" is the index of the first item in "dest" to be replaced.
    679 /// "idx2" is the index of last item to be replaced, but when "empty_idx2" is
    680 /// true then replace all items after "idx1".
    681 /// "op" is the operator, normally "=" but can be "+=" and the like.
    682 /// "varname" is used for error messages.
    683 /// Returns OK or FAIL.
    684 int tv_list_assign_range(list_T *const dest, list_T *const src, const int idx1_arg, const int idx2,
    685                         const bool empty_idx2, const char *const op, const char *const varname)
    686 {
    687  int idx1 = idx1_arg;
    688  listitem_T *const first_li = tv_list_find_index(dest, &idx1);
    689  listitem_T *src_li;
    690 
    691  // Check whether any of the list items is locked before making any changes.
    692  int idx = idx1;
    693  listitem_T *dest_li = first_li;
    694  for (src_li = tv_list_first(src); src_li != NULL && dest_li != NULL;) {
    695    if (value_check_lock(TV_LIST_ITEM_TV(dest_li)->v_lock, varname, TV_CSTRING)) {
    696      return FAIL;
    697    }
    698    src_li = TV_LIST_ITEM_NEXT(src, src_li);
    699    if (src_li == NULL || (!empty_idx2 && idx2 == idx)) {
    700      break;
    701    }
    702    dest_li = TV_LIST_ITEM_NEXT(dest, dest_li);
    703    idx++;
    704  }
    705 
    706  // Assign the List values to the list items.
    707  idx = idx1;
    708  dest_li = first_li;
    709  for (src_li = tv_list_first(src); src_li != NULL;) {
    710    assert(dest_li != NULL);
    711    if (op != NULL && *op != '=') {
    712      eexe_mod_op(TV_LIST_ITEM_TV(dest_li), TV_LIST_ITEM_TV(src_li), op);
    713    } else {
    714      tv_clear(TV_LIST_ITEM_TV(dest_li));
    715      tv_copy(TV_LIST_ITEM_TV(src_li), TV_LIST_ITEM_TV(dest_li));
    716    }
    717    src_li = TV_LIST_ITEM_NEXT(src, src_li);
    718    if (src_li == NULL || (!empty_idx2 && idx2 == idx)) {
    719      break;
    720    }
    721    if (TV_LIST_ITEM_NEXT(dest, dest_li) == NULL) {
    722      // Need to add an empty item.
    723      tv_list_append_number(dest, 0);
    724      // "dest_li" may have become invalid after append, don’t use it.
    725      dest_li = tv_list_last(dest);  // Valid again.
    726    } else {
    727      dest_li = TV_LIST_ITEM_NEXT(dest, dest_li);
    728    }
    729    idx++;
    730  }
    731  if (src_li != NULL) {
    732    emsg(_("E710: List value has more items than target"));
    733    return FAIL;
    734  }
    735  if (empty_idx2
    736      ? (dest_li != NULL && TV_LIST_ITEM_NEXT(dest, dest_li) != NULL)
    737      : idx != idx2) {
    738    emsg(_("E711: List value has not enough items"));
    739    return FAIL;
    740  }
    741  return OK;
    742 }
    743 
    744 /// Flatten up to "maxitems" in "list", starting at "first" to depth "maxdepth".
    745 /// When "first" is NULL use the first item.
    746 /// Does nothing if "maxdepth" is 0.
    747 ///
    748 /// @param[in,out] list   List to flatten
    749 /// @param[in] maxdepth   Maximum depth that will be flattened
    750 ///
    751 /// @return OK or FAIL
    752 void tv_list_flatten(list_T *list, listitem_T *first, int64_t maxitems, int64_t maxdepth)
    753  FUNC_ATTR_NONNULL_ARG(1)
    754 {
    755  listitem_T *item;
    756  int done = 0;
    757  if (maxdepth == 0) {
    758    return;
    759  }
    760 
    761  if (first == NULL) {
    762    item = list->lv_first;
    763  } else {
    764    item = first;
    765  }
    766 
    767  while (item != NULL && done < maxitems) {
    768    listitem_T *next = item->li_next;
    769 
    770    fast_breakcheck();
    771    if (got_int) {
    772      return;
    773    }
    774    if (item->li_tv.v_type == VAR_LIST) {
    775      list_T *itemlist = item->li_tv.vval.v_list;
    776 
    777      tv_list_drop_items(list, item, item);
    778      tv_list_extend(list, itemlist, next);
    779 
    780      if (maxdepth > 0) {
    781        tv_list_flatten(list,
    782                        item->li_prev == NULL ? list->lv_first : item->li_prev->li_next,
    783                        itemlist->lv_len, maxdepth - 1);
    784      }
    785      tv_clear(&item->li_tv);
    786      xfree(item);
    787    }
    788 
    789    done++;
    790    item = next;
    791  }
    792 }
    793 
    794 /// "items(blob)" function
    795 /// Converts a Blob into a List of [index, byte] pairs.
    796 /// Caller must have already checked that argvars[0] is a Blob.
    797 /// A null blob behaves like an empty blob.
    798 static void tv_blob2items(typval_T *argvars, typval_T *rettv)
    799 {
    800  blob_T *blob = argvars[0].vval.v_blob;
    801 
    802  tv_list_alloc_ret(rettv, tv_blob_len(blob));
    803 
    804  for (int i = 0; i < tv_blob_len(blob); i++) {
    805    list_T *l2 = tv_list_alloc(2);
    806    tv_list_append_list(rettv->vval.v_list, l2);
    807    tv_list_append_number(l2, i);
    808    tv_list_append_number(l2, tv_blob_get(blob, i));
    809  }
    810 }
    811 
    812 /// "items(dict)" function
    813 static void tv_dict2items(typval_T *argvars, typval_T *rettv)
    814 {
    815  tv_dict2list(argvars, rettv, kDict2ListItems);
    816 }
    817 
    818 /// "items(list)" function
    819 /// Caller must have already checked that argvars[0] is a List.
    820 static void tv_list2items(typval_T *argvars, typval_T *rettv)
    821 {
    822  list_T *l = argvars[0].vval.v_list;
    823 
    824  tv_list_alloc_ret(rettv, tv_list_len(l));
    825  if (l == NULL) {
    826    return;  // null list behaves like an empty list
    827  }
    828 
    829  varnumber_T idx = 0;
    830  TV_LIST_ITER(l, li, {
    831    list_T *l2 = tv_list_alloc(2);
    832    tv_list_append_list(rettv->vval.v_list, l2);
    833    tv_list_append_number(l2, idx);
    834    tv_list_append_tv(l2, TV_LIST_ITEM_TV(li));
    835    idx++;
    836  });
    837 }
    838 
    839 /// "items(string)" function
    840 /// Caller must have already checked that argvars[0] is a String.
    841 static void tv_string2items(typval_T *argvars, typval_T *rettv)
    842 {
    843  const char *p = argvars[0].vval.v_string;
    844 
    845  tv_list_alloc_ret(rettv, kListLenMayKnow);
    846  if (p == NULL) {
    847    return;  // null string behaves like an empty string
    848  }
    849 
    850  for (varnumber_T idx = 0; *p != NUL; idx++) {
    851    int len = utfc_ptr2len(p);
    852    if (len == 0) {
    853      break;
    854    }
    855    list_T *l2 = tv_list_alloc(2);
    856    tv_list_append_list(rettv->vval.v_list, l2);
    857    tv_list_append_number(l2, idx);
    858    tv_list_append_string(l2, p, len);
    859    p += len;
    860  }
    861 }
    862 
    863 /// Extend first list with the second
    864 ///
    865 /// @param[out]  l1  List to extend.
    866 /// @param[in]  l2  List to extend with.
    867 /// @param[in]  bef  If not NULL, extends before this item.
    868 void tv_list_extend(list_T *const l1, list_T *const l2, listitem_T *const bef)
    869  FUNC_ATTR_NONNULL_ARG(1)
    870 {
    871  int todo = tv_list_len(l2);
    872  listitem_T *const befbef = (bef == NULL ? NULL : bef->li_prev);
    873  listitem_T *const saved_next = (befbef == NULL ? NULL : befbef->li_next);
    874  // We also quit the loop when we have inserted the original item count of
    875  // the list, avoid a hang when we extend a list with itself.
    876  for (listitem_T *item = tv_list_first(l2)
    877       ; item != NULL && todo--
    878       ; item = (item == befbef ? saved_next : item->li_next)) {
    879    tv_list_insert_tv(l1, TV_LIST_ITEM_TV(item), bef);
    880  }
    881 }
    882 
    883 /// Concatenate lists into a new list
    884 ///
    885 /// @param[in]  l1  First list.
    886 /// @param[in]  l2  Second list.
    887 /// @param[out]  ret_tv  Location where new list is saved.
    888 ///
    889 /// @return OK or FAIL.
    890 int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv)
    891  FUNC_ATTR_WARN_UNUSED_RESULT
    892 {
    893  list_T *l;
    894 
    895  tv->v_type = VAR_LIST;
    896  tv->v_lock = VAR_UNLOCKED;
    897  if (l1 == NULL && l2 == NULL) {
    898    l = NULL;
    899  } else if (l1 == NULL) {
    900    l = tv_list_copy(NULL, l2, false, 0);
    901  } else {
    902    l = tv_list_copy(NULL, l1, false, 0);
    903    if (l != NULL && l2 != NULL) {
    904      tv_list_extend(l, l2, NULL);
    905    }
    906  }
    907  if (l == NULL && !(l1 == NULL && l2 == NULL)) {
    908    return FAIL;
    909  }
    910 
    911  tv->vval.v_list = l;
    912  return OK;
    913 }
    914 
    915 static list_T *tv_list_slice(list_T *ol, varnumber_T n1, varnumber_T n2)
    916 {
    917  list_T *l = tv_list_alloc(n2 - n1 + 1);
    918  listitem_T *item = tv_list_find(ol, (int)n1);
    919  for (; n1 <= n2; n1++) {
    920    tv_list_append_tv(l, TV_LIST_ITEM_TV(item));
    921    item = TV_LIST_ITEM_NEXT(rettv->vval.v_list, item);
    922  }
    923  return l;
    924 }
    925 
    926 int tv_list_slice_or_index(list_T *list, bool range, varnumber_T n1_arg, varnumber_T n2_arg,
    927                           bool exclusive, typval_T *rettv, bool verbose)
    928 {
    929  int len = tv_list_len(rettv->vval.v_list);
    930  varnumber_T n1 = n1_arg;
    931  varnumber_T n2 = n2_arg;
    932 
    933  if (n1 < 0) {
    934    n1 = len + n1;
    935  }
    936  if (n1 < 0 || n1 >= len) {
    937    // For a range we allow invalid values and return an empty list.
    938    // A list index out of range is an error.
    939    if (!range) {
    940      if (verbose) {
    941        semsg(_(e_list_index_out_of_range_nr), (int64_t)n1_arg);
    942      }
    943      return FAIL;
    944    }
    945    n1 = len;
    946  }
    947  if (range) {
    948    if (n2 < 0) {
    949      n2 = len + n2;
    950    } else if (n2 >= len) {
    951      n2 = len - (exclusive ? 0 : 1);
    952    }
    953    if (exclusive) {
    954      n2--;
    955    }
    956    if (n2 < 0 || n2 + 1 < n1) {
    957      n2 = -1;
    958    }
    959    list_T *l = tv_list_slice(rettv->vval.v_list, n1, n2);
    960    tv_clear(rettv);
    961    tv_list_set_ret(rettv, l);
    962  } else {
    963    // copy the item to "var1" to avoid that freeing the list makes it
    964    // invalid.
    965    typval_T var1;
    966    tv_copy(TV_LIST_ITEM_TV(tv_list_find(rettv->vval.v_list, (int)n1)), &var1);
    967    tv_clear(rettv);
    968    *rettv = var1;
    969  }
    970  return OK;
    971 }
    972 
    973 typedef struct {
    974  String s;
    975  char *tofree;
    976 } Join;
    977 
    978 /// Join list into a string, helper function
    979 ///
    980 /// @param[out]  gap  Garray where result will be saved.
    981 /// @param[in]  l  List to join.
    982 /// @param[in]  sep  Used separator.
    983 /// @param[in]  join_gap  Garray to keep each list item string.
    984 ///
    985 /// @return OK in case of success, FAIL otherwise.
    986 static int list_join_inner(garray_T *const gap, list_T *const l, const char *const sep,
    987                           garray_T *const join_gap)
    988  FUNC_ATTR_NONNULL_ALL
    989 {
    990  size_t sumlen = 0;
    991  bool first = true;
    992 
    993  // Stringify each item in the list.
    994  TV_LIST_ITER(l, item, {
    995    if (got_int) {
    996      break;
    997    }
    998    String s;
    999    s.data = encode_tv2echo(TV_LIST_ITEM_TV(item), &s.size);
   1000    if (s.data == NULL) {
   1001      return FAIL;
   1002    }
   1003 
   1004    sumlen += s.size;
   1005 
   1006    Join *const p = GA_APPEND_VIA_PTR(Join, join_gap);
   1007    p->s = s;
   1008    p->tofree = s.data;
   1009 
   1010    line_breakcheck();
   1011  });
   1012 
   1013  // Allocate result buffer with its total size, avoid re-allocation and
   1014  // multiple copy operations.  Add 2 for a tailing ']' and NUL.
   1015  size_t seplen = strlen(sep);
   1016  if (join_gap->ga_len >= 2) {
   1017    sumlen += seplen * (size_t)(join_gap->ga_len - 1);
   1018  }
   1019  ga_grow(gap, (int)sumlen + 2);
   1020 
   1021  for (int i = 0; i < join_gap->ga_len && !got_int; i++) {
   1022    if (first) {
   1023      first = false;
   1024    } else {
   1025      ga_concat_len(gap, sep, seplen);
   1026    }
   1027    const Join *const p = ((const Join *)join_gap->ga_data) + i;
   1028 
   1029    if (p->s.data != NULL) {
   1030      ga_concat_len(gap, p->s.data, p->s.size);
   1031    }
   1032    line_breakcheck();
   1033  }
   1034 
   1035  return OK;
   1036 }
   1037 
   1038 /// Join list into a string using given separator
   1039 ///
   1040 /// @param[out]  gap  Garray where the joined list will be saved.
   1041 /// @param[in]  l  List.
   1042 /// @param[in]  sep  Separator.
   1043 ///
   1044 /// @return OK in case of success, FAIL otherwise.
   1045 int tv_list_join(garray_T *const gap, list_T *const l, const char *const sep)
   1046  FUNC_ATTR_NONNULL_ARG(1)
   1047 {
   1048  if (!tv_list_len(l)) {
   1049    return OK;
   1050  }
   1051 
   1052  garray_T join_ga;
   1053  int retval;
   1054 
   1055  ga_init(&join_ga, (int)sizeof(Join), tv_list_len(l));
   1056  retval = list_join_inner(gap, l, sep, &join_ga);
   1057 
   1058 #define FREE_JOIN_TOFREE(join) xfree((join)->tofree)
   1059  GA_DEEP_CLEAR(&join_ga, Join, FREE_JOIN_TOFREE);
   1060 #undef FREE_JOIN_TOFREE
   1061 
   1062  return retval;
   1063 }
   1064 
   1065 /// "join()" function
   1066 void f_join(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   1067 {
   1068  if (argvars[0].v_type != VAR_LIST) {
   1069    emsg(_(e_listreq));
   1070    return;
   1071  }
   1072  const char *const sep = (argvars[1].v_type == VAR_UNKNOWN
   1073                           ? " "
   1074                           : tv_get_string_chk(&argvars[1]));
   1075 
   1076  rettv->v_type = VAR_STRING;
   1077 
   1078  if (sep != NULL) {
   1079    garray_T ga;
   1080    ga_init(&ga, (int)sizeof(char), 80);
   1081    tv_list_join(&ga, argvars[0].vval.v_list, sep);
   1082    ga_append(&ga, NUL);
   1083    rettv->vval.v_string = ga.ga_data;
   1084  } else {
   1085    rettv->vval.v_string = NULL;
   1086  }
   1087 }
   1088 
   1089 /// "list2str()" function
   1090 void f_list2str(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   1091 {
   1092  garray_T ga;
   1093 
   1094  rettv->v_type = VAR_STRING;
   1095  rettv->vval.v_string = NULL;
   1096  if (argvars[0].v_type != VAR_LIST) {
   1097    emsg(_(e_invarg));
   1098    return;
   1099  }
   1100 
   1101  list_T *const l = argvars[0].vval.v_list;
   1102  if (l == NULL) {
   1103    return;  // empty list results in empty string
   1104  }
   1105 
   1106  ga_init(&ga, 1, 80);
   1107  char buf[MB_MAXBYTES + 1];
   1108 
   1109  TV_LIST_ITER_CONST(l, li, {
   1110    const varnumber_T n = tv_get_number(TV_LIST_ITEM_TV(li));
   1111    const size_t buflen = (size_t)utf_char2bytes((int)n, buf);
   1112    buf[buflen] = NUL;
   1113    ga_concat_len(&ga, buf, buflen);
   1114  });
   1115  ga_append(&ga, NUL);
   1116 
   1117  rettv->vval.v_string = ga.ga_data;
   1118 }
   1119 
   1120 /// "remove({list})" function
   1121 void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
   1122 {
   1123  list_T *l;
   1124  bool error = false;
   1125 
   1126  if (value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
   1127                       arg_errmsg, TV_TRANSLATE)) {
   1128    return;
   1129  }
   1130 
   1131  int64_t idx = tv_get_number_chk(&argvars[1], &error);
   1132 
   1133  listitem_T *item;
   1134 
   1135  if (error) {
   1136    // Type error: do nothing, errmsg already given.
   1137  } else if ((item = tv_list_find(l, (int)idx)) == NULL) {
   1138    semsg(_(e_list_index_out_of_range_nr), idx);
   1139  } else {
   1140    if (argvars[2].v_type == VAR_UNKNOWN) {
   1141      // Remove one item, return its value.
   1142      tv_list_drop_items(l, item, item);
   1143      *rettv = *TV_LIST_ITEM_TV(item);
   1144      xfree(item);
   1145    } else {
   1146      listitem_T *item2;
   1147      // Remove range of items, return list with values.
   1148      int64_t end = tv_get_number_chk(&argvars[2], &error);
   1149      if (error) {
   1150        // Type error: do nothing.
   1151      } else if ((item2 = tv_list_find(l, (int)end)) == NULL) {
   1152        semsg(_(e_list_index_out_of_range_nr), end);
   1153      } else {
   1154        int cnt = 0;
   1155 
   1156        listitem_T *li;
   1157        for (li = item; li != NULL; li = TV_LIST_ITEM_NEXT(l, li)) {
   1158          cnt++;
   1159          if (li == item2) {
   1160            break;
   1161          }
   1162        }
   1163        if (li == NULL) {  // Didn't find "item2" after "item".
   1164          emsg(_(e_invrange));
   1165        } else {
   1166          tv_list_move_items(l, item, item2, tv_list_alloc_ret(rettv, cnt),
   1167                             cnt);
   1168        }
   1169      }
   1170    }
   1171  }
   1172 }
   1173 
   1174 static sortinfo_T *sortinfo = NULL;
   1175 
   1176 #define ITEM_COMPARE_FAIL 999
   1177 
   1178 /// Compare functions for f_sort() and f_uniq() below.
   1179 static int item_compare(const void *s1, const void *s2, bool keep_zero)
   1180 {
   1181  ListSortItem *const si1 = (ListSortItem *)s1;
   1182  ListSortItem *const si2 = (ListSortItem *)s2;
   1183 
   1184  typval_T *const tv1 = TV_LIST_ITEM_TV(si1->item);
   1185  typval_T *const tv2 = TV_LIST_ITEM_TV(si2->item);
   1186 
   1187  int res;
   1188 
   1189  if (sortinfo->item_compare_numbers) {
   1190    const varnumber_T v1 = tv_get_number(tv1);
   1191    const varnumber_T v2 = tv_get_number(tv2);
   1192 
   1193    res = v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
   1194    goto item_compare_end;
   1195  }
   1196 
   1197  if (sortinfo->item_compare_float) {
   1198    const float_T v1 = tv_get_float(tv1);
   1199    const float_T v2 = tv_get_float(tv2);
   1200 
   1201    res = v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
   1202    goto item_compare_end;
   1203  }
   1204 
   1205  char *tofree1 = NULL;
   1206  char *tofree2 = NULL;
   1207  char *p1;
   1208  char *p2;
   1209 
   1210  // encode_tv2string() puts quotes around a string and allocates memory.  Don't
   1211  // do that for string variables. Use a single quote when comparing with
   1212  // a non-string to do what the docs promise.
   1213  if (tv1->v_type == VAR_STRING) {
   1214    if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric) {
   1215      p1 = "'";
   1216    } else {
   1217      p1 = tv1->vval.v_string;
   1218    }
   1219  } else {
   1220    tofree1 = p1 = encode_tv2string(tv1, NULL);
   1221  }
   1222  if (tv2->v_type == VAR_STRING) {
   1223    if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric) {
   1224      p2 = "'";
   1225    } else {
   1226      p2 = tv2->vval.v_string;
   1227    }
   1228  } else {
   1229    tofree2 = p2 = encode_tv2string(tv2, NULL);
   1230  }
   1231  if (p1 == NULL) {
   1232    p1 = "";
   1233  }
   1234  if (p2 == NULL) {
   1235    p2 = "";
   1236  }
   1237  if (!sortinfo->item_compare_numeric) {
   1238    if (sortinfo->item_compare_lc) {
   1239      res = strcoll(p1, p2);
   1240    } else {
   1241      res = sortinfo->item_compare_ic ? STRICMP(p1, p2) : strcmp(p1, p2);
   1242    }
   1243  } else {
   1244    double n1 = strtod(p1, &p1);
   1245    double n2 = strtod(p2, &p2);
   1246    res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1;
   1247  }
   1248 
   1249  xfree(tofree1);
   1250  xfree(tofree2);
   1251 
   1252 item_compare_end:
   1253  // When the result would be zero, compare the item indexes.  Makes the
   1254  // sort stable.
   1255  if (res == 0 && !keep_zero) {
   1256    // WARNING: When using uniq si1 and si2 are actually listitem_T **, no
   1257    // indexes are there.
   1258    res = si1->idx > si2->idx ? 1 : -1;
   1259  }
   1260  return res;
   1261 }
   1262 
   1263 static int item_compare_keeping_zero(const void *s1, const void *s2)
   1264 {
   1265  return item_compare(s1, s2, true);
   1266 }
   1267 
   1268 static int item_compare_not_keeping_zero(const void *s1, const void *s2)
   1269 {
   1270  return item_compare(s1, s2, false);
   1271 }
   1272 
   1273 static int item_compare2(const void *s1, const void *s2, bool keep_zero)
   1274 {
   1275  typval_T rettv;
   1276  typval_T argv[3];
   1277  const char *func_name;
   1278  partial_T *partial = sortinfo->item_compare_partial;
   1279 
   1280  // shortcut after failure in previous call; compare all items equal
   1281  if (sortinfo->item_compare_func_err) {
   1282    return 0;
   1283  }
   1284 
   1285  ListSortItem *si1 = (ListSortItem *)s1;
   1286  ListSortItem *si2 = (ListSortItem *)s2;
   1287 
   1288  if (partial == NULL) {
   1289    func_name = sortinfo->item_compare_func;
   1290  } else {
   1291    func_name = partial_name(partial);
   1292  }
   1293 
   1294  // Copy the values.  This is needed to be able to set v_lock to VAR_FIXED
   1295  // in the copy without changing the original list items.
   1296  tv_copy(TV_LIST_ITEM_TV(si1->item), &argv[0]);
   1297  tv_copy(TV_LIST_ITEM_TV(si2->item), &argv[1]);
   1298 
   1299  rettv.v_type = VAR_UNKNOWN;  // tv_clear() uses this
   1300  funcexe_T funcexe = FUNCEXE_INIT;
   1301  funcexe.fe_evaluate = true;
   1302  funcexe.fe_partial = partial;
   1303  funcexe.fe_selfdict = sortinfo->item_compare_selfdict;
   1304  int res = call_func(func_name, -1, &rettv, 2, argv, &funcexe);
   1305  tv_clear(&argv[0]);
   1306  tv_clear(&argv[1]);
   1307 
   1308  if (res == FAIL) {
   1309    // XXX: ITEM_COMPARE_FAIL is unused
   1310    res = ITEM_COMPARE_FAIL;
   1311    sortinfo->item_compare_func_err = true;
   1312  } else {
   1313    varnumber_T n = tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err);
   1314    res = (n > 0) ? 1 : (n < 0) ? -1 : 0;
   1315  }
   1316  if (sortinfo->item_compare_func_err) {
   1317    res = ITEM_COMPARE_FAIL;  // return value has wrong type
   1318  }
   1319  tv_clear(&rettv);
   1320 
   1321  // When the result would be zero, compare the pointers themselves.  Makes
   1322  // the sort stable.
   1323  if (res == 0 && !keep_zero) {
   1324    // WARNING: When using uniq si1 and si2 are actually listitem_T **, no
   1325    // indexes are there.
   1326    res = si1->idx > si2->idx ? 1 : -1;
   1327  }
   1328 
   1329  return res;
   1330 }
   1331 
   1332 static int item_compare2_keeping_zero(const void *s1, const void *s2)
   1333 {
   1334  return item_compare2(s1, s2, true);
   1335 }
   1336 
   1337 static int item_compare2_not_keeping_zero(const void *s1, const void *s2)
   1338 {
   1339  return item_compare2(s1, s2, false);
   1340 }
   1341 
   1342 /// sort() List "l"
   1343 static void do_sort(list_T *l, sortinfo_T *info)
   1344 {
   1345  const int len = tv_list_len(l);
   1346 
   1347  // Make an array with each entry pointing to an item in the List.
   1348  ListSortItem *ptrs = xmalloc((size_t)((unsigned)len * sizeof(ListSortItem)));
   1349 
   1350  // f_sort(): ptrs will be the list to sort
   1351  int i = 0;
   1352  TV_LIST_ITER(l, li, {
   1353    ptrs[i].item = li;
   1354    ptrs[i].idx = i;
   1355    i++;
   1356  });
   1357 
   1358  info->item_compare_func_err = false;
   1359  ListSorter item_compare_func = ((info->item_compare_func == NULL
   1360                                   && info->item_compare_partial == NULL)
   1361                                  ? item_compare_not_keeping_zero
   1362                                  : item_compare2_not_keeping_zero);
   1363 
   1364  // Sort the array with item pointers.
   1365  qsort(ptrs, (size_t)len, sizeof(ListSortItem), item_compare_func);
   1366  if (!info->item_compare_func_err) {
   1367    // Clear the list and append the items in the sorted order.
   1368    l->lv_first = NULL;
   1369    l->lv_last = NULL;
   1370    l->lv_idx_item = NULL;
   1371    l->lv_len = 0;
   1372    for (i = 0; i < len; i++) {
   1373      tv_list_append(l, ptrs[i].item);
   1374    }
   1375  }
   1376  if (info->item_compare_func_err) {
   1377    emsg(_("E702: Sort compare function failed"));
   1378  }
   1379 
   1380  xfree(ptrs);
   1381 }
   1382 
   1383 /// uniq() List "l"
   1384 static void do_uniq(list_T *l, sortinfo_T *info)
   1385 {
   1386  const int len = tv_list_len(l);
   1387 
   1388  // Make an array with each entry pointing to an item in the List.
   1389  ListSortItem *ptrs = xmalloc((size_t)((unsigned)len * sizeof(ListSortItem)));
   1390 
   1391  // f_uniq(): ptrs will be a stack of items to remove.
   1392 
   1393  info->item_compare_func_err = false;
   1394  ListSorter item_compare_func = ((info->item_compare_func == NULL
   1395                                   && info->item_compare_partial == NULL)
   1396                                  ? item_compare_keeping_zero
   1397                                  : item_compare2_keeping_zero);
   1398 
   1399  for (listitem_T *li = TV_LIST_ITEM_NEXT(l, tv_list_first(l)); li != NULL;) {
   1400    listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li);
   1401    if (item_compare_func(&prev_li, &li) == 0) {
   1402      li = tv_list_item_remove(l, li);
   1403    } else {
   1404      li = TV_LIST_ITEM_NEXT(l, li);
   1405    }
   1406    if (info->item_compare_func_err) {
   1407      emsg(_("E882: Uniq compare function failed"));
   1408      break;
   1409    }
   1410  }
   1411 
   1412  xfree(ptrs);
   1413 }
   1414 
   1415 /// Parse the optional arguments to sort() and uniq() and return the values in "info".
   1416 static int parse_sort_uniq_args(typval_T *argvars, sortinfo_T *info)
   1417 {
   1418  info->item_compare_ic = false;
   1419  info->item_compare_lc = false;
   1420  info->item_compare_numeric = false;
   1421  info->item_compare_numbers = false;
   1422  info->item_compare_float = false;
   1423  info->item_compare_func = NULL;
   1424  info->item_compare_partial = NULL;
   1425  info->item_compare_selfdict = NULL;
   1426 
   1427  if (argvars[1].v_type == VAR_UNKNOWN) {
   1428    return OK;
   1429  }
   1430 
   1431  // optional second argument: {func}
   1432  if (argvars[1].v_type == VAR_FUNC) {
   1433    info->item_compare_func = argvars[1].vval.v_string;
   1434  } else if (argvars[1].v_type == VAR_PARTIAL) {
   1435    info->item_compare_partial = argvars[1].vval.v_partial;
   1436  } else {
   1437    bool error = false;
   1438    int nr = (int)tv_get_number_chk(&argvars[1], &error);
   1439    if (error) {
   1440      return FAIL;  // type error; errmsg already given
   1441    }
   1442    if (nr == 1) {
   1443      info->item_compare_ic = true;
   1444    } else if (argvars[1].v_type != VAR_NUMBER) {
   1445      info->item_compare_func = tv_get_string(&argvars[1]);
   1446    } else if (nr != 0) {
   1447      emsg(_(e_invarg));
   1448      return FAIL;
   1449    }
   1450    if (info->item_compare_func != NULL) {
   1451      if (*info->item_compare_func == NUL) {
   1452        // empty string means default sort
   1453        info->item_compare_func = NULL;
   1454      } else if (strcmp(info->item_compare_func, "n") == 0) {
   1455        info->item_compare_func = NULL;
   1456        info->item_compare_numeric = true;
   1457      } else if (strcmp(info->item_compare_func, "N") == 0) {
   1458        info->item_compare_func = NULL;
   1459        info->item_compare_numbers = true;
   1460      } else if (strcmp(info->item_compare_func, "f") == 0) {
   1461        info->item_compare_func = NULL;
   1462        info->item_compare_float = true;
   1463      } else if (strcmp(info->item_compare_func, "i") == 0) {
   1464        info->item_compare_func = NULL;
   1465        info->item_compare_ic = true;
   1466      } else if (strcmp(info->item_compare_func, "l") == 0) {
   1467        info->item_compare_func = NULL;
   1468        info->item_compare_lc = true;
   1469      }
   1470    }
   1471  }
   1472 
   1473  if (argvars[2].v_type != VAR_UNKNOWN) {
   1474    // optional third argument: {dict}
   1475    if (tv_check_for_dict_arg(argvars, 2) == FAIL) {
   1476      return FAIL;
   1477    }
   1478    info->item_compare_selfdict = argvars[2].vval.v_dict;
   1479  }
   1480 
   1481  return OK;
   1482 }
   1483 
   1484 /// "sort()" or "uniq()" function
   1485 static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
   1486 {
   1487  if (argvars[0].v_type != VAR_LIST) {
   1488    semsg(_(e_listarg), sort ? "sort()" : "uniq()");
   1489    return;
   1490  }
   1491 
   1492  // Pointer to current info struct used in compare function. Save and restore
   1493  // the current one for nested calls.
   1494  sortinfo_T info;
   1495  sortinfo_T *old_sortinfo = sortinfo;
   1496  sortinfo = &info;
   1497 
   1498  const char *const arg_errmsg = (sort ? N_("sort() argument") : N_("uniq() argument"));
   1499  list_T *const l = argvars[0].vval.v_list;
   1500  if (value_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) {
   1501    goto theend;
   1502  }
   1503  tv_list_set_ret(rettv, l);
   1504 
   1505  const int len = tv_list_len(l);
   1506  if (len <= 1) {
   1507    goto theend;  // short list sorts pretty quickly
   1508  }
   1509  if (parse_sort_uniq_args(argvars, &info) == FAIL) {
   1510    goto theend;
   1511  }
   1512 
   1513  if (sort) {
   1514    do_sort(l, &info);
   1515  } else {
   1516    do_uniq(l, &info);
   1517  }
   1518 
   1519 theend:
   1520  sortinfo = old_sortinfo;
   1521 }
   1522 
   1523 /// "sort({list})" function
   1524 void f_sort(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   1525 {
   1526  do_sort_uniq(argvars, rettv, true);
   1527 }
   1528 
   1529 /// "uniq({list})" function
   1530 void f_uniq(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   1531 {
   1532  do_sort_uniq(argvars, rettv, false);
   1533 }
   1534 
   1535 /// Check whether two lists are equal
   1536 ///
   1537 /// @param[in]  l1  First list to compare.
   1538 /// @param[in]  l2  Second list to compare.
   1539 /// @param[in]  ic  True if case is to be ignored.
   1540 ///
   1541 /// @return True if lists are equal, false otherwise.
   1542 bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic)
   1543  FUNC_ATTR_WARN_UNUSED_RESULT
   1544 {
   1545  if (l1 == l2) {
   1546    return true;
   1547  }
   1548  if (tv_list_len(l1) != tv_list_len(l2)) {
   1549    return false;
   1550  }
   1551  if (tv_list_len(l1) == 0) {
   1552    // empty and NULL list are considered equal
   1553    return true;
   1554  }
   1555  if (l1 == NULL || l2 == NULL) {
   1556    return false;
   1557  }
   1558 
   1559  listitem_T *item1 = tv_list_first(l1);
   1560  listitem_T *item2 = tv_list_first(l2);
   1561  for (; item1 != NULL && item2 != NULL
   1562       ; (item1 = TV_LIST_ITEM_NEXT(l1, item1),
   1563          item2 = TV_LIST_ITEM_NEXT(l2, item2))) {
   1564    if (!tv_equal(TV_LIST_ITEM_TV(item1), TV_LIST_ITEM_TV(item2), ic)) {
   1565      return false;
   1566    }
   1567  }
   1568  assert(item1 == NULL && item2 == NULL);
   1569  return true;
   1570 }
   1571 
   1572 /// Reverse list in-place
   1573 ///
   1574 /// @param[in,out]  l  List to reverse.
   1575 void tv_list_reverse(list_T *const l)
   1576 {
   1577  if (tv_list_len(l) <= 1) {
   1578    return;
   1579  }
   1580 #define SWAP(a, b) \
   1581  do { \
   1582    tmp = (a); \
   1583    (a) = (b); \
   1584    (b) = tmp; \
   1585  } while (0)
   1586  listitem_T *tmp;
   1587 
   1588  SWAP(l->lv_first, l->lv_last);
   1589  for (listitem_T *li = l->lv_first; li != NULL; li = li->li_next) {
   1590    SWAP(li->li_next, li->li_prev);
   1591  }
   1592 #undef SWAP
   1593 
   1594  l->lv_idx = l->lv_len - l->lv_idx - 1;
   1595 }
   1596 
   1597 // Indexing/searching:
   1598 
   1599 /// Locate item with a given index in a list and return it
   1600 ///
   1601 /// @param[in]  l  List to index.
   1602 /// @param[in]  n  Index. Negative index is counted from the end, -1 is the last
   1603 ///                item.
   1604 ///
   1605 /// @return Item at the given index or NULL if `n` is out of range.
   1606 listitem_T *tv_list_find(list_T *const l, int n)
   1607  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   1608 {
   1609  STATIC_ASSERT(sizeof(n) == sizeof(l->lv_idx),
   1610                "n and lv_idx sizes do not match");
   1611  if (l == NULL) {
   1612    return NULL;
   1613  }
   1614 
   1615  n = tv_list_uidx(l, n);
   1616  if (n == -1) {
   1617    return NULL;
   1618  }
   1619 
   1620  int idx;
   1621  listitem_T *item;
   1622 
   1623  // When there is a cached index may start search from there.
   1624  if (l->lv_idx_item != NULL) {
   1625    if (n < l->lv_idx / 2) {
   1626      // Closest to the start of the list.
   1627      item = l->lv_first;
   1628      idx = 0;
   1629    } else if (n > (l->lv_idx + l->lv_len) / 2) {
   1630      // Closest to the end of the list.
   1631      item = l->lv_last;
   1632      idx = l->lv_len - 1;
   1633    } else {
   1634      // Closest to the cached index.
   1635      item = l->lv_idx_item;
   1636      idx = l->lv_idx;
   1637    }
   1638  } else {
   1639    if (n < l->lv_len / 2) {
   1640      // Closest to the start of the list.
   1641      item = l->lv_first;
   1642      idx = 0;
   1643    } else {
   1644      // Closest to the end of the list.
   1645      item = l->lv_last;
   1646      idx = l->lv_len - 1;
   1647    }
   1648  }
   1649 
   1650  while (n > idx) {
   1651    // Search forward.
   1652    item = item->li_next;
   1653    idx++;
   1654  }
   1655  while (n < idx) {
   1656    // Search backward.
   1657    item = item->li_prev;
   1658    idx--;
   1659  }
   1660 
   1661  assert(idx == n);
   1662  // Cache the used index.
   1663  l->lv_idx = idx;
   1664  l->lv_idx_item = item;
   1665 
   1666  return item;
   1667 }
   1668 
   1669 /// Get list item l[n] as a number
   1670 ///
   1671 /// @param[in]  l  List to index.
   1672 /// @param[in]  n  Index in a list.
   1673 /// @param[out]  ret_error  Location where 1 will be saved if index was not
   1674 ///                         found. May be NULL. If everything is OK,
   1675 ///                         `*ret_error` is not touched.
   1676 ///
   1677 /// @return Integer value at the given index or -1.
   1678 varnumber_T tv_list_find_nr(list_T *const l, const int n, bool *const ret_error)
   1679  FUNC_ATTR_WARN_UNUSED_RESULT
   1680 {
   1681  const listitem_T *const li = tv_list_find(l, n);
   1682  if (li == NULL) {
   1683    if (ret_error != NULL) {
   1684      *ret_error = true;
   1685    }
   1686    return -1;
   1687  }
   1688  return tv_get_number_chk(TV_LIST_ITEM_TV(li), ret_error);
   1689 }
   1690 
   1691 /// Get list item l[n] as a string
   1692 ///
   1693 /// @param[in]  l  List to index.
   1694 /// @param[in]  n  Index in a list.
   1695 ///
   1696 /// @return List item string value or NULL in case of error.
   1697 const char *tv_list_find_str(list_T *const l, const int n)
   1698  FUNC_ATTR_WARN_UNUSED_RESULT
   1699 {
   1700  const listitem_T *const li = tv_list_find(l, n);
   1701  if (li == NULL) {
   1702    semsg(_(e_list_index_out_of_range_nr), (int64_t)n);
   1703    return NULL;
   1704  }
   1705  return tv_get_string(TV_LIST_ITEM_TV(li));
   1706 }
   1707 
   1708 /// Like tv_list_find() but when a negative index is used that is not found use
   1709 /// zero and set "idx" to zero.  Used for first index of a range.
   1710 static listitem_T *tv_list_find_index(list_T *const l, int *const idx)
   1711  FUNC_ATTR_WARN_UNUSED_RESULT
   1712 {
   1713  listitem_T *li = tv_list_find(l, *idx);
   1714  if (li != NULL) {
   1715    return li;
   1716  }
   1717 
   1718  if (*idx < 0) {
   1719    *idx = 0;
   1720    li = tv_list_find(l, *idx);
   1721  }
   1722  return li;
   1723 }
   1724 
   1725 /// Locate item in a list and return its index
   1726 ///
   1727 /// @param[in]  l  List to search.
   1728 /// @param[in]  item  Item to search for.
   1729 ///
   1730 /// @return Index of an item or -1 if item is not in the list.
   1731 int tv_list_idx_of_item(const list_T *const l, const listitem_T *const item)
   1732  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   1733 {
   1734  if (l == NULL) {
   1735    return -1;
   1736  }
   1737  int idx = 0;
   1738  TV_LIST_ITER_CONST(l, li, {
   1739    if (li == item) {
   1740      return idx;
   1741    }
   1742    idx++;
   1743  });
   1744  return -1;
   1745 }
   1746 
   1747 // Dictionaries:
   1748 // Dictionary watchers:
   1749 
   1750 /// Perform all necessary cleanup for a `DictWatcher` instance
   1751 ///
   1752 /// @param  watcher  Watcher to free.
   1753 static void tv_dict_watcher_free(DictWatcher *watcher)
   1754  FUNC_ATTR_NONNULL_ALL
   1755 {
   1756  callback_free(&watcher->callback);
   1757  xfree(watcher->key_pattern);
   1758  xfree(watcher);
   1759 }
   1760 
   1761 /// Add watcher to a dictionary
   1762 ///
   1763 /// @param[in]  dict  Dictionary to add watcher to.
   1764 /// @param[in]  key_pattern  Pattern to watch for.
   1765 /// @param[in]  key_pattern_len  Key pattern length.
   1766 /// @param  callback  Function to be called on events.
   1767 void tv_dict_watcher_add(dict_T *const dict, const char *const key_pattern,
   1768                         const size_t key_pattern_len, Callback callback)
   1769  FUNC_ATTR_NONNULL_ARG(2)
   1770 {
   1771  if (dict == NULL) {
   1772    return;
   1773  }
   1774  DictWatcher *const watcher = xmalloc(sizeof(DictWatcher));
   1775  watcher->key_pattern = xmemdupz(key_pattern, key_pattern_len);
   1776  watcher->key_pattern_len = key_pattern_len;
   1777  watcher->callback = callback;
   1778  watcher->busy = false;
   1779  watcher->needs_free = false;
   1780  QUEUE_INSERT_TAIL(&dict->watchers, &watcher->node);
   1781 }
   1782 
   1783 /// Check whether two callbacks are equal
   1784 ///
   1785 /// @param[in]  cb1  First callback to check.
   1786 /// @param[in]  cb2  Second callback to check.
   1787 ///
   1788 /// @return True if they are equal, false otherwise.
   1789 bool tv_callback_equal(const Callback *cb1, const Callback *cb2)
   1790  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   1791 {
   1792  if (cb1->type != cb2->type) {
   1793    return false;
   1794  }
   1795  switch (cb1->type) {
   1796  case kCallbackFuncref:
   1797    return strcmp(cb1->data.funcref, cb2->data.funcref) == 0;
   1798  case kCallbackPartial:
   1799    // FIXME: this is inconsistent with tv_equal but is needed for precision
   1800    // maybe change dictwatcheradd to return a watcher id instead?
   1801    return cb1->data.partial == cb2->data.partial;
   1802  case kCallbackLua:
   1803    return cb1->data.luaref == cb2->data.luaref;
   1804  case kCallbackNone:
   1805    return true;
   1806  }
   1807  abort();
   1808  return false;
   1809 }
   1810 
   1811 /// Unref/free callback
   1812 void callback_free(Callback *callback)
   1813  FUNC_ATTR_NONNULL_ALL
   1814 {
   1815  switch (callback->type) {
   1816  case kCallbackFuncref:
   1817    func_unref(callback->data.funcref);
   1818    xfree(callback->data.funcref);
   1819    break;
   1820  case kCallbackPartial:
   1821    partial_unref(callback->data.partial);
   1822    break;
   1823  case kCallbackLua:
   1824    NLUA_CLEAR_REF(callback->data.luaref);
   1825    break;
   1826  case kCallbackNone:
   1827    break;
   1828  }
   1829  callback->type = kCallbackNone;
   1830  callback->data.funcref = NULL;
   1831 }
   1832 
   1833 /// Copy a callback into a typval_T.
   1834 void callback_put(Callback *cb, typval_T *tv)
   1835  FUNC_ATTR_NONNULL_ALL
   1836 {
   1837  switch (cb->type) {
   1838  case kCallbackPartial:
   1839    tv->v_type = VAR_PARTIAL;
   1840    tv->vval.v_partial = cb->data.partial;
   1841    cb->data.partial->pt_refcount++;
   1842    break;
   1843  case kCallbackFuncref:
   1844    tv->v_type = VAR_FUNC;
   1845    tv->vval.v_string = xstrdup(cb->data.funcref);
   1846    func_ref(cb->data.funcref);
   1847    break;
   1848  case kCallbackLua:
   1849  // TODO(tjdevries): Unified Callback.
   1850  // At this point this isn't possible, but it'd be nice to put
   1851  // these handled more neatly in one place.
   1852  // So instead, we just do the default and put nil
   1853  default:
   1854    tv->v_type = VAR_SPECIAL;
   1855    tv->vval.v_special = kSpecialVarNull;
   1856    break;
   1857  }
   1858 }
   1859 
   1860 // Copy callback from "src" to "dest", incrementing the refcounts.
   1861 void callback_copy(Callback *dest, Callback *src)
   1862  FUNC_ATTR_NONNULL_ALL
   1863 {
   1864  dest->type = src->type;
   1865  switch (src->type) {
   1866  case kCallbackPartial:
   1867    dest->data.partial = src->data.partial;
   1868    dest->data.partial->pt_refcount++;
   1869    break;
   1870  case kCallbackFuncref:
   1871    dest->data.funcref = xstrdup(src->data.funcref);
   1872    func_ref(src->data.funcref);
   1873    break;
   1874  case kCallbackLua:
   1875    dest->data.luaref = api_new_luaref(src->data.luaref);
   1876    break;
   1877  default:
   1878    dest->data.funcref = NULL;
   1879    break;
   1880  }
   1881 }
   1882 
   1883 /// Generate a string description of a callback
   1884 char *callback_to_string(Callback *cb, Arena *arena)
   1885 {
   1886  if (cb->type == kCallbackLua) {
   1887    return nlua_funcref_str(cb->data.luaref, arena);
   1888  }
   1889 
   1890  const size_t msglen = 100;
   1891  char *msg = xmallocz(msglen);
   1892 
   1893  switch (cb->type) {
   1894  case kCallbackFuncref:
   1895    // TODO(tjdevries): Is this enough space for this?
   1896    snprintf(msg, msglen, "<vim function: %s>", cb->data.funcref);
   1897    break;
   1898  case kCallbackPartial:
   1899    snprintf(msg, msglen, "<vim partial: %s>", cb->data.partial->pt_name);
   1900    break;
   1901  default:
   1902    *msg = NUL;
   1903    break;
   1904  }
   1905  return msg;
   1906 }
   1907 
   1908 /// Remove watcher from a dictionary
   1909 ///
   1910 /// @param  dict  Dictionary to remove watcher from.
   1911 /// @param[in]  key_pattern  Pattern to remove watcher for.
   1912 /// @param[in]  key_pattern_len  Pattern length.
   1913 /// @param  callback  Callback to remove watcher for.
   1914 ///
   1915 /// @return True on success, false if relevant watcher was not found.
   1916 bool tv_dict_watcher_remove(dict_T *const dict, const char *const key_pattern,
   1917                            const size_t key_pattern_len, Callback callback)
   1918  FUNC_ATTR_NONNULL_ARG(2)
   1919 {
   1920  if (dict == NULL) {
   1921    return false;
   1922  }
   1923 
   1924  QUEUE *w = NULL;
   1925  DictWatcher *watcher = NULL;
   1926  bool matched = false;
   1927  bool queue_is_busy = false;
   1928  QUEUE_FOREACH(w, &dict->watchers, {
   1929    watcher = tv_dict_watcher_node_data(w);
   1930    if (watcher->busy) {
   1931      queue_is_busy = true;
   1932    }
   1933    if (tv_callback_equal(&watcher->callback, &callback)
   1934        && watcher->key_pattern_len == key_pattern_len
   1935        && memcmp(watcher->key_pattern, key_pattern, key_pattern_len) == 0) {
   1936      matched = true;
   1937      break;
   1938    }
   1939  })
   1940 
   1941  if (!matched) {
   1942    return false;
   1943  }
   1944 
   1945  if (queue_is_busy) {
   1946    watcher->needs_free = true;
   1947  } else {
   1948    QUEUE_REMOVE(w);
   1949    tv_dict_watcher_free(watcher);
   1950  }
   1951  return true;
   1952 }
   1953 
   1954 /// Test if `key` matches with with `watcher->key_pattern`
   1955 ///
   1956 /// @param[in]  watcher  Watcher to check key pattern from.
   1957 /// @param[in]  key  Key to check.
   1958 ///
   1959 /// @return true if key matches, false otherwise.
   1960 static bool tv_dict_watcher_matches(DictWatcher *watcher, const char *const key)
   1961  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   1962 {
   1963  // For now only allow very simple globbing in key patterns: a '*' at the end
   1964  // of the string means it should match everything up to the '*' instead of the
   1965  // whole string.
   1966  const size_t len = watcher->key_pattern_len;
   1967  if (len && watcher->key_pattern[len - 1] == '*') {
   1968    return strncmp(key, watcher->key_pattern, len - 1) == 0;
   1969  }
   1970  return strcmp(key, watcher->key_pattern) == 0;
   1971 }
   1972 
   1973 /// Send a change notification to all dictionary watchers that match given key
   1974 ///
   1975 /// @param[in]  dict  Dictionary which was modified.
   1976 /// @param[in]  key  Key which was modified.
   1977 /// @param[in]  newtv  New key value.
   1978 /// @param[in]  oldtv  Old key value.
   1979 void tv_dict_watcher_notify(dict_T *const dict, const char *const key, typval_T *const newtv,
   1980                            typval_T *const oldtv)
   1981  FUNC_ATTR_NONNULL_ARG(1, 2)
   1982 {
   1983  typval_T argv[3];
   1984 
   1985  argv[0].v_type = VAR_DICT;
   1986  argv[0].v_lock = VAR_UNLOCKED;
   1987  argv[0].vval.v_dict = dict;
   1988  argv[1].v_type = VAR_STRING;
   1989  argv[1].v_lock = VAR_UNLOCKED;
   1990  argv[1].vval.v_string = xstrdup(key);
   1991  argv[2].v_type = VAR_DICT;
   1992  argv[2].v_lock = VAR_UNLOCKED;
   1993  argv[2].vval.v_dict = tv_dict_alloc();
   1994  argv[2].vval.v_dict->dv_refcount++;
   1995 
   1996  if (newtv) {
   1997    dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("new"));
   1998    tv_copy(newtv, &v->di_tv);
   1999    tv_dict_add(argv[2].vval.v_dict, v);
   2000  }
   2001 
   2002  if (oldtv && oldtv->v_type != VAR_UNKNOWN) {
   2003    dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("old"));
   2004    tv_copy(oldtv, &v->di_tv);
   2005    tv_dict_add(argv[2].vval.v_dict, v);
   2006  }
   2007 
   2008  typval_T rettv;
   2009 
   2010  bool any_needs_free = false;
   2011  dict->dv_refcount++;
   2012  QUEUE *w;
   2013  QUEUE_FOREACH(w, &dict->watchers, {
   2014    DictWatcher *watcher = tv_dict_watcher_node_data(w);
   2015    if (!watcher->busy && tv_dict_watcher_matches(watcher, key)) {
   2016      rettv = TV_INITIAL_VALUE;
   2017      watcher->busy = true;
   2018      callback_call(&watcher->callback, 3, argv, &rettv);
   2019      watcher->busy = false;
   2020      tv_clear(&rettv);
   2021      if (watcher->needs_free) {
   2022        any_needs_free = true;
   2023      }
   2024    }
   2025  })
   2026  if (any_needs_free) {
   2027    QUEUE_FOREACH(w, &dict->watchers, {
   2028      DictWatcher *watcher = tv_dict_watcher_node_data(w);
   2029      if (watcher->needs_free) {
   2030        QUEUE_REMOVE(w);
   2031        tv_dict_watcher_free(watcher);
   2032      }
   2033    })
   2034  }
   2035  tv_dict_unref(dict);
   2036 
   2037  for (size_t i = 1; i < ARRAY_SIZE(argv); i++) {
   2038    tv_clear(argv + i);
   2039  }
   2040 }
   2041 
   2042 // Dictionary item:
   2043 
   2044 /// Allocate a dictionary item
   2045 ///
   2046 /// @note that the type and value of the item (->di_tv) still needs to
   2047 ///       be initialized.
   2048 ///
   2049 /// @param[in]  key  Key, is copied to the new item.
   2050 /// @param[in]  key_len  Key length.
   2051 ///
   2052 /// @return [allocated] new dictionary item.
   2053 dictitem_T *tv_dict_item_alloc_len(const char *const key, const size_t key_len)
   2054  FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   2055  FUNC_ATTR_MALLOC
   2056 {
   2057  // Allocating a struct smaller than its static size is UB (#37160)
   2058  dictitem_T *const di = xmalloc(MAX(sizeof(dictitem_T),
   2059                                     offsetof(dictitem_T, di_key) + key_len + 1));
   2060  memcpy(di->di_key, key, key_len);
   2061  di->di_key[key_len] = NUL;
   2062  di->di_flags = DI_FLAGS_ALLOC;
   2063  di->di_tv.v_lock = VAR_UNLOCKED;
   2064  di->di_tv.v_type = VAR_UNKNOWN;
   2065  return di;
   2066 }
   2067 
   2068 /// Allocate a dictionary item
   2069 ///
   2070 /// @note that the type and value of the item (->di_tv) still needs to
   2071 ///       be initialized.
   2072 ///
   2073 /// @param[in]  key  Key, is copied to the new item.
   2074 ///
   2075 /// @return [allocated] new dictionary item.
   2076 dictitem_T *tv_dict_item_alloc(const char *const key)
   2077  FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   2078  FUNC_ATTR_MALLOC
   2079 {
   2080  return tv_dict_item_alloc_len(key, strlen(key));
   2081 }
   2082 
   2083 /// Free a dictionary item, also clearing the value
   2084 ///
   2085 /// @param  item  Item to free.
   2086 void tv_dict_item_free(dictitem_T *const item)
   2087  FUNC_ATTR_NONNULL_ALL
   2088 {
   2089  tv_clear(&item->di_tv);
   2090  if (item->di_flags & DI_FLAGS_ALLOC) {
   2091    xfree(item);
   2092  }
   2093 }
   2094 
   2095 /// Make a copy of a dictionary item
   2096 ///
   2097 /// @param[in]  di  Item to copy.
   2098 ///
   2099 /// @return [allocated] new dictionary item.
   2100 dictitem_T *tv_dict_item_copy(dictitem_T *const di)
   2101  FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   2102 {
   2103  dictitem_T *const new_di = tv_dict_item_alloc(di->di_key);
   2104  tv_copy(&di->di_tv, &new_di->di_tv);
   2105  return new_di;
   2106 }
   2107 
   2108 /// Remove item from dictionary and free it
   2109 ///
   2110 /// @param  dict  Dictionary to remove item from.
   2111 /// @param  item  Item to remove.
   2112 void tv_dict_item_remove(dict_T *const dict, dictitem_T *const item)
   2113  FUNC_ATTR_NONNULL_ALL
   2114 {
   2115  hashitem_T *const hi = hash_find(&dict->dv_hashtab, item->di_key);
   2116  if (HASHITEM_EMPTY(hi)) {
   2117    semsg(_(e_intern2), "tv_dict_item_remove()");
   2118  } else {
   2119    hash_remove(&dict->dv_hashtab, hi);
   2120  }
   2121  tv_dict_item_free(item);
   2122 }
   2123 
   2124 // Alloc/free:
   2125 
   2126 /// Allocate an empty dictionary.
   2127 /// Caller should take care of the reference count.
   2128 ///
   2129 /// @return [allocated] new dictionary.
   2130 dict_T *tv_dict_alloc(void)
   2131  FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
   2132 {
   2133  dict_T *const d = xcalloc(1, sizeof(dict_T));
   2134 
   2135  // Add the dict to the list of dicts for garbage collection.
   2136  if (gc_first_dict != NULL) {
   2137    gc_first_dict->dv_used_prev = d;
   2138  }
   2139  d->dv_used_next = gc_first_dict;
   2140  d->dv_used_prev = NULL;
   2141  gc_first_dict = d;
   2142 
   2143  hash_init(&d->dv_hashtab);
   2144  d->dv_lock = VAR_UNLOCKED;
   2145  d->dv_scope = VAR_NO_SCOPE;
   2146  d->dv_refcount = 0;
   2147  d->dv_copyID = 0;
   2148  QUEUE_INIT(&d->watchers);
   2149 
   2150  d->lua_table_ref = LUA_NOREF;
   2151 
   2152  return d;
   2153 }
   2154 
   2155 /// Free items contained in a dictionary
   2156 ///
   2157 /// @param[in,out]  d  Dictionary to clear.
   2158 void tv_dict_free_contents(dict_T *const d)
   2159  FUNC_ATTR_NONNULL_ALL
   2160 {
   2161  // Lock the hashtab, we don't want it to resize while freeing items.
   2162  hash_lock(&d->dv_hashtab);
   2163  assert(d->dv_hashtab.ht_locked > 0);
   2164  HASHTAB_ITER(&d->dv_hashtab, hi, {
   2165    // Remove the item before deleting it, just in case there is
   2166    // something recursive causing trouble.
   2167    dictitem_T *const di = TV_DICT_HI2DI(hi);
   2168    hash_remove(&d->dv_hashtab, hi);
   2169    tv_dict_item_free(di);
   2170  });
   2171 
   2172  while (!QUEUE_EMPTY(&d->watchers)) {
   2173    QUEUE *w = QUEUE_HEAD(&d->watchers);
   2174    QUEUE_REMOVE(w);
   2175    DictWatcher *watcher = tv_dict_watcher_node_data(w);
   2176    tv_dict_watcher_free(watcher);
   2177  }
   2178 
   2179  hash_clear(&d->dv_hashtab);
   2180  d->dv_hashtab.ht_locked--;
   2181  hash_init(&d->dv_hashtab);
   2182 }
   2183 
   2184 /// Free a dictionary itself, ignoring items it contains
   2185 ///
   2186 /// Ignores the reference count.
   2187 ///
   2188 /// @param[in,out]  d  Dictionary to free.
   2189 void tv_dict_free_dict(dict_T *const d)
   2190  FUNC_ATTR_NONNULL_ALL
   2191 {
   2192  // Remove the dict from the list of dicts for garbage collection.
   2193  if (d->dv_used_prev == NULL) {
   2194    gc_first_dict = d->dv_used_next;
   2195  } else {
   2196    d->dv_used_prev->dv_used_next = d->dv_used_next;
   2197  }
   2198  if (d->dv_used_next != NULL) {
   2199    d->dv_used_next->dv_used_prev = d->dv_used_prev;
   2200  }
   2201 
   2202  NLUA_CLEAR_REF(d->lua_table_ref);
   2203  xfree(d);
   2204 }
   2205 
   2206 /// Free a dictionary, including all items it contains
   2207 ///
   2208 /// Ignores the reference count.
   2209 ///
   2210 /// @param  d  Dictionary to free.
   2211 void tv_dict_free(dict_T *const d)
   2212  FUNC_ATTR_NONNULL_ALL
   2213 {
   2214  if (tv_in_free_unref_items) {
   2215    return;
   2216  }
   2217 
   2218  tv_dict_free_contents(d);
   2219  tv_dict_free_dict(d);
   2220 }
   2221 
   2222 /// Unreference a dictionary
   2223 ///
   2224 /// Decrements the reference count and frees dictionary when it becomes zero.
   2225 ///
   2226 /// @param[in]  d  Dictionary to operate on.
   2227 void tv_dict_unref(dict_T *const d)
   2228 {
   2229  if (d != NULL && --d->dv_refcount <= 0) {
   2230    tv_dict_free(d);
   2231  }
   2232 }
   2233 
   2234 // Indexing/searching:
   2235 
   2236 /// Find item in dictionary
   2237 ///
   2238 /// @param[in]  d  Dictionary to check.
   2239 /// @param[in]  key  Dictionary key.
   2240 /// @param[in]  len  Key length. If negative, then strlen(key) is used.
   2241 ///
   2242 /// @return found item or NULL if nothing was found.
   2243 dictitem_T *tv_dict_find(const dict_T *const d, const char *const key, const ptrdiff_t len)
   2244  FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   2245 {
   2246  if (d == NULL) {
   2247    return NULL;
   2248  }
   2249  hashitem_T *const hi = (len < 0
   2250                          ? hash_find(&d->dv_hashtab, key)
   2251                          : hash_find_len(&d->dv_hashtab, key, (size_t)len));
   2252  if (HASHITEM_EMPTY(hi)) {
   2253    return NULL;
   2254  }
   2255  return TV_DICT_HI2DI(hi);
   2256 }
   2257 
   2258 /// Check if a key is present in a dictionary.
   2259 ///
   2260 /// @param[in]  d  Dictionary to check.
   2261 /// @param[in]  key  Dictionary key.
   2262 ///
   2263 /// @return whether the key is present in the dictionary.
   2264 bool tv_dict_has_key(const dict_T *const d, const char *const key)
   2265  FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   2266 {
   2267  return tv_dict_find(d, key, -1) != NULL;
   2268 }
   2269 
   2270 /// Get a typval item from a dictionary and copy it into "rettv".
   2271 ///
   2272 /// @param[in]  d  Dictionary to check.
   2273 /// @param[in]  key  Dictionary key.
   2274 /// @param[in]  rettv  Return value.
   2275 /// @return OK in case of success or FAIL if nothing was found.
   2276 int tv_dict_get_tv(dict_T *d, const char *const key, typval_T *rettv)
   2277 {
   2278  dictitem_T *const di = tv_dict_find(d, key, -1);
   2279  if (di == NULL) {
   2280    return FAIL;
   2281  }
   2282 
   2283  tv_copy(&di->di_tv, rettv);
   2284  return OK;
   2285 }
   2286 
   2287 /// Gets a number item from a dictionary.
   2288 ///
   2289 /// @param[in]  d  Dictionary to get item from.
   2290 /// @param[in]  key  Key to find in dictionary.
   2291 ///
   2292 /// @return Number value, or 0 if the item does not exist.
   2293 varnumber_T tv_dict_get_number(const dict_T *const d, const char *const key)
   2294  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   2295 {
   2296  return tv_dict_get_number_def(d, key, 0);
   2297 }
   2298 
   2299 /// Gets a number item from a dictionary, or a given default value.
   2300 ///
   2301 /// @param[in]  d  Dictionary to get item from.
   2302 /// @param[in]  key  Key to find in dictionary.
   2303 /// @param[in]  def  Default value.
   2304 ///
   2305 /// @return Number value, or `def` value if the item does not exist.
   2306 varnumber_T tv_dict_get_number_def(const dict_T *const d, const char *const key, const int def)
   2307  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   2308 {
   2309  dictitem_T *const di = tv_dict_find(d, key, -1);
   2310  if (di == NULL) {
   2311    return def;
   2312  }
   2313  return tv_get_number(&di->di_tv);
   2314 }
   2315 
   2316 varnumber_T tv_dict_get_bool(const dict_T *const d, const char *const key, const int def)
   2317  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   2318 {
   2319  dictitem_T *const di = tv_dict_find(d, key, -1);
   2320  if (di == NULL) {
   2321    return def;
   2322  }
   2323  return tv_get_bool(&di->di_tv);
   2324 }
   2325 
   2326 /// Converts a dict to an environment
   2327 char **tv_dict_to_env(dict_T *denv)
   2328 {
   2329  size_t env_size = (size_t)tv_dict_len(denv);
   2330 
   2331  size_t i = 0;
   2332  char **env = NULL;
   2333 
   2334  // + 1 for NULL
   2335  env = xmalloc((env_size + 1) * sizeof(*env));
   2336 
   2337  TV_DICT_ITER(denv, var, {
   2338    const char *str = tv_get_string(&var->di_tv);
   2339    assert(str);
   2340    size_t len = strlen(var->di_key) + strlen(str) + strlen("=") + 1;
   2341    env[i] = xmalloc(len);
   2342    snprintf(env[i], len, "%s=%s", var->di_key, str);
   2343    i++;
   2344  });
   2345 
   2346  // must be null terminated
   2347  env[env_size] = NULL;
   2348  return env;
   2349 }
   2350 
   2351 /// Get a string item from a dictionary
   2352 ///
   2353 /// @param[in]  d  Dictionary to get item from.
   2354 /// @param[in]  key  Dictionary key.
   2355 /// @param[in]  save  If true, returned string will be placed in the allocated
   2356 ///                   memory.
   2357 ///
   2358 /// @return NULL if key does not exist, empty string in case of type error,
   2359 ///         string item value otherwise. If returned value is not NULL, it may
   2360 ///         be allocated depending on `save` argument.
   2361 char *tv_dict_get_string(const dict_T *const d, const char *const key, const bool save)
   2362  FUNC_ATTR_WARN_UNUSED_RESULT
   2363 {
   2364  static char numbuf[NUMBUFLEN];
   2365  const char *const s = tv_dict_get_string_buf(d, key, numbuf);
   2366  if (save && s != NULL) {
   2367    return xstrdup(s);
   2368  }
   2369  return (char *)s;
   2370 }
   2371 
   2372 /// Get a string item from a dictionary
   2373 ///
   2374 /// @param[in]  d  Dictionary to get item from.
   2375 /// @param[in]  key  Dictionary key.
   2376 /// @param[in]  numbuf  Buffer for non-string items converted to strings, at
   2377 ///                     least of #NUMBUFLEN length.
   2378 ///
   2379 /// @return NULL if key does not exist, empty string in case of type error,
   2380 ///         string item value otherwise.
   2381 const char *tv_dict_get_string_buf(const dict_T *const d, const char *const key, char *const numbuf)
   2382  FUNC_ATTR_WARN_UNUSED_RESULT
   2383 {
   2384  const dictitem_T *const di = tv_dict_find(d, key, -1);
   2385  if (di == NULL) {
   2386    return NULL;
   2387  }
   2388  return tv_get_string_buf(&di->di_tv, numbuf);
   2389 }
   2390 
   2391 /// Get a string item from a dictionary
   2392 ///
   2393 /// @param[in]  d  Dictionary to get item from.
   2394 /// @param[in]  key  Dictionary key.
   2395 /// @param[in]  key_len  Key length.
   2396 /// @param[in]  numbuf  Buffer for non-string items converted to strings, at
   2397 ///                     least of #NUMBUFLEN length.
   2398 /// @param[in]  def  Default return when key does not exist.
   2399 ///
   2400 /// @return `def` when key does not exist,
   2401 ///         NULL in case of type error,
   2402 ///         string item value in case of success.
   2403 const char *tv_dict_get_string_buf_chk(const dict_T *const d, const char *const key,
   2404                                       const ptrdiff_t key_len, char *const numbuf,
   2405                                       const char *const def)
   2406  FUNC_ATTR_WARN_UNUSED_RESULT
   2407 {
   2408  const dictitem_T *const di = tv_dict_find(d, key, key_len);
   2409  if (di == NULL) {
   2410    return def;
   2411  }
   2412  return tv_get_string_buf_chk(&di->di_tv, numbuf);
   2413 }
   2414 
   2415 /// Get a function from a dictionary
   2416 ///
   2417 /// @param[in]  d  Dictionary to get callback from.
   2418 /// @param[in]  key  Dictionary key.
   2419 /// @param[in]  key_len  Key length, may be -1 to use strlen().
   2420 /// @param[out]  result  The address where a pointer to the wanted callback
   2421 ///                      will be left.
   2422 ///
   2423 /// @return true/false on success/failure.
   2424 bool tv_dict_get_callback(dict_T *const d, const char *const key, const ptrdiff_t key_len,
   2425                          Callback *const result)
   2426  FUNC_ATTR_NONNULL_ARG(2, 4) FUNC_ATTR_WARN_UNUSED_RESULT
   2427 {
   2428  result->type = kCallbackNone;
   2429 
   2430  dictitem_T *const di = tv_dict_find(d, key, key_len);
   2431 
   2432  if (di == NULL) {
   2433    return true;
   2434  }
   2435 
   2436  if (!tv_is_func(di->di_tv) && di->di_tv.v_type != VAR_STRING) {
   2437    emsg(_("E6000: Argument is not a function or function name"));
   2438    return false;
   2439  }
   2440 
   2441  typval_T tv;
   2442  tv_copy(&di->di_tv, &tv);
   2443  set_selfdict(&tv, d);
   2444  const bool res = callback_from_typval(result, &tv);
   2445  tv_clear(&tv);
   2446  return res;
   2447 }
   2448 
   2449 /// Check for adding a function to g: or l:.
   2450 /// If the name is wrong give an error message and return true.
   2451 int tv_dict_wrong_func_name(dict_T *d, typval_T *tv, const char *name)
   2452 {
   2453  return (d == get_globvar_dict() || &d->dv_hashtab == get_funccal_local_ht())
   2454         && tv_is_func(*tv)
   2455         && var_wrong_func_name(name, true);
   2456 }
   2457 
   2458 // dict_add*:
   2459 
   2460 /// Add item to dictionary
   2461 ///
   2462 /// @param[out]  d  Dictionary to add to.
   2463 /// @param[in]  item  Item to add.
   2464 ///
   2465 /// @return FAIL if key already exists.
   2466 int tv_dict_add(dict_T *const d, dictitem_T *const item)
   2467  FUNC_ATTR_NONNULL_ALL
   2468 {
   2469  if (tv_dict_wrong_func_name(d, &item->di_tv, item->di_key)) {
   2470    return FAIL;
   2471  }
   2472  return hash_add(&d->dv_hashtab, item->di_key);
   2473 }
   2474 
   2475 /// Add a list entry to dictionary
   2476 ///
   2477 /// @param[out]  d  Dictionary to add entry to.
   2478 /// @param[in]  key  Key to add.
   2479 /// @param[in]  key_len  Key length.
   2480 /// @param  list  List to add. Will have reference count incremented.
   2481 ///
   2482 /// @return OK in case of success, FAIL when key already exists.
   2483 int tv_dict_add_list(dict_T *const d, const char *const key, const size_t key_len,
   2484                     list_T *const list)
   2485  FUNC_ATTR_NONNULL_ALL
   2486 {
   2487  dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
   2488 
   2489  item->di_tv.v_type = VAR_LIST;
   2490  item->di_tv.vval.v_list = list;
   2491  tv_list_ref(list);
   2492  if (tv_dict_add(d, item) == FAIL) {
   2493    tv_dict_item_free(item);
   2494    return FAIL;
   2495  }
   2496  return OK;
   2497 }
   2498 
   2499 /// Add a typval entry to dictionary.
   2500 ///
   2501 /// @param[out]  d  Dictionary to add entry to.
   2502 /// @param[in]  key  Key to add.
   2503 /// @param[in]  key_len  Key length.
   2504 ///
   2505 /// @return FAIL if out of memory or key already exists.
   2506 int tv_dict_add_tv(dict_T *d, const char *key, const size_t key_len, typval_T *tv)
   2507 {
   2508  dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
   2509 
   2510  tv_copy(tv, &item->di_tv);
   2511  if (tv_dict_add(d, item) == FAIL) {
   2512    tv_dict_item_free(item);
   2513    return FAIL;
   2514  }
   2515  return OK;
   2516 }
   2517 
   2518 /// Add a dictionary entry to dictionary
   2519 ///
   2520 /// @param[out]  d  Dictionary to add entry to.
   2521 /// @param[in]  key  Key to add.
   2522 /// @param[in]  key_len  Key length.
   2523 /// @param  dict  Dictionary to add. Will have reference count incremented.
   2524 ///
   2525 /// @return OK in case of success, FAIL when key already exists.
   2526 int tv_dict_add_dict(dict_T *const d, const char *const key, const size_t key_len,
   2527                     dict_T *const dict)
   2528  FUNC_ATTR_NONNULL_ALL
   2529 {
   2530  dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
   2531 
   2532  item->di_tv.v_type = VAR_DICT;
   2533  item->di_tv.vval.v_dict = dict;
   2534  dict->dv_refcount++;
   2535  if (tv_dict_add(d, item) == FAIL) {
   2536    tv_dict_item_free(item);
   2537    return FAIL;
   2538  }
   2539  return OK;
   2540 }
   2541 
   2542 /// Add a number entry to dictionary
   2543 ///
   2544 /// @param[out]  d  Dictionary to add entry to.
   2545 /// @param[in]  key  Key to add.
   2546 /// @param[in]  key_len  Key length.
   2547 /// @param[in]  nr  Number to add.
   2548 ///
   2549 /// @return OK in case of success, FAIL when key already exists.
   2550 int tv_dict_add_nr(dict_T *const d, const char *const key, const size_t key_len,
   2551                   const varnumber_T nr)
   2552 {
   2553  dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
   2554 
   2555  item->di_tv.v_type = VAR_NUMBER;
   2556  item->di_tv.vval.v_number = nr;
   2557  if (tv_dict_add(d, item) == FAIL) {
   2558    tv_dict_item_free(item);
   2559    return FAIL;
   2560  }
   2561  return OK;
   2562 }
   2563 
   2564 /// Add a floating point number entry to dictionary
   2565 ///
   2566 /// @param[out]  d  Dictionary to add entry to.
   2567 /// @param[in]  key  Key to add.
   2568 /// @param[in]  key_len  Key length.
   2569 /// @param[in]  nr  Floating point number to add.
   2570 ///
   2571 /// @return OK in case of success, FAIL when key already exists.
   2572 int tv_dict_add_float(dict_T *const d, const char *const key, const size_t key_len,
   2573                      const float_T nr)
   2574 {
   2575  dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
   2576 
   2577  item->di_tv.v_type = VAR_FLOAT;
   2578  item->di_tv.vval.v_float = nr;
   2579  if (tv_dict_add(d, item) == FAIL) {
   2580    tv_dict_item_free(item);
   2581    return FAIL;
   2582  }
   2583  return OK;
   2584 }
   2585 
   2586 /// Add a boolean entry to dictionary
   2587 ///
   2588 /// @param[out]  d  Dictionary to add entry to.
   2589 /// @param[in]  key  Key to add.
   2590 /// @param[in]  key_len  Key length.
   2591 /// @param[in]  val BoolVarValue to add.
   2592 ///
   2593 /// @return OK in case of success, FAIL when key already exists.
   2594 int tv_dict_add_bool(dict_T *const d, const char *const key, const size_t key_len, BoolVarValue val)
   2595 {
   2596  dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
   2597 
   2598  item->di_tv.v_type = VAR_BOOL;
   2599  item->di_tv.vval.v_bool = val;
   2600  if (tv_dict_add(d, item) == FAIL) {
   2601    tv_dict_item_free(item);
   2602    return FAIL;
   2603  }
   2604  return OK;
   2605 }
   2606 
   2607 /// Add a string entry to dictionary
   2608 ///
   2609 /// @see tv_dict_add_allocated_str
   2610 int tv_dict_add_str(dict_T *const d, const char *const key, const size_t key_len,
   2611                    const char *const val)
   2612  FUNC_ATTR_NONNULL_ARG(1, 2)
   2613 {
   2614  return tv_dict_add_str_len(d, key, key_len, val, -1);
   2615 }
   2616 
   2617 /// Add a string entry to dictionary
   2618 ///
   2619 /// @param[out]  d  Dictionary to add entry to.
   2620 /// @param[in]  key  Key to add.
   2621 /// @param[in]  key_len  Key length.
   2622 /// @param[in]  val  String to add. NULL adds empty string.
   2623 /// @param[in]  len  Use this many bytes from `val`, or -1 for whole string.
   2624 ///
   2625 /// @return OK in case of success, FAIL when key already exists.
   2626 int tv_dict_add_str_len(dict_T *const d, const char *const key, const size_t key_len,
   2627                        const char *const val, int len)
   2628  FUNC_ATTR_NONNULL_ARG(1, 2)
   2629 {
   2630  char *s = NULL;
   2631  if (val != NULL) {
   2632    s = (len < 0) ? xstrdup(val) : xstrndup(val, (size_t)len);
   2633  }
   2634  return tv_dict_add_allocated_str(d, key, key_len, s);
   2635 }
   2636 
   2637 /// Add a string entry to dictionary
   2638 ///
   2639 /// Unlike tv_dict_add_str() saves val to the new dictionary item in place of
   2640 /// creating a new copy.
   2641 ///
   2642 /// @warning String will be freed even in case addition fails.
   2643 ///
   2644 /// @param[out]  d  Dictionary to add entry to.
   2645 /// @param[in]  key  Key to add.
   2646 /// @param[in]  key_len  Key length.
   2647 /// @param[in]  val  String to add.
   2648 ///
   2649 /// @return OK in case of success, FAIL when key already exists.
   2650 int tv_dict_add_allocated_str(dict_T *const d, const char *const key, const size_t key_len,
   2651                              char *const val)
   2652  FUNC_ATTR_NONNULL_ARG(1, 2)
   2653 {
   2654  dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
   2655 
   2656  item->di_tv.v_type = VAR_STRING;
   2657  item->di_tv.vval.v_string = val;
   2658  if (tv_dict_add(d, item) == FAIL) {
   2659    tv_dict_item_free(item);
   2660    return FAIL;
   2661  }
   2662  return OK;
   2663 }
   2664 
   2665 /// Add a function entry to dictionary.
   2666 ///
   2667 /// @param[out]  d  Dictionary to add entry to.
   2668 /// @param[in]  key  Key to add.
   2669 /// @param[in]  key_len  Key length.
   2670 /// @param[in]  fp  Function to add.
   2671 ///
   2672 /// @return OK in case of success, FAIL when key already exists.
   2673 int tv_dict_add_func(dict_T *const d, const char *const key, const size_t key_len,
   2674                     ufunc_T *const fp)
   2675  FUNC_ATTR_NONNULL_ARG(1, 2, 4)
   2676 {
   2677  dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
   2678 
   2679  item->di_tv.v_type = VAR_FUNC;
   2680  item->di_tv.vval.v_string = xmemdupz(fp->uf_name, fp->uf_namelen);
   2681  if (tv_dict_add(d, item) == FAIL) {
   2682    tv_dict_item_free(item);
   2683    return FAIL;
   2684  }
   2685  func_ref(item->di_tv.vval.v_string);
   2686  return OK;
   2687 }
   2688 
   2689 // Operations on the whole dict:
   2690 
   2691 /// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary.
   2692 ///
   2693 /// @param  d  The Dictionary to clear
   2694 void tv_dict_clear(dict_T *const d)
   2695  FUNC_ATTR_NONNULL_ALL
   2696 {
   2697  hash_lock(&d->dv_hashtab);
   2698  assert(d->dv_hashtab.ht_locked > 0);
   2699 
   2700  HASHTAB_ITER(&d->dv_hashtab, hi, {
   2701    tv_dict_item_free(TV_DICT_HI2DI(hi));
   2702    hash_remove(&d->dv_hashtab, hi);
   2703  });
   2704 
   2705  hash_unlock(&d->dv_hashtab);
   2706 }
   2707 
   2708 /// Extend dictionary with items from another dictionary
   2709 ///
   2710 /// @param  d1  Dictionary to extend.
   2711 /// @param[in]  d2  Dictionary to extend with.
   2712 /// @param[in]  action  "error", "force", "move", "keep":
   2713 ///                     e*, including "error": duplicate key gives an error.
   2714 ///                     f*, including "force": duplicate d2 keys override d1.
   2715 ///                     m*, including "move": move items instead of copying.
   2716 ///                     other, including "keep": duplicate d2 keys ignored.
   2717 void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action)
   2718  FUNC_ATTR_NONNULL_ALL
   2719 {
   2720  const bool watched = tv_dict_is_watched(d1);
   2721  const char *const arg_errmsg = _("extend() argument");
   2722  const size_t arg_errmsg_len = strlen(arg_errmsg);
   2723 
   2724  if (*action == 'm') {
   2725    hash_lock(&d2->dv_hashtab);  // don't rehash on hash_remove()
   2726  }
   2727 
   2728  HASHTAB_ITER(&d2->dv_hashtab, hi2, {
   2729    dictitem_T *const di2 = TV_DICT_HI2DI(hi2);
   2730    dictitem_T *const di1 = tv_dict_find(d1, di2->di_key, -1);
   2731    // Check the key to be valid when adding to any scope.
   2732    if (d1->dv_scope != VAR_NO_SCOPE && !valid_varname(di2->di_key)) {
   2733      break;
   2734    }
   2735    if (di1 == NULL) {
   2736      if (*action == 'm') {
   2737        // Cheap way to move a dict item from "d2" to "d1".
   2738        // If dict_add() fails then "d2" won't be empty.
   2739        dictitem_T *const new_di = di2;
   2740        if (tv_dict_add(d1, new_di) == OK) {
   2741          hash_remove(&d2->dv_hashtab, hi2);
   2742          tv_dict_watcher_notify(d1, new_di->di_key, &new_di->di_tv, NULL);
   2743        }
   2744      } else {
   2745        dictitem_T *const new_di = tv_dict_item_copy(di2);
   2746        if (tv_dict_add(d1, new_di) == FAIL) {
   2747          tv_dict_item_free(new_di);
   2748        } else if (watched) {
   2749          tv_dict_watcher_notify(d1, new_di->di_key, &new_di->di_tv, NULL);
   2750        }
   2751      }
   2752    } else if (*action == 'e') {
   2753      semsg(_("E737: Key already exists: %s"), di2->di_key);
   2754      break;
   2755    } else if (*action == 'f' && di2 != di1) {
   2756      typval_T oldtv;
   2757 
   2758      if (value_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len)
   2759          || var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) {
   2760        break;
   2761      }
   2762      // Disallow replacing a builtin function.
   2763      if (tv_dict_wrong_func_name(d1, &di2->di_tv, di2->di_key)) {
   2764        break;
   2765      }
   2766 
   2767      if (watched) {
   2768        tv_copy(&di1->di_tv, &oldtv);
   2769      }
   2770 
   2771      tv_clear(&di1->di_tv);
   2772      tv_copy(&di2->di_tv, &di1->di_tv);
   2773 
   2774      if (watched) {
   2775        tv_dict_watcher_notify(d1, di1->di_key, &di1->di_tv, &oldtv);
   2776        tv_clear(&oldtv);
   2777      }
   2778    }
   2779  });
   2780 
   2781  if (*action == 'm') {
   2782    hash_unlock(&d2->dv_hashtab);
   2783  }
   2784 }
   2785 
   2786 /// Compare two dictionaries
   2787 ///
   2788 /// @param[in]  d1  First dictionary.
   2789 /// @param[in]  d2  Second dictionary.
   2790 /// @param[in]  ic  True if case is to be ignored.
   2791 ///
   2792 /// @return True if dictionaries are equal, false otherwise.
   2793 bool tv_dict_equal(dict_T *const d1, dict_T *const d2, const bool ic)
   2794  FUNC_ATTR_WARN_UNUSED_RESULT
   2795 {
   2796  if (d1 == d2) {
   2797    return true;
   2798  }
   2799  if (tv_dict_len(d1) != tv_dict_len(d2)) {
   2800    return false;
   2801  }
   2802  if (tv_dict_len(d1) == 0) {
   2803    // empty and NULL dicts are considered equal
   2804    return true;
   2805  }
   2806  if (d1 == NULL || d2 == NULL) {
   2807    return false;
   2808  }
   2809 
   2810  TV_DICT_ITER(d1, di1, {
   2811    dictitem_T *const di2 = tv_dict_find(d2, di1->di_key, -1);
   2812    if (di2 == NULL) {
   2813      return false;
   2814    }
   2815    if (!tv_equal(&di1->di_tv, &di2->di_tv, ic)) {
   2816      return false;
   2817    }
   2818  });
   2819  return true;
   2820 }
   2821 
   2822 /// Make a copy of dictionary
   2823 ///
   2824 /// @param[in]  conv  If non-NULL, then all internal strings will be converted.
   2825 /// @param[in]  orig  Original dictionary to copy.
   2826 /// @param[in]  deep  If false, then shallow copy will be done.
   2827 /// @param[in]  copyID  See var_item_copy().
   2828 ///
   2829 /// @return Copied dictionary. May be NULL in case original dictionary is NULL
   2830 ///         or some failure happens. The refcount of the new dictionary is set
   2831 ///         to 1.
   2832 dict_T *tv_dict_copy(const vimconv_T *const conv, dict_T *const orig, const bool deep,
   2833                     const int copyID)
   2834 {
   2835  if (orig == NULL) {
   2836    return NULL;
   2837  }
   2838 
   2839  dict_T *copy = tv_dict_alloc();
   2840  if (copyID != 0) {
   2841    orig->dv_copyID = copyID;
   2842    orig->dv_copydict = copy;
   2843  }
   2844  TV_DICT_ITER(orig, di, {
   2845    if (got_int) {
   2846      break;
   2847    }
   2848    dictitem_T *new_di;
   2849    if (conv == NULL || conv->vc_type == CONV_NONE) {
   2850      new_di = tv_dict_item_alloc(di->di_key);
   2851    } else {
   2852      size_t len = strlen(di->di_key);
   2853      char *const key = string_convert(conv, di->di_key, &len);
   2854      if (key == NULL) {
   2855        new_di = tv_dict_item_alloc_len(di->di_key, len);
   2856      } else {
   2857        new_di = tv_dict_item_alloc_len(key, len);
   2858        xfree(key);
   2859      }
   2860    }
   2861    if (deep) {
   2862      if (var_item_copy(conv, &di->di_tv, &new_di->di_tv, deep,
   2863                        copyID) == FAIL) {
   2864        xfree(new_di);
   2865        break;
   2866      }
   2867    } else {
   2868      tv_copy(&di->di_tv, &new_di->di_tv);
   2869    }
   2870    if (tv_dict_add(copy, new_di) == FAIL) {
   2871      tv_dict_item_free(new_di);
   2872      break;
   2873    }
   2874  });
   2875 
   2876  copy->dv_refcount++;
   2877  if (got_int) {
   2878    tv_dict_unref(copy);
   2879    copy = NULL;
   2880  }
   2881 
   2882  return copy;
   2883 }
   2884 
   2885 /// Set all existing keys in "dict" as read-only.
   2886 ///
   2887 /// This does not protect against adding new keys to the Dictionary.
   2888 ///
   2889 /// @param  dict  The dict whose keys should be frozen.
   2890 void tv_dict_set_keys_readonly(dict_T *const dict)
   2891  FUNC_ATTR_NONNULL_ALL
   2892 {
   2893  TV_DICT_ITER(dict, di, {
   2894    di->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
   2895  });
   2896 }
   2897 
   2898 // Blobs:
   2899 // Alloc/free:
   2900 
   2901 /// Allocate an empty blob.
   2902 ///
   2903 /// Caller should take care of the reference count.
   2904 ///
   2905 /// @return [allocated] new blob.
   2906 blob_T *tv_blob_alloc(void)
   2907  FUNC_ATTR_NONNULL_RET
   2908 {
   2909  blob_T *const blob = xcalloc(1, sizeof(blob_T));
   2910  ga_init(&blob->bv_ga, 1, 100);
   2911  return blob;
   2912 }
   2913 
   2914 /// Free a blob. Ignores the reference count.
   2915 ///
   2916 /// @param[in,out]  b  Blob to free.
   2917 void tv_blob_free(blob_T *const b)
   2918  FUNC_ATTR_NONNULL_ALL
   2919 {
   2920  ga_clear(&b->bv_ga);
   2921  xfree(b);
   2922 }
   2923 
   2924 /// Unreference a blob.
   2925 ///
   2926 /// Decrements the reference count and frees blob when it becomes zero.
   2927 ///
   2928 /// @param[in,out]  b  Blob to operate on.
   2929 void tv_blob_unref(blob_T *const b)
   2930 {
   2931  if (b != NULL && --b->bv_refcount <= 0) {
   2932    tv_blob_free(b);
   2933  }
   2934 }
   2935 
   2936 // Operations on the whole blob:
   2937 
   2938 /// Check whether two blobs are equal.
   2939 ///
   2940 /// @param[in]  b1  First blob.
   2941 /// @param[in]  b2  Second blob.
   2942 ///
   2943 /// @return true if blobs are equal, false otherwise.
   2944 bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2)
   2945  FUNC_ATTR_WARN_UNUSED_RESULT
   2946 {
   2947  const int len1 = tv_blob_len(b1);
   2948  const int len2 = tv_blob_len(b2);
   2949 
   2950  // empty and NULL are considered the same
   2951  if (len1 == 0 && len2 == 0) {
   2952    return true;
   2953  }
   2954  if (b1 == b2) {
   2955    return true;
   2956  }
   2957  if (len1 != len2) {
   2958    return false;
   2959  }
   2960 
   2961  for (int i = 0; i < b1->bv_ga.ga_len; i++) {
   2962    if (tv_blob_get(b1, i) != tv_blob_get(b2, i)) {
   2963      return false;
   2964    }
   2965  }
   2966  return true;
   2967 }
   2968 
   2969 /// Returns a slice of "blob" from index "n1" to "n2" in "rettv".  The length of
   2970 /// the blob is "len".  Returns an empty blob if the indexes are out of range.
   2971 static int tv_blob_slice(const blob_T *blob, int len, varnumber_T n1, varnumber_T n2,
   2972                         bool exclusive, typval_T *rettv)
   2973 {
   2974  // The resulting variable is a sub-blob.  If the indexes
   2975  // are out of range the result is empty.
   2976  if (n1 < 0) {
   2977    n1 = len + n1;
   2978    if (n1 < 0) {
   2979      n1 = 0;
   2980    }
   2981  }
   2982  if (n2 < 0) {
   2983    n2 = len + n2;
   2984  } else if (n2 >= len) {
   2985    n2 = len - (exclusive ? 0 : 1);
   2986  }
   2987  if (exclusive) {
   2988    n2--;
   2989  }
   2990  if (n1 >= len || n2 < 0 || n1 > n2) {
   2991    tv_clear(rettv);
   2992    rettv->v_type = VAR_BLOB;
   2993    rettv->vval.v_blob = NULL;
   2994  } else {
   2995    blob_T *const new_blob = tv_blob_alloc();
   2996    ga_grow(&new_blob->bv_ga, (int)(n2 - n1 + 1));
   2997    new_blob->bv_ga.ga_len = (int)(n2 - n1 + 1);
   2998    for (int i = (int)n1; i <= (int)n2; i++) {
   2999      tv_blob_set(new_blob, i - (int)n1, tv_blob_get(rettv->vval.v_blob, i));
   3000    }
   3001    tv_clear(rettv);
   3002    tv_blob_set_ret(rettv, new_blob);
   3003  }
   3004 
   3005  return OK;
   3006 }
   3007 
   3008 /// Return the byte value in "blob" at index "idx" in "rettv".  If the index is
   3009 /// too big or negative that is an error.  The length of the blob is "len".
   3010 static int tv_blob_index(const blob_T *blob, int len, varnumber_T idx, typval_T *rettv)
   3011 {
   3012  // The resulting variable is a byte value.
   3013  // If the index is too big or negative that is an error.
   3014  if (idx < 0) {
   3015    idx = len + idx;
   3016  }
   3017  if (idx < len && idx >= 0) {
   3018    const int v = (int)tv_blob_get(rettv->vval.v_blob, (int)idx);
   3019    tv_clear(rettv);
   3020    rettv->v_type = VAR_NUMBER;
   3021    rettv->vval.v_number = v;
   3022  } else {
   3023    semsg(_(e_blobidx), idx);
   3024    return FAIL;
   3025  }
   3026 
   3027  return OK;
   3028 }
   3029 
   3030 int tv_blob_slice_or_index(const blob_T *blob, bool is_range, varnumber_T n1, varnumber_T n2,
   3031                           bool exclusive, typval_T *rettv)
   3032 {
   3033  int len = tv_blob_len(rettv->vval.v_blob);
   3034 
   3035  if (is_range) {
   3036    return tv_blob_slice(blob, len, n1, n2, exclusive, rettv);
   3037  } else {
   3038    return tv_blob_index(blob, len, n1, rettv);
   3039  }
   3040 }
   3041 
   3042 /// Check if "n1" is a valid index for a blob with length "bloblen".
   3043 int tv_blob_check_index(int bloblen, varnumber_T n1, bool quiet)
   3044 {
   3045  if (n1 < 0 || n1 > bloblen) {
   3046    if (!quiet) {
   3047      semsg(_(e_blobidx), n1);
   3048    }
   3049    return FAIL;
   3050  }
   3051  return OK;
   3052 }
   3053 
   3054 /// Check if "n1"-"n2" is a valid range for a blob with length "bloblen".
   3055 int tv_blob_check_range(int bloblen, varnumber_T n1, varnumber_T n2, bool quiet)
   3056 {
   3057  if (n2 < 0 || n2 >= bloblen || n2 < n1) {
   3058    if (!quiet) {
   3059      semsg(_(e_blobidx), n2);
   3060    }
   3061    return FAIL;
   3062  }
   3063  return OK;
   3064 }
   3065 
   3066 /// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src".
   3067 /// Caller must make sure "src" is a blob.
   3068 /// Returns FAIL if the number of bytes does not match.
   3069 int tv_blob_set_range(blob_T *dest, varnumber_T n1, varnumber_T n2, typval_T *src)
   3070 {
   3071  if (n2 - n1 + 1 != tv_blob_len(src->vval.v_blob)) {
   3072    emsg(_("E972: Blob value does not have the right number of bytes"));
   3073    return FAIL;
   3074  }
   3075 
   3076  for (int il = (int)n1, ir = 0; il <= (int)n2; il++) {
   3077    tv_blob_set(dest, il, tv_blob_get(src->vval.v_blob, ir++));
   3078  }
   3079  return OK;
   3080 }
   3081 
   3082 /// Store one byte "byte" in blob "blob" at "idx".
   3083 /// Append one byte if needed.
   3084 void tv_blob_set_append(blob_T *blob, int idx, uint8_t byte)
   3085 {
   3086  garray_T *gap = &blob->bv_ga;
   3087 
   3088  // Allow for appending a byte.  Setting a byte beyond
   3089  // the end is an error otherwise.
   3090  if (idx <= gap->ga_len) {
   3091    if (idx == gap->ga_len) {
   3092      ga_grow(gap, 1);
   3093      gap->ga_len++;
   3094    }
   3095    tv_blob_set(blob, idx, byte);
   3096  }
   3097 }
   3098 
   3099 /// "remove({blob})" function
   3100 void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
   3101 {
   3102  blob_T *const b = argvars[0].vval.v_blob;
   3103 
   3104  if (b != NULL && value_check_lock(b->bv_lock, arg_errmsg, TV_TRANSLATE)) {
   3105    return;
   3106  }
   3107 
   3108  bool error = false;
   3109  int64_t idx = tv_get_number_chk(&argvars[1], &error);
   3110 
   3111  if (!error) {
   3112    const int len = tv_blob_len(b);
   3113 
   3114    if (idx < 0) {
   3115      // count from the end
   3116      idx = len + idx;
   3117    }
   3118    if (idx < 0 || idx >= len) {
   3119      semsg(_(e_blobidx), idx);
   3120      return;
   3121    }
   3122    if (argvars[2].v_type == VAR_UNKNOWN) {
   3123      // Remove one item, return its value.
   3124      uint8_t *const p = (uint8_t *)b->bv_ga.ga_data;
   3125      rettv->vval.v_number = (varnumber_T)(*(p + idx));
   3126      memmove(p + idx, p + idx + 1, (size_t)(len - idx - 1));
   3127      b->bv_ga.ga_len--;
   3128    } else {
   3129      // Remove range of items, return blob with values.
   3130      int64_t end = tv_get_number_chk(&argvars[2], &error);
   3131      if (error) {
   3132        return;
   3133      }
   3134      if (end < 0) {
   3135        // count from the end
   3136        end = len + end;
   3137      }
   3138      if (end >= len || idx > end) {
   3139        semsg(_(e_blobidx), end);
   3140        return;
   3141      }
   3142      blob_T *const blob = tv_blob_alloc();
   3143      blob->bv_ga.ga_len = (int)(end - idx + 1);
   3144      ga_grow(&blob->bv_ga, (int)(end - idx + 1));
   3145 
   3146      uint8_t *const p = (uint8_t *)b->bv_ga.ga_data;
   3147      memmove(blob->bv_ga.ga_data, p + idx, (size_t)(end - idx + 1));
   3148      tv_blob_set_ret(rettv, blob);
   3149 
   3150      if (len - end - 1 > 0) {
   3151        memmove(p + idx, p + end + 1, (size_t)(len - end - 1));
   3152      }
   3153      b->bv_ga.ga_len -= (int)(end - idx + 1);
   3154    }
   3155  }
   3156 }
   3157 
   3158 /// blob2list() function
   3159 void f_blob2list(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3160 {
   3161  tv_list_alloc_ret(rettv, kListLenMayKnow);
   3162 
   3163  if (tv_check_for_blob_arg(argvars, 0) == FAIL) {
   3164    return;
   3165  }
   3166 
   3167  blob_T *const blob = argvars->vval.v_blob;
   3168  list_T *const l = rettv->vval.v_list;
   3169  for (int i = 0; i < tv_blob_len(blob); i++) {
   3170    tv_list_append_number(l, tv_blob_get(blob, i));
   3171  }
   3172 }
   3173 
   3174 /// list2blob() function
   3175 void f_list2blob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3176 {
   3177  blob_T *blob = tv_blob_alloc_ret(rettv);
   3178 
   3179  if (tv_check_for_list_arg(argvars, 0) == FAIL) {
   3180    return;
   3181  }
   3182 
   3183  list_T *const l = argvars->vval.v_list;
   3184  if (l == NULL) {
   3185    return;
   3186  }
   3187 
   3188  TV_LIST_ITER_CONST(l, li, {
   3189    bool error = false;
   3190    varnumber_T n = tv_get_number_chk(TV_LIST_ITEM_TV(li), &error);
   3191    if (error || n < 0 || n > 255) {
   3192      if (!error) {
   3193        semsg(_(e_invalid_value_for_blob_nr), (int)n);
   3194      }
   3195      ga_clear(&blob->bv_ga);
   3196      return;
   3197    }
   3198    ga_append(&blob->bv_ga, (uint8_t)n);
   3199  });
   3200 }
   3201 
   3202 // Generic typval operations:
   3203 // Init/alloc/clear:
   3204 // Alloc:
   3205 
   3206 /// Allocate an empty list for a return value
   3207 ///
   3208 /// Also sets reference count.
   3209 ///
   3210 /// @param[out]  ret_tv  Structure where list is saved.
   3211 /// @param[in]  len  Expected number of items to be populated before list
   3212 ///                  becomes accessible from Vimscript. It is still valid to
   3213 ///                  underpopulate a list, value only controls how many elements
   3214 ///                  will be allocated in advance. @see ListLenSpecials.
   3215 ///
   3216 /// @return [allocated] pointer to the created list.
   3217 list_T *tv_list_alloc_ret(typval_T *const ret_tv, const ptrdiff_t len)
   3218  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
   3219 {
   3220  list_T *const l = tv_list_alloc(len);
   3221  tv_list_set_ret(ret_tv, l);
   3222  ret_tv->v_lock = VAR_UNLOCKED;
   3223  return l;
   3224 }
   3225 
   3226 dict_T *tv_dict_alloc_lock(VarLockStatus lock)
   3227  FUNC_ATTR_NONNULL_RET
   3228 {
   3229  dict_T *const d = tv_dict_alloc();
   3230  d->dv_lock = lock;
   3231  return d;
   3232 }
   3233 
   3234 /// Allocate an empty dictionary for a return value
   3235 ///
   3236 /// Also sets reference count.
   3237 ///
   3238 /// @param[out]  ret_tv  Structure where dictionary is saved.
   3239 void tv_dict_alloc_ret(typval_T *const ret_tv)
   3240  FUNC_ATTR_NONNULL_ALL
   3241 {
   3242  dict_T *const d = tv_dict_alloc_lock(VAR_UNLOCKED);
   3243  tv_dict_set_ret(ret_tv, d);
   3244 }
   3245 
   3246 /// Turn a dictionary into a list
   3247 ///
   3248 /// @param[in] argvars Arguments to items(). The first argument is check for being
   3249 ///                    a dictionary, will give an error if not.
   3250 /// @param[out] rettv  Location where result will be saved.
   3251 /// @param[in] what    What to save in rettv.
   3252 static void tv_dict2list(typval_T *const argvars, typval_T *const rettv, const DictListType what)
   3253 {
   3254  if (tv_check_for_dict_arg(argvars, 0) == FAIL) {
   3255    tv_list_alloc_ret(rettv, 0);
   3256    return;
   3257  }
   3258 
   3259  dict_T *d = argvars[0].vval.v_dict;
   3260  tv_list_alloc_ret(rettv, tv_dict_len(d));
   3261  if (d == NULL) {
   3262    // NULL dict behaves like an empty dict
   3263    return;
   3264  }
   3265 
   3266  TV_DICT_ITER(d, di, {
   3267    typval_T tv_item = { .v_lock = VAR_UNLOCKED };
   3268 
   3269    switch (what) {
   3270      case kDict2ListKeys:
   3271        tv_item.v_type = VAR_STRING;
   3272        tv_item.vval.v_string = xstrdup(di->di_key);
   3273        break;
   3274      case kDict2ListValues:
   3275        tv_copy(&di->di_tv, &tv_item);
   3276        break;
   3277      case kDict2ListItems: {
   3278        // items()
   3279        list_T *const sub_l = tv_list_alloc(2);
   3280        tv_item.v_type = VAR_LIST;
   3281        tv_item.vval.v_list = sub_l;
   3282        tv_list_ref(sub_l);
   3283        tv_list_append_string(sub_l, di->di_key, -1);
   3284        tv_list_append_tv(sub_l, &di->di_tv);
   3285        break;
   3286      }
   3287    }
   3288 
   3289    tv_list_append_owned_tv(rettv->vval.v_list, tv_item);
   3290  });
   3291 }
   3292 
   3293 /// "items()" function
   3294 void f_items(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3295 {
   3296  if (argvars[0].v_type == VAR_STRING) {
   3297    tv_string2items(argvars, rettv);
   3298  } else if (argvars[0].v_type == VAR_LIST) {
   3299    tv_list2items(argvars, rettv);
   3300  } else if (argvars[0].v_type == VAR_BLOB) {
   3301    tv_blob2items(argvars, rettv);
   3302  } else if (argvars[0].v_type == VAR_DICT) {
   3303    tv_dict2items(argvars, rettv);
   3304  } else {
   3305    semsg(_(e_list_dict_blob_or_string_required_for_argument_nr), 1);
   3306  }
   3307 }
   3308 
   3309 /// "keys()" function
   3310 void f_keys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3311 {
   3312  tv_dict2list(argvars, rettv, kDict2ListKeys);
   3313 }
   3314 
   3315 /// "values(dict)" function
   3316 void f_values(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3317 {
   3318  tv_dict2list(argvars, rettv, kDict2ListValues);
   3319 }
   3320 
   3321 /// "has_key()" function
   3322 void f_has_key(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3323 {
   3324  if (tv_check_for_dict_arg(argvars, 0) == FAIL) {
   3325    return;
   3326  }
   3327 
   3328  if (argvars[0].vval.v_dict == NULL) {
   3329    return;
   3330  }
   3331 
   3332  rettv->vval.v_number = tv_dict_find(argvars[0].vval.v_dict,
   3333                                      tv_get_string(&argvars[1]),
   3334                                      -1) != NULL;
   3335 }
   3336 
   3337 /// "remove({dict})" function
   3338 void tv_dict_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
   3339 {
   3340  dict_T *d;
   3341  if (argvars[2].v_type != VAR_UNKNOWN) {
   3342    semsg(_(e_toomanyarg), "remove()");
   3343  } else if ((d = argvars[0].vval.v_dict) != NULL
   3344             && !value_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) {
   3345    const char *key = tv_get_string_chk(&argvars[1]);
   3346    if (key != NULL) {
   3347      dictitem_T *di = tv_dict_find(d, key, -1);
   3348      if (di == NULL) {
   3349        semsg(_(e_dictkey), key);
   3350      } else if (!var_check_fixed(di->di_flags, arg_errmsg, TV_TRANSLATE)
   3351                 && !var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE)) {
   3352        *rettv = di->di_tv;
   3353        di->di_tv = TV_INITIAL_VALUE;
   3354        tv_dict_item_remove(d, di);
   3355        if (tv_dict_is_watched(d)) {
   3356          tv_dict_watcher_notify(d, key, NULL, rettv);
   3357        }
   3358      }
   3359    }
   3360  }
   3361 }
   3362 
   3363 /// Allocate an empty blob for a return value.
   3364 ///
   3365 /// Also sets reference count.
   3366 ///
   3367 /// @param[out]  ret_tv  Structure where blob is saved.
   3368 blob_T *tv_blob_alloc_ret(typval_T *const ret_tv)
   3369  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
   3370 {
   3371  blob_T *const b = tv_blob_alloc();
   3372  tv_blob_set_ret(ret_tv, b);
   3373  return b;
   3374 }
   3375 
   3376 /// Copy a blob typval to a different typval.
   3377 ///
   3378 /// @param[in]  from  Blob object to copy from.
   3379 /// @param[out]  to  Blob object to copy to.
   3380 void tv_blob_copy(blob_T *const from, typval_T *const to)
   3381  FUNC_ATTR_NONNULL_ARG(2)
   3382 {
   3383  to->v_type = VAR_BLOB;
   3384  to->v_lock = VAR_UNLOCKED;
   3385  if (from == NULL) {
   3386    to->vval.v_blob = NULL;
   3387  } else {
   3388    tv_blob_alloc_ret(to);
   3389    int len = from->bv_ga.ga_len;
   3390 
   3391    if (len > 0) {
   3392      to->vval.v_blob->bv_ga.ga_data = xmemdup(from->bv_ga.ga_data, (size_t)len);
   3393    }
   3394    to->vval.v_blob->bv_ga.ga_len = len;
   3395    to->vval.v_blob->bv_ga.ga_maxlen = len;
   3396  }
   3397 }
   3398 
   3399 // Clear:
   3400 #define TYPVAL_ENCODE_ALLOW_SPECIALS false
   3401 #define TYPVAL_ENCODE_CHECK_BEFORE
   3402 
   3403 #define TYPVAL_ENCODE_CONV_NIL(tv) \
   3404  do { \
   3405    (tv)->vval.v_special = kSpecialVarNull; \
   3406    (tv)->v_lock = VAR_UNLOCKED; \
   3407  } while (0)
   3408 
   3409 #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
   3410  do { \
   3411    (tv)->vval.v_bool = kBoolVarFalse; \
   3412    (tv)->v_lock = VAR_UNLOCKED; \
   3413  } while (0)
   3414 
   3415 #define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \
   3416  do { \
   3417    (void)(num); \
   3418    (tv)->vval.v_number = 0; \
   3419    (tv)->v_lock = VAR_UNLOCKED; \
   3420  } while (0)
   3421 
   3422 #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num)
   3423 
   3424 #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
   3425  do { \
   3426    (tv)->vval.v_float = 0; \
   3427    (tv)->v_lock = VAR_UNLOCKED; \
   3428  } while (0)
   3429 
   3430 #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \
   3431  do { \
   3432    xfree(buf); \
   3433    (tv)->vval.v_string = NULL; \
   3434    (tv)->v_lock = VAR_UNLOCKED; \
   3435  } while (0)
   3436 
   3437 #define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len)
   3438 
   3439 #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type)
   3440 
   3441 #define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \
   3442  do { \
   3443    tv_blob_unref((tv)->vval.v_blob); \
   3444    (tv)->vval.v_blob = NULL; \
   3445    (tv)->v_lock = VAR_UNLOCKED; \
   3446  } while (0)
   3447 
   3448 static inline int _nothing_conv_func_start(typval_T *const tv, char *const fun)
   3449  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1)
   3450 {
   3451  tv->v_lock = VAR_UNLOCKED;
   3452  if (tv->v_type == VAR_PARTIAL) {
   3453    partial_T *const pt_ = tv->vval.v_partial;
   3454    if (pt_ != NULL && pt_->pt_refcount > 1) {
   3455      pt_->pt_refcount--;
   3456      tv->vval.v_partial = NULL;
   3457      return OK;
   3458    }
   3459  } else {
   3460    func_unref(fun);
   3461    if (fun != tv_empty_string) {
   3462      xfree(fun);
   3463    }
   3464    tv->vval.v_string = NULL;
   3465  }
   3466  return NOTDONE;
   3467 }
   3468 #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun, prefix) \
   3469  do { \
   3470    if (_nothing_conv_func_start(tv, fun) != NOTDONE) { \
   3471      return OK; \
   3472    } \
   3473  } while (0)
   3474 
   3475 #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len)
   3476 #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len)
   3477 
   3478 static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID)
   3479  FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
   3480 {
   3481  if (tv->v_type == VAR_PARTIAL) {
   3482    partial_T *const pt = tv->vval.v_partial;
   3483    if (pt == NULL) {
   3484      return;
   3485    }
   3486    // Dictionary should already be freed by the time.
   3487    // If it was not freed then it is a part of the reference cycle.
   3488    assert(pt->pt_dict == NULL || pt->pt_dict->dv_copyID == copyID);
   3489    pt->pt_dict = NULL;
   3490    // As well as all arguments.
   3491    pt->pt_argc = 0;
   3492    assert(pt->pt_refcount <= 1);
   3493    partial_unref(pt);
   3494    tv->vval.v_partial = NULL;
   3495    assert(tv->v_lock == VAR_UNLOCKED);
   3496  }
   3497 }
   3498 #define TYPVAL_ENCODE_CONV_FUNC_END(tv) _nothing_conv_func_end(tv, copyID)
   3499 
   3500 #define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
   3501  do { \
   3502    tv_list_unref((tv)->vval.v_list); \
   3503    (tv)->vval.v_list = NULL; \
   3504    (tv)->v_lock = VAR_UNLOCKED; \
   3505  } while (0)
   3506 
   3507 static inline void _nothing_conv_empty_dict(typval_T *const tv, dict_T **const dictp)
   3508  FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(2)
   3509 {
   3510  tv_dict_unref(*dictp);
   3511  *dictp = NULL;
   3512  if (tv != NULL) {
   3513    tv->v_lock = VAR_UNLOCKED;
   3514  }
   3515 }
   3516 #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
   3517  do { \
   3518    assert((void *)&(dict) != (void *)&TYPVAL_ENCODE_NODICT_VAR); \
   3519    _nothing_conv_empty_dict(tv, ((dict_T **)&(dict))); \
   3520  } while (0)
   3521 
   3522 static inline int _nothing_conv_real_list_after_start(typval_T *const tv,
   3523                                                      MPConvStackVal *const mpsv)
   3524  FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT
   3525 {
   3526  assert(tv != NULL);
   3527  tv->v_lock = VAR_UNLOCKED;
   3528  if (tv->vval.v_list->lv_refcount > 1) {
   3529    tv->vval.v_list->lv_refcount--;
   3530    tv->vval.v_list = NULL;
   3531    mpsv->data.l.li = NULL;
   3532    return OK;
   3533  }
   3534  return NOTDONE;
   3535 }
   3536 #define TYPVAL_ENCODE_CONV_LIST_START(tv, len)
   3537 
   3538 #define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \
   3539  do { \
   3540    if (_nothing_conv_real_list_after_start(tv, &(mpsv)) != NOTDONE) { \
   3541      goto typval_encode_stop_converting_one_item; \
   3542    } \
   3543  } while (0)
   3544 
   3545 #define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv)
   3546 
   3547 static inline void _nothing_conv_list_end(typval_T *const tv)
   3548  FUNC_ATTR_ALWAYS_INLINE
   3549 {
   3550  if (tv == NULL) {
   3551    return;
   3552  }
   3553  assert(tv->v_type == VAR_LIST);
   3554  list_T *const list = tv->vval.v_list;
   3555  tv_list_unref(list);
   3556  tv->vval.v_list = NULL;
   3557 }
   3558 #define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv)
   3559 
   3560 static inline int _nothing_conv_real_dict_after_start(typval_T *const tv, dict_T **const dictp,
   3561                                                      const void *const nodictvar,
   3562                                                      MPConvStackVal *const mpsv)
   3563  FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT
   3564 {
   3565  if (tv != NULL) {
   3566    tv->v_lock = VAR_UNLOCKED;
   3567  }
   3568  if ((const void *)dictp != nodictvar && (*dictp)->dv_refcount > 1) {
   3569    (*dictp)->dv_refcount--;
   3570    *dictp = NULL;
   3571    mpsv->data.d.todo = 0;
   3572    return OK;
   3573  }
   3574  return NOTDONE;
   3575 }
   3576 #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len)
   3577 
   3578 #define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \
   3579  do { \
   3580    if (_nothing_conv_real_dict_after_start(tv, (dict_T **)&(dict), \
   3581                                            (void *)&TYPVAL_ENCODE_NODICT_VAR, &(mpsv)) \
   3582        != NOTDONE) { \
   3583      goto typval_encode_stop_converting_one_item; \
   3584    } \
   3585  } while (0)
   3586 
   3587 #define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(tv, dict)
   3588 #define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict)
   3589 #define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict)
   3590 
   3591 static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dictp,
   3592                                          const void *const nodictvar)
   3593  FUNC_ATTR_ALWAYS_INLINE
   3594 {
   3595  if ((const void *)dictp != nodictvar) {
   3596    tv_dict_unref(*dictp);
   3597    *dictp = NULL;
   3598  }
   3599 }
   3600 #define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \
   3601  _nothing_conv_dict_end(tv, (dict_T **)&(dict), \
   3602                         (void *)&TYPVAL_ENCODE_NODICT_VAR)
   3603 
   3604 #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type)
   3605 
   3606 #define TYPVAL_ENCODE_SCOPE static
   3607 #define TYPVAL_ENCODE_NAME nothing
   3608 #define TYPVAL_ENCODE_FIRST_ARG_TYPE const void *const
   3609 #define TYPVAL_ENCODE_FIRST_ARG_NAME ignored
   3610 #include "nvim/eval/typval_encode.c.h"
   3611 
   3612 #undef TYPVAL_ENCODE_SCOPE
   3613 #undef TYPVAL_ENCODE_NAME
   3614 #undef TYPVAL_ENCODE_FIRST_ARG_TYPE
   3615 #undef TYPVAL_ENCODE_FIRST_ARG_NAME
   3616 
   3617 #undef TYPVAL_ENCODE_ALLOW_SPECIALS
   3618 #undef TYPVAL_ENCODE_CHECK_BEFORE
   3619 #undef TYPVAL_ENCODE_CONV_NIL
   3620 #undef TYPVAL_ENCODE_CONV_BOOL
   3621 #undef TYPVAL_ENCODE_CONV_NUMBER
   3622 #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
   3623 #undef TYPVAL_ENCODE_CONV_FLOAT
   3624 #undef TYPVAL_ENCODE_CONV_STRING
   3625 #undef TYPVAL_ENCODE_CONV_STR_STRING
   3626 #undef TYPVAL_ENCODE_CONV_EXT_STRING
   3627 #undef TYPVAL_ENCODE_CONV_BLOB
   3628 #undef TYPVAL_ENCODE_CONV_FUNC_START
   3629 #undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS
   3630 #undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF
   3631 #undef TYPVAL_ENCODE_CONV_FUNC_END
   3632 #undef TYPVAL_ENCODE_CONV_EMPTY_LIST
   3633 #undef TYPVAL_ENCODE_CONV_EMPTY_DICT
   3634 #undef TYPVAL_ENCODE_CONV_LIST_START
   3635 #undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
   3636 #undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS
   3637 #undef TYPVAL_ENCODE_CONV_LIST_END
   3638 #undef TYPVAL_ENCODE_CONV_DICT_START
   3639 #undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START
   3640 #undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK
   3641 #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
   3642 #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
   3643 #undef TYPVAL_ENCODE_CONV_DICT_END
   3644 #undef TYPVAL_ENCODE_CONV_RECURSE
   3645 
   3646 /// Free memory for a variable value and set the value to NULL or 0
   3647 ///
   3648 /// @param[in,out]  tv  Value to free.
   3649 void tv_clear(typval_T *const tv)
   3650 {
   3651  if (tv == NULL || tv->v_type == VAR_UNKNOWN) {
   3652    return;
   3653  }
   3654 
   3655  // WARNING: do not translate the string here, gettext is slow and function
   3656  // is used *very* often. At the current state encode_vim_to_nothing() does
   3657  // not error out and does not use the argument anywhere.
   3658  //
   3659  // If situation changes and this argument will be used, translate it in the
   3660  // place where it is used.
   3661  const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument");
   3662  (void)evn_ret;
   3663  assert(evn_ret == OK);
   3664 }
   3665 
   3666 // Free:
   3667 
   3668 /// Free allocated Vimscript object and value stored inside
   3669 ///
   3670 /// @param  tv  Object to free.
   3671 void tv_free(typval_T *tv)
   3672 {
   3673  if (tv == NULL) {
   3674    return;
   3675  }
   3676 
   3677  switch (tv->v_type) {
   3678  case VAR_PARTIAL:
   3679    partial_unref(tv->vval.v_partial);
   3680    break;
   3681  case VAR_FUNC:
   3682    func_unref(tv->vval.v_string);
   3683    FALLTHROUGH;
   3684  case VAR_STRING:
   3685    xfree(tv->vval.v_string);
   3686    break;
   3687  case VAR_BLOB:
   3688    tv_blob_unref(tv->vval.v_blob);
   3689    break;
   3690  case VAR_LIST:
   3691    tv_list_unref(tv->vval.v_list);
   3692    break;
   3693  case VAR_DICT:
   3694    tv_dict_unref(tv->vval.v_dict);
   3695    break;
   3696  case VAR_BOOL:
   3697  case VAR_SPECIAL:
   3698  case VAR_NUMBER:
   3699  case VAR_FLOAT:
   3700  case VAR_UNKNOWN:
   3701    break;
   3702  }
   3703  xfree(tv);
   3704 }
   3705 
   3706 // Copy:
   3707 
   3708 /// Copy typval from one location to another
   3709 ///
   3710 /// When needed allocates string or increases reference count. Does not make
   3711 /// a copy of a container, but copies its reference!
   3712 ///
   3713 /// It is OK for `from` and `to` to point to the same location; this is used to
   3714 /// make a copy later.
   3715 ///
   3716 /// @param[in]  from  Location to copy from.
   3717 /// @param[out]  to  Location to copy to.
   3718 void tv_copy(const typval_T *const from, typval_T *const to)
   3719 {
   3720  to->v_type = from->v_type;
   3721  to->v_lock = VAR_UNLOCKED;
   3722  memmove(&to->vval, &from->vval, sizeof(to->vval));
   3723  switch (from->v_type) {
   3724  case VAR_NUMBER:
   3725  case VAR_FLOAT:
   3726  case VAR_BOOL:
   3727  case VAR_SPECIAL:
   3728    break;
   3729  case VAR_STRING:
   3730  case VAR_FUNC:
   3731    if (from->vval.v_string != NULL) {
   3732      to->vval.v_string = xstrdup(from->vval.v_string);
   3733      if (from->v_type == VAR_FUNC) {
   3734        func_ref(to->vval.v_string);
   3735      }
   3736    }
   3737    break;
   3738  case VAR_PARTIAL:
   3739    if (to->vval.v_partial != NULL) {
   3740      to->vval.v_partial->pt_refcount++;
   3741    }
   3742    break;
   3743  case VAR_BLOB:
   3744    if (from->vval.v_blob != NULL) {
   3745      to->vval.v_blob->bv_refcount++;
   3746    }
   3747    break;
   3748  case VAR_LIST:
   3749    tv_list_ref(to->vval.v_list);
   3750    break;
   3751  case VAR_DICT:
   3752    if (from->vval.v_dict != NULL) {
   3753      to->vval.v_dict->dv_refcount++;
   3754    }
   3755    break;
   3756  case VAR_UNKNOWN:
   3757    semsg(_(e_intern2), "tv_copy(UNKNOWN)");
   3758    break;
   3759  }
   3760 }
   3761 
   3762 // Locks:
   3763 
   3764 /// Lock or unlock an item
   3765 ///
   3766 /// @param[out]  tv  Item to (un)lock.
   3767 /// @param[in]  deep  Levels to (un)lock, -1 to (un)lock everything.
   3768 /// @param[in]  lock  True if it is needed to lock an item, false to unlock.
   3769 /// @param[in]  check_refcount  If true, do not lock a list or dict with a
   3770 ///                             reference count larger than 1.
   3771 void tv_item_lock(typval_T *const tv, const int deep, const bool lock, const bool check_refcount)
   3772  FUNC_ATTR_NONNULL_ALL
   3773 {
   3774  // TODO(ZyX-I): Make this not recursive
   3775  static int recurse = 0;
   3776 
   3777  if (recurse >= DICT_MAXNEST) {
   3778    emsg(_(e_variable_nested_too_deep_for_unlock));
   3779    return;
   3780  }
   3781  if (deep == 0) {
   3782    return;
   3783  }
   3784  recurse++;
   3785 
   3786  // lock/unlock the item itself
   3787 #define CHANGE_LOCK(lock, var) \
   3788  do { \
   3789    (var) = ((VarLockStatus[]) { \
   3790      [VAR_UNLOCKED] = ((lock) ? VAR_LOCKED : VAR_UNLOCKED), \
   3791      [VAR_LOCKED] = ((lock) ? VAR_LOCKED : VAR_UNLOCKED), \
   3792      [VAR_FIXED] = VAR_FIXED, \
   3793    })[var]; \
   3794  } while (0)
   3795  CHANGE_LOCK(lock, tv->v_lock);
   3796 
   3797  switch (tv->v_type) {
   3798  case VAR_BLOB: {
   3799    blob_T *const b = tv->vval.v_blob;
   3800    if (b != NULL && !(check_refcount && b->bv_refcount > 1)) {
   3801      CHANGE_LOCK(lock, b->bv_lock);
   3802    }
   3803    break;
   3804  }
   3805  case VAR_LIST: {
   3806    list_T *const l = tv->vval.v_list;
   3807    if (l != NULL && !(check_refcount && l->lv_refcount > 1)) {
   3808      CHANGE_LOCK(lock, l->lv_lock);
   3809      if (deep < 0 || deep > 1) {
   3810        // Recursive: lock/unlock the items the List contains.
   3811        TV_LIST_ITER(l, li, {
   3812            tv_item_lock(TV_LIST_ITEM_TV(li), deep - 1, lock, check_refcount);
   3813          });
   3814      }
   3815    }
   3816    break;
   3817  }
   3818  case VAR_DICT: {
   3819    dict_T *const d = tv->vval.v_dict;
   3820    if (d != NULL && !(check_refcount && d->dv_refcount > 1)) {
   3821      CHANGE_LOCK(lock, d->dv_lock);
   3822      if (deep < 0 || deep > 1) {
   3823        // recursive: lock/unlock the items the List contains
   3824        TV_DICT_ITER(d, di, {
   3825            tv_item_lock(&di->di_tv, deep - 1, lock, check_refcount);
   3826          });
   3827      }
   3828    }
   3829    break;
   3830  }
   3831  case VAR_NUMBER:
   3832  case VAR_FLOAT:
   3833  case VAR_STRING:
   3834  case VAR_FUNC:
   3835  case VAR_PARTIAL:
   3836  case VAR_BOOL:
   3837  case VAR_SPECIAL:
   3838    break;
   3839  case VAR_UNKNOWN:
   3840    abort();
   3841  }
   3842 #undef CHANGE_LOCK
   3843  recurse--;
   3844 }
   3845 
   3846 /// Check whether Vimscript value is locked itself or refers to a locked container
   3847 ///
   3848 /// @warning Fixed container is not the same as locked.
   3849 ///
   3850 /// @param[in]  tv  Value to check.
   3851 ///
   3852 /// @return True if value is locked, false otherwise.
   3853 bool tv_islocked(const typval_T *const tv)
   3854  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
   3855 {
   3856  return ((tv->v_lock == VAR_LOCKED)
   3857          || (tv->v_type == VAR_LIST
   3858              && (tv_list_locked(tv->vval.v_list) == VAR_LOCKED))
   3859          || (tv->v_type == VAR_DICT
   3860              && tv->vval.v_dict != NULL
   3861              && (tv->vval.v_dict->dv_lock == VAR_LOCKED)));
   3862 }
   3863 
   3864 /// Return true if typval is locked
   3865 ///
   3866 /// Also gives an error message when typval is locked.
   3867 ///
   3868 /// @param[in]  tv  Typval.
   3869 /// @param[in]  name  Variable name, used in the error message.
   3870 /// @param[in]  name_len  Variable name length. Use #TV_TRANSLATE to translate
   3871 ///                       variable name and compute the length. Use #TV_CSTRING
   3872 ///                       to compute the length with strlen() without
   3873 ///                       translating.
   3874 ///
   3875 ///                       Both #TV_… values are used for optimization purposes:
   3876 ///                       variable name with its length is needed only in case
   3877 ///                       of error, when no error occurs computing them is
   3878 ///                       a waste of CPU resources. This especially applies to
   3879 ///                       gettext.
   3880 ///
   3881 /// @return true if variable is locked, false otherwise.
   3882 bool tv_check_lock(const typval_T *tv, const char *name, size_t name_len)
   3883  FUNC_ATTR_WARN_UNUSED_RESULT
   3884 {
   3885  VarLockStatus lock = VAR_UNLOCKED;
   3886 
   3887  switch (tv->v_type) {
   3888  case VAR_BLOB:
   3889    if (tv->vval.v_blob != NULL) {
   3890      lock = tv->vval.v_blob->bv_lock;
   3891    }
   3892    break;
   3893  case VAR_LIST:
   3894    if (tv->vval.v_list != NULL) {
   3895      lock = tv->vval.v_list->lv_lock;
   3896    }
   3897    break;
   3898  case VAR_DICT:
   3899    if (tv->vval.v_dict != NULL) {
   3900      lock = tv->vval.v_dict->dv_lock;
   3901    }
   3902    break;
   3903  default:
   3904    break;
   3905  }
   3906  return value_check_lock(tv->v_lock, name, name_len)
   3907         || (lock != VAR_UNLOCKED && value_check_lock(lock, name, name_len));
   3908 }
   3909 
   3910 /// @return true if variable "name" has a locked (immutable) value
   3911 bool value_check_lock(VarLockStatus lock, const char *name, size_t name_len)
   3912 {
   3913  const char *error_message = NULL;
   3914  switch (lock) {
   3915  case VAR_UNLOCKED:
   3916    return false;
   3917  case VAR_LOCKED:
   3918    error_message = name == NULL ? N_(e_value_is_locked)
   3919                                 : N_(e_value_is_locked_str);
   3920    break;
   3921  case VAR_FIXED:
   3922    error_message = name == NULL ? N_(e_cannot_change_value)
   3923                                 : N_(e_cannot_change_value_of_str);
   3924    break;
   3925  }
   3926  assert(error_message != NULL);
   3927 
   3928  if (name == NULL) {
   3929    emsg(_(error_message));
   3930  } else {
   3931    if (name_len == TV_TRANSLATE) {
   3932      name = _(name);
   3933      name_len = strlen(name);
   3934    } else if (name_len == TV_CSTRING) {
   3935      name_len = strlen(name);
   3936    }
   3937    semsg(_(error_message), (int)name_len, name);
   3938  }
   3939 
   3940  return true;
   3941 }
   3942 
   3943 // Comparison:
   3944 
   3945 static int tv_equal_recurse_limit;
   3946 
   3947 /// Compare two Vimscript values
   3948 ///
   3949 /// Like "==", but strings and numbers are different, as well as floats and
   3950 /// numbers.
   3951 ///
   3952 /// @warning Too nested structures may be considered equal even if they are not.
   3953 ///
   3954 /// @param[in]  tv1  First value to compare.
   3955 /// @param[in]  tv2  Second value to compare.
   3956 /// @param[in]  ic  True if case is to be ignored.
   3957 ///
   3958 /// @return true if values are equal.
   3959 bool tv_equal(typval_T *const tv1, typval_T *const tv2, const bool ic)
   3960  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
   3961 {
   3962  // TODO(ZyX-I): Make this not recursive
   3963  static int recursive_cnt = 0;  // Catch recursive loops.
   3964 
   3965  if (!(tv_is_func(*tv1) && tv_is_func(*tv2)) && tv1->v_type != tv2->v_type) {
   3966    return false;
   3967  }
   3968 
   3969  // Catch lists and dicts that have an endless loop by limiting
   3970  // recursiveness to a limit.  We guess they are equal then.
   3971  // A fixed limit has the problem of still taking an awful long time.
   3972  // Reduce the limit every time running into it. That should work fine for
   3973  // deeply linked structures that are not recursively linked and catch
   3974  // recursiveness quickly.
   3975  if (recursive_cnt == 0) {
   3976    tv_equal_recurse_limit = 1000;
   3977  }
   3978  if (recursive_cnt >= tv_equal_recurse_limit) {
   3979    tv_equal_recurse_limit--;
   3980    return true;
   3981  }
   3982 
   3983  switch (tv1->v_type) {
   3984  case VAR_LIST: {
   3985    recursive_cnt++;
   3986    const bool r = tv_list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
   3987    recursive_cnt--;
   3988    return r;
   3989  }
   3990  case VAR_DICT: {
   3991    recursive_cnt++;
   3992    const bool r = tv_dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
   3993    recursive_cnt--;
   3994    return r;
   3995  }
   3996  case VAR_PARTIAL:
   3997  case VAR_FUNC: {
   3998    if ((tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial == NULL)
   3999        || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial == NULL)) {
   4000      return false;
   4001    }
   4002    recursive_cnt++;
   4003    const bool r = func_equal(tv1, tv2, ic);
   4004    recursive_cnt--;
   4005    return r;
   4006  }
   4007  case VAR_BLOB:
   4008    return tv_blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
   4009  case VAR_NUMBER:
   4010    return tv1->vval.v_number == tv2->vval.v_number;
   4011  case VAR_FLOAT:
   4012    return tv1->vval.v_float == tv2->vval.v_float;
   4013  case VAR_STRING: {
   4014    char buf1[NUMBUFLEN];
   4015    char buf2[NUMBUFLEN];
   4016    const char *s1 = tv_get_string_buf(tv1, buf1);
   4017    const char *s2 = tv_get_string_buf(tv2, buf2);
   4018    return mb_strcmp_ic(ic, s1, s2) == 0;
   4019  }
   4020  case VAR_BOOL:
   4021    return tv1->vval.v_bool == tv2->vval.v_bool;
   4022  case VAR_SPECIAL:
   4023    return tv1->vval.v_special == tv2->vval.v_special;
   4024  case VAR_UNKNOWN:
   4025    // VAR_UNKNOWN can be the result of an invalid expression, let’s say it
   4026    // does not equal anything, not even self.
   4027    return false;
   4028  }
   4029 
   4030  abort();
   4031  return false;
   4032 }
   4033 
   4034 // Type checks:
   4035 
   4036 /// Check that given value is a number or string
   4037 ///
   4038 /// Error messages are compatible with tv_get_number() previously used for the
   4039 /// same purpose in buf*() functions. Special values are not accepted (previous
   4040 /// behaviour: silently fail to find buffer).
   4041 ///
   4042 /// @param[in]  tv  Value to check.
   4043 ///
   4044 /// @return true if everything is OK, false otherwise.
   4045 bool tv_check_str_or_nr(const typval_T *const tv)
   4046  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
   4047 {
   4048  switch (tv->v_type) {
   4049  case VAR_NUMBER:
   4050  case VAR_STRING:
   4051    return true;
   4052  case VAR_FLOAT:
   4053    emsg(_("E805: Expected a Number or a String, Float found"));
   4054    return false;
   4055  case VAR_PARTIAL:
   4056  case VAR_FUNC:
   4057    emsg(_("E703: Expected a Number or a String, Funcref found"));
   4058    return false;
   4059  case VAR_LIST:
   4060    emsg(_("E745: Expected a Number or a String, List found"));
   4061    return false;
   4062  case VAR_DICT:
   4063    emsg(_("E728: Expected a Number or a String, Dictionary found"));
   4064    return false;
   4065  case VAR_BLOB:
   4066    emsg(_("E974: Expected a Number or a String, Blob found"));
   4067    return false;
   4068  case VAR_BOOL:
   4069    emsg(_("E5299: Expected a Number or a String, Boolean found"));
   4070    return false;
   4071  case VAR_SPECIAL:
   4072    emsg(_("E5300: Expected a Number or a String"));
   4073    return false;
   4074  case VAR_UNKNOWN:
   4075    semsg(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)");
   4076    return false;
   4077  }
   4078  abort();
   4079  return false;
   4080 }
   4081 
   4082 #define FUNC_ERROR "E703: Using a Funcref as a Number"
   4083 
   4084 static const char *const num_errors[] = {
   4085  [VAR_PARTIAL] = N_(FUNC_ERROR),
   4086  [VAR_FUNC] = N_(FUNC_ERROR),
   4087  [VAR_LIST] = N_("E745: Using a List as a Number"),
   4088  [VAR_DICT] = N_("E728: Using a Dictionary as a Number"),
   4089  [VAR_FLOAT] = N_("E805: Using a Float as a Number"),
   4090  [VAR_BLOB] = N_("E974: Using a Blob as a Number"),
   4091  [VAR_UNKNOWN] = N_("E685: using an invalid value as a Number"),
   4092 };
   4093 
   4094 #undef FUNC_ERROR
   4095 
   4096 /// Check that given value is a number or can be converted to it
   4097 ///
   4098 /// Error messages are compatible with tv_get_number_chk() previously used for
   4099 /// the same purpose.
   4100 ///
   4101 /// @param[in]  tv  Value to check.
   4102 ///
   4103 /// @return true if everything is OK, false otherwise.
   4104 bool tv_check_num(const typval_T *const tv)
   4105  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4106 {
   4107  switch (tv->v_type) {
   4108  case VAR_NUMBER:
   4109  case VAR_BOOL:
   4110  case VAR_SPECIAL:
   4111  case VAR_STRING:
   4112    return true;
   4113  case VAR_FUNC:
   4114  case VAR_PARTIAL:
   4115  case VAR_LIST:
   4116  case VAR_DICT:
   4117  case VAR_FLOAT:
   4118  case VAR_BLOB:
   4119  case VAR_UNKNOWN:
   4120    emsg(_(num_errors[tv->v_type]));
   4121    return false;
   4122  }
   4123  abort();
   4124  return false;
   4125 }
   4126 
   4127 #define FUNC_ERROR "E729: Using a Funcref as a String"
   4128 
   4129 static const char *const str_errors[] = {
   4130  [VAR_PARTIAL] = N_(FUNC_ERROR),
   4131  [VAR_FUNC] = N_(FUNC_ERROR),
   4132  [VAR_LIST] = N_("E730: Using a List as a String"),
   4133  [VAR_DICT] = N_("E731: Using a Dictionary as a String"),
   4134  [VAR_BLOB] = N_("E976: Using a Blob as a String"),
   4135  [VAR_UNKNOWN] = e_using_invalid_value_as_string,
   4136 };
   4137 
   4138 #undef FUNC_ERROR
   4139 
   4140 /// Check that given value is a Vimscript String or can be "cast" to it.
   4141 ///
   4142 /// Error messages are compatible with tv_get_string_chk() previously used for
   4143 /// the same purpose.
   4144 ///
   4145 /// @param[in]  tv  Value to check.
   4146 ///
   4147 /// @return true if everything is OK, false otherwise.
   4148 bool tv_check_str(const typval_T *const tv)
   4149  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4150 {
   4151  switch (tv->v_type) {
   4152  case VAR_NUMBER:
   4153  case VAR_BOOL:
   4154  case VAR_SPECIAL:
   4155  case VAR_STRING:
   4156  case VAR_FLOAT:
   4157    return true;
   4158  case VAR_PARTIAL:
   4159  case VAR_FUNC:
   4160  case VAR_LIST:
   4161  case VAR_DICT:
   4162  case VAR_BLOB:
   4163  case VAR_UNKNOWN:
   4164    emsg(_(str_errors[tv->v_type]));
   4165    return false;
   4166  }
   4167  abort();
   4168  return false;
   4169 }
   4170 
   4171 // Get:
   4172 
   4173 /// Get the number value of a Vimscript object
   4174 ///
   4175 /// @note Use tv_get_number_chk() if you need to determine whether there was an
   4176 ///       error.
   4177 ///
   4178 /// @param[in]  tv  Object to get value from.
   4179 ///
   4180 /// @return Number value: vim_str2nr() output for VAR_STRING objects, value
   4181 ///         for VAR_NUMBER objects, -1 for other types.
   4182 varnumber_T tv_get_number(const typval_T *const tv)
   4183  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4184 {
   4185  bool error = false;
   4186  return tv_get_number_chk(tv, &error);
   4187 }
   4188 
   4189 /// Get the number value of a Vimscript object
   4190 ///
   4191 /// @param[in]  tv  Object to get value from.
   4192 /// @param[out]  ret_error  If type error occurred then `true` will be written
   4193 ///                         to this location. Otherwise it is not touched.
   4194 ///
   4195 ///                         @note Needs to be initialized to `false` to be
   4196 ///                               useful.
   4197 ///
   4198 /// @return Number value: vim_str2nr() output for VAR_STRING objects, value
   4199 ///         for VAR_NUMBER objects, -1 (ret_error == NULL) or 0 (otherwise) for
   4200 ///         other types.
   4201 varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error)
   4202  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
   4203 {
   4204  switch (tv->v_type) {
   4205  case VAR_FUNC:
   4206  case VAR_PARTIAL:
   4207  case VAR_LIST:
   4208  case VAR_DICT:
   4209  case VAR_BLOB:
   4210  case VAR_FLOAT:
   4211    emsg(_(num_errors[tv->v_type]));
   4212    break;
   4213  case VAR_NUMBER:
   4214    return tv->vval.v_number;
   4215  case VAR_STRING: {
   4216    varnumber_T n = 0;
   4217    if (tv->vval.v_string != NULL) {
   4218      vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, false, NULL);
   4219    }
   4220    return n;
   4221  }
   4222  case VAR_BOOL:
   4223    return tv->vval.v_bool == kBoolVarTrue ? 1 : 0;
   4224  case VAR_SPECIAL:
   4225    return 0;
   4226  case VAR_UNKNOWN:
   4227    semsg(_(e_intern2), "tv_get_number(UNKNOWN)");
   4228    break;
   4229  }
   4230  if (ret_error != NULL) {
   4231    *ret_error = true;
   4232  }
   4233  return (ret_error == NULL ? -1 : 0);
   4234 }
   4235 
   4236 varnumber_T tv_get_bool(const typval_T *const tv)
   4237  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4238 {
   4239  return tv_get_number_chk(tv, NULL);
   4240 }
   4241 
   4242 varnumber_T tv_get_bool_chk(const typval_T *const tv, bool *const ret_error)
   4243  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
   4244 {
   4245  return tv_get_number_chk(tv, ret_error);
   4246 }
   4247 
   4248 /// Get the line number from Vimscript object
   4249 ///
   4250 /// @param[in]  tv  Object to get value from. Is expected to be a number or
   4251 ///                 a special string like ".", "$", … (works with current buffer
   4252 ///                 only).
   4253 ///
   4254 /// @return Line number or -1 or 0.
   4255 linenr_T tv_get_lnum(const typval_T *const tv)
   4256  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4257 {
   4258  const int did_emsg_before = did_emsg;
   4259  linenr_T lnum = (linenr_T)tv_get_number_chk(tv, NULL);
   4260  if (lnum <= 0 && did_emsg_before == did_emsg && tv->v_type != VAR_NUMBER) {
   4261    int fnum;
   4262    // No valid number, try using same function as line() does.
   4263    pos_T *const fp = var2fpos(tv, true, &fnum, false, curwin);
   4264    if (fp != NULL) {
   4265      lnum = fp->lnum;
   4266    }
   4267  }
   4268  return lnum;
   4269 }
   4270 
   4271 /// Get the line number from Vimscript object
   4272 ///
   4273 /// @note Unlike tv_get_lnum(), this one supports only "$" special string.
   4274 ///
   4275 /// @param[in] tv   Object to get value from. Is expected to be a number or
   4276 ///                 a special string "$".
   4277 /// @param[in] buf  Buffer to take last line number from in case tv is "$". May
   4278 ///                 be NULL, in this case "$" results in zero return.
   4279 ///
   4280 /// @return  Line number or 0 in case of error.
   4281 linenr_T tv_get_lnum_buf(const typval_T *const tv, const buf_T *const buf)
   4282  FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT
   4283 {
   4284  if (tv->v_type == VAR_STRING
   4285      && tv->vval.v_string != NULL
   4286      && tv->vval.v_string[0] == '$'
   4287      && tv->vval.v_string[1] == NUL
   4288      && buf != NULL) {
   4289    return buf->b_ml.ml_line_count;
   4290  }
   4291  return (linenr_T)tv_get_number_chk(tv, NULL);
   4292 }
   4293 
   4294 /// Get the floating-point value of a Vimscript object
   4295 ///
   4296 /// Raises an error if object is not number or floating-point.
   4297 ///
   4298 /// @param[in]  tv  Object to get value of.
   4299 ///
   4300 /// @return Floating-point value of the variable or zero.
   4301 float_T tv_get_float(const typval_T *const tv)
   4302  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4303 {
   4304  switch (tv->v_type) {
   4305  case VAR_NUMBER:
   4306    return (float_T)(tv->vval.v_number);
   4307  case VAR_FLOAT:
   4308    return tv->vval.v_float;
   4309  case VAR_PARTIAL:
   4310  case VAR_FUNC:
   4311    emsg(_("E891: Using a Funcref as a Float"));
   4312    break;
   4313  case VAR_STRING:
   4314    emsg(_("E892: Using a String as a Float"));
   4315    break;
   4316  case VAR_LIST:
   4317    emsg(_("E893: Using a List as a Float"));
   4318    break;
   4319  case VAR_DICT:
   4320    emsg(_("E894: Using a Dictionary as a Float"));
   4321    break;
   4322  case VAR_BOOL:
   4323    emsg(_("E362: Using a boolean value as a Float"));
   4324    break;
   4325  case VAR_SPECIAL:
   4326    emsg(_("E907: Using a special value as a Float"));
   4327    break;
   4328  case VAR_BLOB:
   4329    emsg(_("E975: Using a Blob as a Float"));
   4330    break;
   4331  case VAR_UNKNOWN:
   4332    semsg(_(e_intern2), "tv_get_float(UNKNOWN)");
   4333    break;
   4334  }
   4335  return 0;
   4336 }
   4337 
   4338 /// Give an error and return FAIL unless "args[idx]" is a string.
   4339 int tv_check_for_string_arg(const typval_T *const args, const int idx)
   4340  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4341 {
   4342  if (args[idx].v_type != VAR_STRING) {
   4343    semsg(_(e_string_required_for_argument_nr), idx + 1);
   4344    return FAIL;
   4345  }
   4346  return OK;
   4347 }
   4348 
   4349 /// Give an error and return FAIL unless "args[idx]" is a non-empty string.
   4350 int tv_check_for_nonempty_string_arg(const typval_T *const args, const int idx)
   4351  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4352 {
   4353  if (tv_check_for_string_arg(args, idx) == FAIL) {
   4354    return FAIL;
   4355  }
   4356  if (args[idx].vval.v_string == NULL || *args[idx].vval.v_string == NUL) {
   4357    semsg(_(e_non_empty_string_required_for_argument_nr), idx + 1);
   4358    return FAIL;
   4359  }
   4360  return OK;
   4361 }
   4362 
   4363 /// Check for an optional string argument at "idx"
   4364 int tv_check_for_opt_string_arg(const typval_T *const args, const int idx)
   4365  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4366 {
   4367  return (args[idx].v_type == VAR_UNKNOWN
   4368          || tv_check_for_string_arg(args, idx) != FAIL) ? OK : FAIL;
   4369 }
   4370 
   4371 /// Give an error and return FAIL unless "args[idx]" is a number.
   4372 int tv_check_for_number_arg(const typval_T *const args, const int idx)
   4373  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4374 {
   4375  if (args[idx].v_type != VAR_NUMBER) {
   4376    semsg(_(e_number_required_for_argument_nr), idx + 1);
   4377    return FAIL;
   4378  }
   4379  return OK;
   4380 }
   4381 
   4382 /// Check for an optional number argument at "idx"
   4383 int tv_check_for_opt_number_arg(const typval_T *const args, const int idx)
   4384  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4385 {
   4386  return (args[idx].v_type == VAR_UNKNOWN
   4387          || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL;
   4388 }
   4389 
   4390 /// Give an error and return FAIL unless "args[idx]" is a float or a number.
   4391 int tv_check_for_float_or_nr_arg(const typval_T *const args, const int idx)
   4392  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4393 {
   4394  if (args[idx].v_type != VAR_FLOAT && args[idx].v_type != VAR_NUMBER) {
   4395    semsg(_(e_float_or_number_required_for_argument_nr), idx + 1);
   4396    return FAIL;
   4397  }
   4398  return OK;
   4399 }
   4400 
   4401 /// Give an error and return FAIL unless "args[idx]" is a bool.
   4402 int tv_check_for_bool_arg(const typval_T *const args, const int idx)
   4403  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4404 {
   4405  if (args[idx].v_type != VAR_BOOL
   4406      && !(args[idx].v_type == VAR_NUMBER
   4407           && (args[idx].vval.v_number == 0
   4408               || args[idx].vval.v_number == 1))) {
   4409    semsg(_(e_bool_required_for_argument_nr), idx + 1);
   4410    return FAIL;
   4411  }
   4412  return OK;
   4413 }
   4414 
   4415 /// Check for an optional bool argument at "idx".
   4416 /// Return FAIL if the type is wrong.
   4417 int tv_check_for_opt_bool_arg(const typval_T *const args, const int idx)
   4418  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4419 {
   4420  if (args[idx].v_type == VAR_UNKNOWN) {
   4421    return OK;
   4422  }
   4423  return tv_check_for_bool_arg(args, idx);
   4424 }
   4425 
   4426 /// Give an error and return FAIL unless "args[idx]" is a blob.
   4427 int tv_check_for_blob_arg(const typval_T *const args, const int idx)
   4428  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4429 {
   4430  if (args[idx].v_type != VAR_BLOB) {
   4431    semsg(_(e_blob_required_for_argument_nr), idx + 1);
   4432    return FAIL;
   4433  }
   4434  return OK;
   4435 }
   4436 
   4437 /// Give an error and return FAIL unless "args[idx]" is a list.
   4438 int tv_check_for_list_arg(const typval_T *const args, const int idx)
   4439  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4440 {
   4441  if (args[idx].v_type != VAR_LIST) {
   4442    semsg(_(e_list_required_for_argument_nr), idx + 1);
   4443    return FAIL;
   4444  }
   4445  return OK;
   4446 }
   4447 
   4448 /// Give an error and return FAIL unless "args[idx]" is a dict.
   4449 int tv_check_for_dict_arg(const typval_T *const args, const int idx)
   4450  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4451 {
   4452  if (args[idx].v_type != VAR_DICT) {
   4453    semsg(_(e_dict_required_for_argument_nr), idx + 1);
   4454    return FAIL;
   4455  }
   4456  return OK;
   4457 }
   4458 
   4459 /// Give an error and return FAIL unless "args[idx]" is a non-NULL dict.
   4460 int tv_check_for_nonnull_dict_arg(const typval_T *const args, const int idx)
   4461  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4462 {
   4463  if (tv_check_for_dict_arg(args, idx) == FAIL) {
   4464    return FAIL;
   4465  }
   4466  if (args[idx].vval.v_dict == NULL) {
   4467    semsg(_(e_non_null_dict_required_for_argument_nr), idx + 1);
   4468    return FAIL;
   4469  }
   4470  return OK;
   4471 }
   4472 
   4473 /// Check for an optional dict argument at "idx"
   4474 int tv_check_for_opt_dict_arg(const typval_T *const args, const int idx)
   4475  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4476 {
   4477  return (args[idx].v_type == VAR_UNKNOWN
   4478          || tv_check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL;
   4479 }
   4480 
   4481 /// Give an error and return FAIL unless "args[idx]" is a string or
   4482 /// a number.
   4483 int tv_check_for_string_or_number_arg(const typval_T *const args, const int idx)
   4484  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4485 {
   4486  if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_NUMBER) {
   4487    semsg(_(e_string_or_number_required_for_argument_nr), idx + 1);
   4488    return FAIL;
   4489  }
   4490  return OK;
   4491 }
   4492 
   4493 /// Give an error and return FAIL unless "args[idx]" is a buffer number.
   4494 /// Buffer number can be a number or a string.
   4495 int tv_check_for_buffer_arg(const typval_T *const args, const int idx)
   4496  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4497 {
   4498  return tv_check_for_string_or_number_arg(args, idx);
   4499 }
   4500 
   4501 /// Give an error and return FAIL unless "args[idx]" is a line number.
   4502 /// Line number can be a number or a string.
   4503 int tv_check_for_lnum_arg(const typval_T *const args, const int idx)
   4504  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4505 {
   4506  return tv_check_for_string_or_number_arg(args, idx);
   4507 }
   4508 
   4509 /// Give an error and return FAIL unless "args[idx]" is a string or a list.
   4510 int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx)
   4511  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4512 {
   4513  if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_LIST) {
   4514    semsg(_(e_string_or_list_required_for_argument_nr), idx + 1);
   4515    return FAIL;
   4516  }
   4517  return OK;
   4518 }
   4519 
   4520 /// Give an error and return FAIL unless "args[idx]" is a string, a list or a blob.
   4521 int tv_check_for_string_or_list_or_blob_arg(const typval_T *const args, const int idx)
   4522  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4523 {
   4524  if (args[idx].v_type != VAR_STRING
   4525      && args[idx].v_type != VAR_LIST
   4526      && args[idx].v_type != VAR_BLOB) {
   4527    semsg(_(e_string_list_or_blob_required_for_argument_nr), idx + 1);
   4528    return FAIL;
   4529  }
   4530  return OK;
   4531 }
   4532 
   4533 /// Check for an optional string or list argument at "idx"
   4534 int tv_check_for_opt_string_or_list_arg(const typval_T *const args, const int idx)
   4535  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4536 {
   4537  return (args[idx].v_type == VAR_UNKNOWN
   4538          || tv_check_for_string_or_list_arg(args, idx) != FAIL) ? OK : FAIL;
   4539 }
   4540 
   4541 /// Give an error and return FAIL unless "args[idx]" is a string
   4542 /// or a function reference.
   4543 int tv_check_for_string_or_func_arg(const typval_T *const args, const int idx)
   4544  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4545 {
   4546  if (args[idx].v_type != VAR_PARTIAL
   4547      && args[idx].v_type != VAR_FUNC
   4548      && args[idx].v_type != VAR_STRING) {
   4549    semsg(_(e_string_or_function_required_for_argument_nr), idx + 1);
   4550    return FAIL;
   4551  }
   4552  return OK;
   4553 }
   4554 
   4555 /// Give an error and return FAIL unless "args[idx]" is a list or a blob.
   4556 int tv_check_for_list_or_blob_arg(const typval_T *const args, const int idx)
   4557  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   4558 {
   4559  if (args[idx].v_type != VAR_LIST && args[idx].v_type != VAR_BLOB) {
   4560    semsg(_(e_list_or_blob_required_for_argument_nr), idx + 1);
   4561    return FAIL;
   4562  }
   4563  return OK;
   4564 }
   4565 
   4566 /// Get the string value of a "stringish" Vimscript object.
   4567 ///
   4568 /// @param[in]  tv  Object to get value of.
   4569 /// @param  buf  Buffer used to hold numbers and special variables converted to
   4570 ///              string. When function encounters one of these stringified value
   4571 ///              will be written to buf and buf will be returned.
   4572 ///
   4573 ///              Buffer must have NUMBUFLEN size.
   4574 ///
   4575 /// @return Object value if it is VAR_STRING object, number converted to
   4576 ///         a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or NULL.
   4577 const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf)
   4578  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4579 {
   4580  switch (tv->v_type) {
   4581  case VAR_NUMBER:
   4582    snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number);
   4583    return buf;
   4584  case VAR_FLOAT:
   4585    vim_snprintf(buf, NUMBUFLEN, "%g", tv->vval.v_float);
   4586    return buf;
   4587  case VAR_STRING:
   4588    if (tv->vval.v_string != NULL) {
   4589      return tv->vval.v_string;
   4590    }
   4591    return "";
   4592  case VAR_BOOL:
   4593    STRCPY(buf, encode_bool_var_names[tv->vval.v_bool]);
   4594    return buf;
   4595  case VAR_SPECIAL:
   4596    STRCPY(buf, encode_special_var_names[tv->vval.v_special]);
   4597    return buf;
   4598  case VAR_PARTIAL:
   4599  case VAR_FUNC:
   4600  case VAR_LIST:
   4601  case VAR_DICT:
   4602  case VAR_BLOB:
   4603  case VAR_UNKNOWN:
   4604    emsg(_(str_errors[tv->v_type]));
   4605    return NULL;
   4606  }
   4607  abort();
   4608  return NULL;
   4609 }
   4610 
   4611 /// Get the string value of a "stringish" Vimscript object.
   4612 ///
   4613 /// @warning For number and special values it uses a single, static buffer. It
   4614 ///          may be used only once, next call to tv_get_string may reuse it. Use
   4615 ///          tv_get_string_buf() if you need to use tv_get_string() output after
   4616 ///          calling it again.
   4617 ///
   4618 /// @param[in]  tv  Object to get value of.
   4619 ///
   4620 /// @return Object value if it is VAR_STRING object, number converted to
   4621 ///         a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or NULL.
   4622 const char *tv_get_string_chk(const typval_T *const tv)
   4623  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4624 {
   4625  static char mybuf[NUMBUFLEN];
   4626 
   4627  return tv_get_string_buf_chk(tv, mybuf);
   4628 }
   4629 
   4630 /// Get the string value of a "stringish" Vimscript object.
   4631 ///
   4632 /// @warning For number and special values it uses a single, static buffer. It
   4633 ///          may be used only once, next call to tv_get_string may reuse it. Use
   4634 ///          tv_get_string_buf() if you need to use tv_get_string() output after
   4635 ///          calling it again.
   4636 ///
   4637 /// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but
   4638 ///       return NULL on error.
   4639 ///
   4640 /// @param[in]  tv  Object to get value of.
   4641 ///
   4642 /// @return Object value if it is VAR_STRING object, number converted to
   4643 ///         a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or empty
   4644 ///         string.
   4645 const char *tv_get_string(const typval_T *const tv)
   4646  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
   4647 {
   4648  static char mybuf[NUMBUFLEN];
   4649  return tv_get_string_buf((typval_T *)tv, mybuf);
   4650 }
   4651 
   4652 /// Get the string value of a "stringish" Vimscript object.
   4653 ///
   4654 /// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but
   4655 ///       return NULL on error.
   4656 ///
   4657 /// @param[in]  tv  Object to get value of.
   4658 /// @param  buf  Buffer used to hold numbers and special variables converted to
   4659 ///              string. When function encounters one of these stringified value
   4660 ///              will be written to buf and buf will be returned.
   4661 ///
   4662 ///              Buffer must have NUMBUFLEN size.
   4663 ///
   4664 /// @return Object value if it is VAR_STRING object, number converted to
   4665 ///         a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or empty
   4666 ///         string.
   4667 const char *tv_get_string_buf(const typval_T *const tv, char *const buf)
   4668  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
   4669 {
   4670  const char *const res = tv_get_string_buf_chk(tv, buf);
   4671 
   4672  return res != NULL ? res : "";
   4673 }
   4674 
   4675 /// Return true when "tv" is not falsy: non-zero, non-empty string, non-empty
   4676 /// list, etc.  Mostly like what JavaScript does, except that empty list and
   4677 /// empty dictionary are false.
   4678 bool tv2bool(const typval_T *const tv)
   4679 {
   4680  switch (tv->v_type) {
   4681  case VAR_NUMBER:
   4682    return tv->vval.v_number != 0;
   4683  case VAR_FLOAT:
   4684    return tv->vval.v_float != 0.0;
   4685  case VAR_PARTIAL:
   4686    return tv->vval.v_partial != NULL;
   4687  case VAR_FUNC:
   4688  case VAR_STRING:
   4689    return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
   4690  case VAR_LIST:
   4691    return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
   4692  case VAR_DICT:
   4693    return tv->vval.v_dict != NULL && tv->vval.v_dict->dv_hashtab.ht_used > 0;
   4694  case VAR_BOOL:
   4695    return tv->vval.v_bool == kBoolVarTrue;
   4696  case VAR_SPECIAL:
   4697    return tv->vval.v_special != kSpecialVarNull;
   4698  case VAR_BLOB:
   4699    return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
   4700  case VAR_UNKNOWN:
   4701    break;
   4702  }
   4703  return false;
   4704 }