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
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.
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) { \
540
551
/// Remove entry from the linked list
957
971
if (p_verbose > 0) {
959
973
smsg(_("Reading ShaDa file \"%s\"%s%s%s"),
961
(flags & kShaDaWantInfo) ? _(" info") : "",
962
(flags & kShaDaWantMarks) ? _(" marks") : "",
963
(flags & kShaDaGetOldfiles) ? _(" oldfiles") : "",
964
of_ret != 0 ? _(" FAILED") : "");
975
(flags & kShaDaWantInfo) ? _(" info") : "",
976
(flags & kShaDaWantMarks) ? _(" marks") : "",
977
(flags & kShaDaGetOldfiles) ? _(" oldfiles") : "",
978
of_ret != 0 ? _(" FAILED") : "");
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.
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)
1167
1182
/// Find buffer for given buffer name (cached)
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,
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,
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,
1357
.magic = cur_entry.data.search_pattern.magic,
1358
.no_scs = !cur_entry.data.search_pattern.smartcase,
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,
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,
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,
1662
const size_t max_kbyte)
1676
/// @return kSDWriteSuccessfull, kSDWriteFailed or kSDWriteIgnError.
1677
static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
1679
const size_t max_kbyte)
1663
1680
FUNC_ATTR_NONNULL_ALL
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) \
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; \
1678
#define DUMP_ADDITIONAL_DATA(src) \
1697
#define DUMP_ADDITIONAL_DATA(src, what) \
1680
1699
dict_T *const d = (src); \
1681
1700
if (d != NULL) { \
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);
1757
char vardesc[256] = "variable g:";
1758
memcpy(&vardesc[sizeof("variable g:") - 1], varname.data,
1760
if (vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc)
1762
ret = kSDWriteIgnError;
1763
EMSG2(_(WERR "Failed to write variable %s"),
1764
entry.data.global_var.name);
1736
1765
goto shada_pack_entry_error;
1738
DUMP_ADDITIONAL_ELEMENTS(entry.data.global_var.additional_elements);
1767
DUMP_ADDITIONAL_ELEMENTS(entry.data.global_var.additional_elements,
1741
1771
case kSDItemSubString: {
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
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);
2430
2454
const unsigned srni_flags = (unsigned) (
2431
kSDReadUndisableableData
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
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));
2439
2463
msgpack_packer *const packer = msgpack_packer_new(sd_writer,
2440
2464
&msgpack_sd_writer_write);
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],
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;
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],
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,
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;
2906
hms_dealloc(&wms->hms[i]);
2907
2933
if (ret == kSDWriteFailed) {
2908
2934
goto shada_write_exit;
3377
3409
tgt = proc(obj.via.attr); \
3379
3411
#define CHECK_KEY_IS_STR(entry_name) \
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")), \
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); \
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")), \
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); \
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) \
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)), \
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 \
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++; \
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) \
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)
3630
BOOLEAN_KEY("search pattern", SEARCH_KEY_SMARTCASE,
3631
entry->data.search_pattern.smartcase)
3633
BOOLEAN_KEY("search pattern", SEARCH_KEY_HAS_LINE_OFFSET,
3634
entry->data.search_pattern.has_line_offset)
3636
BOOLEAN_KEY("search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END,
3637
entry->data.search_pattern.place_cursor_at_end)
3639
BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_LAST_USED,
3640
entry->data.search_pattern.is_last_used)
3642
BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_SUBSTITUTE_PATTERN,
3643
entry->data.search_pattern.is_substitute_pattern)
3645
BOOLEAN_KEY("search pattern", SEARCH_KEY_HIGHLIGHTED,
3646
entry->data.search_pattern.highlighted)
3648
BOOLEAN_KEY("search pattern", SEARCH_KEY_BACKWARD,
3649
entry->data.search_pattern.search_backward)
3651
INTEGER_KEY("search pattern", SEARCH_KEY_OFFSET,
3652
entry->data.search_pattern.offset)
3654
CONVERTED_STRING_KEY("search pattern", SEARCH_KEY_PAT,
3655
entry->data.search_pattern.pat)
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)
3659
3680
if (entry->data.search_pattern.pat == NULL) {
3660
3681
emsgu(_(READERR("search pattern", "has no pattern")), initial_fpos);
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);
3692
LONG_KEY("mark", KEY_LNUM, entry->data.filemark.mark.lnum)
3694
INTEGER_KEY("mark", KEY_COL, entry->data.filemark.mark.col)
3696
STRING_KEY("mark", KEY_FILE, entry->data.filemark.fname)
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)
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")),
3749
CLEAR_GA_AND_ERROR_OUT(ad_ga);
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")),
3755
CLEAR_GA_AND_ERROR_OUT(ad_ga);
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);
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);
3725
3772
TYPED_KEY("register", REG_KEY_TYPE, "an unsigned integer",
3726
3773
entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8)
3728
TYPED_KEY("register", KEY_NAME_CHAR, "an unsigned integer",
3729
entry->data.reg.name, POSITIVE_INTEGER, u64, TOCHAR)
3731
TYPED_KEY("register", REG_KEY_WIDTH, "an unsigned integer",
3732
entry->data.reg.width, POSITIVE_INTEGER, u64, TOSIZE)
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) {
3739
"has " REG_KEY_CONTENTS " key with non-array value")),
3741
CLEAR_GA_AND_ERROR_OUT(ad_ga);
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")),
3747
CLEAR_GA_AND_ERROR_OUT(ad_ga);
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);
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);
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)
3767
3780
if (entry->data.reg.contents == NULL) {
3768
3781
emsgu(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")),
3951
3964
const size_t j = i;
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)
3958
INTEGER_KEY("buffer list entry", KEY_COL,
3959
entry->data.buffer_list.buffers[j].pos.col)
3961
STRING_KEY("buffer list entry", KEY_FILE,
3962
entry->data.buffer_list.buffers[j].fname)
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)