neovim

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

shada.c (131615B)


      1 #include <assert.h>
      2 #include <inttypes.h>
      3 #include <stdbool.h>
      4 #include <stddef.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <sys/stat.h>
      8 #include <uv.h>
      9 
     10 #include "auto/config.h"
     11 #include "klib/kvec.h"
     12 #include "mpack/mpack_core.h"
     13 #include "nvim/api/keysets_defs.h"
     14 #include "nvim/api/private/defs.h"
     15 #include "nvim/api/private/dispatch.h"
     16 #include "nvim/api/private/helpers.h"
     17 #include "nvim/ascii_defs.h"
     18 #include "nvim/buffer.h"
     19 #include "nvim/buffer_defs.h"
     20 #include "nvim/cmdhist.h"
     21 #include "nvim/eval.h"
     22 #include "nvim/eval/decode.h"
     23 #include "nvim/eval/encode.h"
     24 #include "nvim/eval/typval.h"
     25 #include "nvim/eval/typval_defs.h"
     26 #include "nvim/eval/vars.h"
     27 #include "nvim/ex_cmds.h"
     28 #include "nvim/ex_cmds_defs.h"
     29 #include "nvim/ex_docmd.h"
     30 #include "nvim/fileio.h"
     31 #include "nvim/gettext_defs.h"
     32 #include "nvim/globals.h"
     33 #include "nvim/hashtab.h"
     34 #include "nvim/hashtab_defs.h"
     35 #include "nvim/macros_defs.h"
     36 #include "nvim/map_defs.h"
     37 #include "nvim/mark.h"
     38 #include "nvim/mark_defs.h"
     39 #include "nvim/mbyte.h"
     40 #include "nvim/memory.h"
     41 #include "nvim/memory_defs.h"
     42 #include "nvim/message.h"
     43 #include "nvim/msgpack_rpc/packer.h"
     44 #include "nvim/msgpack_rpc/packer_defs.h"
     45 #include "nvim/msgpack_rpc/unpacker.h"
     46 #include "nvim/normal_defs.h"
     47 #include "nvim/option.h"
     48 #include "nvim/option_vars.h"
     49 #include "nvim/os/fileio.h"
     50 #include "nvim/os/fileio_defs.h"
     51 #include "nvim/os/fs.h"
     52 #include "nvim/os/fs_defs.h"
     53 #include "nvim/os/os.h"
     54 #include "nvim/os/os_defs.h"
     55 #include "nvim/os/time.h"
     56 #include "nvim/os/time_defs.h"
     57 #include "nvim/path.h"
     58 #include "nvim/pos_defs.h"
     59 #include "nvim/regexp.h"
     60 #include "nvim/register.h"
     61 #include "nvim/search.h"
     62 #include "nvim/shada.h"
     63 #include "nvim/strings.h"
     64 #include "nvim/types_defs.h"
     65 #include "nvim/version.h"
     66 #include "nvim/vim_defs.h"
     67 
     68 #ifdef HAVE_BE64TOH
     69 # define _BSD_SOURCE 1  // NOLINT(bugprone-reserved-identifier)
     70 # define _DEFAULT_SOURCE 1  // NOLINT(bugprone-reserved-identifier)
     71 # include ENDIAN_INCLUDE_FILE
     72 #endif
     73 
     74 #define SEARCH_KEY_MAGIC sm
     75 #define SEARCH_KEY_SMARTCASE sc
     76 #define SEARCH_KEY_HAS_LINE_OFFSET sl
     77 #define SEARCH_KEY_PLACE_CURSOR_AT_END se
     78 #define SEARCH_KEY_IS_LAST_USED su
     79 #define SEARCH_KEY_IS_SUBSTITUTE_PATTERN ss
     80 #define SEARCH_KEY_HIGHLIGHTED sh
     81 #define SEARCH_KEY_OFFSET so
     82 #define SEARCH_KEY_PAT sp
     83 #define SEARCH_KEY_BACKWARD sb
     84 
     85 #define REG_KEY_TYPE rt
     86 #define REG_KEY_WIDTH rw
     87 #define REG_KEY_CONTENTS rc
     88 #define REG_KEY_UNNAMED ru
     89 
     90 #define KEY_LNUM l
     91 #define KEY_COL c
     92 #define KEY_FILE f
     93 #define KEY_NAME_CHAR n
     94 
     95 // Error messages formerly used by viminfo code:
     96 //   E136: viminfo: Too many errors, skipping rest of file
     97 //   E137: Viminfo file is not writable: %s
     98 //   E138: Can't write viminfo file %s!
     99 //   E195: Cannot open ShaDa file for reading
    100 //   E574: Unknown register type %d
    101 //   E575: Illegal starting char
    102 //   E576: Missing '>'
    103 //   E577: Illegal register name
    104 //   E886: Can't rename viminfo file to %s!
    105 //   E929: Too many viminfo temp files, like %s!
    106 // Now only six of them are used:
    107 //   E137: ShaDa file is not writeable (for pre-open checks)
    108 //   E929: All %s.tmp.X files exist, cannot write ShaDa file!
    109 //   RCERR (E576) for critical read errors.
    110 //   RNERR (E136) for various errors when renaming.
    111 //   RERR (E575) for various errors inside read ShaDa file.
    112 //   SERR (E886) for various “system” errors (always contains output of
    113 //   strerror)
    114 //   WERR (E574) for various ignorable write errors
    115 
    116 /// Common prefix for all errors inside ShaDa file
    117 ///
    118 /// I.e. errors occurred while parsing, but not system errors occurred while
    119 /// reading.
    120 #define RERR "E575: "
    121 
    122 /// Common prefix for critical read errors
    123 ///
    124 /// I.e. errors that make shada_read_next_item return kSDReadStatusNotShaDa.
    125 #define RCERR "E576: "
    126 
    127 /// Common prefix for all “system” errors
    128 #define SERR "E886: "
    129 
    130 /// Common prefix for all “rename” errors
    131 #define RNERR "E136: "
    132 
    133 /// Common prefix for all ignorable “write” errors
    134 #define WERR "E574: "
    135 
    136 /// Callback function for add_search_pattern
    137 typedef void (*SearchPatternGetter)(SearchPattern *);
    138 
    139 /// Possible ShaDa entry types
    140 ///
    141 /// @warning Enum values are part of the API and must not be altered.
    142 ///
    143 /// All values that are not in enum are ignored.
    144 typedef enum {
    145  kSDItemUnknown = -1,       ///< Unknown item.
    146  kSDItemMissing = 0,        ///< Missing value. Should never appear in a file.
    147  kSDItemHeader = 1,         ///< Header. Present for debugging purposes.
    148  kSDItemSearchPattern = 2,  ///< Last search pattern (*not* history item).
    149                             ///< Comes from user searches (e.g. when typing
    150                             ///< "/pat") or :substitute command calls.
    151  kSDItemSubString = 3,      ///< Last substitute replacement string.
    152  kSDItemHistoryEntry = 4,   ///< History item.
    153  kSDItemRegister = 5,       ///< Register.
    154  kSDItemVariable = 6,       ///< Global variable.
    155  kSDItemGlobalMark = 7,     ///< Global mark definition.
    156  kSDItemJump = 8,           ///< Item from jump list.
    157  kSDItemBufferList = 9,     ///< Buffer list.
    158  kSDItemLocalMark = 10,     ///< Buffer-local mark.
    159  kSDItemChange = 11,        ///< Item from buffer change list.
    160 } ShadaEntryType;
    161 #define SHADA_LAST_ENTRY ((uint64_t)kSDItemChange)
    162 
    163 /// Possible results when reading ShaDa file
    164 typedef enum {
    165  kSDReadStatusSuccess,    ///< Reading was successful.
    166  kSDReadStatusFinished,   ///< Nothing more to read.
    167  kSDReadStatusReadError,  ///< Failed to read from file.
    168  kSDReadStatusNotShaDa,   ///< Input is most likely not a ShaDa file.
    169  kSDReadStatusMalformed,  ///< Error in the currently read item.
    170 } ShaDaReadResult;
    171 
    172 /// Possible results of shada_write function.
    173 typedef enum {
    174  kSDWriteSuccessful,    ///< Writing was successful.
    175  kSDWriteReadNotShada,  ///< Writing was successful, but when reading it
    176                         ///< attempted to read file that did not look like
    177                         ///< a ShaDa file.
    178  kSDWriteFailed,        ///< Writing was not successful (e.g. because there
    179                         ///< was no space left on device).
    180  kSDWriteIgnError,      ///< Writing resulted in a error which can be ignored
    181                         ///< (e.g. when trying to dump a function reference or
    182                         ///< self-referencing container in a variable).
    183 } ShaDaWriteResult;
    184 
    185 /// Flags for shada_read_next_item
    186 enum SRNIFlags {
    187  kSDReadHeader = (1 << kSDItemHeader),  ///< Determines whether header should
    188                                         ///< be read (it is usually ignored).
    189  kSDReadUndisableableData = (
    190                              (1 << kSDItemSearchPattern)
    191                              | (1 << kSDItemSubString)
    192                              | (1 << kSDItemJump)),  ///< Data reading which cannot be disabled by
    193                                                      ///< &shada or other options except for disabling
    194                                                      ///< reading ShaDa as a whole.
    195  kSDReadRegisters = (1 << kSDItemRegister),  ///< Determines whether registers
    196                                              ///< should be read (may only be
    197                                              ///< disabled when writing, but
    198                                              ///< not when reading).
    199  kSDReadHistory = (1 << kSDItemHistoryEntry),  ///< Determines whether history
    200                                                ///< should be read (can only be
    201                                                ///< disabled by &history).
    202  kSDReadVariables = (1 << kSDItemVariable),  ///< Determines whether variables
    203                                              ///< should be read (disabled by
    204                                              ///< removing ! from &shada).
    205  kSDReadBufferList = (1 << kSDItemBufferList),  ///< Determines whether buffer
    206                                                 ///< list should be read
    207                                                 ///< (disabled by removing
    208                                                 ///< % entry from &shada).
    209  kSDReadUnknown = (1 << (SHADA_LAST_ENTRY + 1)),  ///< Determines whether
    210                                                   ///< unknown items should be
    211                                                   ///< read (usually disabled).
    212  kSDReadGlobalMarks = (1 << kSDItemGlobalMark),  ///< Determines whether global
    213                                                  ///< marks should be read. Can
    214                                                  ///< only be disabled by
    215                                                  ///< having f0 in &shada when
    216                                                  ///< writing.
    217  kSDReadLocalMarks = (1 << kSDItemLocalMark),  ///< Determines whether local
    218                                                ///< marks should be read. Can
    219                                                ///< only be disabled by
    220                                                ///< disabling &shada or putting
    221                                                ///< '0 there. Is also used for
    222                                                ///< v:oldfiles.
    223  kSDReadChanges = (1 << kSDItemChange),  ///< Determines whether change list
    224                                          ///< should be read. Can only be
    225                                          ///< disabled by disabling &shada or
    226                                          ///< putting '0 there.
    227 };
    228 // Note: SRNIFlags enum name was created only to make it possible to reference
    229 // it. This name is not actually used anywhere outside of the documentation.
    230 
    231 /// Structure defining a single ShaDa file entry
    232 typedef struct {
    233  ShadaEntryType type;
    234  // If the entry was read from file, string data will be allocated and needs to be freed.
    235  // Entries can also be constructed from nvim internal data structures (like registers)
    236  // and reference their allocated strings. then shada code must not attempt to free these.
    237  bool can_free_entry;
    238  Timestamp timestamp;
    239  union {
    240    Dict header;
    241    struct shada_filemark {
    242      char name;
    243      pos_T mark;
    244      char *fname;
    245    } filemark;
    246    Dict(_shada_search_pat) search_pattern;
    247    struct history_item {
    248      uint8_t histtype;
    249      char *string;
    250      char sep;
    251    } history_item;
    252    struct reg {  // yankreg_T
    253      char name;
    254      MotionType type;
    255      String *contents;
    256      bool is_unnamed;
    257      size_t contents_size;
    258      size_t width;
    259    } reg;
    260    struct global_var {
    261      char *name;
    262      typval_T value;
    263    } global_var;
    264    struct {
    265      uint64_t type;
    266      char *contents;
    267      size_t size;
    268    } unknown_item;
    269    struct sub_string {
    270      char *sub;
    271    } sub_string;
    272    struct buffer_list {
    273      size_t size;
    274      struct buffer_list_buffer {
    275        pos_T pos;
    276        char *fname;
    277        AdditionalData *additional_data;
    278      } *buffers;
    279    } buffer_list;
    280  } data;
    281  AdditionalData *additional_data;
    282 } ShadaEntry;
    283 
    284 /// One entry in sized linked list
    285 typedef struct hm_llist_entry {
    286  ShadaEntry data;              ///< Entry data.
    287  struct hm_llist_entry *next;  ///< Pointer to next entry or NULL.
    288  struct hm_llist_entry *prev;  ///< Pointer to previous entry or NULL.
    289 } HMLListEntry;
    290 
    291 /// Sized linked list structure for history merger
    292 typedef struct {
    293  HMLListEntry *entries;  ///< Pointer to the start of the allocated array of
    294                          ///< entries.
    295  HMLListEntry *first;    ///< First entry in the list (is not necessary start
    296                          ///< of the array) or NULL.
    297  HMLListEntry *last;     ///< Last entry in the list or NULL.
    298  HMLListEntry *free_entry;  ///< Last free entry removed by hmll_remove.
    299  HMLListEntry *last_free_entry;  ///< Last unused element in entries array.
    300  size_t size;            ///< Number of allocated entries.
    301  size_t num_entries;     ///< Number of entries already used.
    302  PMap(cstr_t) contained_entries;  ///< Map all history entry strings to
    303                                   ///< corresponding entry pointers.
    304 } HMLList;
    305 
    306 typedef struct {
    307  HMLList hmll;
    308  bool do_merge;
    309  bool reading;
    310  const void *iter;
    311  ShadaEntry last_hist_entry;
    312  uint8_t history_type;
    313 } HistoryMergerState;
    314 
    315 /// Structure that holds one file marks.
    316 typedef struct {
    317  ShadaEntry marks[NLOCALMARKS];  ///< All file marks.
    318  ShadaEntry changes[JUMPLISTSIZE];  ///< All file changes.
    319  size_t changes_size;  ///< Number of changes occupied.
    320  ShadaEntry *additional_marks;  ///< All marks with unknown names.
    321  size_t additional_marks_size;  ///< Size of the additional_marks array.
    322  Timestamp greatest_timestamp;  ///< Greatest timestamp among marks.
    323 } FileMarks;
    324 
    325 /// State structure used by shada_write
    326 ///
    327 /// Before actually writing most of the data is read to this structure.
    328 typedef struct {
    329  HistoryMergerState hms[HIST_COUNT];  ///< Structures for history merging.
    330  ShadaEntry global_marks[NMARKS];  ///< Named global marks.
    331  ShadaEntry numbered_marks[EXTRA_MARKS];  ///< Numbered marks.
    332  ShadaEntry registers[NUM_SAVED_REGISTERS];  ///< All registers.
    333  ShadaEntry jumps[JUMPLISTSIZE];  ///< All dumped jumps.
    334  size_t jumps_size;  ///< Number of jumps occupied.
    335  ShadaEntry search_pattern;  ///< Last search pattern.
    336  ShadaEntry sub_search_pattern;  ///< Last s/ search pattern.
    337  ShadaEntry replacement;  ///< Last s// replacement string.
    338  Set(cstr_t) dumped_variables;  ///< Names of already dumped variables.
    339  PMap(cstr_t) file_marks;  ///< All file marks.
    340 } WriteMergerState;
    341 
    342 #include "shada.c.generated.h"
    343 
    344 #define DEF_SDE(name, attr, ...) \
    345  [kSDItem##name] = { \
    346    .timestamp = 0, \
    347    .type = kSDItem##name, \
    348    .additional_data = NULL, \
    349    .data = { \
    350      .attr = { __VA_ARGS__ } \
    351    } \
    352  }
    353 #define DEFAULT_POS { 1, 0, 0 }
    354 static const pos_T default_pos = DEFAULT_POS;
    355 static const ShadaEntry sd_default_values[] = {
    356  [kSDItemMissing] = { .type = kSDItemMissing, .timestamp = 0 },
    357  DEF_SDE(Header, header, .size = 0),
    358  DEF_SDE(SearchPattern, search_pattern,
    359          .magic = true,
    360          .smartcase = false,
    361          .has_line_offset = false,
    362          .place_cursor_at_end = false,
    363          .offset = 0,
    364          .is_last_used = true,
    365          .is_substitute_pattern = false,
    366          .highlighted = false,
    367          .search_backward = false,
    368          .pat = STRING_INIT),
    369  DEF_SDE(SubString, sub_string, .sub = NULL),
    370  DEF_SDE(HistoryEntry, history_item,
    371          .histtype = HIST_CMD,
    372          .string = NULL,
    373          .sep = NUL),
    374  DEF_SDE(Register, reg,
    375          .name = NUL,
    376          .type = kMTCharWise,
    377          .contents = NULL,
    378          .contents_size = 0,
    379          .is_unnamed = false,
    380          .width = 0),
    381  DEF_SDE(Variable, global_var,
    382          .name = NULL,
    383          .value = { .v_type = VAR_UNKNOWN, .vval = { .v_string = NULL } }),
    384  DEF_SDE(GlobalMark, filemark,
    385          .name = '"',
    386          .mark = DEFAULT_POS,
    387          .fname = NULL),
    388  DEF_SDE(Jump, filemark,
    389          .name = NUL,
    390          .mark = DEFAULT_POS,
    391          .fname = NULL),
    392  DEF_SDE(BufferList, buffer_list,
    393          .size = 0,
    394          .buffers = NULL),
    395  DEF_SDE(LocalMark, filemark,
    396          .name = '"',
    397          .mark = DEFAULT_POS,
    398          .fname = NULL),
    399  DEF_SDE(Change, filemark,
    400          .name = NUL,
    401          .mark = DEFAULT_POS,
    402          .fname = NULL),
    403 };
    404 #undef DEFAULT_POS
    405 #undef DEF_SDE
    406 
    407 /// Initialize new linked list
    408 ///
    409 /// @param[out]  hmll       List to initialize.
    410 /// @param[in]   size       Maximum size of the list.
    411 static inline void hmll_init(HMLList *const hmll, const size_t size)
    412  FUNC_ATTR_NONNULL_ALL
    413 {
    414  *hmll = (HMLList) {
    415    .entries = xcalloc(size, sizeof(hmll->entries[0])),
    416    .first = NULL,
    417    .last = NULL,
    418    .free_entry = NULL,
    419    .size = size,
    420    .num_entries = 0,
    421    .contained_entries = MAP_INIT,
    422  };
    423  hmll->last_free_entry = hmll->entries;
    424 }
    425 
    426 /// Iterate over HMLList in forward direction
    427 ///
    428 /// @param  hmll       Pointer to the list.
    429 /// @param  cur_entry  Name of the variable to iterate over.
    430 /// @param  code       Code to execute on each iteration.
    431 ///
    432 /// @return `for` cycle header (use `HMLL_FORALL(hmll, cur_entry) {body}`).
    433 #define HMLL_FORALL(hmll, cur_entry, code) \
    434  for (HMLListEntry *(cur_entry) = (hmll)->first; (cur_entry) != NULL; \
    435       (cur_entry) = (cur_entry)->next) { \
    436    code \
    437  } \
    438 
    439 /// Remove entry from the linked list
    440 ///
    441 /// @param  hmll        List to remove from.
    442 /// @param  hmll_entry  Entry to remove.
    443 static inline void hmll_remove(HMLList *const hmll, HMLListEntry *const hmll_entry)
    444  FUNC_ATTR_NONNULL_ALL
    445 {
    446  if (hmll_entry == hmll->last_free_entry - 1) {
    447    hmll->last_free_entry--;
    448  } else {
    449    assert(hmll->free_entry == NULL);
    450    hmll->free_entry = hmll_entry;
    451  }
    452  ptr_t val = pmap_del(cstr_t)(&hmll->contained_entries,
    453                               hmll_entry->data.data.history_item.string, NULL);
    454  assert(val);
    455  (void)val;
    456  if (hmll_entry->next == NULL) {
    457    hmll->last = hmll_entry->prev;
    458  } else {
    459    hmll_entry->next->prev = hmll_entry->prev;
    460  }
    461  if (hmll_entry->prev == NULL) {
    462    hmll->first = hmll_entry->next;
    463  } else {
    464    hmll_entry->prev->next = hmll_entry->next;
    465  }
    466  hmll->num_entries--;
    467  shada_free_shada_entry(&hmll_entry->data);
    468 }
    469 
    470 /// Insert entry to the linked list
    471 ///
    472 /// @param[out]  hmll            List to insert to.
    473 /// @param[in]   hmll_entry      Entry to insert after or NULL if it is needed
    474 ///                              to insert at the first entry.
    475 /// @param[in]   data            Data to insert.
    476 /// @param[in]   can_free_entry  True if data can be freed.
    477 static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, const ShadaEntry data)
    478  FUNC_ATTR_NONNULL_ARG(1)
    479 {
    480  if (hmll->num_entries == hmll->size) {
    481    if (hmll_entry == hmll->first) {
    482      hmll_entry = NULL;
    483    }
    484    assert(hmll->first != NULL);
    485    hmll_remove(hmll, hmll->first);
    486  }
    487  HMLListEntry *target_entry;
    488  if (hmll->free_entry == NULL) {
    489    assert((size_t)(hmll->last_free_entry - hmll->entries)
    490           == hmll->num_entries);
    491    target_entry = hmll->last_free_entry++;
    492  } else {
    493    assert((size_t)(hmll->last_free_entry - hmll->entries) - 1
    494           == hmll->num_entries);
    495    target_entry = hmll->free_entry;
    496    hmll->free_entry = NULL;
    497  }
    498  target_entry->data = data;
    499  bool new_item = false;
    500  ptr_t *val = pmap_put_ref(cstr_t)(&hmll->contained_entries, data.data.history_item.string,
    501                                    NULL, &new_item);
    502  if (new_item) {
    503    *val = target_entry;
    504  }
    505  hmll->num_entries++;
    506  target_entry->prev = hmll_entry;
    507  if (hmll_entry == NULL) {
    508    target_entry->next = hmll->first;
    509    hmll->first = target_entry;
    510  } else {
    511    target_entry->next = hmll_entry->next;
    512    hmll_entry->next = target_entry;
    513  }
    514  if (target_entry->next == NULL) {
    515    hmll->last = target_entry;
    516  } else {
    517    target_entry->next->prev = target_entry;
    518  }
    519 }
    520 
    521 /// Free linked list
    522 ///
    523 /// @param[in]  hmll  List to free.
    524 static inline void hmll_dealloc(HMLList *const hmll)
    525  FUNC_ATTR_NONNULL_ALL
    526 {
    527  map_destroy(cstr_t, &hmll->contained_entries);
    528  xfree(hmll->entries);
    529 }
    530 
    531 /// Wrapper for read that can be used when lseek cannot be used
    532 ///
    533 /// E.g. when trying to read from a pipe.
    534 ///
    535 /// @param[in,out]  sd_reader  File read.
    536 /// @param[in]      offset     Amount of bytes to skip.
    537 ///
    538 /// @return kSDReadStatusReadError, kSDReadStatusNotShaDa or
    539 ///         kSDReadStatusSuccess.
    540 static ShaDaReadResult sd_reader_skip(FileDescriptor *const sd_reader, const size_t offset)
    541  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
    542 {
    543  const ptrdiff_t skip_bytes = file_skip(sd_reader, offset);
    544  if (skip_bytes < 0) {
    545    semsg(_(SERR "System error while skipping in ShaDa file: %s"), os_strerror((int)skip_bytes));
    546    return kSDReadStatusReadError;
    547  } else if (skip_bytes != (ptrdiff_t)offset) {
    548    assert(skip_bytes < (ptrdiff_t)offset);
    549    if (file_eof(sd_reader)) {
    550      semsg(_(RCERR "Reading ShaDa file: last entry specified that it occupies %" PRIu64 " bytes, "
    551              "but file ended earlier"),
    552            (uint64_t)offset);
    553    } else {
    554      semsg(_(SERR "System error while skipping in ShaDa file: %s"), _("too few bytes read"));
    555    }
    556    return kSDReadStatusNotShaDa;
    557  }
    558  return kSDReadStatusSuccess;
    559 }
    560 
    561 /// Wrapper for closing file descriptors
    562 static void close_file(FileDescriptor *cookie)
    563 {
    564  const int error = file_close(cookie, !!p_fs);
    565  if (error != 0) {
    566    semsg(_(SERR "System error while closing ShaDa file: %s"),
    567          os_strerror(error));
    568  }
    569 }
    570 
    571 /// Read ShaDa file
    572 ///
    573 /// @param[in]  file   File to read or NULL to use default name.
    574 /// @param[in]  flags  Flags, see ShaDaReadFileFlags enum.
    575 ///
    576 /// @return FAIL if reading failed for some reason and OK otherwise.
    577 static int shada_read_file(const char *const file, const int flags)
    578  FUNC_ATTR_WARN_UNUSED_RESULT
    579 {
    580  char *const fname = shada_filename(file);
    581  if (fname == NULL) {
    582    return FAIL;
    583  }
    584 
    585  FileDescriptor sd_reader;
    586  int of_ret = file_open(&sd_reader, fname, kFileReadOnly, 0);
    587 
    588  if (p_verbose > 1) {
    589    verbose_enter();
    590    smsg(0, _("Reading ShaDa file \"%s\"%s%s%s%s"),
    591         fname,
    592         (flags & kShaDaWantInfo) ? _(" info") : "",
    593         (flags & kShaDaWantMarks) ? _(" marks") : "",
    594         (flags & kShaDaGetOldfiles) ? _(" oldfiles") : "",
    595         of_ret != 0 ? _(" FAILED") : "");
    596    verbose_leave();
    597  }
    598 
    599  if (of_ret != 0) {
    600    if (of_ret != UV_ENOENT || (flags & kShaDaMissingError)) {
    601      semsg(_(SERR "System error while opening ShaDa file %s for reading: %s"),
    602            fname, os_strerror(of_ret));
    603    }
    604    xfree(fname);
    605    return FAIL;
    606  }
    607  xfree(fname);
    608 
    609  shada_read(&sd_reader, flags);
    610  close_file(&sd_reader);
    611 
    612  return OK;
    613 }
    614 
    615 /// Wrapper for hist_iter() function which produces ShadaEntry values
    616 ///
    617 /// @param[in]   iter          Current iteration state.
    618 /// @param[in]   history_type  Type of the history (HIST_*).
    619 /// @param[in]   zero          If true, then item is removed from instance
    620 ///                            memory upon reading.
    621 /// @param[out]  hist          Location where iteration results should be saved.
    622 ///
    623 /// @return Next iteration state.
    624 static const void *shada_hist_iter(const void *const iter, const uint8_t history_type,
    625                                   const bool zero, ShadaEntry *const hist)
    626  FUNC_ATTR_NONNULL_ARG(4) FUNC_ATTR_WARN_UNUSED_RESULT
    627 {
    628  histentry_T hist_he;
    629  const void *const ret = hist_iter(iter, history_type, zero, &hist_he);
    630  if (hist_he.hisstr == NULL) {
    631    *hist = (ShadaEntry) { .type = kSDItemMissing };
    632  } else {
    633    *hist = (ShadaEntry) {
    634      .can_free_entry = zero,
    635      .type = kSDItemHistoryEntry,
    636      .timestamp = hist_he.timestamp,
    637      .data = {
    638        .history_item = {
    639          .histtype = history_type,
    640          .string = hist_he.hisstr,
    641          .sep = (char)(history_type == HIST_SEARCH
    642                        ? hist_he.hisstr[hist_he.hisstrlen + 1]
    643                        : 0),
    644        }
    645      },
    646      .additional_data = hist_he.additional_data,
    647    };
    648  }
    649  return ret;
    650 }
    651 
    652 /// Insert history entry
    653 ///
    654 /// Inserts history entry at the end of the ring buffer (may insert earlier
    655 /// according to the timestamp). If entry was already in the ring buffer
    656 /// existing entry will be removed unless it has greater timestamp.
    657 ///
    658 /// Before the new entry entries from the current Neovim history will be
    659 /// inserted unless `do_iter` argument is false.
    660 ///
    661 /// @param[in,out]  hms_p           Ring buffer and associated structures.
    662 /// @param[in]      entry           Inserted entry.
    663 /// @param[in]      do_iter         Determines whether Neovim own history should
    664 ///                                 be used. Must be true only if inserting
    665 ///                                 entry from current Neovim history.
    666 static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, const bool do_iter)
    667  FUNC_ATTR_NONNULL_ALL
    668 {
    669  if (do_iter) {
    670    while (hms_p->last_hist_entry.type != kSDItemMissing
    671           && hms_p->last_hist_entry.timestamp < entry.timestamp) {
    672      hms_insert(hms_p, hms_p->last_hist_entry, false);
    673      if (hms_p->iter == NULL) {
    674        hms_p->last_hist_entry.type = kSDItemMissing;
    675        break;
    676      }
    677      hms_p->iter = shada_hist_iter(hms_p->iter, hms_p->history_type,
    678                                    hms_p->reading, &hms_p->last_hist_entry);
    679    }
    680  }
    681  HMLList *const hmll = &hms_p->hmll;
    682  cstr_t *key_alloc = NULL;
    683  ptr_t *val = pmap_ref(cstr_t)(&hms_p->hmll.contained_entries, entry.data.history_item.string,
    684                                &key_alloc);
    685  if (val) {
    686    HMLListEntry *const existing_entry = *val;
    687    if (entry.timestamp > existing_entry->data.timestamp) {
    688      hmll_remove(hmll, existing_entry);
    689    } else if (!do_iter && entry.timestamp == existing_entry->data.timestamp) {
    690      // Prefer entry from the current Neovim instance.
    691      shada_free_shada_entry(&existing_entry->data);
    692      existing_entry->data = entry;
    693      // Previous key was freed above, as part of freeing the ShaDa entry.
    694      *key_alloc = entry.data.history_item.string;
    695      return;
    696    } else {
    697      return;
    698    }
    699  }
    700  HMLListEntry *insert_after;
    701  // Iterate over HMLList in backward direction
    702  for (insert_after = hmll->last; insert_after != NULL; insert_after = insert_after->prev) {
    703    if (insert_after->data.timestamp <= entry.timestamp) {
    704      break;
    705    }
    706  }
    707  hmll_insert(hmll, insert_after, entry);
    708 }
    709 
    710 /// Initialize the history merger
    711 ///
    712 /// @param[out]  hms_p         Structure to be initialized.
    713 /// @param[in]   history_type  History type (one of HIST_\* values).
    714 /// @param[in]   num_elements  Number of elements in the result.
    715 /// @param[in]   do_merge      Prepare structure for merging elements.
    716 /// @param[in]   reading       If true, then merger is reading history for use
    717 ///                            in Neovim.
    718 static inline void hms_init(HistoryMergerState *const hms_p, const uint8_t history_type,
    719                            const size_t num_elements, const bool do_merge, const bool reading)
    720  FUNC_ATTR_NONNULL_ALL
    721 {
    722  hmll_init(&hms_p->hmll, num_elements);
    723  hms_p->do_merge = do_merge;
    724  hms_p->reading = reading;
    725  hms_p->iter = shada_hist_iter(NULL, history_type, hms_p->reading,
    726                                &hms_p->last_hist_entry);
    727  hms_p->history_type = history_type;
    728 }
    729 
    730 /// Merge in all remaining Neovim own history entries
    731 ///
    732 /// @param[in,out]  hms_p  Merger structure into which history should be
    733 ///                        inserted.
    734 static inline void hms_insert_whole_neovim_history(HistoryMergerState *const hms_p)
    735  FUNC_ATTR_NONNULL_ALL
    736 {
    737  while (hms_p->last_hist_entry.type != kSDItemMissing) {
    738    hms_insert(hms_p, hms_p->last_hist_entry, false);
    739    if (hms_p->iter == NULL) {
    740      break;
    741    }
    742    hms_p->iter = shada_hist_iter(hms_p->iter, hms_p->history_type,
    743                                  hms_p->reading, &hms_p->last_hist_entry);
    744  }
    745 }
    746 
    747 /// Convert merger structure to Neovim internal structure for history
    748 ///
    749 /// @param[in]   hms_p       Converted merger structure.
    750 /// @param[out]  hist_array  Array with the results.
    751 /// @param[out]  new_hisidx  New last history entry index.
    752 /// @param[out]  new_hisnum  Amount of history items in merger structure.
    753 static inline void hms_to_he_array(const HistoryMergerState *const hms_p,
    754                                   histentry_T *const hist_array, int *const new_hisidx,
    755                                   int *const new_hisnum)
    756  FUNC_ATTR_NONNULL_ALL
    757 {
    758  histentry_T *hist = hist_array;
    759  HMLL_FORALL(&hms_p->hmll, cur_entry,  {
    760    hist->timestamp = cur_entry->data.timestamp;
    761    hist->hisnum = (int)(hist - hist_array) + 1;
    762    hist->hisstr = cur_entry->data.data.history_item.string;
    763    hist->hisstrlen = strlen(cur_entry->data.data.history_item.string);
    764    hist->additional_data = cur_entry->data.additional_data;
    765    hist++;
    766  })
    767  *new_hisnum = (int)(hist - hist_array);
    768  *new_hisidx = *new_hisnum - 1;
    769 }
    770 
    771 /// Free history merger structure
    772 ///
    773 /// @param[in]  hms_p  Structure to be freed.
    774 static inline void hms_dealloc(HistoryMergerState *const hms_p)
    775  FUNC_ATTR_NONNULL_ALL
    776 {
    777  hmll_dealloc(&hms_p->hmll);
    778 }
    779 
    780 /// Iterate over all history entries in history merger, in order
    781 ///
    782 /// @param[in]   hms_p      Merger structure to iterate over.
    783 /// @param[out]  cur_entry  Name of the iterator variable.
    784 /// @param       code       Code to execute on each iteration.
    785 ///
    786 /// @return for cycle header. Use `HMS_ITER(hms_p, cur_entry) {body}`.
    787 #define HMS_ITER(hms_p, cur_entry, code) \
    788  HMLL_FORALL(&((hms_p)->hmll), cur_entry, code)
    789 
    790 /// Iterate over global variables
    791 ///
    792 /// @warning No modifications to global variable Dict must be performed
    793 ///          while iteration is in progress.
    794 ///
    795 /// @param[in]   iter   Iterator. Pass NULL to start iteration.
    796 /// @param[out]  name   Variable name.
    797 /// @param[out]  rettv  Variable value.
    798 ///
    799 /// @return Pointer that needs to be passed to next `var_shada_iter` invocation
    800 ///         or NULL to indicate that iteration is over.
    801 static const void *var_shada_iter(const void *const iter, const char **const name, typval_T *rettv,
    802                                  var_flavour_T flavour)
    803  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2, 3)
    804 {
    805  const hashitem_T *hi;
    806  hashtab_T *globvarht = get_globvar_ht();
    807  const hashitem_T *hifirst = globvarht->ht_array;
    808  const size_t hinum = (size_t)globvarht->ht_mask + 1;
    809  *name = NULL;
    810  if (iter == NULL) {
    811    hi = globvarht->ht_array;
    812    while ((size_t)(hi - hifirst) < hinum
    813           && (HASHITEM_EMPTY(hi)
    814               || !(var_flavour(hi->hi_key) & flavour))) {
    815      hi++;
    816    }
    817    if ((size_t)(hi - hifirst) == hinum) {
    818      return NULL;
    819    }
    820  } else {
    821    hi = (const hashitem_T *)iter;
    822  }
    823  *name = TV_DICT_HI2DI(hi)->di_key;
    824  tv_copy(&TV_DICT_HI2DI(hi)->di_tv, rettv);
    825  while ((size_t)(++hi - hifirst) < hinum) {
    826    if (!HASHITEM_EMPTY(hi) && (var_flavour(hi->hi_key) & flavour)) {
    827      return hi;
    828    }
    829  }
    830  return NULL;
    831 }
    832 
    833 /// Find buffer for given buffer name (cached)
    834 ///
    835 /// @param[in,out]  fname_bufs  Cache containing fname to buffer mapping.
    836 /// @param[in]      fname       File name to find.
    837 ///
    838 /// @return Pointer to the buffer or NULL.
    839 static buf_T *find_buffer(PMap(cstr_t) *const fname_bufs, const char *const fname)
    840  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
    841 {
    842  cstr_t *key_alloc = NULL;
    843  bool new_item = false;
    844  buf_T **ref = (buf_T **)pmap_put_ref(cstr_t)(fname_bufs, fname, &key_alloc, &new_item);
    845  if (new_item) {
    846    *key_alloc = xstrdup(fname);
    847  } else {
    848    return *ref;  // item already existed (can be a NULL value)
    849  }
    850 
    851  FOR_ALL_BUFFERS(buf) {
    852    if (buf->b_ffname != NULL) {
    853      if (path_fnamecmp(fname, buf->b_ffname) == 0) {
    854        *ref = buf;
    855        return buf;
    856      }
    857    }
    858  }
    859  *ref = NULL;
    860  return NULL;
    861 }
    862 
    863 /// Compare two marks
    864 static inline bool marks_equal(const pos_T a, const pos_T b)
    865 {
    866  return (a.lnum == b.lnum) && (a.col == b.col);
    867 }
    868 
    869 /// adjust "jumps_arr" to make space to insert an item just before the item at "i"
    870 /// (or after the last if i == jl_len)
    871 ///
    872 /// Higher incidies indicate newer items. If the list is full, discard the oldest item
    873 /// (or don't insert the considered item if it is older)
    874 ///
    875 /// @return the actual position a new item should be inserted or -1 if it shouldn't be inserted
    876 static int marklist_insert(void *jumps_arr, size_t jump_size, int jl_len, int i)
    877 {
    878  char *jumps = (char *)jumps_arr;  // for pointer maffs
    879  if (i > 0) {
    880    if (jl_len == JUMPLISTSIZE) {
    881      i--;
    882      if (i > 0) {
    883        // delete oldest item to make room for new element
    884        memmove(jumps, jumps + jump_size, jump_size * (size_t)i);
    885      }
    886    } else if (i != jl_len) {
    887      // insert at position i, move newer items out of the way
    888      memmove(jumps + (size_t)(i + 1) * jump_size, jumps + (size_t)i * jump_size,
    889              jump_size * (size_t)(jl_len - i));
    890    }
    891  } else if (i == 0) {
    892    if (jl_len == JUMPLISTSIZE) {
    893      return -1;  // don't insert, older than the entire list
    894    } else if (jl_len > 0) {
    895      // insert i as the oldest item
    896      memmove(jumps + jump_size, jumps, jump_size * (size_t)jl_len);
    897    }
    898  }
    899  return i;
    900 }
    901 
    902 /// Read data from ShaDa file
    903 ///
    904 /// @param[in]  sd_reader  Structure containing file reader definition.
    905 /// @param[in]  flags      What to read, see ShaDaReadFileFlags enum.
    906 static void shada_read(FileDescriptor *const sd_reader, const int flags)
    907  FUNC_ATTR_NONNULL_ALL
    908 {
    909  list_T *oldfiles_list = get_vim_var_list(VV_OLDFILES);
    910  const bool force = flags & kShaDaForceit;
    911  const bool get_old_files = (flags & (kShaDaGetOldfiles | kShaDaForceit)
    912                              && (force || tv_list_len(oldfiles_list) == 0));
    913  const bool want_marks = flags & kShaDaWantMarks;
    914  const unsigned srni_flags =
    915    (unsigned)(
    916               (flags & kShaDaWantInfo
    917                ? (kSDReadUndisableableData
    918                   | kSDReadRegisters
    919                   | kSDReadGlobalMarks
    920                   | (p_hi ? kSDReadHistory : 0)
    921                   | (find_shada_parameter('!') != NULL
    922                      ? kSDReadVariables
    923                      : 0)
    924                   | (find_shada_parameter('%') != NULL
    925                      && ARGCOUNT == 0
    926                      ? kSDReadBufferList
    927                      : 0))
    928                : 0)
    929               | (want_marks && get_shada_parameter('\'') > 0
    930                  ? kSDReadLocalMarks | kSDReadChanges
    931                  : 0)
    932               | (get_old_files
    933                  ? kSDReadLocalMarks
    934                  : 0));
    935  if (srni_flags == 0) {
    936    // Nothing to do.
    937    return;
    938  }
    939  HistoryMergerState hms[HIST_COUNT];
    940  if (srni_flags & kSDReadHistory) {
    941    for (int i = 0; i < HIST_COUNT; i++) {
    942      hms_init(&hms[i], (uint8_t)i, (size_t)p_hi, true, true);
    943    }
    944  }
    945  ShadaEntry cur_entry;
    946  Set(ptr_t) cl_bufs = SET_INIT;
    947  PMap(cstr_t) fname_bufs = MAP_INIT;
    948  Set(cstr_t) oldfiles_set = SET_INIT;
    949  if (get_old_files && (oldfiles_list == NULL || force)) {
    950    oldfiles_list = tv_list_alloc(kListLenUnknown);
    951    set_vim_var_list(VV_OLDFILES, oldfiles_list);
    952  }
    953  ShaDaReadResult srni_ret;
    954  while ((srni_ret = shada_read_next_item(sd_reader, &cur_entry, srni_flags, 0))
    955         != kSDReadStatusFinished) {
    956    switch (srni_ret) {
    957    case kSDReadStatusSuccess:
    958      break;
    959    case kSDReadStatusFinished:
    960      // Should be handled by the while condition.
    961      abort();
    962    case kSDReadStatusNotShaDa:
    963    case kSDReadStatusReadError:
    964      goto shada_read_main_cycle_end;
    965    case kSDReadStatusMalformed:
    966      continue;
    967    }
    968    switch (cur_entry.type) {
    969    case kSDItemMissing:
    970      abort();
    971    case kSDItemUnknown:
    972      break;
    973    case kSDItemHeader:
    974      shada_free_shada_entry(&cur_entry);
    975      break;
    976    case kSDItemSearchPattern:
    977      if (!force) {
    978        SearchPattern pat;
    979        if (cur_entry.data.search_pattern.is_substitute_pattern) {
    980          get_substitute_pattern(&pat);
    981        } else {
    982          get_search_pattern(&pat);
    983        }
    984        if (pat.pat != NULL && pat.timestamp >= cur_entry.timestamp) {
    985          shada_free_shada_entry(&cur_entry);
    986          break;
    987        }
    988      }
    989 
    990      SearchPattern spat = (SearchPattern) {
    991        .magic = cur_entry.data.search_pattern.magic,
    992        .no_scs = !cur_entry.data.search_pattern.smartcase,
    993        .off = {
    994          .dir = cur_entry.data.search_pattern.search_backward ? '?' : '/',
    995          .line = cur_entry.data.search_pattern.has_line_offset,
    996          .end = cur_entry.data.search_pattern.place_cursor_at_end,
    997          .off = cur_entry.data.search_pattern.offset,
    998        },
    999        .pat = cur_entry.data.search_pattern.pat.data,
   1000        .patlen = cur_entry.data.search_pattern.pat.size,
   1001        .additional_data = cur_entry.additional_data,
   1002        .timestamp = cur_entry.timestamp,
   1003      };
   1004 
   1005      if (cur_entry.data.search_pattern.is_substitute_pattern) {
   1006        set_substitute_pattern(spat);
   1007      } else {
   1008        set_search_pattern(spat);
   1009      }
   1010 
   1011      if (cur_entry.data.search_pattern.is_last_used) {
   1012        set_last_used_pattern(cur_entry.data.search_pattern.is_substitute_pattern);
   1013        set_no_hlsearch(!cur_entry.data.search_pattern.highlighted);
   1014      }
   1015      // Do not free shada entry: its allocated memory was saved above.
   1016      break;
   1017    case kSDItemSubString:
   1018      if (!force) {
   1019        SubReplacementString sub;
   1020        sub_get_replacement(&sub);
   1021        if (sub.sub != NULL && sub.timestamp >= cur_entry.timestamp) {
   1022          shada_free_shada_entry(&cur_entry);
   1023          break;
   1024        }
   1025      }
   1026      sub_set_replacement((SubReplacementString) {
   1027        .sub = cur_entry.data.sub_string.sub,
   1028        .timestamp = cur_entry.timestamp,
   1029        .additional_data = cur_entry.additional_data,
   1030      });
   1031      // Without using regtilde and without / &cpo flag previous substitute
   1032      // string is close to useless: you can only use it with :& or :~ and
   1033      // that’s all because s//~ is not available until the first call to
   1034      // regtilde. Vim was not calling this for some reason.
   1035      regtilde(cur_entry.data.sub_string.sub, magic_isset(), false);
   1036      // Do not free shada entry: its allocated memory was saved above.
   1037      break;
   1038    case kSDItemHistoryEntry:
   1039      if (cur_entry.data.history_item.histtype >= HIST_COUNT) {
   1040        shada_free_shada_entry(&cur_entry);
   1041        break;
   1042      }
   1043      hms_insert(hms + cur_entry.data.history_item.histtype, cur_entry, true);
   1044      // Do not free shada entry: its allocated memory was saved above.
   1045      break;
   1046    case kSDItemRegister:
   1047      if (cur_entry.data.reg.type != kMTCharWise
   1048          && cur_entry.data.reg.type != kMTLineWise
   1049          && cur_entry.data.reg.type != kMTBlockWise) {
   1050        shada_free_shada_entry(&cur_entry);
   1051        break;
   1052      }
   1053      if (!force) {
   1054        const yankreg_T *const reg = op_reg_get(cur_entry.data.reg.name);
   1055        if (reg == NULL || reg->timestamp >= cur_entry.timestamp) {
   1056          shada_free_shada_entry(&cur_entry);
   1057          break;
   1058        }
   1059      }
   1060      if (!op_reg_set(cur_entry.data.reg.name, (yankreg_T) {
   1061        .y_array = cur_entry.data.reg.contents,
   1062        .y_size = cur_entry.data.reg.contents_size,
   1063        .y_type = cur_entry.data.reg.type,
   1064        .y_width = (colnr_T)cur_entry.data.reg.width,
   1065        .timestamp = cur_entry.timestamp,
   1066        .additional_data = cur_entry.additional_data,
   1067      }, cur_entry.data.reg.is_unnamed)) {
   1068        shada_free_shada_entry(&cur_entry);
   1069      }
   1070      // Do not free shada entry: its allocated memory was saved above.
   1071      break;
   1072    case kSDItemVariable:
   1073      var_set_global(cur_entry.data.global_var.name,
   1074                     cur_entry.data.global_var.value);
   1075      cur_entry.data.global_var.value.v_type = VAR_UNKNOWN;
   1076      shada_free_shada_entry(&cur_entry);
   1077      break;
   1078    case kSDItemJump:
   1079    case kSDItemGlobalMark: {
   1080      buf_T *buf = find_buffer(&fname_bufs, cur_entry.data.filemark.fname);
   1081      if (buf != NULL) {
   1082        XFREE_CLEAR(cur_entry.data.filemark.fname);
   1083      }
   1084      xfmark_T fm = (xfmark_T) {
   1085        .fname = buf == NULL ? cur_entry.data.filemark.fname : NULL,
   1086        .fmark = {
   1087          .mark = cur_entry.data.filemark.mark,
   1088          .fnum = (buf == NULL ? 0 : buf->b_fnum),
   1089          .timestamp = cur_entry.timestamp,
   1090          .view = INIT_FMARKV,
   1091          .additional_data = cur_entry.additional_data,
   1092        },
   1093      };
   1094      if (cur_entry.type == kSDItemGlobalMark) {
   1095        if (!mark_set_global(cur_entry.data.filemark.name, fm, !force)) {
   1096          shada_free_shada_entry(&cur_entry);
   1097          break;
   1098        }
   1099      } else {
   1100        int i;
   1101        for (i = curwin->w_jumplistlen; i > 0; i--) {
   1102          const xfmark_T jl_entry = curwin->w_jumplist[i - 1];
   1103          if (jl_entry.fmark.timestamp <= cur_entry.timestamp) {
   1104            if (marks_equal(jl_entry.fmark.mark, cur_entry.data.filemark.mark)
   1105                && (buf == NULL
   1106                    ? (jl_entry.fname != NULL && strcmp(fm.fname, jl_entry.fname) == 0)
   1107                    : fm.fmark.fnum == jl_entry.fmark.fnum)) {
   1108              i = -1;
   1109            }
   1110            break;
   1111          }
   1112        }
   1113        if (i > 0 && curwin->w_jumplistlen == JUMPLISTSIZE) {
   1114          free_xfmark(curwin->w_jumplist[0]);
   1115        }
   1116        i = marklist_insert(curwin->w_jumplist, sizeof(*curwin->w_jumplist),
   1117                            curwin->w_jumplistlen, i);
   1118 
   1119        if (i != -1) {
   1120          curwin->w_jumplist[i] = fm;
   1121          if (curwin->w_jumplistlen < JUMPLISTSIZE) {
   1122            curwin->w_jumplistlen++;
   1123          }
   1124          if (curwin->w_jumplistidx >= i && curwin->w_jumplistidx + 1 <= curwin->w_jumplistlen) {
   1125            curwin->w_jumplistidx++;
   1126          }
   1127        } else {
   1128          shada_free_shada_entry(&cur_entry);
   1129        }
   1130      }
   1131 
   1132      // Do not free shada entry: its allocated memory was saved above.
   1133      break;
   1134    }
   1135    case kSDItemBufferList:
   1136      for (size_t i = 0; i < cur_entry.data.buffer_list.size; i++) {
   1137        char *const sfname =
   1138          path_try_shorten_fname(cur_entry.data.buffer_list.buffers[i].fname);
   1139        buf_T *const buf =
   1140          buflist_new(cur_entry.data.buffer_list.buffers[i].fname, sfname, 0, BLN_LISTED);
   1141        if (buf != NULL) {
   1142          fmarkv_T view = INIT_FMARKV;
   1143          RESET_FMARK(&buf->b_last_cursor,
   1144                      cur_entry.data.buffer_list.buffers[i].pos, 0, view);
   1145          buflist_setfpos(buf, curwin, buf->b_last_cursor.mark.lnum,
   1146                          buf->b_last_cursor.mark.col, false);
   1147 
   1148          xfree(buf->additional_data);
   1149          buf->additional_data = cur_entry.data.buffer_list.buffers[i].additional_data;
   1150          cur_entry.data.buffer_list.buffers[i].additional_data = NULL;
   1151        }
   1152      }
   1153      shada_free_shada_entry(&cur_entry);
   1154      break;
   1155    case kSDItemChange:
   1156    case kSDItemLocalMark: {
   1157      if (get_old_files && !set_has(cstr_t, &oldfiles_set, cur_entry.data.filemark.fname)) {
   1158        char *fname = cur_entry.data.filemark.fname;
   1159        if (want_marks) {
   1160          // Do not bother with allocating memory for the string if already
   1161          // allocated string from cur_entry can be used. It cannot be used if
   1162          // want_marks is set because this way it may be used for a mark.
   1163          fname = xstrdup(fname);
   1164        }
   1165        set_put(cstr_t, &oldfiles_set, fname);
   1166        tv_list_append_allocated_string(oldfiles_list, fname);
   1167        if (!want_marks) {
   1168          // Avoid free because this string was already used.
   1169          cur_entry.data.filemark.fname = NULL;
   1170        }
   1171      }
   1172      if (!want_marks) {
   1173        shada_free_shada_entry(&cur_entry);
   1174        break;
   1175      }
   1176      buf_T *buf = find_buffer(&fname_bufs, cur_entry.data.filemark.fname);
   1177      if (buf == NULL) {
   1178        shada_free_shada_entry(&cur_entry);
   1179        break;
   1180      }
   1181      const fmark_T fm = (fmark_T) {
   1182        .mark = cur_entry.data.filemark.mark,
   1183        .fnum = 0,
   1184        .timestamp = cur_entry.timestamp,
   1185        .view = INIT_FMARKV,
   1186        .additional_data = cur_entry.additional_data,
   1187      };
   1188      if (cur_entry.type == kSDItemLocalMark) {
   1189        if (!mark_set_local(cur_entry.data.filemark.name, buf, fm, !force)) {
   1190          shada_free_shada_entry(&cur_entry);
   1191          break;
   1192        }
   1193      } else {
   1194        set_put(ptr_t, &cl_bufs, buf);
   1195        int i;
   1196        for (i = buf->b_changelistlen; i > 0; i--) {
   1197          const fmark_T jl_entry = buf->b_changelist[i - 1];
   1198          if (jl_entry.timestamp <= cur_entry.timestamp) {
   1199            if (marks_equal(jl_entry.mark, cur_entry.data.filemark.mark)) {
   1200              i = -1;
   1201            }
   1202            break;
   1203          }
   1204        }
   1205        if (i > 0 && buf->b_changelistlen == JUMPLISTSIZE) {
   1206          free_fmark(buf->b_changelist[0]);
   1207        }
   1208        i = marklist_insert(buf->b_changelist, sizeof(*buf->b_changelist), buf->b_changelistlen, i);
   1209        if (i != -1) {
   1210          buf->b_changelist[i] = fm;
   1211          if (buf->b_changelistlen < JUMPLISTSIZE) {
   1212            buf->b_changelistlen++;
   1213          }
   1214        } else {
   1215          xfree(fm.additional_data);
   1216        }
   1217      }
   1218      // only free fname part of shada entry, as additional_data was saved or freed above.
   1219      xfree(cur_entry.data.filemark.fname);
   1220      break;
   1221    }
   1222    }
   1223  }
   1224 shada_read_main_cycle_end:
   1225  // Warning: shada_hist_iter returns ShadaEntry elements which use strings from
   1226  //          original history list. This means that once such entry is removed
   1227  //          from the history Neovim array will no longer be valid. To reduce
   1228  //          amount of memory allocations ShaDa file reader allocates enough
   1229  //          memory for the history string itself and separator character which
   1230  //          may be assigned right away.
   1231  if (srni_flags & kSDReadHistory) {
   1232    for (int i = 0; i < HIST_COUNT; i++) {
   1233      hms_insert_whole_neovim_history(&hms[i]);
   1234      clr_history(i);
   1235      int *new_hisidx;
   1236      int *new_hisnum;
   1237      histentry_T *hist = hist_get_array((uint8_t)i, &new_hisidx, &new_hisnum);
   1238      if (hist != NULL) {
   1239        hms_to_he_array(&hms[i], hist, new_hisidx, new_hisnum);
   1240      }
   1241      hms_dealloc(&hms[i]);
   1242    }
   1243  }
   1244  if (cl_bufs.h.n_occupied) {
   1245    FOR_ALL_TAB_WINDOWS(tp, wp) {
   1246      (void)tp;
   1247      if (set_has(ptr_t, &cl_bufs, wp->w_buffer)) {
   1248        wp->w_changelistidx = wp->w_buffer->b_changelistlen;
   1249      }
   1250    }
   1251  }
   1252  set_destroy(ptr_t, &cl_bufs);
   1253  const char *key;
   1254  map_foreach_key(&fname_bufs, key, {
   1255    xfree((char *)key);
   1256  })
   1257  map_destroy(cstr_t, &fname_bufs);
   1258  set_destroy(cstr_t, &oldfiles_set);
   1259 }
   1260 
   1261 /// Default shada file location: cached path
   1262 static char *default_shada_file = NULL;
   1263 
   1264 /// Get the default ShaDa file
   1265 static const char *shada_get_default_file(void)
   1266  FUNC_ATTR_WARN_UNUSED_RESULT
   1267 {
   1268  if (default_shada_file == NULL) {
   1269    char *shada_dir = stdpaths_user_state_subpath("shada", 0, false);
   1270    default_shada_file = concat_fnames_realloc(shada_dir, "main.shada", true);
   1271  }
   1272  return default_shada_file;
   1273 }
   1274 
   1275 /// Get the ShaDa file name to use
   1276 ///
   1277 /// If "file" is given and not empty, use it (has already been expanded by
   1278 /// cmdline functions). Otherwise use "-i file_name", value from 'shada' or the
   1279 /// default, and expand environment variables.
   1280 ///
   1281 /// @param[in]  file  Forced file name or NULL.
   1282 ///
   1283 /// @return  An allocated string containing shada file name,
   1284 ///          or NULL if shada file should not be used.
   1285 static char *shada_filename(const char *file)
   1286  FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
   1287 {
   1288  if (file == NULL || *file == NUL) {
   1289    if (p_shadafile != NULL && *p_shadafile != NUL) {
   1290      // Check if writing to ShaDa file was disabled ("-i NONE" or "--clean").
   1291      if (!strequal(p_shadafile, "NONE")) {
   1292        file = p_shadafile;
   1293      } else {
   1294        return NULL;
   1295      }
   1296    } else {
   1297      if ((file = find_shada_parameter('n')) == NULL || *file == NUL) {
   1298        file = shada_get_default_file();
   1299      }
   1300      // XXX It used to be one level lower, so that whatever is in
   1301      //     `p_shadafile` was expanded. I intentionally moved it here
   1302      //     because various expansions must have already be done by the shell.
   1303      //     If shell is not performing them then they should be done in main.c
   1304      //     where arguments are parsed, *not here*.
   1305      size_t len = expand_env((char *)file, &(NameBuff[0]), MAXPATHL);
   1306      file = &(NameBuff[0]);
   1307      return xmemdupz(file, len);
   1308    }
   1309  }
   1310  return xstrdup(file);
   1311 }
   1312 
   1313 #define KEY_NAME_(s) #s
   1314 #define PACK_KEY(s) mpack_str(STATIC_CSTR_AS_STRING(KEY_NAME_(s)), &sbuf);
   1315 #define KEY_NAME(s) KEY_NAME_(s)
   1316 
   1317 #define SHADA_MPACK_FREE_SPACE (4 * MPACK_ITEM_SIZE)
   1318 
   1319 static void shada_check_buffer(PackerBuffer *packer)
   1320 {
   1321  if (mpack_remaining(packer) < SHADA_MPACK_FREE_SPACE) {
   1322    packer->packer_flush(packer);
   1323  }
   1324 }
   1325 
   1326 static uint32_t additional_data_len(AdditionalData *src)
   1327 {
   1328  return src ? src->nitems : 0;
   1329 }
   1330 
   1331 static void dump_additional_data(AdditionalData *src, PackerBuffer *sbuf)
   1332 {
   1333  if (src != NULL) {
   1334    mpack_raw(src->data, src->nbytes, sbuf);
   1335  }
   1336 }
   1337 
   1338 /// Write single ShaDa entry
   1339 ///
   1340 /// @param[in]  packer     Packer used to write entry.
   1341 /// @param[in]  entry      Entry written.
   1342 /// @param[in]  max_kbyte  Maximum size of an item in KiB. Zero means no
   1343 ///                        restrictions.
   1344 ///
   1345 /// @return kSDWriteSuccessful, kSDWriteFailed or kSDWriteIgnError.
   1346 static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry entry,
   1347                                         const size_t max_kbyte)
   1348  FUNC_ATTR_NONNULL_ALL
   1349 {
   1350  ShaDaWriteResult ret = kSDWriteFailed;
   1351  PackerBuffer sbuf = packer_string_buffer();
   1352 
   1353 #define CHECK_DEFAULT(entry, attr) \
   1354  (sd_default_values[(entry).type].data.attr == (entry).data.attr)
   1355 #define ONE_IF_NOT_DEFAULT(entry, attr) \
   1356  ((uint32_t)(!CHECK_DEFAULT(entry, attr)))
   1357 
   1358 #define PACK_BOOL(entry, name, attr) \
   1359  do { \
   1360    if (!CHECK_DEFAULT(entry, search_pattern.attr)) { \
   1361      PACK_KEY(name); \
   1362      mpack_bool(&sbuf.ptr, !sd_default_values[(entry).type].data.search_pattern.attr); \
   1363    } \
   1364  } while (0)
   1365 
   1366  shada_check_buffer(&sbuf);
   1367  switch (entry.type) {
   1368  case kSDItemMissing:
   1369    abort();
   1370  case kSDItemUnknown:
   1371    mpack_raw(entry.data.unknown_item.contents, entry.data.unknown_item.size, &sbuf);
   1372    break;
   1373  case kSDItemHistoryEntry: {
   1374    const bool is_hist_search =
   1375      entry.data.history_item.histtype == HIST_SEARCH;
   1376    uint32_t arr_size = (2 + (uint32_t)is_hist_search
   1377                         + additional_data_len(entry.additional_data));
   1378    mpack_array(&sbuf.ptr, arr_size);
   1379    mpack_uint(&sbuf.ptr, entry.data.history_item.histtype);
   1380    mpack_bin(cstr_as_string(entry.data.history_item.string), &sbuf);
   1381    if (is_hist_search) {
   1382      mpack_uint(&sbuf.ptr, (uint8_t)entry.data.history_item.sep);
   1383    }
   1384    dump_additional_data(entry.additional_data, &sbuf);
   1385    break;
   1386  }
   1387  case kSDItemVariable: {
   1388    bool is_blob = (entry.data.global_var.value.v_type == VAR_BLOB);
   1389    uint32_t arr_size = 2 + (is_blob ? 1 : 0) + additional_data_len(entry.additional_data);
   1390    mpack_array(&sbuf.ptr, arr_size);
   1391    const String varname = cstr_as_string(entry.data.global_var.name);
   1392    mpack_bin(varname, &sbuf);
   1393    char vardesc[256] = "variable g:";
   1394    memcpy(&vardesc[sizeof("variable g:") - 1], varname.data,
   1395           varname.size + 1);
   1396    if (encode_vim_to_msgpack(&sbuf, &entry.data.global_var.value, vardesc)
   1397        == FAIL) {
   1398      ret = kSDWriteIgnError;
   1399      semsg(_(WERR "Failed to write variable %s"),
   1400            entry.data.global_var.name);
   1401      goto shada_pack_entry_error;
   1402    }
   1403    if (is_blob) {
   1404      mpack_check_buffer(&sbuf);
   1405      mpack_integer(&sbuf.ptr, VAR_TYPE_BLOB);
   1406    }
   1407    dump_additional_data(entry.additional_data, &sbuf);
   1408    break;
   1409  }
   1410  case kSDItemSubString: {
   1411    uint32_t arr_size = 1 + additional_data_len(entry.additional_data);
   1412    mpack_array(&sbuf.ptr, arr_size);
   1413    mpack_bin(cstr_as_string(entry.data.sub_string.sub), &sbuf);
   1414    dump_additional_data(entry.additional_data, &sbuf);
   1415    break;
   1416  }
   1417  case kSDItemSearchPattern: {
   1418    uint32_t entry_map_size = (1  // Search pattern is always present
   1419                               + ONE_IF_NOT_DEFAULT(entry, search_pattern.magic)
   1420                               + ONE_IF_NOT_DEFAULT(entry, search_pattern.is_last_used)
   1421                               + ONE_IF_NOT_DEFAULT(entry, search_pattern.smartcase)
   1422                               + ONE_IF_NOT_DEFAULT(entry, search_pattern.has_line_offset)
   1423                               + ONE_IF_NOT_DEFAULT(entry, search_pattern.place_cursor_at_end)
   1424                               + ONE_IF_NOT_DEFAULT(entry,
   1425                                                    search_pattern.is_substitute_pattern)
   1426                               + ONE_IF_NOT_DEFAULT(entry, search_pattern.highlighted)
   1427                               + ONE_IF_NOT_DEFAULT(entry, search_pattern.offset)
   1428                               + ONE_IF_NOT_DEFAULT(entry, search_pattern.search_backward)
   1429                               + additional_data_len(entry.additional_data));
   1430    mpack_map(&sbuf.ptr, entry_map_size);
   1431    PACK_KEY(SEARCH_KEY_PAT);
   1432    mpack_bin(entry.data.search_pattern.pat, &sbuf);
   1433    PACK_BOOL(entry, SEARCH_KEY_MAGIC, magic);
   1434    PACK_BOOL(entry, SEARCH_KEY_IS_LAST_USED, is_last_used);
   1435    PACK_BOOL(entry, SEARCH_KEY_SMARTCASE, smartcase);
   1436    PACK_BOOL(entry, SEARCH_KEY_HAS_LINE_OFFSET, has_line_offset);
   1437    PACK_BOOL(entry, SEARCH_KEY_PLACE_CURSOR_AT_END, place_cursor_at_end);
   1438    PACK_BOOL(entry, SEARCH_KEY_IS_SUBSTITUTE_PATTERN, is_substitute_pattern);
   1439    PACK_BOOL(entry, SEARCH_KEY_HIGHLIGHTED, highlighted);
   1440    PACK_BOOL(entry, SEARCH_KEY_BACKWARD, search_backward);
   1441    if (!CHECK_DEFAULT(entry, search_pattern.offset)) {
   1442      PACK_KEY(SEARCH_KEY_OFFSET);
   1443      mpack_integer(&sbuf.ptr, entry.data.search_pattern.offset);
   1444    }
   1445 #undef PACK_BOOL
   1446    dump_additional_data(entry.additional_data, &sbuf);
   1447    break;
   1448  }
   1449  case kSDItemChange:
   1450  case kSDItemGlobalMark:
   1451  case kSDItemLocalMark:
   1452  case kSDItemJump: {
   1453    size_t entry_map_size = (1  // File name
   1454                             + ONE_IF_NOT_DEFAULT(entry, filemark.mark.lnum)
   1455                             + ONE_IF_NOT_DEFAULT(entry, filemark.mark.col)
   1456                             + ONE_IF_NOT_DEFAULT(entry, filemark.name)
   1457                             + additional_data_len(entry.additional_data));
   1458    mpack_map(&sbuf.ptr, (uint32_t)entry_map_size);
   1459    PACK_KEY(KEY_FILE);
   1460    mpack_bin(cstr_as_string(entry.data.filemark.fname), &sbuf);
   1461    if (!CHECK_DEFAULT(entry, filemark.mark.lnum)) {
   1462      PACK_KEY(KEY_LNUM);
   1463      mpack_integer(&sbuf.ptr, entry.data.filemark.mark.lnum);
   1464    }
   1465    if (!CHECK_DEFAULT(entry, filemark.mark.col)) {
   1466      PACK_KEY(KEY_COL);
   1467      mpack_integer(&sbuf.ptr, entry.data.filemark.mark.col);
   1468    }
   1469    assert(entry.type == kSDItemJump || entry.type == kSDItemChange
   1470           ? CHECK_DEFAULT(entry, filemark.name)
   1471           : true);
   1472    if (!CHECK_DEFAULT(entry, filemark.name)) {
   1473      PACK_KEY(KEY_NAME_CHAR);
   1474      mpack_uint(&sbuf.ptr, (uint8_t)entry.data.filemark.name);
   1475    }
   1476    dump_additional_data(entry.additional_data, &sbuf);
   1477    break;
   1478  }
   1479  case kSDItemRegister: {
   1480    uint32_t entry_map_size = (2  // Register contents and name
   1481                               + ONE_IF_NOT_DEFAULT(entry, reg.type)
   1482                               + ONE_IF_NOT_DEFAULT(entry, reg.width)
   1483                               + ONE_IF_NOT_DEFAULT(entry, reg.is_unnamed)
   1484                               + additional_data_len(entry.additional_data));
   1485 
   1486    mpack_map(&sbuf.ptr, entry_map_size);
   1487    PACK_KEY(REG_KEY_CONTENTS);
   1488    mpack_array(&sbuf.ptr, (uint32_t)entry.data.reg.contents_size);
   1489    for (size_t i = 0; i < entry.data.reg.contents_size; i++) {
   1490      mpack_bin(entry.data.reg.contents[i], &sbuf);
   1491    }
   1492    PACK_KEY(KEY_NAME_CHAR);
   1493    mpack_uint(&sbuf.ptr, (uint8_t)entry.data.reg.name);
   1494    if (!CHECK_DEFAULT(entry, reg.type)) {
   1495      PACK_KEY(REG_KEY_TYPE);
   1496      mpack_uint(&sbuf.ptr, (uint8_t)entry.data.reg.type);
   1497    }
   1498    if (!CHECK_DEFAULT(entry, reg.width)) {
   1499      PACK_KEY(REG_KEY_WIDTH);
   1500      mpack_uint64(&sbuf.ptr, (uint64_t)entry.data.reg.width);
   1501    }
   1502    if (!CHECK_DEFAULT(entry, reg.is_unnamed)) {
   1503      PACK_KEY(REG_KEY_UNNAMED);
   1504      mpack_bool(&sbuf.ptr, entry.data.reg.is_unnamed);
   1505    }
   1506    dump_additional_data(entry.additional_data, &sbuf);
   1507    break;
   1508  }
   1509  case kSDItemBufferList:
   1510    mpack_array(&sbuf.ptr, (uint32_t)entry.data.buffer_list.size);
   1511    for (size_t i = 0; i < entry.data.buffer_list.size; i++) {
   1512      size_t entry_map_size = (1  // Buffer name
   1513                               + (size_t)(entry.data.buffer_list.buffers[i].pos.lnum
   1514                                          != default_pos.lnum)
   1515                               + (size_t)(entry.data.buffer_list.buffers[i].pos.col
   1516                                          != default_pos.col)
   1517                               + additional_data_len(entry.data.buffer_list.buffers[i].
   1518                                                     additional_data));
   1519      mpack_map(&sbuf.ptr, (uint32_t)entry_map_size);
   1520      PACK_KEY(KEY_FILE);
   1521      mpack_bin(cstr_as_string(entry.data.buffer_list.buffers[i].fname), &sbuf);
   1522      if (entry.data.buffer_list.buffers[i].pos.lnum != 1) {
   1523        PACK_KEY(KEY_LNUM);
   1524        mpack_uint64(&sbuf.ptr, (uint64_t)entry.data.buffer_list.buffers[i].pos.lnum);
   1525      }
   1526      if (entry.data.buffer_list.buffers[i].pos.col != 0) {
   1527        PACK_KEY(KEY_COL);
   1528        mpack_uint64(&sbuf.ptr, (uint64_t)entry.data.buffer_list.buffers[i].pos.col);
   1529      }
   1530      dump_additional_data(entry.data.buffer_list.buffers[i].additional_data, &sbuf);
   1531    }
   1532    break;
   1533  case kSDItemHeader:
   1534    mpack_map(&sbuf.ptr, (uint32_t)entry.data.header.size);
   1535    for (size_t i = 0; i < entry.data.header.size; i++) {
   1536      mpack_str(entry.data.header.items[i].key, &sbuf);
   1537      const Object obj = entry.data.header.items[i].value;
   1538      switch (obj.type) {
   1539      case kObjectTypeString:
   1540        mpack_bin(obj.data.string, &sbuf);
   1541        break;
   1542      case kObjectTypeInteger:
   1543        mpack_integer(&sbuf.ptr, obj.data.integer);
   1544        break;
   1545      default:
   1546        abort();
   1547      }
   1548    }
   1549    break;
   1550  }
   1551 #undef CHECK_DEFAULT
   1552 #undef ONE_IF_NOT_DEFAULT
   1553  String packed = packer_take_string(&sbuf);
   1554  if (!max_kbyte || packed.size <= max_kbyte * 1024) {
   1555    shada_check_buffer(packer);
   1556 
   1557    if (entry.type == kSDItemUnknown) {
   1558      mpack_uint64(&packer->ptr, entry.data.unknown_item.type);
   1559    } else {
   1560      mpack_uint64(&packer->ptr, (uint64_t)entry.type);
   1561    }
   1562    mpack_uint64(&packer->ptr, (uint64_t)entry.timestamp);
   1563    if (packed.size > 0) {
   1564      mpack_uint64(&packer->ptr, (uint64_t)packed.size);
   1565      mpack_raw(packed.data, packed.size, packer);
   1566    }
   1567 
   1568    if (packer->anyint != 0) {  // error code
   1569      goto shada_pack_entry_error;
   1570    }
   1571  }
   1572  ret = kSDWriteSuccessful;
   1573 shada_pack_entry_error:
   1574  xfree(sbuf.startptr);
   1575  return ret;
   1576 }
   1577 
   1578 /// Write single ShaDa entry and free it afterwards
   1579 ///
   1580 /// Will not free if entry could not be freed.
   1581 ///
   1582 /// @param[in]  packer     Packer used to write entry.
   1583 /// @param[in]  entry      Entry written.
   1584 /// @param[in]  max_kbyte  Maximum size of an item in KiB. Zero means no
   1585 ///                        restrictions.
   1586 static inline ShaDaWriteResult shada_pack_pfreed_entry(PackerBuffer *const packer, ShadaEntry entry,
   1587                                                       const size_t max_kbyte)
   1588  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE
   1589 {
   1590  ShaDaWriteResult ret = shada_pack_entry(packer, entry, max_kbyte);
   1591  shada_free_shada_entry(&entry);
   1592  return ret;
   1593 }
   1594 
   1595 /// Compare two FileMarks structure to order them by greatest_timestamp
   1596 ///
   1597 /// Order is reversed: structure with greatest greatest_timestamp comes first.
   1598 /// Function signature is compatible with qsort.
   1599 static int compare_file_marks(const void *a, const void *b)
   1600  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
   1601 {
   1602  const FileMarks *const *const a_fms = a;
   1603  const FileMarks *const *const b_fms = b;
   1604  return ((*a_fms)->greatest_timestamp == (*b_fms)->greatest_timestamp
   1605          ? 0
   1606          : ((*a_fms)->greatest_timestamp > (*b_fms)->greatest_timestamp ? -1 : 1));
   1607 }
   1608 
   1609 /// Parse msgpack object that has given length
   1610 ///
   1611 /// @param[in]   sd_reader     Structure containing file reader definition.
   1612 /// @param[in]   length        Object length.
   1613 /// @param[out]  ret_unpacked  Location where read result should be saved. If
   1614 ///                            NULL then unpacked data will be freed. Must be
   1615 ///                            NULL if `ret_buf` is NULL.
   1616 /// @param[out]  ret_buf       Buffer containing parsed string.
   1617 ///
   1618 /// @return kSDReadStatusNotShaDa, kSDReadStatusReadError or
   1619 ///         kSDReadStatusSuccess.
   1620 static ShaDaReadResult shada_check_status(uintmax_t initial_fpos, int status, size_t remaining)
   1621  FUNC_ATTR_WARN_UNUSED_RESULT
   1622 {
   1623  switch (status) {
   1624  case MPACK_OK:
   1625    if (remaining) {
   1626      semsg(_(RCERR "Failed to parse ShaDa file: extra bytes in msgpack string "
   1627              "at position %" PRIu64),
   1628            (uint64_t)initial_fpos);
   1629      return kSDReadStatusNotShaDa;
   1630    }
   1631    return kSDReadStatusSuccess;
   1632  case MPACK_EOF:
   1633    semsg(_(RCERR "Failed to parse ShaDa file: incomplete msgpack string "
   1634            "at position %" PRIu64),
   1635          (uint64_t)initial_fpos);
   1636    return kSDReadStatusNotShaDa;
   1637  default:
   1638    semsg(_(RCERR "Failed to parse ShaDa file due to a msgpack parser error "
   1639            "at position %" PRIu64),
   1640          (uint64_t)initial_fpos);
   1641    return kSDReadStatusNotShaDa;
   1642  }
   1643 }
   1644 
   1645 /// Format shada entry for debugging purposes
   1646 ///
   1647 /// @param[in]  entry  ShaDa entry to format.
   1648 ///
   1649 /// @return string representing ShaDa entry in a static buffer.
   1650 static const char *shada_format_entry(const ShadaEntry entry)
   1651  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_UNUSED FUNC_ATTR_NONNULL_RET
   1652 {
   1653  static char ret[1024];
   1654  ret[0] = 0;
   1655  vim_snprintf(S_LEN(ret), "%s", "[ ] ts=%" PRIu64 " ");
   1656  //                         ^ Space for `can_free_entry`
   1657 #define FORMAT_MARK_ENTRY(entry_name, name_fmt, name_fmt_arg) \
   1658  do { \
   1659    vim_snprintf_add(S_LEN(ret), \
   1660                     entry_name " {" name_fmt " file=[%zu]\"%.512s\", " \
   1661                     "pos={l=%" PRIdLINENR ",c=%" PRIdCOLNR ",a=%" PRIdCOLNR "}, " \
   1662                     "}", \
   1663                     name_fmt_arg, \
   1664                     strlen(entry.data.filemark.fname), \
   1665                     entry.data.filemark.fname, \
   1666                     entry.data.filemark.mark.lnum, \
   1667                     entry.data.filemark.mark.col, \
   1668                     entry.data.filemark.mark.coladd); \
   1669  } while (0)
   1670  switch (entry.type) {
   1671  case kSDItemMissing:
   1672    vim_snprintf_add(S_LEN(ret), "Missing");
   1673    break;
   1674  case kSDItemHeader:
   1675    vim_snprintf_add(S_LEN(ret), "Header { TODO }");
   1676    break;
   1677  case kSDItemBufferList:
   1678    vim_snprintf_add(S_LEN(ret), "BufferList { TODO }");
   1679    break;
   1680  case kSDItemUnknown:
   1681    vim_snprintf_add(S_LEN(ret), "Unknown { TODO }");
   1682    break;
   1683  case kSDItemSearchPattern:
   1684    vim_snprintf_add(S_LEN(ret), "SearchPattern { TODO }");
   1685    break;
   1686  case kSDItemSubString:
   1687    vim_snprintf_add(S_LEN(ret), "SubString { TODO }");
   1688    break;
   1689  case kSDItemHistoryEntry:
   1690    vim_snprintf_add(S_LEN(ret), "HistoryEntry { TODO }");
   1691    break;
   1692  case kSDItemRegister:
   1693    vim_snprintf_add(S_LEN(ret), "Register { TODO }");
   1694    break;
   1695  case kSDItemVariable:
   1696    vim_snprintf_add(S_LEN(ret), "Variable { TODO }");
   1697    break;
   1698  case kSDItemGlobalMark:
   1699    FORMAT_MARK_ENTRY("GlobalMark", " name='%c',", entry.data.filemark.name);
   1700    break;
   1701  case kSDItemChange:
   1702    FORMAT_MARK_ENTRY("Change", "%s", "");
   1703    break;
   1704  case kSDItemLocalMark:
   1705    FORMAT_MARK_ENTRY("LocalMark", " name='%c',", entry.data.filemark.name);
   1706    break;
   1707  case kSDItemJump:
   1708    FORMAT_MARK_ENTRY("Jump", "%s", "");
   1709    break;
   1710 #undef FORMAT_MARK_ENTRY
   1711  }
   1712  ret[1] = (entry.can_free_entry ? 'T' : 'F');
   1713  return ret;
   1714 }
   1715 
   1716 /// Read and merge in ShaDa file, used when writing
   1717 ///
   1718 /// @param[in]      sd_reader   Structure containing file reader definition.
   1719 /// @param[in]      srni_flags  Flags determining what to read.
   1720 /// @param[in]      max_kbyte   Maximum size of one element.
   1721 /// @param[in,out]  ret_wms     Location where results are saved.
   1722 /// @param[out]     packer      MessagePack packer for entries which are not
   1723 ///                             merged.
   1724 static inline ShaDaWriteResult shada_read_when_writing(FileDescriptor *const sd_reader,
   1725                                                       const unsigned srni_flags,
   1726                                                       const size_t max_kbyte,
   1727                                                       WriteMergerState *const wms,
   1728                                                       PackerBuffer *const packer)
   1729  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   1730 {
   1731  ShaDaWriteResult ret = kSDWriteSuccessful;
   1732  ShadaEntry entry;
   1733  ShaDaReadResult srni_ret;
   1734 
   1735 #define COMPARE_WITH_ENTRY(wms_entry_, entry) \
   1736  do { \
   1737    ShadaEntry *const wms_entry = (wms_entry_); \
   1738    if (wms_entry->type != kSDItemMissing) { \
   1739      if (wms_entry->timestamp >= (entry).timestamp) { \
   1740        shada_free_shada_entry(&entry); \
   1741        break; \
   1742      } \
   1743      shada_free_shada_entry(wms_entry); \
   1744    } \
   1745    *wms_entry = entry; \
   1746  } while (0)
   1747 
   1748  while ((srni_ret = shada_read_next_item(sd_reader, &entry, srni_flags,
   1749                                          max_kbyte))
   1750         != kSDReadStatusFinished) {
   1751    switch (srni_ret) {
   1752    case kSDReadStatusSuccess:
   1753      break;
   1754    case kSDReadStatusFinished:
   1755      // Should be handled by the while condition.
   1756      abort();
   1757    case kSDReadStatusNotShaDa:
   1758      ret = kSDWriteReadNotShada;
   1759      FALLTHROUGH;
   1760    case kSDReadStatusReadError:
   1761      return ret;
   1762    case kSDReadStatusMalformed:
   1763      continue;
   1764    }
   1765    switch (entry.type) {
   1766    case kSDItemMissing:
   1767      break;
   1768    case kSDItemHeader:
   1769    case kSDItemBufferList:
   1770      abort();
   1771    case kSDItemUnknown:
   1772      ret = shada_pack_entry(packer, entry, 0);
   1773      shada_free_shada_entry(&entry);
   1774      break;
   1775    case kSDItemSearchPattern:
   1776      COMPARE_WITH_ENTRY((entry.data.search_pattern.is_substitute_pattern
   1777                          ? &wms->sub_search_pattern
   1778                          : &wms->search_pattern), entry);
   1779      break;
   1780    case kSDItemSubString:
   1781      COMPARE_WITH_ENTRY(&wms->replacement, entry);
   1782      break;
   1783    case kSDItemHistoryEntry:
   1784      if (entry.data.history_item.histtype >= HIST_COUNT) {
   1785        ret = shada_pack_entry(packer, entry, 0);
   1786        shada_free_shada_entry(&entry);
   1787        break;
   1788      }
   1789      if (wms->hms[entry.data.history_item.histtype].hmll.size != 0) {
   1790        hms_insert(&wms->hms[entry.data.history_item.histtype], entry, true);
   1791      } else {
   1792        shada_free_shada_entry(&entry);
   1793      }
   1794      break;
   1795    case kSDItemRegister: {
   1796      const int idx = op_reg_index(entry.data.reg.name);
   1797      if (idx < 0) {
   1798        ret = shada_pack_entry(packer, entry, 0);
   1799        shada_free_shada_entry(&entry);
   1800        break;
   1801      }
   1802      COMPARE_WITH_ENTRY(&wms->registers[idx], entry);
   1803      break;
   1804    }
   1805    case kSDItemVariable:
   1806      if (!set_has(cstr_t, &wms->dumped_variables, entry.data.global_var.name)) {
   1807        ret = shada_pack_entry(packer, entry, 0);
   1808      }
   1809      shada_free_shada_entry(&entry);
   1810      break;
   1811    case kSDItemGlobalMark:
   1812      if (ascii_isdigit(entry.data.filemark.name)) {
   1813        bool processed_mark = false;
   1814        // Completely ignore numbered mark names, make a list sorted by
   1815        // timestamp.
   1816        for (size_t i = ARRAY_SIZE(wms->numbered_marks); i > 0; i--) {
   1817          ShadaEntry wms_entry = wms->numbered_marks[i - 1];
   1818          if (wms_entry.type != kSDItemGlobalMark) {
   1819            continue;
   1820          }
   1821          // Ignore duplicates.
   1822          if (wms_entry.timestamp == entry.timestamp
   1823              && (wms_entry.additional_data == NULL
   1824                  && entry.additional_data == NULL)
   1825              && marks_equal(wms_entry.data.filemark.mark,
   1826                             entry.data.filemark.mark)
   1827              && strcmp(wms_entry.data.filemark.fname,
   1828                        entry.data.filemark.fname) == 0) {
   1829            shada_free_shada_entry(&entry);
   1830            processed_mark = true;
   1831            break;
   1832          }
   1833          if (wms_entry.timestamp >= entry.timestamp) {
   1834            processed_mark = true;
   1835            if (i < ARRAY_SIZE(wms->numbered_marks)) {
   1836              replace_numbered_mark(wms, i, entry);
   1837            } else {
   1838              shada_free_shada_entry(&entry);
   1839            }
   1840            break;
   1841          }
   1842        }
   1843        if (!processed_mark) {
   1844          replace_numbered_mark(wms, 0, entry);
   1845        }
   1846      } else {
   1847        const int idx = mark_global_index(entry.data.filemark.name);
   1848        if (idx < 0) {
   1849          ret = shada_pack_entry(packer, entry, 0);
   1850          shada_free_shada_entry(&entry);
   1851          break;
   1852        }
   1853 
   1854        // Global or numbered mark.
   1855        ShadaEntry *mark = idx < 26 ? &wms->global_marks[idx] : &wms->numbered_marks[idx - 26];
   1856 
   1857        if (mark->type == kSDItemMissing) {
   1858          if (namedfm[idx].fmark.timestamp >= entry.timestamp) {
   1859            shada_free_shada_entry(&entry);
   1860            break;
   1861          }
   1862        }
   1863        COMPARE_WITH_ENTRY(mark, entry);
   1864      }
   1865      break;
   1866    case kSDItemChange:
   1867    case kSDItemLocalMark: {
   1868      if (shada_removable(entry.data.filemark.fname)) {
   1869        shada_free_shada_entry(&entry);
   1870        break;
   1871      }
   1872      const char *const fname = entry.data.filemark.fname;
   1873      cstr_t *key = NULL;
   1874      bool new_item = false;
   1875      ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, &key, &new_item);
   1876      if (new_item) {
   1877        *key = xstrdup(fname);
   1878      }
   1879      if (*val == NULL) {
   1880        *val = xcalloc(1, sizeof(FileMarks));
   1881      }
   1882      FileMarks *const filemarks = *val;
   1883      if (entry.timestamp > filemarks->greatest_timestamp) {
   1884        filemarks->greatest_timestamp = entry.timestamp;
   1885      }
   1886      if (entry.type == kSDItemLocalMark) {
   1887        const int idx = mark_local_index(entry.data.filemark.name);
   1888        if (idx < 0) {
   1889          filemarks->additional_marks = xrealloc(filemarks->additional_marks,
   1890                                                 (++filemarks->additional_marks_size
   1891                                                  * sizeof(filemarks->additional_marks[0])));
   1892          filemarks->additional_marks[filemarks->additional_marks_size - 1] =
   1893            entry;
   1894        } else {
   1895          ShadaEntry *const wms_entry = &filemarks->marks[idx];
   1896          bool set_wms = true;
   1897          if (wms_entry->type != kSDItemMissing) {
   1898            if (wms_entry->timestamp >= entry.timestamp) {
   1899              shada_free_shada_entry(&entry);
   1900              break;
   1901            }
   1902            if (wms_entry->can_free_entry) {
   1903              if (*key == wms_entry->data.filemark.fname) {
   1904                *key = entry.data.filemark.fname;
   1905              }
   1906              shada_free_shada_entry(wms_entry);
   1907            }
   1908          } else {
   1909            FOR_ALL_BUFFERS(buf) {
   1910              if (buf->b_ffname != NULL
   1911                  && path_fnamecmp(entry.data.filemark.fname, buf->b_ffname) == 0) {
   1912                fmark_T fm;
   1913                mark_get(buf, curwin, &fm, kMarkBufLocal, (int)entry.data.filemark.name);
   1914                if (fm.timestamp >= entry.timestamp) {
   1915                  set_wms = false;
   1916                  shada_free_shada_entry(&entry);
   1917                  break;
   1918                }
   1919              }
   1920            }
   1921          }
   1922          if (set_wms) {
   1923            *wms_entry = entry;
   1924          }
   1925        }
   1926      } else {
   1927        int i;
   1928        for (i = (int)filemarks->changes_size; i > 0; i--) {
   1929          const ShadaEntry jl_entry = filemarks->changes[i - 1];
   1930          if (jl_entry.timestamp <= (entry).timestamp) {
   1931            if (marks_equal(jl_entry.data.filemark.mark, entry.data.filemark.mark)) {
   1932              i = -1;
   1933            }
   1934            break;
   1935          }
   1936        }
   1937        if (i > 0 && filemarks->changes_size == JUMPLISTSIZE) {
   1938          shada_free_shada_entry(&filemarks->changes[0]);
   1939        }
   1940        i = marklist_insert(filemarks->changes, sizeof(*filemarks->changes),
   1941                            (int)filemarks->changes_size, i);
   1942        if (i != -1) {
   1943          filemarks->changes[i] = entry;
   1944          if (filemarks->changes_size < JUMPLISTSIZE) {
   1945            filemarks->changes_size++;
   1946          }
   1947        } else {
   1948          shada_free_shada_entry(&(entry));
   1949        }
   1950      }
   1951      break;
   1952    }
   1953    case kSDItemJump:
   1954      ;
   1955      int i;
   1956      for (i = (int)wms->jumps_size; i > 0; i--) {
   1957        const ShadaEntry jl_entry = wms->jumps[i - 1];
   1958        if (jl_entry.timestamp <= entry.timestamp) {
   1959          if (marks_equal(jl_entry.data.filemark.mark, entry.data.filemark.mark)
   1960              && strcmp(jl_entry.data.filemark.fname, entry.data.filemark.fname) == 0) {
   1961            i = -1;
   1962          }
   1963          break;
   1964        }
   1965      }
   1966      if (i > 0 && wms->jumps_size == JUMPLISTSIZE) {
   1967        shada_free_shada_entry(&wms->jumps[0]);
   1968      }
   1969      i = marklist_insert(wms->jumps, sizeof(*wms->jumps), (int)wms->jumps_size, i);
   1970      if (i != -1) {
   1971        wms->jumps[i] = entry;
   1972        if (wms->jumps_size < JUMPLISTSIZE) {
   1973          wms->jumps_size++;
   1974        }
   1975      } else {
   1976        shada_free_shada_entry(&entry);
   1977      }
   1978      break;
   1979    }
   1980  }
   1981 #undef COMPARE_WITH_ENTRY
   1982  return ret;
   1983 }
   1984 
   1985 /// Check whether buffer should be ignored
   1986 ///
   1987 /// @param[in]  buf  buf_T* to check.
   1988 /// @param[in]  removable_bufs  Cache of buffers ignored due to their location.
   1989 ///
   1990 /// @return true or false.
   1991 static inline bool ignore_buf(const buf_T *const buf, Set(ptr_t) *const removable_bufs)
   1992  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
   1993 {
   1994  return (buf == NULL || buf->b_ffname == NULL || !buf->b_p_bl || bt_quickfix(buf) \
   1995          || bt_terminal(buf) || set_has(ptr_t, removable_bufs, (ptr_t)buf));
   1996 }
   1997 
   1998 /// Get list of buffers to write to the shada file
   1999 ///
   2000 /// @param[in]  removable_bufs  Buffers which are ignored
   2001 ///
   2002 /// @return  ShadaEntry  List of buffers to save, kSDItemBufferList entry.
   2003 static inline ShadaEntry shada_get_buflist(Set(ptr_t) *const removable_bufs)
   2004  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
   2005 {
   2006  int max_bufs = get_shada_parameter('%');
   2007  size_t buf_count = 0;
   2008  FOR_ALL_BUFFERS(buf) {
   2009    if (!ignore_buf(buf, removable_bufs)
   2010        && (max_bufs < 0 || buf_count < (size_t)max_bufs)) {
   2011      buf_count++;
   2012    }
   2013  }
   2014 
   2015  ShadaEntry buflist_entry = (ShadaEntry) {
   2016    .type = kSDItemBufferList,
   2017    .timestamp = os_time(),
   2018    .data = {
   2019      .buffer_list = {
   2020        .size = buf_count,
   2021        .buffers = xmalloc(buf_count
   2022                           * sizeof(*buflist_entry.data.buffer_list.buffers)),
   2023      },
   2024    },
   2025  };
   2026  size_t i = 0;
   2027  FOR_ALL_BUFFERS(buf) {
   2028    if (ignore_buf(buf, removable_bufs)) {
   2029      continue;
   2030    }
   2031    if (i >= buf_count) {
   2032      break;
   2033    }
   2034    buflist_entry.data.buffer_list.buffers[i] = (struct buffer_list_buffer) {
   2035      .pos = buf->b_last_cursor.mark,
   2036      .fname = buf->b_ffname,
   2037      .additional_data = buf->additional_data,
   2038    };
   2039    i++;
   2040  }
   2041 
   2042  return buflist_entry;
   2043 }
   2044 
   2045 /// Save search pattern to ShadaEntry
   2046 ///
   2047 /// @param[out]  ret_pse  Location where result will be saved.
   2048 /// @param[in]  get_pattern  Function used to get pattern.
   2049 /// @param[in]  is_substitute_pattern  True if pattern in question is substitute
   2050 ///                                    pattern. Also controls whether some
   2051 ///                                    fields should be initialized to default
   2052 ///                                    or values from get_pattern.
   2053 /// @param[in]  search_last_used  Result of search_was_last_used().
   2054 /// @param[in]  search_highlighted  True if search pattern was highlighted by
   2055 ///                                 &hlsearch and this information should be
   2056 ///                                 saved.
   2057 static inline void add_search_pattern(ShadaEntry *const ret_pse,
   2058                                      const SearchPatternGetter get_pattern,
   2059                                      const bool is_substitute_pattern, const bool search_last_used,
   2060                                      const bool search_highlighted)
   2061  FUNC_ATTR_ALWAYS_INLINE
   2062 {
   2063  const ShadaEntry defaults = sd_default_values[kSDItemSearchPattern];
   2064  SearchPattern pat;
   2065  get_pattern(&pat);
   2066  if (pat.pat != NULL) {
   2067    *ret_pse = (ShadaEntry) {
   2068      .can_free_entry = false,
   2069      .type = kSDItemSearchPattern,
   2070      .timestamp = pat.timestamp,
   2071      .data = {
   2072        .search_pattern = {
   2073          .magic = pat.magic,
   2074          .smartcase = !pat.no_scs,
   2075          .has_line_offset = (is_substitute_pattern
   2076                              ? defaults.data.search_pattern.has_line_offset
   2077                              : pat.off.line),
   2078          .place_cursor_at_end = (
   2079                                  is_substitute_pattern
   2080                                  ? defaults.data.search_pattern.place_cursor_at_end
   2081                                  : pat.off.end),
   2082          .offset = (is_substitute_pattern
   2083                     ? defaults.data.search_pattern.offset
   2084                     : pat.off.off),
   2085          .is_last_used = (is_substitute_pattern ^ search_last_used),
   2086          .is_substitute_pattern = is_substitute_pattern,
   2087          .highlighted = ((is_substitute_pattern ^ search_last_used)
   2088                          && search_highlighted),
   2089          .pat = cstr_as_string(pat.pat),
   2090          .search_backward = (!is_substitute_pattern && pat.off.dir == '?'),
   2091        }
   2092      },
   2093      .additional_data = pat.additional_data,
   2094    };
   2095  }
   2096 }
   2097 
   2098 /// Initialize registers for writing to the ShaDa file
   2099 ///
   2100 /// @param[in]  wms  The WriteMergerState used when writing.
   2101 /// @param[in]  max_reg_lines  The maximum number of register lines.
   2102 static inline void shada_initialize_registers(WriteMergerState *const wms, int max_reg_lines)
   2103  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE
   2104 {
   2105  const void *reg_iter = NULL;
   2106  const bool limit_reg_lines = max_reg_lines >= 0;
   2107  do {
   2108    yankreg_T reg;
   2109    char name = NUL;
   2110    bool is_unnamed = false;
   2111    reg_iter = op_global_reg_iter(reg_iter, &name, &reg, &is_unnamed);
   2112    if (name == NUL) {
   2113      break;
   2114    }
   2115    if (limit_reg_lines && reg.y_size > (size_t)max_reg_lines) {
   2116      continue;
   2117    }
   2118    wms->registers[op_reg_index(name)] = (ShadaEntry) {
   2119      .can_free_entry = false,
   2120      .type = kSDItemRegister,
   2121      .timestamp = reg.timestamp,
   2122      .data = {
   2123        .reg = {
   2124          .contents = reg.y_array,
   2125          .contents_size = reg.y_size,
   2126          .type = reg.y_type,
   2127          .width = (size_t)(reg.y_type == kMTBlockWise ? reg.y_width : 0),
   2128          .name = name,
   2129          .is_unnamed = is_unnamed,
   2130        }
   2131      },
   2132      .additional_data = reg.additional_data,
   2133    };
   2134  } while (reg_iter != NULL);
   2135 }
   2136 
   2137 /// Replace numbered mark in WriteMergerState
   2138 ///
   2139 /// Frees the last mark, moves (including adjusting mark names) marks from idx
   2140 /// to the last-but-one one and saves the new mark at given index.
   2141 ///
   2142 /// @param[out]  wms  Merger state to adjust.
   2143 /// @param[in]  idx  Index at which new mark should be placed.
   2144 /// @param[in]  entry  New mark.
   2145 static inline void replace_numbered_mark(WriteMergerState *const wms, const size_t idx,
   2146                                         const ShadaEntry entry)
   2147  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE
   2148 {
   2149  shada_free_shada_entry(&ARRAY_LAST_ENTRY(wms->numbered_marks));
   2150  for (size_t i = idx; i < ARRAY_SIZE(wms->numbered_marks) - 1; i++) {
   2151    if (wms->numbered_marks[i].type == kSDItemGlobalMark) {
   2152      wms->numbered_marks[i].data.filemark.name = (char)('0' + (int)i + 1);
   2153    }
   2154  }
   2155  memmove(wms->numbered_marks + idx + 1, wms->numbered_marks + idx,
   2156          sizeof(wms->numbered_marks[0])
   2157          * (ARRAY_SIZE(wms->numbered_marks) - 1 - idx));
   2158  wms->numbered_marks[idx] = entry;
   2159  wms->numbered_marks[idx].data.filemark.name = (char)('0' + (int)idx);
   2160 }
   2161 
   2162 /// Find buffers ignored due to their location.
   2163 ///
   2164 /// @param[out]  removable_bufs  Cache of buffers ignored due to their location.
   2165 static inline void find_removable_bufs(Set(ptr_t) *removable_bufs)
   2166 {
   2167  FOR_ALL_BUFFERS(buf) {
   2168    if (buf->b_ffname != NULL && shada_removable(buf->b_ffname)) {
   2169      set_put(ptr_t, removable_bufs, (ptr_t)buf);
   2170    }
   2171  }
   2172 }
   2173 
   2174 /// Translate a history type number to the associated character
   2175 static int hist_type2char(const int type)
   2176  FUNC_ATTR_CONST
   2177 {
   2178  switch (type) {
   2179  case HIST_CMD:
   2180    return ':';
   2181  case HIST_SEARCH:
   2182    return '/';
   2183  case HIST_EXPR:
   2184    return '=';
   2185  case HIST_INPUT:
   2186    return '@';
   2187  case HIST_DEBUG:
   2188    return '>';
   2189  default:
   2190    abort();
   2191  }
   2192  return NUL;
   2193 }
   2194 
   2195 static PackerBuffer packer_buffer_for_file(FileDescriptor *file)
   2196 {
   2197  if (file_space(file) < SHADA_MPACK_FREE_SPACE) {
   2198    file_flush(file);
   2199  }
   2200  return (PackerBuffer) {
   2201    .startptr = file->buffer,
   2202    .ptr = file->write_pos,
   2203    .endptr = file->buffer + ARENA_BLOCK_SIZE,
   2204    .anydata = file,
   2205    .anyint = 0,  // set to nonzero if error
   2206    .packer_flush = flush_file_buffer,
   2207  };
   2208 }
   2209 
   2210 static void flush_file_buffer(PackerBuffer *buffer)
   2211 {
   2212  FileDescriptor *fd = buffer->anydata;
   2213  fd->write_pos = buffer->ptr;
   2214  buffer->anyint = file_flush(fd);
   2215  buffer->ptr = fd->write_pos;
   2216 }
   2217 
   2218 /// Write ShaDa file
   2219 ///
   2220 /// @param[in]  sd_writer  Structure containing file writer definition.
   2221 /// @param[in]  sd_reader  Structure containing file reader definition. If it is
   2222 ///                        not NULL then contents of this file will be merged
   2223 ///                        with current Neovim runtime.
   2224 static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
   2225                                    FileDescriptor *const sd_reader)
   2226  FUNC_ATTR_NONNULL_ARG(1)
   2227 {
   2228  ShaDaWriteResult ret = kSDWriteSuccessful;
   2229  int max_kbyte_i = get_shada_parameter('s');
   2230  if (max_kbyte_i < 0) {
   2231    max_kbyte_i = 10;
   2232  }
   2233  if (max_kbyte_i == 0) {
   2234    return ret;
   2235  }
   2236 
   2237  WriteMergerState *const wms = xcalloc(1, sizeof(*wms));
   2238  bool dump_one_history[HIST_COUNT];
   2239  const bool dump_global_vars = (find_shada_parameter('!') != NULL);
   2240  int max_reg_lines = get_shada_parameter('<');
   2241  if (max_reg_lines < 0) {
   2242    max_reg_lines = get_shada_parameter('"');
   2243  }
   2244  const bool dump_registers = (max_reg_lines != 0);
   2245  Set(ptr_t) removable_bufs = SET_INIT;
   2246  const size_t max_kbyte = (size_t)max_kbyte_i;
   2247  const size_t num_marked_files = (size_t)get_shada_parameter('\'');
   2248  const bool dump_global_marks = get_shada_parameter('f') != 0;
   2249  bool dump_history = false;
   2250 
   2251  // Initialize history merger
   2252  for (int i = 0; i < HIST_COUNT; i++) {
   2253    int num_saved = get_shada_parameter(hist_type2char(i));
   2254    if (num_saved == -1) {
   2255      num_saved = (int)p_hi;
   2256    }
   2257    if (num_saved > 0) {
   2258      dump_history = true;
   2259      dump_one_history[i] = true;
   2260      hms_init(&wms->hms[i], (uint8_t)i, (size_t)num_saved, sd_reader != NULL, false);
   2261    } else {
   2262      dump_one_history[i] = false;
   2263    }
   2264  }
   2265 
   2266  const unsigned srni_flags = (unsigned)(kSDReadUndisableableData
   2267                                         | kSDReadUnknown
   2268                                         | (dump_history ? kSDReadHistory : 0)
   2269                                         | (dump_registers ? kSDReadRegisters : 0)
   2270                                         | (dump_global_vars ? kSDReadVariables : 0)
   2271                                         | (dump_global_marks ? kSDReadGlobalMarks : 0)
   2272                                         | (num_marked_files ? kSDReadLocalMarks |
   2273                                            kSDReadChanges : 0));
   2274 
   2275  PackerBuffer packer = packer_buffer_for_file(sd_writer);
   2276 
   2277  // Set b_last_cursor for all the buffers that have a window.
   2278  //
   2279  // It is needed to correctly save '"' mark on exit. Has a side effect of
   2280  // setting '"' mark in all windows on :wshada to the current cursor
   2281  // position (basically what :wviminfo used to do).
   2282  FOR_ALL_TAB_WINDOWS(tp, wp) {
   2283    set_last_cursor(wp);
   2284  }
   2285 
   2286  find_removable_bufs(&removable_bufs);
   2287 
   2288  // Write header
   2289  if (shada_pack_entry(&packer, (ShadaEntry) {
   2290    .type = kSDItemHeader,
   2291    .timestamp = os_time(),
   2292    .data = {
   2293      .header = {
   2294        .size = 5,
   2295        .capacity = 5,
   2296        .items = ((KeyValuePair[]) {
   2297          { STATIC_CSTR_AS_STRING("generator"),
   2298            STATIC_CSTR_AS_OBJ("nvim") },
   2299          { STATIC_CSTR_AS_STRING("version"),
   2300            CSTR_AS_OBJ(longVersion) },
   2301          { STATIC_CSTR_AS_STRING("max_kbyte"),
   2302            INTEGER_OBJ((Integer)max_kbyte) },
   2303          { STATIC_CSTR_AS_STRING("pid"),
   2304            INTEGER_OBJ((Integer)os_get_pid()) },
   2305          { STATIC_CSTR_AS_STRING("encoding"),
   2306            CSTR_AS_OBJ(p_enc) },
   2307        }),
   2308      }
   2309    }
   2310  }, 0) == kSDWriteFailed) {
   2311    ret = kSDWriteFailed;
   2312    goto shada_write_exit;
   2313  }
   2314 
   2315  // Write buffer list
   2316  if (find_shada_parameter('%') != NULL) {
   2317    ShadaEntry buflist_entry = shada_get_buflist(&removable_bufs);
   2318    if (shada_pack_entry(&packer, buflist_entry, 0) == kSDWriteFailed) {
   2319      xfree(buflist_entry.data.buffer_list.buffers);
   2320      ret = kSDWriteFailed;
   2321      goto shada_write_exit;
   2322    }
   2323    xfree(buflist_entry.data.buffer_list.buffers);
   2324  }
   2325 
   2326  // Write some of the variables
   2327  if (dump_global_vars) {
   2328    const void *var_iter = NULL;
   2329    const Timestamp cur_timestamp = os_time();
   2330    do {
   2331      typval_T vartv;
   2332      const char *name = NULL;
   2333      var_iter = var_shada_iter(var_iter, &name, &vartv, VAR_FLAVOUR_SHADA);
   2334      if (name == NULL) {
   2335        break;
   2336      }
   2337      switch (vartv.v_type) {
   2338      case VAR_FUNC:
   2339      case VAR_PARTIAL:
   2340        tv_clear(&vartv);
   2341        continue;
   2342      case VAR_DICT: {
   2343        dict_T *di = vartv.vval.v_dict;
   2344        int copyID = get_copyID();
   2345        if (!set_ref_in_ht(&di->dv_hashtab, copyID, NULL)
   2346            && copyID == di->dv_copyID) {
   2347          tv_clear(&vartv);
   2348          continue;
   2349        }
   2350        break;
   2351      }
   2352      case VAR_LIST: {
   2353        list_T *l = vartv.vval.v_list;
   2354        int copyID = get_copyID();
   2355        if (!set_ref_in_list_items(l, copyID, NULL)
   2356            && copyID == l->lv_copyID) {
   2357          tv_clear(&vartv);
   2358          continue;
   2359        }
   2360        break;
   2361      }
   2362      default:
   2363        break;
   2364      }
   2365      typval_T tgttv;
   2366      tv_copy(&vartv, &tgttv);
   2367      ShaDaWriteResult spe_ret;
   2368      if ((spe_ret = shada_pack_entry(&packer, (ShadaEntry) {
   2369        .type = kSDItemVariable,
   2370        .timestamp = cur_timestamp,
   2371        .data = {
   2372          .global_var = {
   2373            .name = (char *)name,
   2374            .value = tgttv,
   2375          }
   2376        },
   2377        .additional_data = NULL,
   2378      }, max_kbyte)) == kSDWriteFailed) {
   2379        tv_clear(&vartv);
   2380        tv_clear(&tgttv);
   2381        ret = kSDWriteFailed;
   2382        goto shada_write_exit;
   2383      }
   2384      tv_clear(&vartv);
   2385      tv_clear(&tgttv);
   2386      if (spe_ret == kSDWriteSuccessful) {
   2387        set_put(cstr_t, &wms->dumped_variables, name);
   2388      }
   2389    } while (var_iter != NULL);
   2390  }
   2391 
   2392  if (num_marked_files > 0) {  // Skip if '0 in 'shada'
   2393    // Initialize jump list
   2394    wms->jumps_size = shada_init_jumps(wms->jumps, &removable_bufs);
   2395  }
   2396 
   2397  if (dump_one_history[HIST_SEARCH] > 0) {  // Skip if /0 in 'shada'
   2398    const bool search_highlighted = !(no_hlsearch
   2399                                      || find_shada_parameter('h') != NULL);
   2400    const bool search_last_used = search_was_last_used();
   2401 
   2402    // Initialize search pattern
   2403    add_search_pattern(&wms->search_pattern, &get_search_pattern, false,
   2404                       search_last_used, search_highlighted);
   2405 
   2406    // Initialize substitute search pattern
   2407    add_search_pattern(&wms->sub_search_pattern, &get_substitute_pattern, true,
   2408                       search_last_used, search_highlighted);
   2409 
   2410    // Initialize substitute replacement string
   2411    SubReplacementString sub;
   2412    sub_get_replacement(&sub);
   2413    if (sub.sub != NULL) {  // Don't store empty replacement string
   2414      wms->replacement = (ShadaEntry) {
   2415        .can_free_entry = false,
   2416        .type = kSDItemSubString,
   2417        .timestamp = sub.timestamp,
   2418        .data = {
   2419          .sub_string = {
   2420            .sub = sub.sub,
   2421          }
   2422        },
   2423        .additional_data = sub.additional_data,
   2424      };
   2425    }
   2426  }
   2427 
   2428  // Initialize global marks
   2429  if (dump_global_marks) {
   2430    const void *global_mark_iter = NULL;
   2431    size_t digit_mark_idx = 0;
   2432    do {
   2433      char name = NUL;
   2434      xfmark_T fm;
   2435      global_mark_iter = mark_global_iter(global_mark_iter, &name, &fm);
   2436      if (name == NUL) {
   2437        break;
   2438      }
   2439      const char *fname;
   2440      if (fm.fmark.fnum == 0) {
   2441        assert(fm.fname != NULL);
   2442        if (shada_removable(fm.fname)) {
   2443          continue;
   2444        }
   2445        fname = fm.fname;
   2446      } else {
   2447        const buf_T *const buf = buflist_findnr(fm.fmark.fnum);
   2448        if (buf == NULL || buf->b_ffname == NULL
   2449            || set_has(ptr_t, &removable_bufs, (ptr_t)buf)) {
   2450          continue;
   2451        }
   2452        fname = buf->b_ffname;
   2453      }
   2454      const ShadaEntry entry = {
   2455        .can_free_entry = false,
   2456        .type = kSDItemGlobalMark,
   2457        .timestamp = fm.fmark.timestamp,
   2458        .data = {
   2459          .filemark = {
   2460            .mark = fm.fmark.mark,
   2461            .name = name,
   2462            .fname = (char *)fname,
   2463          }
   2464        },
   2465        .additional_data = fm.fmark.additional_data,
   2466      };
   2467      if (ascii_isdigit(name)) {
   2468        replace_numbered_mark(wms, digit_mark_idx++, entry);
   2469      } else {
   2470        wms->global_marks[mark_global_index(name)] = entry;
   2471      }
   2472    } while (global_mark_iter != NULL);
   2473  }
   2474 
   2475  // Initialize registers
   2476  if (dump_registers) {
   2477    shada_initialize_registers(wms, max_reg_lines);
   2478  }
   2479 
   2480  // Initialize buffers
   2481  if (num_marked_files > 0) {
   2482    FOR_ALL_BUFFERS(buf) {
   2483      if (ignore_buf(buf, &removable_bufs)) {
   2484        continue;
   2485      }
   2486      const void *local_marks_iter = NULL;
   2487      const char *const fname = buf->b_ffname;
   2488      cstr_t *map_key = NULL;
   2489      bool new_item = false;
   2490      ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, &map_key, &new_item);
   2491      if (new_item) {
   2492        *map_key = xstrdup(fname);
   2493      }
   2494      if (*val == NULL) {
   2495        *val = xcalloc(1, sizeof(FileMarks));
   2496      }
   2497      FileMarks *const filemarks = *val;
   2498      do {
   2499        fmark_T fm;
   2500        char name = NUL;
   2501        local_marks_iter = mark_buffer_iter(local_marks_iter, buf, &name, &fm);
   2502        if (name == NUL) {
   2503          break;
   2504        }
   2505        filemarks->marks[mark_local_index(name)] = (ShadaEntry) {
   2506          .can_free_entry = false,
   2507          .type = kSDItemLocalMark,
   2508          .timestamp = fm.timestamp,
   2509          .data = {
   2510            .filemark = {
   2511              .mark = fm.mark,
   2512              .name = name,
   2513              .fname = (char *)fname,
   2514            }
   2515          },
   2516          .additional_data = fm.additional_data,
   2517        };
   2518        if (fm.timestamp > filemarks->greatest_timestamp) {
   2519          filemarks->greatest_timestamp = fm.timestamp;
   2520        }
   2521      } while (local_marks_iter != NULL);
   2522      for (int i = 0; i < buf->b_changelistlen; i++) {
   2523        const fmark_T fm = buf->b_changelist[i];
   2524        filemarks->changes[i] = (ShadaEntry) {
   2525          .can_free_entry = false,
   2526          .type = kSDItemChange,
   2527          .timestamp = fm.timestamp,
   2528          .data = {
   2529            .filemark = {
   2530              .mark = fm.mark,
   2531              .fname = (char *)fname,
   2532            }
   2533          },
   2534          .additional_data = fm.additional_data,
   2535        };
   2536        if (fm.timestamp > filemarks->greatest_timestamp) {
   2537          filemarks->greatest_timestamp = fm.timestamp;
   2538        }
   2539      }
   2540      filemarks->changes_size = (size_t)buf->b_changelistlen;
   2541    }
   2542  }
   2543 
   2544  if (sd_reader != NULL) {
   2545    const ShaDaWriteResult srww_ret = shada_read_when_writing(sd_reader, srni_flags, max_kbyte, wms,
   2546                                                              &packer);
   2547    if (srww_ret != kSDWriteSuccessful) {
   2548      ret = srww_ret;
   2549    }
   2550  }
   2551 
   2552  // Update numbered marks: replace '0 mark with the current position,
   2553  // remove '9 and shift all other marks. Skip if f0 in 'shada'.
   2554  if (dump_global_marks && !ignore_buf(curbuf, &removable_bufs) && curwin->w_cursor.lnum != 0) {
   2555    replace_numbered_mark(wms, 0, (ShadaEntry) {
   2556      .can_free_entry = false,
   2557      .type = kSDItemGlobalMark,
   2558      .timestamp = os_time(),
   2559      .data = {
   2560        .filemark = {
   2561          .mark = curwin->w_cursor,
   2562          .name = '0',
   2563          .fname = curbuf->b_ffname,
   2564        }
   2565      },
   2566      .additional_data = NULL,
   2567    });
   2568  }
   2569 
   2570  // Write the rest
   2571 #define PACK_WMS_ARRAY(wms_array) \
   2572  do { \
   2573    for (size_t i_ = 0; i_ < ARRAY_SIZE(wms_array); i_++) { \
   2574      if ((wms_array)[i_].type != kSDItemMissing) { \
   2575        if (shada_pack_pfreed_entry(&packer, (wms_array)[i_], max_kbyte) \
   2576            == kSDWriteFailed) { \
   2577          ret = kSDWriteFailed; \
   2578          goto shada_write_exit; \
   2579        } \
   2580      } \
   2581    } \
   2582  } while (0)
   2583  PACK_WMS_ARRAY(wms->global_marks);
   2584  PACK_WMS_ARRAY(wms->numbered_marks);
   2585  PACK_WMS_ARRAY(wms->registers);
   2586  for (size_t i = 0; i < wms->jumps_size; i++) {
   2587    if (shada_pack_pfreed_entry(&packer, wms->jumps[i], max_kbyte)
   2588        == kSDWriteFailed) {
   2589      ret = kSDWriteFailed;
   2590      goto shada_write_exit;
   2591    }
   2592  }
   2593 #define PACK_WMS_ENTRY(wms_entry) \
   2594  do { \
   2595    if ((wms_entry).type != kSDItemMissing) { \
   2596      if (shada_pack_pfreed_entry(&packer, wms_entry, max_kbyte) \
   2597          == kSDWriteFailed) { \
   2598        ret = kSDWriteFailed; \
   2599        goto shada_write_exit; \
   2600      } \
   2601    } \
   2602  } while (0)
   2603  PACK_WMS_ENTRY(wms->search_pattern);
   2604  PACK_WMS_ENTRY(wms->sub_search_pattern);
   2605  PACK_WMS_ENTRY(wms->replacement);
   2606 #undef PACK_WMS_ENTRY
   2607 
   2608  const size_t file_markss_size = map_size(&wms->file_marks);
   2609  FileMarks **const all_file_markss =
   2610    xmalloc(file_markss_size * sizeof(*all_file_markss));
   2611  FileMarks **cur_file_marks = all_file_markss;
   2612  ptr_t val;
   2613  map_foreach_value(&wms->file_marks, val, {
   2614    *cur_file_marks++ = val;
   2615  })
   2616  qsort((void *)all_file_markss, file_markss_size, sizeof(*all_file_markss),
   2617        &compare_file_marks);
   2618  const size_t file_markss_to_dump = MIN(num_marked_files, file_markss_size);
   2619  for (size_t i = 0; i < file_markss_to_dump; i++) {
   2620    PACK_WMS_ARRAY(all_file_markss[i]->marks);
   2621    for (size_t j = 0; j < all_file_markss[i]->changes_size; j++) {
   2622      if (shada_pack_pfreed_entry(&packer, all_file_markss[i]->changes[j],
   2623                                  max_kbyte) == kSDWriteFailed) {
   2624        ret = kSDWriteFailed;
   2625        goto shada_write_exit;
   2626      }
   2627    }
   2628    for (size_t j = 0; j < all_file_markss[i]->additional_marks_size; j++) {
   2629      if (shada_pack_entry(&packer, all_file_markss[i]->additional_marks[j],
   2630                           0) == kSDWriteFailed) {
   2631        shada_free_shada_entry(&all_file_markss[i]->additional_marks[j]);
   2632        ret = kSDWriteFailed;
   2633        goto shada_write_exit;
   2634      }
   2635      shada_free_shada_entry(&all_file_markss[i]->additional_marks[j]);
   2636    }
   2637    xfree(all_file_markss[i]->additional_marks);
   2638  }
   2639  xfree(all_file_markss);
   2640 #undef PACK_WMS_ARRAY
   2641 
   2642  if (dump_history) {
   2643    for (int i = 0; i < HIST_COUNT; i++) {
   2644      if (dump_one_history[i]) {
   2645        hms_insert_whole_neovim_history(&wms->hms[i]);
   2646        HMS_ITER(&wms->hms[i], cur_entry, {
   2647          if (shada_pack_pfreed_entry(&packer, cur_entry->data, max_kbyte) == kSDWriteFailed) {
   2648            ret = kSDWriteFailed;
   2649            break;
   2650          }
   2651        })
   2652        if (ret == kSDWriteFailed) {
   2653          goto shada_write_exit;
   2654        }
   2655      }
   2656    }
   2657  }
   2658 
   2659 shada_write_exit:
   2660  for (int i = 0; i < HIST_COUNT; i++) {
   2661    if (dump_one_history[i]) {
   2662      hms_dealloc(&wms->hms[i]);
   2663    }
   2664  }
   2665  const char *stored_key = NULL;
   2666  map_foreach(&wms->file_marks, stored_key, val, {
   2667    xfree((char *)stored_key);
   2668    xfree(val);
   2669  })
   2670  map_destroy(cstr_t, &wms->file_marks);
   2671  set_destroy(ptr_t, &removable_bufs);
   2672  packer.packer_flush(&packer);
   2673  set_destroy(cstr_t, &wms->dumped_variables);
   2674  xfree(wms);
   2675  return ret;
   2676 }
   2677 
   2678 #undef PACK_KEY
   2679 
   2680 /// Write ShaDa file to a given location
   2681 ///
   2682 /// @param[in]  fname    File to write to. If it is NULL or empty then default
   2683 ///                      location is used.
   2684 /// @param[in]  nomerge  If true then old file is ignored.
   2685 ///
   2686 /// @return OK if writing was successful, FAIL otherwise.
   2687 int shada_write_file(const char *const file, bool nomerge)
   2688 {
   2689  char *const fname = shada_filename(file);
   2690  if (fname == NULL) {
   2691    return FAIL;
   2692  }
   2693 
   2694  char *tempname = NULL;
   2695  FileDescriptor sd_writer;
   2696  FileDescriptor sd_reader;
   2697  bool did_open_writer = false;
   2698  bool did_open_reader = false;
   2699 
   2700  if (!nomerge) {
   2701    int error;
   2702    if ((error = file_open(&sd_reader, fname, kFileReadOnly, 0)) != 0) {
   2703      if (error != UV_ENOENT) {
   2704        semsg(_(SERR "System error while opening ShaDa file %s for reading "
   2705                "to merge before writing it: %s"),
   2706              fname, os_strerror(error));
   2707        // Try writing the file even if opening it emerged any issues besides
   2708        // file not existing: maybe writing will succeed nevertheless.
   2709      }
   2710      nomerge = true;
   2711      goto shada_write_file_nomerge;
   2712    } else {
   2713      did_open_reader = true;
   2714    }
   2715    tempname = modname(fname, ".tmp.a", false);
   2716    if (tempname == NULL) {
   2717      nomerge = true;
   2718      goto shada_write_file_nomerge;
   2719    }
   2720 
   2721    // Save permissions from the original file, with modifications:
   2722    int perm = (int)os_getperm(fname);
   2723    perm = (perm >= 0) ? ((perm & 0777) | 0600) : 0600;
   2724    //                 ^3         ^1       ^2      ^2,3
   2725    // 1: Strip SUID bit if any.
   2726    // 2: Make sure that user can always read and write the result.
   2727    // 3: If somebody happened to delete the file after it was opened for
   2728    //    reading use u=rw permissions.
   2729 shada_write_file_open: {}
   2730    error = file_open(&sd_writer, tempname, kFileCreateOnly|kFileNoSymlink, perm);
   2731    if (error) {
   2732      if (error == UV_EEXIST || error == UV_ELOOP) {
   2733        // File already exists, try another name
   2734        char *const wp = tempname + strlen(tempname) - 1;
   2735        if (*wp == 'z') {
   2736          // Tried names from .tmp.a to .tmp.z, all failed. Something must be
   2737          // wrong then.
   2738          semsg(_("E138: All %s.tmp.X files exist, cannot write ShaDa file!"),
   2739                fname);
   2740          xfree(fname);
   2741          xfree(tempname);
   2742          if (did_open_reader) {
   2743            close_file(&sd_reader);
   2744          }
   2745          return FAIL;
   2746        }
   2747        (*wp)++;
   2748        goto shada_write_file_open;
   2749      } else {
   2750        semsg(_(SERR "System error while opening temporary ShaDa file %s "
   2751                "for writing: %s"), tempname, os_strerror(error));
   2752      }
   2753    } else {
   2754      did_open_writer = true;
   2755    }
   2756  }
   2757  if (nomerge) {
   2758 shada_write_file_nomerge: {}
   2759    char *const tail = path_tail_with_sep(fname);
   2760    if (tail != fname) {
   2761      const char tail_save = *tail;
   2762      *tail = NUL;
   2763      if (!os_isdir(fname)) {
   2764        int ret;
   2765        char *failed_dir;
   2766        if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir, NULL)) != 0) {
   2767          semsg(_(SERR "Failed to create directory %s "
   2768                  "for writing ShaDa file: %s"),
   2769                failed_dir, os_strerror(ret));
   2770          xfree(fname);
   2771          xfree(failed_dir);
   2772          return FAIL;
   2773        }
   2774      }
   2775      *tail = tail_save;
   2776    }
   2777    int error = file_open(&sd_writer, fname, kFileCreate|kFileTruncate, 0600);
   2778    if (error) {
   2779      semsg(_(SERR "System error while opening ShaDa file %s for writing: %s"),
   2780            fname, os_strerror(error));
   2781    } else {
   2782      did_open_writer = true;
   2783    }
   2784  }
   2785 
   2786  if (!did_open_writer) {
   2787    xfree(fname);
   2788    xfree(tempname);
   2789    if (did_open_reader) {
   2790      close_file(&sd_reader);
   2791    }
   2792    return FAIL;
   2793  }
   2794 
   2795  if (p_verbose > 1) {
   2796    verbose_enter();
   2797    smsg(0, _("Writing ShaDa file \"%s\""), fname);
   2798    verbose_leave();
   2799  }
   2800 
   2801  const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge ? NULL : &sd_reader));
   2802  assert(sw_ret != kSDWriteIgnError);
   2803  if (!nomerge) {
   2804    if (did_open_reader) {
   2805      close_file(&sd_reader);
   2806    }
   2807    bool did_remove = false;
   2808    if (sw_ret == kSDWriteSuccessful) {
   2809      FileInfo old_info;
   2810      if (!os_fileinfo(fname, &old_info)
   2811          || S_ISDIR(old_info.stat.st_mode)
   2812 #ifdef UNIX
   2813          // For Unix we check the owner of the file.  It's not very nice
   2814          // to overwrite a user's viminfo file after a "su root", with a
   2815          // viminfo file that the user can't read.
   2816          || (getuid() != ROOT_UID
   2817              && !(old_info.stat.st_uid == getuid()
   2818                   ? (old_info.stat.st_mode & 0200)
   2819                   : (old_info.stat.st_gid == getgid()
   2820                      ? (old_info.stat.st_mode & 0020)
   2821                      : (old_info.stat.st_mode & 0002))))
   2822 #endif
   2823          ) {
   2824        semsg(_("E137: ShaDa file is not writable: %s"), fname);
   2825        goto shada_write_file_did_not_remove;
   2826      }
   2827 #ifdef UNIX
   2828      if (getuid() == ROOT_UID) {
   2829        if (old_info.stat.st_uid != ROOT_UID
   2830            || old_info.stat.st_gid != getgid()) {
   2831          const uv_uid_t old_uid = (uv_uid_t)old_info.stat.st_uid;
   2832          const uv_gid_t old_gid = (uv_gid_t)old_info.stat.st_gid;
   2833          const int fchown_ret = os_fchown(file_fd(&sd_writer),
   2834                                           old_uid, old_gid);
   2835          if (fchown_ret != 0) {
   2836            semsg(_(RNERR "Failed setting uid and gid for file %s: %s"),
   2837                  tempname, os_strerror(fchown_ret));
   2838            goto shada_write_file_did_not_remove;
   2839          }
   2840        }
   2841      }
   2842 #endif
   2843      if (vim_rename(tempname, fname) == -1) {
   2844        semsg(_(RNERR "Can't rename ShaDa file from %s to %s!"),
   2845              tempname, fname);
   2846      } else {
   2847        did_remove = true;
   2848        os_remove(tempname);
   2849      }
   2850    } else {
   2851      if (sw_ret == kSDWriteReadNotShada) {
   2852        semsg(_(RNERR "Did not rename %s because %s "
   2853                "does not look like a ShaDa file"), tempname, fname);
   2854      } else {
   2855        semsg(_(RNERR "Did not rename %s to %s because there were errors "
   2856                "during writing it"), tempname, fname);
   2857      }
   2858    }
   2859    if (!did_remove) {
   2860 shada_write_file_did_not_remove:
   2861      semsg(_(RNERR "Do not forget to remove %s or rename it manually to %s."),
   2862            tempname, fname);
   2863    }
   2864    xfree(tempname);
   2865  }
   2866  close_file(&sd_writer);
   2867 
   2868  xfree(fname);
   2869  return OK;
   2870 }
   2871 
   2872 /// Read marks information from ShaDa file
   2873 ///
   2874 /// @return OK in case of success, FAIL otherwise.
   2875 int shada_read_marks(void)
   2876 {
   2877  return shada_read_file(NULL, kShaDaWantMarks);
   2878 }
   2879 
   2880 /// Read all information from ShaDa file
   2881 ///
   2882 /// @param[in]  fname    File to write to. If it is NULL or empty then default
   2883 /// @param[in]  forceit  If true, use forced reading (prioritize file contents
   2884 ///                      over current Neovim state).
   2885 /// @param[in]  missing_ok  If true, do not error out when file is missing.
   2886 ///
   2887 /// @return OK in case of success, FAIL otherwise.
   2888 int shada_read_everything(const char *const fname, const bool forceit, const bool missing_ok)
   2889 {
   2890  return shada_read_file(fname,
   2891                         kShaDaWantInfo|kShaDaWantMarks|kShaDaGetOldfiles
   2892                         |(forceit ? kShaDaForceit : 0)
   2893                         |(missing_ok ? 0 : kShaDaMissingError));
   2894 }
   2895 
   2896 static void shada_free_shada_entry(ShadaEntry *const entry)
   2897 {
   2898  if (entry == NULL || !entry->can_free_entry) {
   2899    return;
   2900  }
   2901  switch (entry->type) {
   2902  case kSDItemMissing:
   2903    break;
   2904  case kSDItemUnknown:
   2905    xfree(entry->data.unknown_item.contents);
   2906    break;
   2907  case kSDItemHeader:
   2908    api_free_dict(entry->data.header);
   2909    break;
   2910  case kSDItemChange:
   2911  case kSDItemJump:
   2912  case kSDItemGlobalMark:
   2913  case kSDItemLocalMark:
   2914    xfree(entry->data.filemark.fname);
   2915    break;
   2916  case kSDItemSearchPattern:
   2917    api_free_string(entry->data.search_pattern.pat);
   2918    break;
   2919  case kSDItemRegister:
   2920    for (size_t i = 0; i < entry->data.reg.contents_size; i++) {
   2921      api_free_string(entry->data.reg.contents[i]);
   2922    }
   2923    xfree(entry->data.reg.contents);
   2924    break;
   2925  case kSDItemHistoryEntry:
   2926    xfree(entry->data.history_item.string);
   2927    break;
   2928  case kSDItemVariable:
   2929    xfree(entry->data.global_var.name);
   2930    tv_clear(&entry->data.global_var.value);
   2931    break;
   2932  case kSDItemSubString:
   2933    xfree(entry->data.sub_string.sub);
   2934    break;
   2935  case kSDItemBufferList:
   2936    for (size_t i = 0; i < entry->data.buffer_list.size; i++) {
   2937      xfree(entry->data.buffer_list.buffers[i].fname);
   2938      xfree(entry->data.buffer_list.buffers[i].additional_data);
   2939    }
   2940    xfree(entry->data.buffer_list.buffers);
   2941    break;
   2942  }
   2943  XFREE_CLEAR(entry->additional_data);
   2944 }
   2945 
   2946 #ifndef HAVE_BE64TOH
   2947 static inline uint64_t vim_be64toh(uint64_t big_endian_64_bits)
   2948 {
   2949 # ifdef ORDER_BIG_ENDIAN
   2950  return big_endian_64_bits;
   2951 # else
   2952  // It may appear that when !defined(ORDER_BIG_ENDIAN) actual order is big
   2953  // endian. This variant is suboptimal, but it works regardless of actual
   2954  // order.
   2955  uint8_t *buf = (uint8_t *)&big_endian_64_bits;
   2956  uint64_t ret = 0;
   2957  for (size_t i = 8; i; i--) {
   2958    ret |= ((uint64_t)buf[i - 1]) << ((8 - i) * 8);
   2959  }
   2960  return ret;
   2961 # endif
   2962 }
   2963 # define be64toh vim_be64toh
   2964 #endif
   2965 
   2966 /// Read given number of bytes into given buffer, display error if needed
   2967 ///
   2968 /// @param[in]   sd_reader  Structure containing file reader definition.
   2969 /// @param[out]  buffer     Where to save the results.
   2970 /// @param[in]   length     How many bytes should be read.
   2971 ///
   2972 /// @return kSDReadStatusSuccess if everything was OK, kSDReadStatusNotShaDa if
   2973 ///         there were not enough bytes to read or kSDReadStatusReadError if
   2974 ///         there was some error while reading.
   2975 static ShaDaReadResult fread_len(FileDescriptor *const sd_reader, char *const buffer,
   2976                                 const size_t length)
   2977  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   2978 {
   2979  const ptrdiff_t read_bytes = file_read(sd_reader, buffer, length);
   2980  if (read_bytes < 0) {
   2981    semsg(_(SERR "System error while reading ShaDa file: %s"),
   2982          os_strerror((int)read_bytes));
   2983    return kSDReadStatusReadError;
   2984  }
   2985 
   2986  if (read_bytes != (ptrdiff_t)length) {
   2987    semsg(_(RCERR "Error while reading ShaDa file: "
   2988            "last entry specified that it occupies %" PRIu64 " bytes, "
   2989            "but file ended earlier"),
   2990          (uint64_t)length);
   2991    return kSDReadStatusNotShaDa;
   2992  }
   2993  return kSDReadStatusSuccess;
   2994 }
   2995 
   2996 /// Read next unsigned integer from file
   2997 ///
   2998 /// Errors out if the result is not an unsigned integer.
   2999 ///
   3000 /// Unlike msgpack own function this one works with `FILE *` and reads *exactly*
   3001 /// as much bytes as needed, making it possible to avoid both maintaining own
   3002 /// buffer and calling `fseek`.
   3003 ///
   3004 /// One byte from file stream is always consumed, even if it is not correct.
   3005 ///
   3006 /// @param[in]   sd_reader  Structure containing file reader definition.
   3007 /// @param[out]  result     Location where result is saved.
   3008 ///
   3009 /// @return kSDReadStatusSuccess if reading was successful,
   3010 ///         kSDReadStatusNotShaDa if there were not enough bytes to read or
   3011 ///         kSDReadStatusReadError if reading failed for whatever reason.
   3012 ///         kSDReadStatusFinished if eof and that was allowed
   3013 static ShaDaReadResult msgpack_read_uint64(FileDescriptor *const sd_reader, bool allow_eof,
   3014                                           uint64_t *const result)
   3015  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   3016 {
   3017  const uintmax_t fpos = sd_reader->bytes_read;
   3018 
   3019  uint8_t ret;
   3020  ptrdiff_t read_bytes = file_read(sd_reader, (char *)&ret, 1);
   3021 
   3022  if (read_bytes < 0) {
   3023    semsg(_(SERR "System error while reading integer from ShaDa file: %s"),
   3024          os_strerror((int)read_bytes));
   3025    return kSDReadStatusReadError;
   3026  } else if (read_bytes == 0) {
   3027    if (allow_eof && file_eof(sd_reader)) {
   3028      return kSDReadStatusFinished;
   3029    }
   3030    semsg(_(RCERR "Error while reading ShaDa file: "
   3031            "expected positive integer at position %" PRIu64
   3032            ", but got nothing"),
   3033          (uint64_t)fpos);
   3034    return kSDReadStatusNotShaDa;
   3035  }
   3036 
   3037  int first_char = (int)ret;
   3038  if (~first_char & 0x80) {
   3039    // Positive fixnum
   3040    *result = (uint64_t)((uint8_t)first_char);
   3041  } else {
   3042    size_t length = 0;
   3043    switch (first_char) {
   3044    case 0xCC:    // uint8
   3045      length = 1;
   3046      break;
   3047    case 0xCD:    // uint16
   3048      length = 2;
   3049      break;
   3050    case 0xCE:    // uint32
   3051      length = 4;
   3052      break;
   3053    case 0xCF:    // uint64
   3054      length = 8;
   3055      break;
   3056    default:
   3057      semsg(_(RCERR "Error while reading ShaDa file: "
   3058              "expected positive integer at position %" PRIu64),
   3059            (uint64_t)fpos);
   3060      return kSDReadStatusNotShaDa;
   3061    }
   3062    uint64_t buf = 0;
   3063    char *buf_u8 = (char *)&buf;
   3064    ShaDaReadResult fl_ret;
   3065    if ((fl_ret = fread_len(sd_reader, &(buf_u8[sizeof(buf) - length]), length))
   3066        != kSDReadStatusSuccess) {
   3067      return fl_ret;
   3068    }
   3069    *result = be64toh(buf);
   3070  }
   3071  return kSDReadStatusSuccess;
   3072 }
   3073 
   3074 #define READERR(entry_name, error_desc) \
   3075  RERR "Error while reading ShaDa file: " \
   3076  entry_name " entry at position %" PRIu64 " " \
   3077  error_desc
   3078 
   3079 /// Iterate over shada file contents
   3080 ///
   3081 /// @param[in]   sd_reader  Structure containing file reader definition.
   3082 /// @param[out]  entry      Address where next entry contents will be saved.
   3083 /// @param[in]   flags      Flags, determining whether and which items should be
   3084 ///                         skipped (see SRNIFlags enum).
   3085 /// @param[in]   max_kbyte  If non-zero, skip reading entries which have length
   3086 ///                         greater then given.
   3087 ///
   3088 /// @return Any value from ShaDaReadResult enum.
   3089 static ShaDaReadResult shada_read_next_item(FileDescriptor *const sd_reader,
   3090                                            ShadaEntry *const entry, const unsigned flags,
   3091                                            const size_t max_kbyte)
   3092  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   3093 {
   3094  ShaDaReadResult ret = kSDReadStatusMalformed;
   3095 shada_read_next_item_start:
   3096  // Set entry type to kSDItemMissing and also make sure that all pointers in
   3097  // data union are NULL so they are safe to xfree(). This is needed in case
   3098  // somebody calls goto shada_read_next_item_error before anything is set in
   3099  // the switch.
   3100  CLEAR_POINTER(entry);
   3101  if (file_eof(sd_reader)) {
   3102    return kSDReadStatusFinished;
   3103  }
   3104 
   3105  bool verify_but_ignore = false;
   3106 
   3107  // First: manually unpack type, timestamp and length.
   3108  // This is needed to avoid both seeking and having to maintain a buffer.
   3109  uint64_t type_u64 = (uint64_t)kSDItemMissing;
   3110  uint64_t timestamp_u64;
   3111  uint64_t length_u64;
   3112 
   3113  const uint64_t initial_fpos = sd_reader->bytes_read;
   3114  AdditionalDataBuilder ad = KV_INITIAL_VALUE;
   3115  uint32_t read_additional_array_elements = 0;
   3116  char *error_alloc = NULL;
   3117 
   3118  ShaDaReadResult mru_ret;
   3119  if (((mru_ret = msgpack_read_uint64(sd_reader, true, &type_u64))
   3120       != kSDReadStatusSuccess)
   3121      || ((mru_ret = msgpack_read_uint64(sd_reader, false,
   3122                                         &timestamp_u64))
   3123          != kSDReadStatusSuccess)
   3124      || ((mru_ret = msgpack_read_uint64(sd_reader, false,
   3125                                         &length_u64))
   3126          != kSDReadStatusSuccess)) {
   3127    return mru_ret;
   3128  }
   3129 
   3130  if (length_u64 > PTRDIFF_MAX) {
   3131    semsg(_(RCERR "Error while reading ShaDa file: "
   3132            "there is an item at position %" PRIu64 " "
   3133            "that is stated to be too long"),
   3134          initial_fpos);
   3135    return kSDReadStatusNotShaDa;
   3136  }
   3137 
   3138  const size_t length = (size_t)length_u64;
   3139  entry->timestamp = (Timestamp)timestamp_u64;
   3140  entry->can_free_entry = true;  // all allocations are owned by the entry
   3141 
   3142  if (type_u64 == 0) {
   3143    // kSDItemUnknown cannot possibly pass that far because it is -1 and that
   3144    // will fail in msgpack_read_uint64. But kSDItemMissing may and it will
   3145    // otherwise be skipped because (1 << 0) will never appear in flags.
   3146    semsg(_(RCERR "Error while reading ShaDa file: "
   3147            "there is an item at position %" PRIu64 " "
   3148            "that must not be there: Missing items are "
   3149            "for internal uses only"),
   3150          initial_fpos);
   3151    return kSDReadStatusNotShaDa;
   3152  }
   3153 
   3154  if ((type_u64 > SHADA_LAST_ENTRY
   3155       ? !(flags & kSDReadUnknown)
   3156       : !((unsigned)(1 << type_u64) & flags))
   3157      || (max_kbyte && length > max_kbyte * 1024)) {
   3158    // First entry is unknown or equal to "\n" (10)? Most likely this means that
   3159    // current file is not a ShaDa file because first item should normally be
   3160    // a header (excluding tests where first item is tested item). Check this by
   3161    // parsing entry contents: in non-ShaDa files this will most likely result
   3162    // in incomplete MessagePack string.
   3163    if (initial_fpos == 0
   3164        && (type_u64 == '\n' || type_u64 > SHADA_LAST_ENTRY)) {
   3165      verify_but_ignore = true;
   3166    } else {
   3167      const ShaDaReadResult srs_ret = sd_reader_skip(sd_reader, length);
   3168      if (srs_ret != kSDReadStatusSuccess) {
   3169        return srs_ret;
   3170      }
   3171      goto shada_read_next_item_start;
   3172    }
   3173  }
   3174 
   3175  const uint64_t parse_pos = sd_reader->bytes_read;
   3176  bool buf_allocated = false;
   3177  // try to avoid allocation for small items which fits entirely
   3178  // in the internal buffer of sd_reader
   3179  char *buf = file_try_read_buffered(sd_reader, length);
   3180  if (!buf) {
   3181    buf_allocated = true;
   3182    buf = xmalloc(length);
   3183    const ShaDaReadResult fl_ret = fread_len(sd_reader, buf, length);
   3184    if (fl_ret != kSDReadStatusSuccess) {
   3185      ret = fl_ret;
   3186      goto shada_read_next_item_error;
   3187    }
   3188  }
   3189 
   3190  const char *read_ptr = buf;
   3191  size_t read_size = length;
   3192 
   3193  if (verify_but_ignore) {
   3194    int status = unpack_skip(&read_ptr, &read_size);
   3195    ShaDaReadResult spm_ret = shada_check_status(parse_pos, status, read_size);
   3196    if (buf_allocated) {
   3197      xfree(buf);
   3198    }
   3199    if (spm_ret != kSDReadStatusSuccess) {
   3200      return spm_ret;
   3201    }
   3202    goto shada_read_next_item_start;
   3203  }
   3204 
   3205  if (type_u64 > SHADA_LAST_ENTRY) {
   3206    entry->type = kSDItemUnknown;
   3207    entry->data.unknown_item.size = length;
   3208    entry->data.unknown_item.type = type_u64;
   3209    if (initial_fpos == 0) {
   3210      int status = unpack_skip(&read_ptr, &read_size);
   3211      ShaDaReadResult spm_ret = shada_check_status(parse_pos, status, read_size);
   3212      if (spm_ret != kSDReadStatusSuccess) {
   3213        if (buf_allocated) {
   3214          xfree(buf);
   3215        }
   3216        entry->type = kSDItemMissing;
   3217        return spm_ret;
   3218      }
   3219    }
   3220    entry->data.unknown_item.contents = buf_allocated ? buf : xmemdup(buf, length);
   3221    return kSDReadStatusSuccess;
   3222  }
   3223 
   3224  entry->data = sd_default_values[type_u64].data;
   3225  switch ((ShadaEntryType)type_u64) {
   3226  case kSDItemHeader:
   3227    // TODO(bfredl): header is written to file and provides useful debugging
   3228    // info. It is never read by nvim (earlier we parsed it back to a
   3229    // Dict, but that value was never used)
   3230    break;
   3231  case kSDItemSearchPattern: {
   3232    Dict(_shada_search_pat) *it = &entry->data.search_pattern;
   3233    if (!unpack_keydict(it, DictHash(_shada_search_pat), &ad, &read_ptr, &read_size,
   3234                        &error_alloc)) {
   3235      semsg(_(READERR("search pattern", "%s")), initial_fpos, error_alloc);
   3236      it->pat = NULL_STRING;
   3237      goto shada_read_next_item_error;
   3238    }
   3239 
   3240    if (!HAS_KEY(it, _shada_search_pat, sp)) {  // SEARCH_KEY_PAT
   3241      semsg(_(READERR("search pattern", "has no pattern")), initial_fpos);
   3242      goto shada_read_next_item_error;
   3243    }
   3244    entry->data.search_pattern.pat = copy_string(entry->data.search_pattern.pat, NULL);
   3245 
   3246    break;
   3247  }
   3248  case kSDItemChange:
   3249  case kSDItemJump:
   3250  case kSDItemGlobalMark:
   3251  case kSDItemLocalMark: {
   3252    Dict(_shada_mark) it = { 0 };
   3253    if (!unpack_keydict(&it, DictHash(_shada_mark), &ad, &read_ptr, &read_size, &error_alloc)) {
   3254      semsg(_(READERR("mark", "%s")), initial_fpos, error_alloc);
   3255      goto shada_read_next_item_error;
   3256    }
   3257 
   3258    if (HAS_KEY(&it, _shada_mark, n)) {
   3259      if (type_u64 == kSDItemJump || type_u64 == kSDItemChange) {
   3260        semsg(_(READERR("mark", "has n key which is only valid for "
   3261                        "local and global mark entries")), initial_fpos);
   3262        goto shada_read_next_item_error;
   3263      }
   3264      entry->data.filemark.name = (char)it.n;
   3265    }
   3266 
   3267    if (HAS_KEY(&it, _shada_mark, l)) {
   3268      entry->data.filemark.mark.lnum = (linenr_T)it.l;
   3269    }
   3270    if (HAS_KEY(&it, _shada_mark, c)) {
   3271      entry->data.filemark.mark.col = (colnr_T)it.c;
   3272    }
   3273    if (HAS_KEY(&it, _shada_mark, f)) {
   3274      entry->data.filemark.fname = xmemdupz(it.f.data, it.f.size);
   3275    }
   3276 
   3277    if (entry->data.filemark.fname == NULL) {
   3278      semsg(_(READERR("mark", "is missing file name")), initial_fpos);
   3279      goto shada_read_next_item_error;
   3280    }
   3281    if (entry->data.filemark.mark.lnum <= 0) {
   3282      semsg(_(READERR("mark", "has invalid line number")), initial_fpos);
   3283      goto shada_read_next_item_error;
   3284    }
   3285    if (entry->data.filemark.mark.col < 0) {
   3286      semsg(_(READERR("mark", "has invalid column number")), initial_fpos);
   3287      goto shada_read_next_item_error;
   3288    }
   3289    break;
   3290  }
   3291  case kSDItemRegister: {
   3292    Dict(_shada_register) it = { 0 };
   3293    if (!unpack_keydict(&it, DictHash(_shada_register), &ad, &read_ptr, &read_size, &error_alloc)) {
   3294      semsg(_(READERR("register", "%s")), initial_fpos, error_alloc);
   3295      kv_destroy(it.rc);
   3296      goto shada_read_next_item_error;
   3297    }
   3298    if (it.rc.size == 0) {
   3299      semsg(_(READERR("register",
   3300                      "has " KEY_NAME(REG_KEY_CONTENTS) " key with missing or empty array")),
   3301            initial_fpos);
   3302      goto shada_read_next_item_error;
   3303    }
   3304    entry->data.reg.contents_size = it.rc.size;
   3305    entry->data.reg.contents = xmalloc(it.rc.size * sizeof(String));
   3306    for (size_t j = 0; j < it.rc.size; j++) {
   3307      entry->data.reg.contents[j] = copy_string(it.rc.items[j], NULL);
   3308    }
   3309    kv_destroy(it.rc);
   3310 
   3311 #define REGISTER_VAL(name, loc, type) \
   3312  if (HAS_KEY(&it, _shada_register, name)) { \
   3313    loc = (type)it.name; \
   3314  }
   3315    REGISTER_VAL(REG_KEY_UNNAMED, entry->data.reg.is_unnamed, bool)
   3316    REGISTER_VAL(REG_KEY_TYPE, entry->data.reg.type, uint8_t)
   3317    REGISTER_VAL(KEY_NAME_CHAR, entry->data.reg.name, char)
   3318    REGISTER_VAL(REG_KEY_WIDTH, entry->data.reg.width, size_t)
   3319    break;
   3320  }
   3321  case kSDItemHistoryEntry: {
   3322    ssize_t len = unpack_array(&read_ptr, &read_size);
   3323 
   3324    if (len < 2) {
   3325      semsg(_(READERR("history", "is not an array with enough elements")), initial_fpos);
   3326      goto shada_read_next_item_error;
   3327    }
   3328    Integer hist_type;
   3329    if (!unpack_integer(&read_ptr, &read_size, &hist_type)) {
   3330      semsg(_(READERR("history", "has wrong history type type")), initial_fpos);
   3331      goto shada_read_next_item_error;
   3332    }
   3333    const String item = unpack_string(&read_ptr, &read_size);
   3334    if (!item.data) {
   3335      semsg(_(READERR("history", "has wrong history string type")), initial_fpos);
   3336      goto shada_read_next_item_error;
   3337    }
   3338    if (memchr(item.data, 0, item.size) != NULL) {
   3339      semsg(_(READERR("history", "contains string with zero byte inside")), initial_fpos);
   3340      goto shada_read_next_item_error;
   3341    }
   3342    entry->data.history_item.histtype = (uint8_t)hist_type;
   3343    const bool is_hist_search = entry->data.history_item.histtype == HIST_SEARCH;
   3344    if (is_hist_search) {
   3345      if (len < 3) {
   3346        semsg(_(READERR("search history",
   3347                        "does not have separator character")), initial_fpos);
   3348        goto shada_read_next_item_error;
   3349      }
   3350      Integer sep_type;
   3351      if (!unpack_integer(&read_ptr, &read_size, &sep_type)) {
   3352        semsg(_(READERR("search history", "has wrong history separator type")), initial_fpos);
   3353        goto shada_read_next_item_error;
   3354      }
   3355      entry->data.history_item.sep = (char)sep_type;
   3356    }
   3357    size_t strsize = (item.size
   3358                      + 1  // Zero byte
   3359                      + 1);  // Separator character
   3360    entry->data.history_item.string = xmalloc(strsize);
   3361    memcpy(entry->data.history_item.string, item.data, item.size);
   3362    entry->data.history_item.string[strsize - 2] = 0;
   3363    entry->data.history_item.string[strsize - 1] = entry->data.history_item.sep;
   3364    read_additional_array_elements = (uint32_t)(len - (2 + is_hist_search));
   3365    break;
   3366  }
   3367  case kSDItemVariable: {
   3368    ssize_t len = unpack_array(&read_ptr, &read_size);
   3369 
   3370    if (len < 2) {
   3371      semsg(_(READERR("variable", "is not an array with enough elements")), initial_fpos);
   3372      goto shada_read_next_item_error;
   3373    }
   3374 
   3375    String name = unpack_string(&read_ptr, &read_size);
   3376 
   3377    if (!name.data) {
   3378      semsg(_(READERR("variable", "has wrong variable name type")), initial_fpos);
   3379      goto shada_read_next_item_error;
   3380    }
   3381    entry->data.global_var.name = xmemdupz(name.data, name.size);
   3382 
   3383    String binval = unpack_string(&read_ptr, &read_size);
   3384 
   3385    bool is_blob = false;
   3386    if (binval.data) {
   3387      if (len > 2) {
   3388        // A msgpack BIN could be a String or Blob; an additional VAR_TYPE_BLOB
   3389        // element is stored with Blobs which can be used to differentiate them
   3390        Integer type;
   3391        if (!unpack_integer(&read_ptr, &read_size, &type) || type != VAR_TYPE_BLOB) {
   3392          semsg(_(READERR("variable", "has wrong variable type")),
   3393                initial_fpos);
   3394          goto shada_read_next_item_error;
   3395        }
   3396        is_blob = true;
   3397      }
   3398      entry->data.global_var.value = decode_string(binval.data, binval.size, is_blob, false);
   3399    } else {
   3400      int status = unpack_typval(&read_ptr, &read_size, &entry->data.global_var.value);
   3401      if (status != MPACK_OK) {
   3402        semsg(_(READERR("variable", "has value that cannot "
   3403                        "be converted to the Vimscript value")), initial_fpos);
   3404        goto shada_read_next_item_error;
   3405      }
   3406    }
   3407    read_additional_array_elements = (uint32_t)(len - 2 - (is_blob ? 1 : 0));
   3408    break;
   3409  }
   3410  case kSDItemSubString: {
   3411    ssize_t len = unpack_array(&read_ptr, &read_size);
   3412 
   3413    if (len < 1) {
   3414      semsg(_(READERR("sub string", "is not an array with enough elements")), initial_fpos);
   3415      goto shada_read_next_item_error;
   3416    }
   3417 
   3418    String sub = unpack_string(&read_ptr, &read_size);
   3419    if (!sub.data) {
   3420      semsg(_(READERR("sub string", "has wrong sub string type")), initial_fpos);
   3421      goto shada_read_next_item_error;
   3422    }
   3423    entry->data.sub_string.sub = xmemdupz(sub.data, sub.size);
   3424    read_additional_array_elements = (uint32_t)(len - 1);
   3425    break;
   3426  }
   3427  case kSDItemBufferList: {
   3428    ssize_t len = unpack_array(&read_ptr, &read_size);
   3429    if (len < 0) {
   3430      semsg(_(READERR("buffer list", "is not an array")), initial_fpos);
   3431      goto shada_read_next_item_error;
   3432    }
   3433    if (len == 0) {
   3434      break;
   3435    }
   3436    entry->data.buffer_list.buffers = xcalloc((size_t)len,
   3437                                              sizeof(*entry->data.buffer_list.buffers));
   3438    for (size_t i = 0; i < (size_t)len; i++) {
   3439      entry->data.buffer_list.size++;
   3440      Dict(_shada_buflist_item) it = { 0 };
   3441      AdditionalDataBuilder it_ad = KV_INITIAL_VALUE;
   3442      if (!unpack_keydict(&it, DictHash(_shada_buflist_item), &it_ad, &read_ptr, &read_size,
   3443                          &error_alloc)) {
   3444        semsg(_(RERR "Error while reading ShaDa file: "
   3445                "buffer list at position %" PRIu64 " contains entry that %s"),
   3446              initial_fpos, error_alloc);
   3447        kv_destroy(it_ad);
   3448        goto shada_read_next_item_error;
   3449      }
   3450      struct buffer_list_buffer *e = &entry->data.buffer_list.buffers[i];
   3451      e->additional_data = (AdditionalData *)it_ad.items;
   3452      e->pos = default_pos;
   3453      if (HAS_KEY(&it, _shada_buflist_item, l)) {
   3454        e->pos.lnum = (linenr_T)it.l;
   3455      }
   3456      if (HAS_KEY(&it, _shada_buflist_item, c)) {
   3457        e->pos.col = (colnr_T)it.c;
   3458      }
   3459      if (HAS_KEY(&it, _shada_buflist_item, f)) {
   3460        e->fname = xmemdupz(it.f.data, it.f.size);
   3461      }
   3462 
   3463      if (e->pos.lnum <= 0) {
   3464        semsg(_(RERR "Error while reading ShaDa file: "
   3465                "buffer list at position %" PRIu64 " "
   3466                "contains entry with invalid line number"),
   3467              initial_fpos);
   3468        goto shada_read_next_item_error;
   3469      }
   3470      if (e->pos.col < 0) {
   3471        semsg(_(RERR "Error while reading ShaDa file: "
   3472                "buffer list at position %" PRIu64 " "
   3473                "contains entry with invalid column number"),
   3474              initial_fpos);
   3475        goto shada_read_next_item_error;
   3476      }
   3477      if (e->fname == NULL) {
   3478        semsg(_(RERR "Error while reading ShaDa file: "
   3479                "buffer list at position %" PRIu64 " "
   3480                "contains entry that does not have a file name"),
   3481              initial_fpos);
   3482        goto shada_read_next_item_error;
   3483      }
   3484    }
   3485    break;
   3486  }
   3487  case kSDItemMissing:
   3488  case kSDItemUnknown:
   3489    abort();
   3490  }
   3491 
   3492  for (uint32_t i = 0; i < read_additional_array_elements; i++) {
   3493    const char *item_start = read_ptr;
   3494    int status = unpack_skip(&read_ptr, &read_size);
   3495    if (status) {
   3496      goto shada_read_next_item_error;
   3497    }
   3498 
   3499    push_additional_data(&ad, item_start, (size_t)(read_ptr - item_start));
   3500  }
   3501 
   3502  if (read_size) {
   3503    semsg(_(READERR("item", "additional bytes")), initial_fpos);
   3504    goto shada_read_next_item_error;
   3505  }
   3506 
   3507  entry->type = (ShadaEntryType)type_u64;
   3508  entry->additional_data = (AdditionalData *)ad.items;
   3509  ret = kSDReadStatusSuccess;
   3510 shada_read_next_item_end:
   3511  if (buf_allocated) {
   3512    xfree(buf);
   3513  }
   3514  return ret;
   3515 shada_read_next_item_error:
   3516  entry->type = (ShadaEntryType)type_u64;
   3517  shada_free_shada_entry(entry);
   3518  entry->type = kSDItemMissing;
   3519  xfree(error_alloc);
   3520  kv_destroy(ad);
   3521  goto shada_read_next_item_end;
   3522 }
   3523 
   3524 /// Check whether "name" is on removable media (according to 'shada')
   3525 ///
   3526 /// @param[in]  name  Checked name.
   3527 ///
   3528 /// @return True if it is, false otherwise.
   3529 static bool shada_removable(const char *name)
   3530  FUNC_ATTR_WARN_UNUSED_RESULT
   3531 {
   3532  char part[MAXPATHL + 1];
   3533  bool retval = false;
   3534 
   3535  char *new_name = home_replace_save(NULL, name);
   3536  for (char *p = p_shada; *p;) {
   3537    copy_option_part(&p, part, ARRAY_SIZE(part), ", ");
   3538    if (part[0] == 'r') {
   3539      home_replace(NULL, part + 1, NameBuff, MAXPATHL, true);
   3540      size_t n = strlen(NameBuff);
   3541      if (mb_strnicmp(NameBuff, new_name, n) == 0) {
   3542        retval = true;
   3543        break;
   3544      }
   3545    }
   3546  }
   3547  xfree(new_name);
   3548  return retval;
   3549 }
   3550 
   3551 /// Initialize ShaDa jumplist entries.
   3552 ///
   3553 /// @param[in,out]  jumps           Array of ShaDa entries to set.
   3554 /// @param[in]      removable_bufs  Cache of buffers ignored due to their
   3555 ///                                 location.
   3556 ///
   3557 /// @return number of jumplist entries
   3558 static inline size_t shada_init_jumps(ShadaEntry *jumps, Set(ptr_t) *const removable_bufs)
   3559 {
   3560  // Initialize jump list
   3561  size_t jumps_size = 0;
   3562  const void *jump_iter = NULL;
   3563  setpcmark();
   3564  cleanup_jumplist(curwin, false);
   3565  do {
   3566    xfmark_T fm;
   3567    jump_iter = mark_jumplist_iter(jump_iter, curwin, &fm);
   3568 
   3569    if (fm.fmark.mark.lnum == 0) {
   3570      siemsg("ShaDa: mark lnum zero (ji:%p, js:%p, len:%i)",
   3571             (void *)jump_iter, (void *)&curwin->w_jumplist[0],
   3572             curwin->w_jumplistlen);
   3573      continue;
   3574    }
   3575    const buf_T *const buf = (fm.fmark.fnum == 0 ? NULL : buflist_findnr(fm.fmark.fnum));
   3576    if (buf != NULL ? ignore_buf(buf, removable_bufs) : fm.fmark.fnum != 0) {
   3577      continue;
   3578    }
   3579    const char *const fname =
   3580      (fm.fmark.fnum == 0 ? (fm.fname == NULL ? NULL : fm.fname) : buf ? buf->b_ffname : NULL);
   3581    if (fname == NULL) {
   3582      continue;
   3583    }
   3584    jumps[jumps_size++] = (ShadaEntry) {
   3585      .can_free_entry = false,
   3586      .type = kSDItemJump,
   3587      .timestamp = fm.fmark.timestamp,
   3588      .data = {
   3589        .filemark = {
   3590          .name = NUL,
   3591          .mark = fm.fmark.mark,
   3592          .fname = (char *)fname,
   3593        }
   3594      },
   3595      .additional_data = fm.fmark.additional_data,
   3596    };
   3597  } while (jump_iter != NULL);
   3598  return jumps_size;
   3599 }
   3600 
   3601 /// Write registers ShaDa entries in given msgpack_sbuffer.
   3602 ///
   3603 /// @param[in]  sbuf  target msgpack_sbuffer to write to.
   3604 String shada_encode_regs(void)
   3605  FUNC_ATTR_NONNULL_ALL
   3606 {
   3607  WriteMergerState *const wms = xcalloc(1, sizeof(*wms));
   3608  shada_initialize_registers(wms, -1);
   3609  PackerBuffer packer = packer_string_buffer();
   3610  for (size_t i = 0; i < ARRAY_SIZE(wms->registers); i++) {
   3611    if (wms->registers[i].type == kSDItemRegister) {
   3612      if (kSDWriteFailed
   3613          == shada_pack_pfreed_entry(&packer, wms->registers[i], 0)) {
   3614        abort();
   3615      }
   3616    }
   3617  }
   3618  xfree(wms);
   3619  return packer_take_string(&packer);
   3620 }
   3621 
   3622 /// Write jumplist ShaDa entries in given msgpack_sbuffer.
   3623 ///
   3624 /// @param[in]  sbuf            target msgpack_sbuffer to write to.
   3625 String shada_encode_jumps(void)
   3626  FUNC_ATTR_NONNULL_ALL
   3627 {
   3628  Set(ptr_t) removable_bufs = SET_INIT;
   3629  find_removable_bufs(&removable_bufs);
   3630  ShadaEntry jumps[JUMPLISTSIZE];
   3631  size_t jumps_size = shada_init_jumps(jumps, &removable_bufs);
   3632  PackerBuffer packer = packer_string_buffer();
   3633  for (size_t i = 0; i < jumps_size; i++) {
   3634    if (kSDWriteFailed == shada_pack_pfreed_entry(&packer, jumps[i], 0)) {
   3635      abort();
   3636    }
   3637  }
   3638  return packer_take_string(&packer);
   3639 }
   3640 
   3641 /// Write buffer list ShaDa entry in given msgpack_sbuffer.
   3642 ///
   3643 /// @param[in]  sbuf            target msgpack_sbuffer to write to.
   3644 String shada_encode_buflist(void)
   3645  FUNC_ATTR_NONNULL_ALL
   3646 {
   3647  Set(ptr_t) removable_bufs = SET_INIT;
   3648  find_removable_bufs(&removable_bufs);
   3649  ShadaEntry buflist_entry = shada_get_buflist(&removable_bufs);
   3650 
   3651  PackerBuffer packer = packer_string_buffer();
   3652  if (kSDWriteFailed == shada_pack_entry(&packer, buflist_entry, 0)) {
   3653    abort();
   3654  }
   3655  xfree(buflist_entry.data.buffer_list.buffers);
   3656  return packer_take_string(&packer);
   3657 }
   3658 
   3659 /// Write global variables ShaDa entries in given msgpack_sbuffer.
   3660 ///
   3661 /// @param[in]  sbuf            target msgpack_sbuffer to write to.
   3662 String shada_encode_gvars(void)
   3663  FUNC_ATTR_NONNULL_ALL
   3664 {
   3665  PackerBuffer packer = packer_string_buffer();
   3666  const void *var_iter = NULL;
   3667  const Timestamp cur_timestamp = os_time();
   3668  do {
   3669    typval_T vartv;
   3670    const char *name = NULL;
   3671    var_iter = var_shada_iter(var_iter, &name, &vartv,
   3672                              VAR_FLAVOUR_DEFAULT | VAR_FLAVOUR_SESSION | VAR_FLAVOUR_SHADA);
   3673    if (name == NULL) {
   3674      break;
   3675    }
   3676    if (vartv.v_type != VAR_FUNC && vartv.v_type != VAR_PARTIAL) {
   3677      typval_T tgttv;
   3678      tv_copy(&vartv, &tgttv);
   3679      ShaDaWriteResult r = shada_pack_entry(&packer, (ShadaEntry) {
   3680        .type = kSDItemVariable,
   3681        .timestamp = cur_timestamp,
   3682        .data = {
   3683          .global_var = {
   3684            .name = (char *)name,
   3685            .value = tgttv,
   3686          }
   3687        },
   3688        .additional_data = NULL,
   3689      }, 0);
   3690      if (kSDWriteFailed == r) {
   3691        abort();
   3692      }
   3693      tv_clear(&tgttv);
   3694    }
   3695    tv_clear(&vartv);
   3696  } while (var_iter != NULL);
   3697  return packer_take_string(&packer);
   3698 }
   3699 
   3700 /// Read ShaDa from String.
   3701 ///
   3702 /// @param[in]  string   string to read from.
   3703 /// @param[in]  flags  Flags, see ShaDaReadFileFlags enum.
   3704 void shada_read_string(String string, const int flags)
   3705  FUNC_ATTR_NONNULL_ALL
   3706 {
   3707  if (string.size == 0) {
   3708    return;
   3709  }
   3710  FileDescriptor sd_reader;
   3711  file_open_buffer(&sd_reader, string.data, string.size);
   3712  shada_read(&sd_reader, flags);
   3713  close_file(&sd_reader);
   3714 }
   3715 
   3716 /// Find the parameter represented by the given character (eg ', :, ", or /),
   3717 /// and return its associated value in the 'shada' string.
   3718 /// Only works for number parameters, not for 'r' or 'n'.
   3719 /// If the parameter is not specified in the string or there is no following
   3720 /// number, return -1.
   3721 int get_shada_parameter(int type)
   3722 {
   3723  char *p = find_shada_parameter(type);
   3724  if (p != NULL && ascii_isdigit(*p)) {
   3725    return atoi(p);
   3726  }
   3727  return -1;
   3728 }
   3729 
   3730 /// Find the parameter represented by the given character (eg ''', ':', '"', or
   3731 /// '/') in the 'shada' option and return a pointer to the string after it.
   3732 /// Return NULL if the parameter is not specified in the string.
   3733 char *find_shada_parameter(int type)
   3734 {
   3735  for (char *p = p_shada; *p; p++) {
   3736    if (*p == type) {
   3737      return p + 1;
   3738    }
   3739    if (*p == 'n') {                // 'n' is always the last one
   3740      break;
   3741    }
   3742    p = vim_strchr(p, ',');         // skip until next ','
   3743    if (p == NULL) {                // hit the end without finding parameter
   3744      break;
   3745    }
   3746  }
   3747  return NULL;
   3748 }
   3749 
   3750 /// Read marks for the current buffer from the ShaDa file, when we support
   3751 /// buffer marks and the buffer has a name.
   3752 void check_marks_read(void)
   3753 {
   3754  if (!curbuf->b_marks_read && get_shada_parameter('\'') > 0
   3755      && curbuf->b_ffname != NULL) {
   3756    shada_read_marks();
   3757  }
   3758 
   3759  // Always set b_marks_read; needed when 'shada' is changed to include
   3760  // the ' parameter after opening a buffer.
   3761  curbuf->b_marks_read = true;
   3762 }