diff options
Diffstat (limited to 'src/nvim/shada.c')
-rw-r--r-- | src/nvim/shada.c | 205 |
1 files changed, 105 insertions, 100 deletions
diff --git a/src/nvim/shada.c b/src/nvim/shada.c index be898142f0..0b148993f8 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -17,40 +17,49 @@ #include "nvim/api/private/helpers.h" #include "nvim/ascii_defs.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/cmdhist.h" #include "nvim/eval.h" #include "nvim/eval/decode.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/fileio.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" -#include "nvim/gettext.h" +#include "nvim/garray_defs.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/hashtab.h" +#include "nvim/hashtab_defs.h" #include "nvim/macros_defs.h" #include "nvim/map_defs.h" #include "nvim/mark.h" +#include "nvim/mark_defs.h" #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/msgpack_rpc/helpers.h" -#include "nvim/normal.h" +#include "nvim/normal_defs.h" #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/option_vars.h" #include "nvim/os/fileio.h" +#include "nvim/os/fileio_defs.h" #include "nvim/os/fs.h" +#include "nvim/os/fs_defs.h" #include "nvim/os/os.h" +#include "nvim/os/os_defs.h" #include "nvim/os/time.h" +#include "nvim/os/time_defs.h" #include "nvim/path.h" #include "nvim/pos_defs.h" #include "nvim/regexp.h" #include "nvim/search.h" #include "nvim/shada.h" #include "nvim/strings.h" +#include "nvim/types_defs.h" #include "nvim/version.h" #include "nvim/vim_defs.h" @@ -347,25 +356,25 @@ typedef struct { PMap(cstr_t) file_marks; ///< All file marks. } WriteMergerState; -struct sd_read_def; +typedef struct sd_read_def ShaDaReadDef; /// Function used to close files defined by ShaDaReadDef -typedef void (*ShaDaReadCloser)(struct sd_read_def *const sd_reader) +typedef void (*ShaDaReadCloser)(ShaDaReadDef *const sd_reader) REAL_FATTR_NONNULL_ALL; /// Function used to read ShaDa files -typedef ptrdiff_t (*ShaDaFileReader)(struct sd_read_def *const sd_reader, +typedef ptrdiff_t (*ShaDaFileReader)(ShaDaReadDef *const sd_reader, void *const dest, const size_t size) REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; /// Function used to skip in ShaDa files -typedef int (*ShaDaFileSkipper)(struct sd_read_def *const sd_reader, +typedef int (*ShaDaFileSkipper)(ShaDaReadDef *const sd_reader, const size_t offset) REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; /// Structure containing necessary pointers for reading ShaDa files -typedef struct sd_read_def { +struct sd_read_def { ShaDaFileReader read; ///< Reader function. ShaDaReadCloser close; ///< Close function. ShaDaFileSkipper skip; ///< Function used to skip some bytes. @@ -374,27 +383,7 @@ typedef struct sd_read_def { const char *error; ///< Error message in case of error. uintmax_t fpos; ///< Current position (amount of bytes read since ///< reader structure initialization). May overflow. -} ShaDaReadDef; - -struct sd_write_def; - -/// Function used to close files defined by ShaDaWriteDef -typedef void (*ShaDaWriteCloser)(struct sd_write_def *const sd_writer) - REAL_FATTR_NONNULL_ALL; - -/// Function used to write ShaDa files -typedef ptrdiff_t (*ShaDaFileWriter)(struct sd_write_def *const sd_writer, - const void *const src, - const size_t size) - REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; - -/// Structure containing necessary pointers for writing ShaDa files -typedef struct sd_write_def { - ShaDaFileWriter write; ///< Writer function. - ShaDaWriteCloser close; ///< Close function. - void *cookie; ///< Data describing object written to. - const char *error; ///< Error message in case of error. -} ShaDaWriteDef; +}; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "shada.c.generated.h" @@ -626,33 +615,12 @@ static int read_char(ShaDaReadDef *const sd_reader) return (int)ret; } -/// Wrapper for writing to file descriptors -/// -/// @return -1 or number of bytes written. -static ptrdiff_t write_file(ShaDaWriteDef *const sd_writer, const void *const dest, - const size_t size) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT -{ - const ptrdiff_t ret = file_write(sd_writer->cookie, dest, size); - if (ret < 0) { - sd_writer->error = os_strerror((int)ret); - return -1; - } - return ret; -} - /// Wrapper for closing file descriptors opened for reading static void close_sd_reader(ShaDaReadDef *const sd_reader) FUNC_ATTR_NONNULL_ALL { close_file(sd_reader->cookie); -} - -/// Wrapper for closing file descriptors opened for writing -static void close_sd_writer(ShaDaWriteDef *const sd_writer) - FUNC_ATTR_NONNULL_ALL -{ - close_file(sd_writer->cookie); + xfree(sd_reader->cookie); } /// Wrapper for read that reads to IObuff and ignores bytes read @@ -721,8 +689,6 @@ static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader, const size_ static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd_reader) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - int error; - *sd_reader = (ShaDaReadDef) { .read = &read_file, .close = &close_sd_reader, @@ -730,9 +696,11 @@ static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd .error = NULL, .eof = false, .fpos = 0, - .cookie = file_open_new(&error, fname, kFileReadOnly, 0), + .cookie = xmalloc(sizeof(FileDescriptor)), }; - if (sd_reader->cookie == NULL) { + int error = file_open(sd_reader->cookie, fname, kFileReadOnly, 0); + if (error) { + XFREE_CLEAR(sd_reader->cookie); return error; } @@ -742,25 +710,26 @@ static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd } /// Wrapper for closing file descriptors -static void close_file(void *cookie) +static void close_file(FileDescriptor *cookie) { - const int error = file_free(cookie, !!p_fs); + const int error = file_close(cookie, !!p_fs); if (error != 0) { semsg(_(SERR "System error while closing ShaDa file: %s"), os_strerror(error)); } } -/// Msgpack callback for writing to ShaDaWriteDef* +/// Msgpack callback for writing to FileDescriptor* static int msgpack_sd_writer_write(void *data, const char *buf, size_t len) { - ShaDaWriteDef *const sd_writer = (ShaDaWriteDef *)data; - ptrdiff_t written_bytes = sd_writer->write(sd_writer, buf, len); - if (written_bytes == -1) { + FileDescriptor *const sd_writer = (FileDescriptor *)data; + const ptrdiff_t ret = file_write(sd_writer, buf, len); + if (ret < 0) { semsg(_(SERR "System error while writing ShaDa file: %s"), - sd_writer->error); + os_strerror((int)ret)); return -1; } + return 0; } @@ -997,6 +966,48 @@ static inline void hms_dealloc(HistoryMergerState *const hms_p) #define HMS_ITER(hms_p, cur_entry, code) \ HMLL_FORALL(&((hms_p)->hmll), cur_entry, code) +/// Iterate over global variables +/// +/// @warning No modifications to global variable dictionary must be performed +/// while iteration is in progress. +/// +/// @param[in] iter Iterator. Pass NULL to start iteration. +/// @param[out] name Variable name. +/// @param[out] rettv Variable value. +/// +/// @return Pointer that needs to be passed to next `var_shada_iter` invocation +/// or NULL to indicate that iteration is over. +static const void *var_shada_iter(const void *const iter, const char **const name, typval_T *rettv, + var_flavour_T flavour) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2, 3) +{ + const hashitem_T *hi; + const hashitem_T *hifirst = globvarht.ht_array; + const size_t hinum = (size_t)globvarht.ht_mask + 1; + *name = NULL; + if (iter == NULL) { + hi = globvarht.ht_array; + while ((size_t)(hi - hifirst) < hinum + && (HASHITEM_EMPTY(hi) + || !(var_flavour(hi->hi_key) & flavour))) { + hi++; + } + if ((size_t)(hi - hifirst) == hinum) { + return NULL; + } + } else { + hi = (const hashitem_T *)iter; + } + *name = TV_DICT_HI2DI(hi)->di_key; + tv_copy(&TV_DICT_HI2DI(hi)->di_tv, rettv); + while ((size_t)(++hi - hifirst) < hinum) { + if (!HASHITEM_EMPTY(hi) && (var_flavour(hi->hi_key) & flavour)) { + return hi; + } + } + return NULL; +} + /// Find buffer for given buffer name (cached) /// /// @param[in,out] fname_bufs Cache containing fname to buffer mapping. @@ -1118,7 +1129,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) } HistoryMergerState hms[HIST_COUNT]; if (srni_flags & kSDReadHistory) { - for (HistoryType i = 0; i < HIST_COUNT; i++) { + for (int i = 0; i < HIST_COUNT; i++) { hms_init(&hms[i], (uint8_t)i, (size_t)p_hi, true, true); } } @@ -1211,7 +1222,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) // string is close to useless: you can only use it with :& or :~ and // that’s all because s//~ is not available until the first call to // regtilde. Vim was not calling this for some reason. - (void)regtilde(cur_entry.data.sub_string.sub, magic_isset(), false); + regtilde(cur_entry.data.sub_string.sub, magic_isset(), false); // Do not free shada entry: its allocated memory was saved above. break; case kSDItemHistoryEntry: @@ -1382,7 +1393,7 @@ shada_read_main_cycle_end: // memory for the history string itself and separator character which // may be assigned right away. if (srni_flags & kSDReadHistory) { - for (HistoryType i = 0; i < HIST_COUNT; i++) { + for (int i = 0; i < HIST_COUNT; i++) { hms_insert_whole_neovim_history(&hms[i]); clr_history(i); int *new_hisidx; @@ -1823,9 +1834,7 @@ static int compare_file_marks(const void *a, const void *b) const FileMarks *const *const b_fms = b; return ((*a_fms)->greatest_timestamp == (*b_fms)->greatest_timestamp ? 0 - : ((*a_fms)->greatest_timestamp > (*b_fms)->greatest_timestamp - ? -1 - : 1)); + : ((*a_fms)->greatest_timestamp > (*b_fms)->greatest_timestamp ? -1 : 1)); } /// Parse msgpack object that has given length @@ -2373,7 +2382,7 @@ static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse, static inline void shada_initialize_registers(WriteMergerState *const wms, int max_reg_lines) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { - const void *reg_iter = NULL; + iter_register_T reg_iter = ITER_REGISTER_NULL; const bool limit_reg_lines = max_reg_lines >= 0; do { yankreg_T reg; @@ -2404,7 +2413,7 @@ static inline void shada_initialize_registers(WriteMergerState *const wms, int m } } }; - } while (reg_iter != NULL); + } while (reg_iter != ITER_REGISTER_NULL); } /// Replace numbered mark in WriteMergerState @@ -2473,7 +2482,7 @@ static int hist_type2char(const int type) /// @param[in] sd_reader Structure containing file reader definition. If it is /// not NULL then contents of this file will be merged /// with current Neovim runtime. -static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef *const sd_reader) +static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer, ShaDaReadDef *const sd_reader) FUNC_ATTR_NONNULL_ARG(1) { ShaDaWriteResult ret = kSDWriteSuccessful; @@ -2500,7 +2509,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef bool dump_history = false; // Initialize history merger - for (HistoryType i = 0; i < HIST_COUNT; i++) { + for (int i = 0; i < HIST_COUNT; i++) { int num_saved = get_shada_parameter(hist_type2char(i)); if (num_saved == -1) { num_saved = (int)p_hi; @@ -2605,7 +2614,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef case VAR_LIST: { list_T *l = vartv.vval.v_list; int copyID = get_copyID(); - if (!set_ref_in_list(l, copyID, NULL) + if (!set_ref_in_list_items(l, copyID, NULL) && copyID == l->lv_copyID) { tv_clear(&vartv); continue; @@ -2894,7 +2903,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef #undef PACK_WMS_ARRAY if (dump_history) { - for (size_t i = 0; i < HIST_COUNT; i++) { + for (int i = 0; i < HIST_COUNT; i++) { if (dump_one_history[i]) { hms_insert_whole_neovim_history(&wms->hms[i]); HMS_ITER(&wms->hms[i], cur_entry, { @@ -2914,7 +2923,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef } shada_write_exit: - for (size_t i = 0; i < HIST_COUNT; i++) { + for (int i = 0; i < HIST_COUNT; i++) { if (dump_one_history[i]) { hms_dealloc(&wms->hms[i]); } @@ -2947,12 +2956,9 @@ int shada_write_file(const char *const file, bool nomerge) char *const fname = shada_filename(file); char *tempname = NULL; - ShaDaWriteDef sd_writer = { - .write = &write_file, - .close = &close_sd_writer, - .error = NULL, - }; + FileDescriptor sd_writer; ShaDaReadDef sd_reader = { .close = NULL }; + bool did_open_writer = false; if (!nomerge) { int error; @@ -2982,8 +2988,8 @@ int shada_write_file(const char *const file, bool nomerge) // 3: If somebody happened to delete the file after it was opened for // reading use u=rw permissions. shada_write_file_open: {} - sd_writer.cookie = file_open_new(&error, tempname, kFileCreateOnly|kFileNoSymlink, perm); - if (sd_writer.cookie == NULL) { + error = file_open(&sd_writer, tempname, kFileCreateOnly|kFileNoSymlink, perm); + if (error) { if (error == UV_EEXIST || error == UV_ELOOP) { // File already exists, try another name char *const wp = tempname + strlen(tempname) - 1; @@ -3004,6 +3010,8 @@ shada_write_file_open: {} semsg(_(SERR "System error while opening temporary ShaDa file %s " "for writing: %s"), tempname, os_strerror(error)); } + } else { + did_open_writer = true; } } if (nomerge) { @@ -3026,16 +3034,16 @@ shada_write_file_nomerge: {} } *tail = tail_save; } - int error; - sd_writer.cookie = file_open_new(&error, fname, kFileCreate|kFileTruncate, - 0600); - if (sd_writer.cookie == NULL) { + int error = file_open(&sd_writer, fname, kFileCreate|kFileTruncate, 0600); + if (error) { semsg(_(SERR "System error while opening ShaDa file %s for writing: %s"), fname, os_strerror(error)); + } else { + did_open_writer = true; } } - if (sd_writer.cookie == NULL) { + if (!did_open_writer) { xfree(fname); xfree(tempname); if (sd_reader.cookie != NULL) { @@ -3050,9 +3058,7 @@ shada_write_file_nomerge: {} verbose_leave(); } - const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge - ? NULL - : &sd_reader)); + const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge ? NULL : &sd_reader)); assert(sw_ret != kSDWriteIgnError); if (!nomerge) { sd_reader.close(&sd_reader); @@ -3082,7 +3088,7 @@ shada_write_file_nomerge: {} || old_info.stat.st_gid != getgid()) { const uv_uid_t old_uid = (uv_uid_t)old_info.stat.st_uid; const uv_gid_t old_gid = (uv_gid_t)old_info.stat.st_gid; - const int fchown_ret = os_fchown(file_fd(sd_writer.cookie), + const int fchown_ret = os_fchown(file_fd(&sd_writer), old_uid, old_gid); if (fchown_ret != 0) { semsg(_(RNERR "Failed setting uid and gid for file %s: %s"), @@ -3115,7 +3121,7 @@ shada_write_file_did_not_remove: } xfree(tempname); } - sd_writer.close(&sd_writer); + close_file(&sd_writer); xfree(fname); return OK; @@ -3358,7 +3364,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const CLEAR_GA_AND_ERROR_OUT(ad_ga); \ } #define CHECKED_KEY(un, entry_name, name, error_desc, tgt, condition, attr, proc) \ - else if (CHECK_KEY((un).data.via.map.ptr[i].key, name)) /* NOLINT(readability/braces) */ \ + else if (CHECK_KEY((un).data.via.map.ptr[i].key, name)) \ { \ CHECKED_ENTRY(condition, \ "has " name " key value " error_desc, \ @@ -3389,7 +3395,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const #define INTEGER_KEY(un, entry_name, name, tgt) \ INT_KEY(un, entry_name, name, tgt, TOINT) #define ADDITIONAL_KEY(un) \ - else { /* NOLINT(readability/braces) */ \ + else { \ ga_grow(&ad_ga, 1); \ memcpy(((char *)ad_ga.ga_data) + ((size_t)ad_ga.ga_len \ * sizeof(*(un).data.via.map.ptr)), \ @@ -3579,10 +3585,9 @@ shada_read_next_item_start: entry->data = sd_default_values[type_u64].data; switch ((ShadaEntryType)type_u64) { case kSDItemHeader: - if (!msgpack_rpc_to_dictionary(&(unpacked.data), &(entry->data.header))) { - semsg(_(READERR("header", "is not a dictionary")), initial_fpos); - goto shada_read_next_item_error; - } + // TODO(bfredl): header is written to file and provides useful debugging + // info. It is never read by nvim (earlier we parsed it back to a + // Dictionary, but that value was never used) break; case kSDItemSearchPattern: { if (unpacked.data.type != MSGPACK_OBJECT_MAP) { @@ -3983,7 +3988,7 @@ static bool shada_removable(const char *name) char *new_name = home_replace_save(NULL, name); for (char *p = p_shada; *p;) { - (void)copy_option_part(&p, part, ARRAY_SIZE(part), ", "); + copy_option_part(&p, part, ARRAY_SIZE(part), ", "); if (part[0] == 'r') { home_replace(NULL, part + 1, NameBuff, MAXPATHL, true); size_t n = strlen(NameBuff); |