~ubuntu-branches/debian/sid/neovim/sid

« back to all changes in this revision

Viewing changes to src/nvim/shada.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2016-02-20 22:41:32 UTC
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: package-import@ubuntu.com-20160220224132-e24n8lh3yo5ylt23
Tags: upstream-0.1.2
ImportĀ upstreamĀ versionĀ 0.1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifdef HAVE_BE64TOH
2
 
# define _BSD_SOURCE 1
3
 
# define _DEFAULT_SOURCE 1
4
 
# include <endian.h>
5
 
#endif
6
1
#include <stdlib.h>
7
2
#include <stddef.h>
8
3
#include <stdbool.h>
10
5
#include <stdint.h>
11
6
#include <inttypes.h>
12
7
#include <errno.h>
13
 
#include <unistd.h>
 
8
#include <fcntl.h>
14
9
#include <assert.h>
15
10
 
16
11
#include <msgpack.h>
47
42
#include "nvim/lib/khash.h"
48
43
#include "nvim/lib/kvec.h"
49
44
 
 
45
#ifdef HAVE_BE64TOH
 
46
# define _BSD_SOURCE 1
 
47
# define _DEFAULT_SOURCE 1
 
48
# include <endian.h>
 
49
#endif
 
50
 
50
51
// Note: when using bufset hash pointers are intentionally casted to uintptr_t
51
52
// and not to khint32_t or khint64_t: this way compiler must give a warning
52
53
// (-Wconversion) when types change.
120
121
//   E576: Missing '>'
121
122
//   E577: Illegal register name
122
123
//   E886: Can't rename viminfo file to %s!
123
 
// Now only five of them are used:
 
124
// Now only six of them are used:
124
125
//   E137: ShaDa file is not writeable (for pre-open checks)
125
126
//   E138: All %s.tmp.X files exist, cannot write ShaDa file!
126
127
//   RCERR (E576) for critical read errors.
128
129
//   RERR (E575) for various errors inside read ShaDa file.
129
130
//   SERR (E886) for various ā€œsystemā€ errors (always contains output of
130
131
//   strerror)
 
132
//   WERR (E574) for various ignorable write errors
131
133
 
132
134
/// Common prefix for all errors inside ShaDa file
133
135
///
146
148
/// Common prefix for all ā€œrenameā€ errors
147
149
#define RNERR "E136: "
148
150
 
 
151
/// Common prefix for all ignorable ā€œwriteā€ errors
 
152
#define WERR "E574: "
 
153
 
149
154
/// Flags for shada_read_file and children
150
155
typedef enum {
151
156
  kShaDaWantInfo = 1,       ///< Load non-mark information
196
201
                         ///< a ShaDa file.
197
202
  kSDWriteFailed,        ///< Writing was not successfull (e.g. because there
198
203
                         ///< was no space left on device).
 
204
  kSDWriteIgnError,      ///< Writing resulted in a error which can be ignored
 
205
                         ///< (e.g. when trying to dump a function reference or
 
206
                         ///< self-referencing container in a variable).
199
207
} ShaDaWriteResult;
200
208
 
201
209
/// Flags for shada_read_next_item
203
211
  kSDReadHeader = (1 << kSDItemHeader),  ///< Determines whether header should
204
212
                                         ///< be read (it is usually ignored).
205
213
  kSDReadUndisableableData = (
206
 
    (1 << kSDItemSearchPattern)
207
 
    | (1 << kSDItemSubString)
208
 
    | (1 << kSDItemJump)),  ///< Data reading which cannot be disabled by &shada
209
 
                            ///< or other options except for disabling reading
210
 
                            ///< ShaDa as a whole.
 
214
      (1 << kSDItemSearchPattern)
 
215
      | (1 << kSDItemSubString)
 
216
      | (1 << kSDItemJump)),  ///< Data reading which cannot be disabled by
 
217
                              ///< &shada or other options except for disabling
 
218
                              ///< reading ShaDa as a whole.
211
219
  kSDReadRegisters = (1 << kSDItemRegister),  ///< Determines whether registers
212
220
                                              ///< should be read (may only be
213
221
                                              ///< disabled when writing, but
444
452
        .attr = { __VA_ARGS__ } \
445
453
      } \
446
454
    }
447
 
#define DEFAULT_POS {1, 0, 0}
 
455
#define DEFAULT_POS { 1, 0, 0 }
448
456
static const pos_T default_pos = DEFAULT_POS;
449
457
static const ShadaEntry sd_default_values[] = {
450
458
  [kSDItemMissing] = { .type = kSDItemMissing, .timestamp = 0 },
531
539
///
532
540
/// @param  hmll       Pointer to the list.
533
541
/// @param  cur_entry  Name of the variable to iterate over.
 
542
/// @param  code       Code to execute on each iteration.
534
543
///
535
544
/// @return `for` cycle header (use `HMLL_FORALL(hmll, cur_entry) {body}`).
536
 
#define HMLL_FORALL(hmll, cur_entry) \
 
545
#define HMLL_FORALL(hmll, cur_entry, code) \
537
546
    for (HMLListEntry *cur_entry = (hmll)->first; cur_entry != NULL; \
538
 
         cur_entry = cur_entry->next)
 
547
         cur_entry = cur_entry->next) { \
 
548
      code \
 
549
    } \
539
550
 
540
551
/// Remove entry from the linked list
541
552
///
631
642
/// @param  hmll       Pointer to the list.
632
643
/// @param  cur_entry  Name of the variable to iterate over, must be already
633
644
///                    defined.
 
645
/// @param  code       Code to execute on each iteration.
634
646
///
635
647
/// @return `for` cycle header (use `HMLL_FORALL(hmll, cur_entry) {body}`).
636
 
#define HMLL_ITER_BACK(hmll, cur_entry) \
 
648
#define HMLL_ITER_BACK(hmll, cur_entry, code) \
637
649
    for (cur_entry = (hmll)->last; cur_entry != NULL; \
638
 
         cur_entry = cur_entry->prev)
 
650
         cur_entry = cur_entry->prev) { \
 
651
      code \
 
652
    }
639
653
 
640
654
/// Free linked list
641
655
///
746
760
  FUNC_ATTR_NONNULL_ALL
747
761
{
748
762
  const int fd = (int)(intptr_t) sd_writer->cookie;
749
 
  if (fsync(fd) < 0) {
 
763
  if (os_fsync(fd) < 0) {
750
764
    emsg2(_(SERR "System error while synchronizing ShaDa file: %s"),
751
 
          strerror(errno));
 
765
          os_strerror(errno));
752
766
    errno = 0;
753
767
  }
754
768
  close_file(fd);
957
971
  if (p_verbose > 0) {
958
972
    verbose_enter();
959
973
    smsg(_("Reading ShaDa file \"%s\"%s%s%s"),
960
 
        fname,
961
 
        (flags & kShaDaWantInfo) ? _(" info") : "",
962
 
        (flags & kShaDaWantMarks) ? _(" marks") : "",
963
 
        (flags & kShaDaGetOldfiles) ? _(" oldfiles") : "",
964
 
        of_ret != 0 ? _(" FAILED") : "");
 
974
         fname,
 
975
         (flags & kShaDaWantInfo) ? _(" info") : "",
 
976
         (flags & kShaDaWantMarks) ? _(" marks") : "",
 
977
         (flags & kShaDaGetOldfiles) ? _(" oldfiles") : "",
 
978
         of_ret != 0 ? _(" FAILED") : "");
965
979
    verbose_leave();
966
980
  }
967
981
 
1009
1023
          .histtype = history_type,
1010
1024
          .string = (char *) hist_he.hisstr,
1011
1025
          .sep = (char) (history_type == HIST_SEARCH
1012
 
                        ? (char) hist_he.hisstr[STRLEN(hist_he.hisstr) + 1]
1013
 
                        : 0),
 
1026
                         ? (char) hist_he.hisstr[STRLEN(hist_he.hisstr) + 1]
 
1027
                         : 0),
1014
1028
          .additional_elements = hist_he.additional_elements,
1015
1029
        }
1016
1030
      }
1072
1086
    }
1073
1087
  }
1074
1088
  HMLListEntry *insert_after;
1075
 
  HMLL_ITER_BACK(hmll, insert_after) {
 
1089
  HMLL_ITER_BACK(hmll, insert_after, {
1076
1090
    if (insert_after->data.timestamp <= entry.timestamp) {
1077
1091
      break;
1078
1092
    }
1079
 
  }
 
1093
  })
1080
1094
  hmll_insert(hmll, insert_after, entry, can_free_entry);
1081
1095
}
1082
1096
 
1134
1148
  FUNC_ATTR_NONNULL_ALL
1135
1149
{
1136
1150
  histentry_T *hist = hist_array;
1137
 
  HMLL_FORALL(&hms_p->hmll, cur_entry) {
 
1151
  HMLL_FORALL(&hms_p->hmll, cur_entry,  {
1138
1152
    hist->timestamp = cur_entry->data.timestamp;
1139
1153
    hist->hisnum = (int) (hist - hist_array) + 1;
1140
1154
    hist->hisstr = (char_u *) cur_entry->data.data.history_item.string;
1141
1155
    hist->additional_elements =
1142
1156
        cur_entry->data.data.history_item.additional_elements;
1143
1157
    hist++;
1144
 
  }
 
1158
  })
1145
1159
  *new_hisnum = (int) (hist - hist_array);
1146
1160
  *new_hisidx = *new_hisnum - 1;
1147
1161
}
1159
1173
///
1160
1174
/// @param[in]   hms_p      Merger structure to iterate over.
1161
1175
/// @param[out]  cur_entry  Name of the iterator variable.
 
1176
/// @param       code       Code to execute on each iteration.
1162
1177
///
1163
1178
/// @return for cycle header. Use `HMS_ITER(hms_p, cur_entry) {body}`.
1164
 
#define HMS_ITER(hms_p, cur_entry) \
1165
 
    HMLL_FORALL(&((hms_p)->hmll), cur_entry)
 
1179
#define HMS_ITER(hms_p, cur_entry, code) \
 
1180
    HMLL_FORALL(&((hms_p)->hmll), cur_entry, code)
1166
1181
 
1167
1182
/// Find buffer for given buffer name (cached)
1168
1183
///
1339
1354
        (cur_entry.data.search_pattern.is_substitute_pattern
1340
1355
         ? &set_substitute_pattern
1341
1356
         : &set_search_pattern)((SearchPattern) {
1342
 
          .magic = cur_entry.data.search_pattern.magic,
1343
 
          .no_scs = !cur_entry.data.search_pattern.smartcase,
1344
 
          .off = {
1345
 
            .dir = cur_entry.data.search_pattern.search_backward ? '?' : '/',
1346
 
            .line = cur_entry.data.search_pattern.has_line_offset,
1347
 
            .end = cur_entry.data.search_pattern.place_cursor_at_end,
1348
 
            .off = cur_entry.data.search_pattern.offset,
1349
 
          },
1350
 
          .pat = (char_u *) cur_entry.data.search_pattern.pat,
1351
 
          .additional_data = cur_entry.data.search_pattern.additional_data,
1352
 
          .timestamp = cur_entry.timestamp,
1353
 
        });
 
1357
           .magic = cur_entry.data.search_pattern.magic,
 
1358
           .no_scs = !cur_entry.data.search_pattern.smartcase,
 
1359
           .off = {
 
1360
             .dir = cur_entry.data.search_pattern.search_backward ? '?' : '/',
 
1361
             .line = cur_entry.data.search_pattern.has_line_offset,
 
1362
             .end = cur_entry.data.search_pattern.place_cursor_at_end,
 
1363
             .off = cur_entry.data.search_pattern.offset,
 
1364
           },
 
1365
           .pat = (char_u *) cur_entry.data.search_pattern.pat,
 
1366
           .additional_data = cur_entry.data.search_pattern.additional_data,
 
1367
           .timestamp = cur_entry.timestamp,
 
1368
         });
1354
1369
        if (cur_entry.data.search_pattern.is_last_used) {
1355
1370
          set_last_used_pattern(
1356
1371
              cur_entry.data.search_pattern.is_substitute_pattern);
1657
1672
/// @param[in]  entry      Entry written.
1658
1673
/// @param[in]  max_kbyte  Maximum size of an item in KiB. Zero means no
1659
1674
///                        restrictions.
1660
 
static bool shada_pack_entry(msgpack_packer *const packer,
1661
 
                             ShadaEntry entry,
1662
 
                             const size_t max_kbyte)
 
1675
///
 
1676
/// @return kSDWriteSuccessfull, kSDWriteFailed or kSDWriteIgnError.
 
1677
static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 
1678
                                         ShadaEntry entry,
 
1679
                                         const size_t max_kbyte)
1663
1680
  FUNC_ATTR_NONNULL_ALL
1664
1681
{
 
1682
  ShaDaWriteResult ret = kSDWriteFailed;
1665
1683
  msgpack_sbuffer sbuf;
1666
1684
  msgpack_sbuffer_init(&sbuf);
1667
1685
  msgpack_packer *spacker = msgpack_packer_new(&sbuf, &msgpack_sbuffer_write);
1668
 
#define DUMP_ADDITIONAL_ELEMENTS(src) \
 
1686
#define DUMP_ADDITIONAL_ELEMENTS(src, what) \
1669
1687
  do { \
1670
1688
    if ((src) != NULL) { \
1671
1689
      for (listitem_T *li = (src)->lv_first; li != NULL; li = li->li_next) { \
1672
 
        if (vim_to_msgpack(spacker, &li->li_tv) == FAIL) { \
 
1690
        if (vim_to_msgpack(spacker, &li->li_tv, \
 
1691
                           _("additional elements of ShaDa " what)) == FAIL) { \
1673
1692
          goto shada_pack_entry_error; \
1674
1693
        } \
1675
1694
      } \
1676
1695
    } \
1677
1696
  } while (0)
1678
 
#define DUMP_ADDITIONAL_DATA(src) \
 
1697
#define DUMP_ADDITIONAL_DATA(src, what) \
1679
1698
  do { \
1680
1699
    dict_T *const d = (src); \
1681
1700
    if (d != NULL) { \
1687
1706
          const size_t key_len = strlen((const char *) hi->hi_key); \
1688
1707
          msgpack_pack_str(spacker, key_len); \
1689
1708
          msgpack_pack_str_body(spacker, (const char *) hi->hi_key, key_len); \
1690
 
          if (vim_to_msgpack(spacker, &di->di_tv) == FAIL) { \
 
1709
          if (vim_to_msgpack(spacker, &di->di_tv, \
 
1710
                             _("additional data of ShaDa " what)) == FAIL) { \
1691
1711
            goto shada_pack_entry_error; \
1692
1712
          } \
1693
1713
        } \
1722
1742
      if (is_hist_search) {
1723
1743
        msgpack_pack_uint8(spacker, (uint8_t) entry.data.history_item.sep);
1724
1744
      }
1725
 
      DUMP_ADDITIONAL_ELEMENTS(entry.data.history_item.additional_elements);
 
1745
      DUMP_ADDITIONAL_ELEMENTS(entry.data.history_item.additional_elements,
 
1746
                               "history entry item");
1726
1747
      break;
1727
1748
    }
1728
1749
    case kSDItemVariable: {
1731
1752
          ? 0
1732
1753
          : entry.data.global_var.additional_elements->lv_len);
1733
1754
      msgpack_pack_array(spacker, arr_size);
1734
 
      PACK_BIN(cstr_as_string(entry.data.global_var.name));
1735
 
      if (vim_to_msgpack(spacker, &entry.data.global_var.value) == FAIL) {
 
1755
      const String varname = cstr_as_string(entry.data.global_var.name);
 
1756
      PACK_BIN(varname);
 
1757
      char vardesc[256] = "variable g:";
 
1758
      memcpy(&vardesc[sizeof("variable g:") - 1], varname.data,
 
1759
             varname.size + 1);
 
1760
      if (vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc)
 
1761
          == FAIL) {
 
1762
        ret = kSDWriteIgnError;
 
1763
        EMSG2(_(WERR "Failed to write variable %s"),
 
1764
              entry.data.global_var.name);
1736
1765
        goto shada_pack_entry_error;
1737
1766
      }
1738
 
      DUMP_ADDITIONAL_ELEMENTS(entry.data.global_var.additional_elements);
 
1767
      DUMP_ADDITIONAL_ELEMENTS(entry.data.global_var.additional_elements,
 
1768
                               "variable item");
1739
1769
      break;
1740
1770
    }
1741
1771
    case kSDItemSubString: {
1745
1775
          : entry.data.sub_string.additional_elements->lv_len);
1746
1776
      msgpack_pack_array(spacker, arr_size);
1747
1777
      PACK_BIN(cstr_as_string(entry.data.sub_string.sub));
1748
 
      DUMP_ADDITIONAL_ELEMENTS(entry.data.sub_string.additional_elements);
 
1778
      DUMP_ADDITIONAL_ELEMENTS(entry.data.sub_string.additional_elements,
 
1779
                               "sub string item");
1749
1780
      break;
1750
1781
    }
1751
1782
    case kSDItemSearchPattern: {
1792
1823
        msgpack_pack_int64(spacker, entry.data.search_pattern.offset);
1793
1824
      }
1794
1825
#undef PACK_BOOL
1795
 
      DUMP_ADDITIONAL_DATA(entry.data.search_pattern.additional_data);
 
1826
      DUMP_ADDITIONAL_DATA(entry.data.search_pattern.additional_data,
 
1827
                           "search pattern item");
1796
1828
      break;
1797
1829
    }
1798
1830
    case kSDItemChange:
1827
1859
        PACK_STATIC_STR(KEY_NAME_CHAR);
1828
1860
        msgpack_pack_uint8(spacker, (uint8_t) entry.data.filemark.name);
1829
1861
      }
1830
 
      DUMP_ADDITIONAL_DATA(entry.data.filemark.additional_data);
 
1862
      DUMP_ADDITIONAL_DATA(entry.data.filemark.additional_data,
 
1863
                           "mark (change, jump, global or local) item");
1831
1864
      break;
1832
1865
    }
1833
1866
    case kSDItemRegister: {
1855
1888
        PACK_STATIC_STR(REG_KEY_WIDTH);
1856
1889
        msgpack_pack_uint64(spacker, (uint64_t) entry.data.reg.width);
1857
1890
      }
1858
 
      DUMP_ADDITIONAL_DATA(entry.data.reg.additional_data);
 
1891
      DUMP_ADDITIONAL_DATA(entry.data.reg.additional_data, "register item");
1859
1892
      break;
1860
1893
    }
1861
1894
    case kSDItemBufferList: {
1886
1919
          msgpack_pack_uint64(
1887
1920
              spacker, (uint64_t) entry.data.buffer_list.buffers[i].pos.col);
1888
1921
        }
1889
 
        DUMP_ADDITIONAL_DATA(entry.data.buffer_list.buffers[i].additional_data);
 
1922
        DUMP_ADDITIONAL_DATA(entry.data.buffer_list.buffers[i].additional_data,
 
1923
                             "buffer list subitem");
1890
1924
      }
1891
1925
      break;
1892
1926
    }
1937
1971
  }
1938
1972
  msgpack_packer_free(spacker);
1939
1973
  msgpack_sbuffer_destroy(&sbuf);
1940
 
  return true;
 
1974
  return kSDWriteSuccessfull;
1941
1975
shada_pack_entry_error:
1942
1976
  msgpack_packer_free(spacker);
1943
1977
  msgpack_sbuffer_destroy(&sbuf);
1944
 
  return false;
 
1978
  return ret;
1945
1979
}
1946
1980
#undef PACK_STRING
1947
1981
 
1956
1990
///                        is assumed that entry was already converted.
1957
1991
/// @param[in]  max_kbyte  Maximum size of an item in KiB. Zero means no
1958
1992
///                        restrictions.
1959
 
static bool shada_pack_encoded_entry(msgpack_packer *const packer,
1960
 
                                     const vimconv_T *const sd_conv,
1961
 
                                     PossiblyFreedShadaEntry entry,
1962
 
                                     const size_t max_kbyte)
 
1993
static ShaDaWriteResult shada_pack_encoded_entry(msgpack_packer *const packer,
 
1994
                                                 const vimconv_T *const sd_conv,
 
1995
                                                 PossiblyFreedShadaEntry entry,
 
1996
                                                 const size_t max_kbyte)
1963
1997
  FUNC_ATTR_NONNULL_ALL
1964
1998
{
1965
 
  bool ret = true;
 
1999
  ShaDaWriteResult ret = kSDWriteSuccessfull;
1966
2000
  if (entry.can_free_entry) {
1967
2001
    ret = shada_pack_entry(packer, entry.data, max_kbyte);
1968
2002
    shada_free_shada_entry(&entry.data);
2235
2269
        assert(false);
2236
2270
      }
2237
2271
      case kSDItemUnknown: {
2238
 
        if (!shada_pack_entry(packer, entry, 0)) {
2239
 
          ret = kSDWriteFailed;
2240
 
        }
 
2272
        ret = shada_pack_entry(packer, entry, 0);
2241
2273
        shada_free_shada_entry(&entry);
2242
2274
        break;
2243
2275
      }
2253
2285
      }
2254
2286
      case kSDItemHistoryEntry: {
2255
2287
        if (entry.data.history_item.histtype >= HIST_COUNT) {
2256
 
          if (!shada_pack_entry(packer, entry, 0)) {
2257
 
            ret = kSDWriteFailed;
2258
 
          }
 
2288
          ret = shada_pack_entry(packer, entry, 0);
2259
2289
          shada_free_shada_entry(&entry);
2260
2290
          break;
2261
2291
        }
2266
2296
      case kSDItemRegister: {
2267
2297
        const int idx = op_reg_index(entry.data.reg.name);
2268
2298
        if (idx < 0) {
2269
 
          if (!shada_pack_entry(packer, entry, 0)) {
2270
 
            ret = kSDWriteFailed;
2271
 
          }
 
2299
          ret = shada_pack_entry(packer, entry, 0);
2272
2300
          shada_free_shada_entry(&entry);
2273
2301
          break;
2274
2302
        }
2277
2305
      }
2278
2306
      case kSDItemVariable: {
2279
2307
        if (!in_strset(&wms->dumped_variables, entry.data.global_var.name)) {
2280
 
          if (!shada_pack_entry(packer, entry, 0)) {
2281
 
            ret = kSDWriteFailed;
2282
 
          }
 
2308
          ret = shada_pack_entry(packer, entry, 0);
2283
2309
        }
2284
2310
        shada_free_shada_entry(&entry);
2285
2311
        break;
2287
2313
      case kSDItemGlobalMark: {
2288
2314
        const int idx = mark_global_index(entry.data.filemark.name);
2289
2315
        if (idx < 0) {
2290
 
          if (!shada_pack_entry(packer, entry, 0)) {
2291
 
            ret = kSDWriteFailed;
2292
 
          }
 
2316
          ret = shada_pack_entry(packer, entry, 0);
2293
2317
          shada_free_shada_entry(&entry);
2294
2318
          break;
2295
2319
        }
2428
2452
  }
2429
2453
 
2430
2454
  const unsigned srni_flags = (unsigned) (
2431
 
    kSDReadUndisableableData
2432
 
    | kSDReadUnknown
2433
 
    | (dump_history ? kSDReadHistory : 0)
2434
 
    | (dump_registers ? kSDReadRegisters : 0)
2435
 
    | (dump_global_vars ? kSDReadVariables : 0)
2436
 
    | (dump_global_marks ? kSDReadGlobalMarks : 0)
2437
 
    | (num_marked_files ? kSDReadLocalMarks | kSDReadChanges : 0));
 
2455
      kSDReadUndisableableData
 
2456
      | kSDReadUnknown
 
2457
      | (dump_history ? kSDReadHistory : 0)
 
2458
      | (dump_registers ? kSDReadRegisters : 0)
 
2459
      | (dump_global_vars ? kSDReadVariables : 0)
 
2460
      | (dump_global_marks ? kSDReadGlobalMarks : 0)
 
2461
      | (num_marked_files ? kSDReadLocalMarks | kSDReadChanges : 0));
2438
2462
 
2439
2463
  msgpack_packer *const packer = msgpack_packer_new(sd_writer,
2440
2464
                                                    &msgpack_sd_writer_write);
2456
2480
  }
2457
2481
 
2458
2482
  // Write header
2459
 
  if (!shada_pack_entry(packer, (ShadaEntry) {
 
2483
  if (shada_pack_entry(packer, (ShadaEntry) {
2460
2484
    .type = kSDItemHeader,
2461
2485
    .timestamp = os_time(),
2462
2486
    .data = {
2477
2501
        }),
2478
2502
      }
2479
2503
    }
2480
 
  }, 0)) {
 
2504
  }, 0) == kSDWriteFailed) {
2481
2505
    ret = kSDWriteFailed;
2482
2506
    goto shada_write_exit;
2483
2507
  }
2517
2541
      };
2518
2542
      i++;
2519
2543
    }
2520
 
    if (!shada_pack_entry(packer, buflist_entry, 0)) {
 
2544
    if (shada_pack_entry(packer, buflist_entry, 0) == kSDWriteFailed) {
2521
2545
      xfree(buflist_entry.data.buffer_list.buffers);
2522
2546
      ret = kSDWriteFailed;
2523
2547
      goto shada_write_exit;
2543
2567
      } else {
2544
2568
        copy_tv(&vartv, &tgttv);
2545
2569
      }
2546
 
      if (!shada_pack_entry(packer, (ShadaEntry) {
 
2570
      ShaDaWriteResult spe_ret;
 
2571
      if ((spe_ret = shada_pack_entry(packer, (ShadaEntry) {
2547
2572
        .type = kSDItemVariable,
2548
2573
        .timestamp = cur_timestamp,
2549
2574
        .data = {
2553
2578
            .additional_elements = NULL,
2554
2579
          }
2555
2580
        }
2556
 
      }, max_kbyte)) {
 
2581
      }, max_kbyte)) == kSDWriteFailed) {
2557
2582
        clear_tv(&vartv);
2558
2583
        clear_tv(&tgttv);
2559
2584
        ret = kSDWriteFailed;
2561
2586
      }
2562
2587
      clear_tv(&vartv);
2563
2588
      clear_tv(&tgttv);
2564
 
      int kh_ret;
2565
 
      (void) kh_put(strset, &wms->dumped_variables, name, &kh_ret);
 
2589
      if (spe_ret == kSDWriteSuccessfull) {
 
2590
        int kh_ret;
 
2591
        (void) kh_put(strset, &wms->dumped_variables, name, &kh_ret);
 
2592
      }
2566
2593
    } while (var_iter != NULL);
2567
2594
  }
2568
2595
 
2819
2846
  do { \
2820
2847
    for (size_t i_ = 0; i_ < ARRAY_SIZE(wms_array); i_++) { \
2821
2848
      if (wms_array[i_].data.type != kSDItemMissing) { \
2822
 
        if (!shada_pack_encoded_entry(packer, &sd_writer->sd_conv, \
2823
 
                                      wms_array[i_], \
2824
 
                                      max_kbyte)) { \
 
2849
        if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, \
 
2850
                                     wms_array[i_], \
 
2851
                                     max_kbyte) == kSDWriteFailed) { \
2825
2852
          ret = kSDWriteFailed; \
2826
2853
          goto shada_write_exit; \
2827
2854
        } \
2831
2858
  PACK_WMS_ARRAY(wms->global_marks);
2832
2859
  PACK_WMS_ARRAY(wms->registers);
2833
2860
  for (size_t i = 0; i < wms->jumps_size; i++) {
2834
 
    if (!shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms->jumps[i],
2835
 
                                  max_kbyte)) {
 
2861
    if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms->jumps[i],
 
2862
                                 max_kbyte) == kSDWriteFailed) {
2836
2863
      ret = kSDWriteFailed;
2837
2864
      goto shada_write_exit;
2838
2865
    }
2840
2867
#define PACK_WMS_ENTRY(wms_entry) \
2841
2868
  do { \
2842
2869
    if (wms_entry.data.type != kSDItemMissing) { \
2843
 
      if (!shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms_entry, \
2844
 
                                    max_kbyte)) { \
 
2870
      if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms_entry, \
 
2871
                                   max_kbyte) == kSDWriteFailed) { \
2845
2872
        ret = kSDWriteFailed; \
2846
2873
        goto shada_write_exit; \
2847
2874
      } \
2868
2895
  for (size_t i = 0; i < file_markss_to_dump; i++) {
2869
2896
    PACK_WMS_ARRAY(all_file_markss[i]->marks);
2870
2897
    for (size_t j = 0; j < all_file_markss[i]->changes_size; j++) {
2871
 
      if (!shada_pack_encoded_entry(packer, &sd_writer->sd_conv,
2872
 
                                    all_file_markss[i]->changes[j],
2873
 
                                    max_kbyte)) {
 
2898
      if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv,
 
2899
                                   all_file_markss[i]->changes[j],
 
2900
                                   max_kbyte) == kSDWriteFailed) {
2874
2901
        ret = kSDWriteFailed;
2875
2902
        goto shada_write_exit;
2876
2903
      }
2877
2904
    }
2878
2905
    for (size_t j = 0; j < all_file_markss[i]->additional_marks_size; j++) {
2879
 
      if (!shada_pack_entry(packer, all_file_markss[i]->additional_marks[j],
2880
 
                            0)) {
 
2906
      if (shada_pack_entry(packer, all_file_markss[i]->additional_marks[j],
 
2907
                           0) == kSDWriteFailed) {
2881
2908
        shada_free_shada_entry(&all_file_markss[i]->additional_marks[j]);
2882
2909
        ret = kSDWriteFailed;
2883
2910
        goto shada_write_exit;
2893
2920
    for (size_t i = 0; i < HIST_COUNT; i++) {
2894
2921
      if (dump_one_history[i]) {
2895
2922
        hms_insert_whole_neovim_history(&wms->hms[i]);
2896
 
        HMS_ITER(&wms->hms[i], cur_entry) {
2897
 
          if (!shada_pack_encoded_entry(
2898
 
                  packer, &sd_writer->sd_conv, (PossiblyFreedShadaEntry) {
2899
 
                    .data = cur_entry->data,
2900
 
                    .can_free_entry = cur_entry->can_free_entry,
2901
 
                  }, max_kbyte)) {
 
2923
        HMS_ITER(&wms->hms[i], cur_entry, {
 
2924
          if (shada_pack_encoded_entry(
 
2925
              packer, &sd_writer->sd_conv, (PossiblyFreedShadaEntry) {
 
2926
                .data = cur_entry->data,
 
2927
                .can_free_entry = cur_entry->can_free_entry,
 
2928
              }, max_kbyte) == kSDWriteFailed) {
2902
2929
            ret = kSDWriteFailed;
2903
2930
            break;
2904
2931
          }
2905
 
        }
2906
 
        hms_dealloc(&wms->hms[i]);
 
2932
        })
2907
2933
        if (ret == kSDWriteFailed) {
2908
2934
          goto shada_write_exit;
2909
2935
        }
2912
2938
  }
2913
2939
 
2914
2940
shada_write_exit:
 
2941
  for (size_t i = 0; i < HIST_COUNT; i++) {
 
2942
    if (dump_one_history[i]) {
 
2943
      hms_dealloc(&wms->hms[i]);
 
2944
    }
 
2945
  }
2915
2946
  kh_dealloc(file_marks, &wms->file_marks);
2916
2947
  kh_dealloc(bufset, &removable_bufs);
2917
2948
  msgpack_packer_free(packer);
3034
3065
  const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge
3035
3066
                                                           ? NULL
3036
3067
                                                           : &sd_reader));
 
3068
  assert(sw_ret != kSDWriteIgnError);
3037
3069
#ifndef UNIX
3038
3070
  sd_writer.close(&sd_writer);
3039
3071
#endif
3353
3385
    entry_name " entry at position %" PRIu64 " " \
3354
3386
    error_desc
3355
3387
#define CHECK_KEY(key, expected) ( \
3356
 
  key.via.str.size == sizeof(expected) - 1 \
3357
 
  && STRNCMP(key.via.str.ptr, expected, sizeof(expected) - 1) == 0)
 
3388
    key.via.str.size == sizeof(expected) - 1 \
 
3389
    && STRNCMP(key.via.str.ptr, expected, sizeof(expected) - 1) == 0)
3358
3390
#define CLEAR_GA_AND_ERROR_OUT(ga) \
3359
3391
    do { \
3360
3392
      ga_clear(&ga); \
3377
3409
    tgt = proc(obj.via.attr); \
3378
3410
  } while (0)
3379
3411
#define CHECK_KEY_IS_STR(entry_name) \
3380
 
  do { \
3381
 
    if (unpacked.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) { \
3382
 
      emsgu(_(READERR(entry_name, "has key which is not a string")), \
3383
 
            initial_fpos); \
3384
 
      CLEAR_GA_AND_ERROR_OUT(ad_ga); \
3385
 
    } else if (unpacked.data.via.map.ptr[i].key.via.str.size == 0) { \
3386
 
      emsgu(_(READERR(entry_name, "has empty key")), initial_fpos); \
3387
 
      CLEAR_GA_AND_ERROR_OUT(ad_ga); \
3388
 
    } \
3389
 
  } while (0)
 
3412
  if (unpacked.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) { \
 
3413
    emsgu(_(READERR(entry_name, "has key which is not a string")), \
 
3414
          initial_fpos); \
 
3415
    CLEAR_GA_AND_ERROR_OUT(ad_ga); \
 
3416
  } else if (unpacked.data.via.map.ptr[i].key.via.str.size == 0) { \
 
3417
    emsgu(_(READERR(entry_name, "has empty key")), initial_fpos); \
 
3418
    CLEAR_GA_AND_ERROR_OUT(ad_ga); \
 
3419
  }
3390
3420
#define CHECKED_KEY(entry_name, name, error_desc, tgt, condition, attr, proc) \
3391
 
  if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, name)) { \
 
3421
  else if (CHECK_KEY( /* NOLINT(readability/braces) */ \
 
3422
      unpacked.data.via.map.ptr[i].key, name)) { \
3392
3423
    CHECKED_ENTRY( \
3393
3424
        condition, "has " name " key value " error_desc, \
3394
3425
        entry_name, unpacked.data.via.map.ptr[i].val, \
3408
3439
#define INT_KEY(entry_name, name, tgt, proc) \
3409
3440
  CHECKED_KEY( \
3410
3441
      entry_name, name, "which is not an integer", tgt, \
3411
 
      (unpacked.data.via.map.ptr[i].val.type \
3412
 
              == MSGPACK_OBJECT_POSITIVE_INTEGER \
3413
 
       || unpacked.data.via.map.ptr[i].val.type \
3414
 
              == MSGPACK_OBJECT_NEGATIVE_INTEGER), \
 
3442
      ((unpacked.data.via.map.ptr[i].val.type \
 
3443
        == MSGPACK_OBJECT_POSITIVE_INTEGER) \
 
3444
       || (unpacked.data.via.map.ptr[i].val.type \
 
3445
           == MSGPACK_OBJECT_NEGATIVE_INTEGER)), \
3415
3446
      i64, proc)
3416
3447
#define INTEGER_KEY(entry_name, name, tgt) \
3417
3448
  INT_KEY(entry_name, name, tgt, TOINT)
3418
3449
#define LONG_KEY(entry_name, name, tgt) \
3419
3450
  INT_KEY(entry_name, name, tgt, TOLONG)
3420
3451
#define ADDITIONAL_KEY \
3421
 
  { \
 
3452
  else { /* NOLINT(readability/braces) */ \
3422
3453
    ga_grow(&ad_ga, 1); \
3423
3454
    memcpy(((char *)ad_ga.ga_data) + ((size_t) ad_ga.ga_len \
3424
3455
                                      * sizeof(*unpacked.data.via.map.ptr)), \
3427
3458
    ad_ga.ga_len++; \
3428
3459
  }
3429
3460
#define CONVERTED(str, len) ( \
3430
 
  sd_reader->sd_conv.vc_type != CONV_NONE \
3431
 
  ? get_converted_string(&sd_reader->sd_conv, (str), (len)) \
3432
 
  : xmemdupz((str), (len)))
 
3461
    sd_reader->sd_conv.vc_type != CONV_NONE \
 
3462
    ? get_converted_string(&sd_reader->sd_conv, (str), (len)) \
 
3463
    : xmemdupz((str), (len)))
3433
3464
#define BIN_CONVERTED(b) CONVERTED(b.ptr, b.size)
3434
3465
#define SET_ADDITIONAL_DATA(tgt, name) \
3435
3466
      do { \
3623
3654
      garray_T ad_ga;
3624
3655
      ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1);
3625
3656
      for (size_t i = 0; i < unpacked.data.via.map.size; i++) {
3626
 
        CHECK_KEY_IS_STR("search pattern");
 
3657
        CHECK_KEY_IS_STR("search pattern")
3627
3658
        BOOLEAN_KEY("search pattern", SEARCH_KEY_MAGIC,
3628
3659
                    entry->data.search_pattern.magic)
3629
 
        else
3630
 
          BOOLEAN_KEY("search pattern", SEARCH_KEY_SMARTCASE,
3631
 
                      entry->data.search_pattern.smartcase)
3632
 
        else
3633
 
          BOOLEAN_KEY("search pattern", SEARCH_KEY_HAS_LINE_OFFSET,
3634
 
                      entry->data.search_pattern.has_line_offset)
3635
 
        else
3636
 
          BOOLEAN_KEY("search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END,
3637
 
                      entry->data.search_pattern.place_cursor_at_end)
3638
 
        else
3639
 
          BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_LAST_USED,
3640
 
                      entry->data.search_pattern.is_last_used)
3641
 
        else
3642
 
          BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_SUBSTITUTE_PATTERN,
3643
 
                      entry->data.search_pattern.is_substitute_pattern)
3644
 
        else
3645
 
          BOOLEAN_KEY("search pattern", SEARCH_KEY_HIGHLIGHTED,
3646
 
                      entry->data.search_pattern.highlighted)
3647
 
        else
3648
 
          BOOLEAN_KEY("search pattern", SEARCH_KEY_BACKWARD,
3649
 
                      entry->data.search_pattern.search_backward)
3650
 
        else
3651
 
          INTEGER_KEY("search pattern", SEARCH_KEY_OFFSET,
3652
 
                      entry->data.search_pattern.offset)
3653
 
        else
3654
 
          CONVERTED_STRING_KEY("search pattern", SEARCH_KEY_PAT,
3655
 
                               entry->data.search_pattern.pat)
3656
 
        else
3657
 
          ADDITIONAL_KEY
 
3660
        BOOLEAN_KEY("search pattern", SEARCH_KEY_SMARTCASE,
 
3661
                    entry->data.search_pattern.smartcase)
 
3662
        BOOLEAN_KEY("search pattern", SEARCH_KEY_HAS_LINE_OFFSET,
 
3663
                    entry->data.search_pattern.has_line_offset)
 
3664
        BOOLEAN_KEY("search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END,
 
3665
                    entry->data.search_pattern.place_cursor_at_end)
 
3666
        BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_LAST_USED,
 
3667
                    entry->data.search_pattern.is_last_used)
 
3668
        BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_SUBSTITUTE_PATTERN,
 
3669
                    entry->data.search_pattern.is_substitute_pattern)
 
3670
        BOOLEAN_KEY("search pattern", SEARCH_KEY_HIGHLIGHTED,
 
3671
                    entry->data.search_pattern.highlighted)
 
3672
        BOOLEAN_KEY("search pattern", SEARCH_KEY_BACKWARD,
 
3673
                    entry->data.search_pattern.search_backward)
 
3674
        INTEGER_KEY("search pattern", SEARCH_KEY_OFFSET,
 
3675
                    entry->data.search_pattern.offset)
 
3676
        CONVERTED_STRING_KEY("search pattern", SEARCH_KEY_PAT,
 
3677
                             entry->data.search_pattern.pat)
 
3678
        ADDITIONAL_KEY
3658
3679
      }
3659
3680
      if (entry->data.search_pattern.pat == NULL) {
3660
3681
        emsgu(_(READERR("search pattern", "has no pattern")), initial_fpos);
3675
3696
      garray_T ad_ga;
3676
3697
      ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1);
3677
3698
      for (size_t i = 0; i < unpacked.data.via.map.size; i++) {
3678
 
        CHECK_KEY_IS_STR("mark");
 
3699
        CHECK_KEY_IS_STR("mark")
3679
3700
        if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, KEY_NAME_CHAR)) {
3680
3701
          if (type_u64 == kSDItemJump || type_u64 == kSDItemChange) {
3681
3702
            emsgu(_(READERR("mark", "has n key which is only valid for "
3688
3709
              "has n key value which is not an unsigned integer",
3689
3710
              "mark", unpacked.data.via.map.ptr[i].val,
3690
3711
              entry->data.filemark.name, u64, TOCHAR);
3691
 
        } else {
3692
 
          LONG_KEY("mark", KEY_LNUM, entry->data.filemark.mark.lnum)
3693
 
          else
3694
 
            INTEGER_KEY("mark", KEY_COL, entry->data.filemark.mark.col)
3695
 
          else
3696
 
            STRING_KEY("mark", KEY_FILE, entry->data.filemark.fname)
3697
 
          else
3698
 
            ADDITIONAL_KEY
3699
3712
        }
 
3713
        LONG_KEY("mark", KEY_LNUM, entry->data.filemark.mark.lnum)
 
3714
        INTEGER_KEY("mark", KEY_COL, entry->data.filemark.mark.col)
 
3715
        STRING_KEY("mark", KEY_FILE, entry->data.filemark.fname)
 
3716
        ADDITIONAL_KEY
3700
3717
      }
3701
3718
      if (entry->data.filemark.fname == NULL) {
3702
3719
        emsgu(_(READERR("mark", "is missing file name")), initial_fpos);
3721
3738
      garray_T ad_ga;
3722
3739
      ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1);
3723
3740
      for (size_t i = 0; i < unpacked.data.via.map.size; i++) {
3724
 
        CHECK_KEY_IS_STR("register");
 
3741
        CHECK_KEY_IS_STR("register")
 
3742
        if (CHECK_KEY(unpacked.data.via.map.ptr[i].key,
 
3743
                      REG_KEY_CONTENTS)) {
 
3744
          if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) {
 
3745
            emsgu(_(READERR("register",
 
3746
                            "has " REG_KEY_CONTENTS
 
3747
                            " key with non-array value")),
 
3748
                  initial_fpos);
 
3749
            CLEAR_GA_AND_ERROR_OUT(ad_ga);
 
3750
          }
 
3751
          if (unpacked.data.via.map.ptr[i].val.via.array.size == 0) {
 
3752
            emsgu(_(READERR("register",
 
3753
                            "has " REG_KEY_CONTENTS " key with empty array")),
 
3754
                  initial_fpos);
 
3755
            CLEAR_GA_AND_ERROR_OUT(ad_ga);
 
3756
          }
 
3757
          const msgpack_object_array arr =
 
3758
              unpacked.data.via.map.ptr[i].val.via.array;
 
3759
          for (size_t i = 0; i < arr.size; i++) {
 
3760
            if (arr.ptr[i].type != MSGPACK_OBJECT_BIN) {
 
3761
              emsgu(_(READERR("register", "has " REG_KEY_CONTENTS " array "
 
3762
                              "with non-binary value")), initial_fpos);
 
3763
              CLEAR_GA_AND_ERROR_OUT(ad_ga);
 
3764
            }
 
3765
          }
 
3766
          entry->data.reg.contents_size = arr.size;
 
3767
          entry->data.reg.contents = xmalloc(arr.size * sizeof(char *));
 
3768
          for (size_t i = 0; i < arr.size; i++) {
 
3769
            entry->data.reg.contents[i] = BIN_CONVERTED(arr.ptr[i].via.bin);
 
3770
          }
 
3771
        }
3725
3772
        TYPED_KEY("register", REG_KEY_TYPE, "an unsigned integer",
3726
3773
                  entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8)
3727
 
        else
3728
 
          TYPED_KEY("register", KEY_NAME_CHAR, "an unsigned integer",
3729
 
                    entry->data.reg.name, POSITIVE_INTEGER, u64, TOCHAR)
3730
 
        else
3731
 
          TYPED_KEY("register", REG_KEY_WIDTH, "an unsigned integer",
3732
 
                    entry->data.reg.width, POSITIVE_INTEGER, u64, TOSIZE)
3733
 
        else
3734
 
          if (CHECK_KEY(unpacked.data.via.map.ptr[i].key,
3735
 
                        REG_KEY_CONTENTS)) {
3736
 
            if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) {
3737
 
              emsgu(_(READERR(
3738
 
                          "register",
3739
 
                          "has " REG_KEY_CONTENTS " key with non-array value")),
3740
 
                      initial_fpos);
3741
 
              CLEAR_GA_AND_ERROR_OUT(ad_ga);
3742
 
            }
3743
 
            if (unpacked.data.via.map.ptr[i].val.via.array.size == 0) {
3744
 
              emsgu(_(READERR("register",
3745
 
                              "has " REG_KEY_CONTENTS " key with empty array")),
3746
 
                    initial_fpos);
3747
 
              CLEAR_GA_AND_ERROR_OUT(ad_ga);
3748
 
            }
3749
 
            const msgpack_object_array arr =
3750
 
                unpacked.data.via.map.ptr[i].val.via.array;
3751
 
            for (size_t i = 0; i < arr.size; i++) {
3752
 
              if (arr.ptr[i].type != MSGPACK_OBJECT_BIN) {
3753
 
                emsgu(_(READERR("register", "has " REG_KEY_CONTENTS " array "
3754
 
                                "with non-binary value")), initial_fpos);
3755
 
                CLEAR_GA_AND_ERROR_OUT(ad_ga);
3756
 
              }
3757
 
            }
3758
 
            entry->data.reg.contents_size = arr.size;
3759
 
            entry->data.reg.contents = xmalloc(arr.size * sizeof(char *));
3760
 
            for (size_t i = 0; i < arr.size; i++) {
3761
 
              entry->data.reg.contents[i] = BIN_CONVERTED(arr.ptr[i].via.bin);
3762
 
            }
3763
 
          } else {
3764
 
            ADDITIONAL_KEY
3765
 
          }
 
3774
        TYPED_KEY("register", KEY_NAME_CHAR, "an unsigned integer",
 
3775
                  entry->data.reg.name, POSITIVE_INTEGER, u64, TOCHAR)
 
3776
        TYPED_KEY("register", REG_KEY_WIDTH, "an unsigned integer",
 
3777
                  entry->data.reg.width, POSITIVE_INTEGER, u64, TOSIZE)
 
3778
        ADDITIONAL_KEY
3766
3779
      }
3767
3780
      if (entry->data.reg.contents == NULL) {
3768
3781
        emsgu(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")),
3830
3843
            + 1);  // Separator character
3831
3844
        entry->data.history_item.string = xmalloc(strsize);
3832
3845
        memcpy(entry->data.history_item.string,
3833
 
              unpacked.data.via.array.ptr[1].via.bin.ptr,
3834
 
              unpacked.data.via.array.ptr[1].via.bin.size);
 
3846
               unpacked.data.via.array.ptr[1].via.bin.ptr,
 
3847
               unpacked.data.via.array.ptr[1].via.bin.size);
3835
3848
      } else {
3836
3849
        size_t len = unpacked.data.via.array.ptr[1].via.bin.size;
3837
3850
        char *const converted = string_convert(
3951
3964
            const size_t j = i;
3952
3965
            {
3953
3966
              for (size_t i = 0; i < unpacked.data.via.map.size; i++) {
3954
 
                CHECK_KEY_IS_STR("buffer list entry");
 
3967
                CHECK_KEY_IS_STR("buffer list entry")
3955
3968
                LONG_KEY("buffer list entry", KEY_LNUM,
3956
 
                        entry->data.buffer_list.buffers[j].pos.lnum)
3957
 
                else
3958
 
                  INTEGER_KEY("buffer list entry", KEY_COL,
3959
 
                              entry->data.buffer_list.buffers[j].pos.col)
3960
 
                else
3961
 
                  STRING_KEY("buffer list entry", KEY_FILE,
3962
 
                             entry->data.buffer_list.buffers[j].fname)
3963
 
                else
3964
 
                  ADDITIONAL_KEY
 
3969
                         entry->data.buffer_list.buffers[j].pos.lnum)
 
3970
                INTEGER_KEY("buffer list entry", KEY_COL,
 
3971
                            entry->data.buffer_list.buffers[j].pos.col)
 
3972
                STRING_KEY("buffer list entry", KEY_FILE,
 
3973
                           entry->data.buffer_list.buffers[j].fname)
 
3974
                ADDITIONAL_KEY
3965
3975
              }
3966
3976
            }
3967
3977
          }