aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/private/helpers.h6
-rw-r--r--src/nvim/buffer.c2
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/eval.c17
-rw-r--r--src/nvim/eval/decode.c18
-rw-r--r--src/nvim/eval/encode.c622
-rw-r--r--src/nvim/eval/typval_encode.h563
-rw-r--r--src/nvim/ex_docmd.c2
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/lib/kvec.h257
-rw-r--r--src/nvim/lib/queue.h158
-rw-r--r--src/nvim/main.c12
-rw-r--r--src/nvim/main.h3
-rw-r--r--src/nvim/msgpack_rpc/channel.c30
-rw-r--r--src/nvim/msgpack_rpc/server.c3
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/os/input.c12
-rw-r--r--src/nvim/os/shell.c7
-rw-r--r--src/nvim/os/signal.c11
-rw-r--r--src/nvim/os/time.c3
-rw-r--r--src/nvim/state.c5
-rw-r--r--src/nvim/terminal.c7
-rw-r--r--src/nvim/tui/input.c5
-rw-r--r--src/nvim/tui/tui.c5
-rw-r--r--src/nvim/ui_bridge.c3
26 files changed, 1026 insertions, 732 deletions
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index a0f14ac7a4..7ed726c7ce 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -62,12 +62,10 @@
#define NIL ((Object) {.type = kObjectTypeNil})
#define PUT(dict, k, v) \
- kv_push(KeyValuePair, \
- dict, \
- ((KeyValuePair) {.key = cstr_to_string(k), .value = v}))
+ kv_push(dict, ((KeyValuePair) { .key = cstr_to_string(k), .value = v }))
#define ADD(array, item) \
- kv_push(Object, array, item)
+ kv_push(array, item)
#define STATIC_CSTR_AS_STRING(s) ((String) {.data = s, .size = sizeof(s) - 1})
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 72716daf0e..a1f2439e0a 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -4950,7 +4950,7 @@ int bufhl_add_hl(buf_T *buf,
bufhl_vec_T* lineinfo = map_ref(linenr_T, bufhl_vec_T)(buf->b_bufhl_info,
lnum, true);
- bufhl_hl_item_T *hlentry = kv_pushp(bufhl_hl_item_T, *lineinfo);
+ bufhl_hl_item_T *hlentry = kv_pushp(*lineinfo);
hlentry->src_id = src_id;
hlentry->hl_id = hl_id;
hlentry->start = col_start;
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index e131da8fe0..44aaedb9b4 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -961,7 +961,7 @@ static int insert_handle_key(InsertState *s)
break;
case K_EVENT: // some event
- queue_process_events(loop.events);
+ queue_process_events(main_loop.events);
break;
case K_FOCUSGAINED: // Neovim has been given focus
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 420a712e3e..e6f40a0bb8 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -67,6 +67,7 @@
#include "nvim/syntax.h"
#include "nvim/tag.h"
#include "nvim/ui.h"
+#include "nvim/main.h"
#include "nvim/mouse.h"
#include "nvim/terminal.h"
#include "nvim/undo.h"
@@ -11812,7 +11813,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
list_T *rv = list_alloc();
ui_busy_start();
- Queue *waiting_jobs = queue_new_parent(loop_on_put, &loop);
+ Queue *waiting_jobs = queue_new_parent(loop_on_put, &main_loop);
// For each item in the input list append an integer to the output list. -3
// is used to represent an invalid job id, -2 is for a interrupted job and
// -1 for jobs that were skipped or timed out.
@@ -11890,7 +11891,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
}
// restore the parent queue for the job
queue_process_events(data->events);
- queue_replace_parent(data->events, loop.events);
+ queue_replace_parent(data->events, main_loop.events);
}
queue_free(waiting_jobs);
@@ -16534,8 +16535,8 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv)
timer->timer_id = last_timer_id++;
timer->callback = func;
- time_watcher_init(&loop, &timer->tw, timer);
- timer->tw.events = queue_new_child(loop.events);
+ time_watcher_init(&main_loop, &timer->tw, timer);
+ timer->tw.events = queue_new_child(main_loop.events);
// if main loop is blocked, don't queue up multiple events
timer->tw.blockable = true;
time_watcher_start(&timer->tw, timer_due_cb, timeout,
@@ -21712,11 +21713,11 @@ static inline TerminalJobData *common_job_init(char **argv,
data->on_stderr = on_stderr;
data->on_exit = on_exit;
data->self = self;
- data->events = queue_new_child(loop.events);
+ data->events = queue_new_child(main_loop.events);
if (pty) {
- data->proc.pty = pty_process_init(&loop, data);
+ data->proc.pty = pty_process_init(&main_loop, data);
} else {
- data->proc.uv = libuv_process_init(&loop, data);
+ data->proc.uv = libuv_process_init(&main_loop, data);
}
Process *proc = (Process *)&data->proc;
proc->argv = argv;
@@ -21814,7 +21815,7 @@ static inline void free_term_job_data(TerminalJobData *data)
{
// data->queue may still be used after this function returns(process_wait), so
// only free in the next event loop iteration
- queue_put(loop.fast_events, free_term_job_data_event, 1, data);
+ queue_put(main_loop.fast_events, free_term_job_data_event, 1, data);
}
// vimscript job callbacks must be executed on Nvim main loop
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 0774ef515f..43e9f76c0f 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -101,7 +101,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
FUNC_ATTR_NONNULL_ALL
{
if (kv_size(*container_stack) == 0) {
- kv_push(ValuesStackItem, *stack, obj);
+ kv_push(*stack, obj);
return OK;
}
ContainerStackItem last_container = kv_last(*container_stack);
@@ -190,7 +190,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
*next_map_special = true;
return OK;
}
- kv_push(ValuesStackItem, *stack, obj);
+ kv_push(*stack, obj);
}
return OK;
}
@@ -628,10 +628,8 @@ int json_decode_string(const char *const buf, const size_t buf_len,
convert_setup(&conv, (char_u *) "utf-8", p_enc);
conv.vc_fail = true;
int ret = OK;
- ValuesStack stack;
- kv_init(stack);
- ContainerStack container_stack;
- kv_init(container_stack);
+ ValuesStack stack = KV_INITIAL_VALUE;
+ ContainerStack container_stack = KV_INITIAL_VALUE;
rettv->v_type = VAR_UNKNOWN;
bool didcomma = false;
bool didcolon = false;
@@ -815,13 +813,13 @@ json_decode_string_cycle_start:
.v_lock = VAR_UNLOCKED,
.vval = { .v_list = list },
};
- kv_push(ContainerStackItem, container_stack, ((ContainerStackItem) {
+ kv_push(container_stack, ((ContainerStackItem) {
.stack_index = kv_size(stack),
.s = p,
.container = tv,
.special_val = NULL,
}));
- kv_push(ValuesStackItem, stack, OBJ(tv, false, didcomma, didcolon));
+ kv_push(stack, OBJ(tv, false, didcomma, didcolon));
break;
}
case '{': {
@@ -845,13 +843,13 @@ json_decode_string_cycle_start:
.vval = { .v_dict = dict },
};
}
- kv_push(ContainerStackItem, container_stack, ((ContainerStackItem) {
+ kv_push(container_stack, ((ContainerStackItem) {
.stack_index = kv_size(stack),
.s = p,
.container = tv,
.special_val = val_list,
}));
- kv_push(ValuesStackItem, stack, OBJ(tv, false, didcomma, didcolon));
+ kv_push(stack, OBJ(tv, false, didcomma, didcolon));
break;
}
default: {
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index c651a50be9..54daf7557e 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -6,6 +6,7 @@
#include <msgpack.h>
#include <inttypes.h>
+#include <stddef.h>
#include <assert.h>
#include <math.h>
@@ -22,6 +23,7 @@
#include "nvim/ascii.h"
#include "nvim/vim.h" // For _()
#include "nvim/lib/kvec.h"
+#include "nvim/eval/typval_encode.h"
#define ga_concat(a, b) ga_concat(a, (char_u *)b)
#define utf_ptr2char(b) utf_ptr2char((char_u *)b)
@@ -32,29 +34,6 @@
#define convert_setup(vcp, from, to) \
(convert_setup(vcp, (char_u *)from, (char_u *)to))
-/// Structure representing current VimL to messagepack conversion state
-typedef struct {
- enum {
- kMPConvDict, ///< Convert dict_T *dictionary.
- kMPConvList, ///< Convert list_T *list.
- kMPConvPairs, ///< Convert mapping represented as a list_T* of pairs.
- } type;
- union {
- struct {
- dict_T *dict; ///< Currently converted dictionary.
- hashitem_T *hi; ///< Currently converted dictionary item.
- size_t todo; ///< Amount of items left to process.
- } d; ///< State of dictionary conversion.
- struct {
- list_T *list; ///< Currently converted list.
- listitem_T *li; ///< Currently converted list item.
- } l; ///< State of list or generic mapping conversion.
- } data; ///< Data to convert.
-} MPConvStackVal;
-
-/// Stack used to convert VimL values to messagepack.
-typedef kvec_t(MPConvStackVal) MPConvStack;
-
const char *const encode_special_var_names[] = {
[kSpecialVarNull] = "null",
[kSpecialVarTrue] = "true",
@@ -275,368 +254,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf,
: OK);
}
-/// Code for checking whether container references itself
-///
-/// @param[in,out] val Container to check.
-/// @param copyID_attr Name of the container attribute that holds copyID.
-/// After checking whether value of this attribute is
-/// copyID (variable) it is set to copyID.
-#define CHECK_SELF_REFERENCE(val, copyID_attr, conv_type) \
- do { \
- if ((val)->copyID_attr == copyID) { \
- CONV_RECURSE((val), conv_type); \
- } \
- (val)->copyID_attr = copyID; \
- } while (0)
-
-#define TV_STRLEN(tv) \
- (tv->vval.v_string == NULL ? 0 : STRLEN(tv->vval.v_string))
-
-/// Define functions which convert VimL value to something else
-///
-/// Creates function `vim_to_{name}(firstargtype firstargname, typval_T *const
-/// tv)` which returns OK or FAIL and helper functions.
-///
-/// @param firstargtype Type of the first argument. It will be used to return
-/// the results.
-/// @param firstargname Name of the first argument.
-/// @param name Name of the target converter.
-#define DEFINE_VIML_CONV_FUNCTIONS(scope, name, firstargtype, firstargname) \
-static int name##_convert_one_value(firstargtype firstargname, \
- MPConvStack *const mpstack, \
- typval_T *const tv, \
- const int copyID, \
- const char *const objname) \
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \
-{ \
- switch (tv->v_type) { \
- case VAR_STRING: { \
- CONV_STRING(tv->vval.v_string, TV_STRLEN(tv)); \
- break; \
- } \
- case VAR_NUMBER: { \
- CONV_NUMBER(tv->vval.v_number); \
- break; \
- } \
- case VAR_FLOAT: { \
- CONV_FLOAT(tv->vval.v_float); \
- break; \
- } \
- case VAR_FUNC: { \
- CONV_FUNC(tv->vval.v_string); \
- break; \
- } \
- case VAR_LIST: { \
- if (tv->vval.v_list == NULL || tv->vval.v_list->lv_len == 0) { \
- CONV_EMPTY_LIST(); \
- break; \
- } \
- CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, kMPConvList); \
- CONV_LIST_START(tv->vval.v_list); \
- kv_push(MPConvStackVal, *mpstack, ((MPConvStackVal) { \
- .type = kMPConvList, \
- .data = { \
- .l = { \
- .list = tv->vval.v_list, \
- .li = tv->vval.v_list->lv_first, \
- }, \
- }, \
- })); \
- break; \
- } \
- case VAR_SPECIAL: { \
- switch (tv->vval.v_special) { \
- case kSpecialVarNull: { \
- CONV_NIL(); \
- break; \
- } \
- case kSpecialVarTrue: \
- case kSpecialVarFalse: { \
- CONV_BOOL(tv->vval.v_special == kSpecialVarTrue); \
- break; \
- } \
- } \
- break; \
- } \
- case VAR_DICT: { \
- if (tv->vval.v_dict == NULL \
- || tv->vval.v_dict->dv_hashtab.ht_used == 0) { \
- CONV_EMPTY_DICT(); \
- break; \
- } \
- const dictitem_T *type_di; \
- const dictitem_T *val_di; \
- if (CONV_ALLOW_SPECIAL \
- && tv->vval.v_dict->dv_hashtab.ht_used == 2 \
- && (type_di = dict_find((dict_T *) tv->vval.v_dict, \
- (char_u *) "_TYPE", -1)) != NULL \
- && type_di->di_tv.v_type == VAR_LIST \
- && (val_di = dict_find((dict_T *) tv->vval.v_dict, \
- (char_u *) "_VAL", -1)) != NULL) { \
- size_t i; \
- for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) { \
- if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) { \
- break; \
- } \
- } \
- if (i == ARRAY_SIZE(eval_msgpack_type_lists)) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- switch ((MessagePackType) i) { \
- case kMPNil: { \
- CONV_NIL(); \
- break; \
- } \
- case kMPBoolean: { \
- if (val_di->di_tv.v_type != VAR_NUMBER) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- CONV_BOOL(val_di->di_tv.vval.v_number); \
- break; \
- } \
- case kMPInteger: { \
- const list_T *val_list; \
- varnumber_T sign; \
- varnumber_T highest_bits; \
- varnumber_T high_bits; \
- varnumber_T low_bits; \
- /* List of 4 integers; first is signed (should be 1 or -1, but */ \
- /* this is not checked), second is unsigned and have at most */ \
- /* one (sign is -1) or two (sign is 1) non-zero bits (number of */ \
- /* bits is not checked), other unsigned and have at most 31 */ \
- /* non-zero bits (number of bits is not checked).*/ \
- if (val_di->di_tv.v_type != VAR_LIST \
- || (val_list = val_di->di_tv.vval.v_list) == NULL \
- || val_list->lv_len != 4 \
- || val_list->lv_first->li_tv.v_type != VAR_NUMBER \
- || (sign = val_list->lv_first->li_tv.vval.v_number) == 0 \
- || val_list->lv_first->li_next->li_tv.v_type != VAR_NUMBER \
- || (highest_bits = \
- val_list->lv_first->li_next->li_tv.vval.v_number) < 0 \
- || val_list->lv_last->li_prev->li_tv.v_type != VAR_NUMBER \
- || (high_bits = \
- val_list->lv_last->li_prev->li_tv.vval.v_number) < 0 \
- || val_list->lv_last->li_tv.v_type != VAR_NUMBER \
- || (low_bits = val_list->lv_last->li_tv.vval.v_number) < 0) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- uint64_t number = ((uint64_t) (((uint64_t) highest_bits) << 62) \
- | (uint64_t) (((uint64_t) high_bits) << 31) \
- | (uint64_t) low_bits); \
- if (sign > 0) { \
- CONV_UNSIGNED_NUMBER(number); \
- } else { \
- CONV_NUMBER(-number); \
- } \
- break; \
- } \
- case kMPFloat: { \
- if (val_di->di_tv.v_type != VAR_FLOAT) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- CONV_FLOAT(val_di->di_tv.vval.v_float); \
- break; \
- } \
- case kMPString: \
- case kMPBinary: { \
- const bool is_string = ((MessagePackType) i == kMPString); \
- if (val_di->di_tv.v_type != VAR_LIST) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- size_t len; \
- char *buf; \
- if (!encode_vim_list_to_buf(val_di->di_tv.vval.v_list, &len, \
- &buf)) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- if (is_string) { \
- CONV_STR_STRING(buf, len); \
- } else { \
- CONV_STRING(buf, len); \
- } \
- xfree(buf); \
- break; \
- } \
- case kMPArray: { \
- if (val_di->di_tv.v_type != VAR_LIST) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, lv_copyID, \
- kMPConvList); \
- CONV_LIST_START(val_di->di_tv.vval.v_list); \
- kv_push(MPConvStackVal, *mpstack, ((MPConvStackVal) { \
- .type = kMPConvList, \
- .data = { \
- .l = { \
- .list = val_di->di_tv.vval.v_list, \
- .li = val_di->di_tv.vval.v_list->lv_first, \
- }, \
- }, \
- })); \
- break; \
- } \
- case kMPMap: { \
- if (val_di->di_tv.v_type != VAR_LIST) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- list_T *const val_list = val_di->di_tv.vval.v_list; \
- if (val_list == NULL || val_list->lv_len == 0) { \
- CONV_EMPTY_DICT(); \
- break; \
- } \
- for (const listitem_T *li = val_list->lv_first; li != NULL; \
- li = li->li_next) { \
- if (li->li_tv.v_type != VAR_LIST \
- || li->li_tv.vval.v_list->lv_len != 2) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- } \
- CHECK_SELF_REFERENCE(val_list, lv_copyID, kMPConvPairs); \
- CONV_DICT_START(val_list->lv_len); \
- kv_push(MPConvStackVal, *mpstack, ((MPConvStackVal) { \
- .type = kMPConvPairs, \
- .data = { \
- .l = { \
- .list = val_list, \
- .li = val_list->lv_first, \
- }, \
- }, \
- })); \
- break; \
- } \
- case kMPExt: { \
- const list_T *val_list; \
- varnumber_T type; \
- if (val_di->di_tv.v_type != VAR_LIST \
- || (val_list = val_di->di_tv.vval.v_list) == NULL \
- || val_list->lv_len != 2 \
- || (val_list->lv_first->li_tv.v_type != VAR_NUMBER) \
- || (type = val_list->lv_first->li_tv.vval.v_number) > INT8_MAX \
- || type < INT8_MIN \
- || (val_list->lv_last->li_tv.v_type != VAR_LIST)) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- size_t len; \
- char *buf; \
- if (!encode_vim_list_to_buf(val_list->lv_last->li_tv.vval.v_list, \
- &len, &buf)) { \
- goto name##_convert_one_value_regular_dict; \
- } \
- CONV_EXT_STRING(buf, len, type); \
- xfree(buf); \
- break; \
- } \
- } \
- break; \
- } \
-name##_convert_one_value_regular_dict: \
- CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, kMPConvDict); \
- CONV_DICT_START(tv->vval.v_dict->dv_hashtab.ht_used); \
- kv_push(MPConvStackVal, *mpstack, ((MPConvStackVal) { \
- .type = kMPConvDict, \
- .data = { \
- .d = { \
- .dict = tv->vval.v_dict, \
- .hi = tv->vval.v_dict->dv_hashtab.ht_array, \
- .todo = tv->vval.v_dict->dv_hashtab.ht_used, \
- }, \
- }, \
- })); \
- break; \
- } \
- case VAR_UNKNOWN: { \
- EMSG2(_(e_intern2), #name "_convert_one_value()"); \
- return FAIL; \
- } \
- } \
- return OK; \
-} \
-\
-scope int encode_vim_to_##name(firstargtype firstargname, typval_T *const tv, \
- const char *const objname) \
- FUNC_ATTR_WARN_UNUSED_RESULT \
-{ \
- const int copyID = get_copyID(); \
- MPConvStack mpstack; \
- kv_init(mpstack); \
- if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \
- == FAIL) { \
- goto encode_vim_to_##name##_error_ret; \
- } \
- while (kv_size(mpstack)) { \
- MPConvStackVal *cur_mpsv = &kv_A(mpstack, kv_size(mpstack) - 1); \
- typval_T *cur_tv = NULL; \
- switch (cur_mpsv->type) { \
- case kMPConvDict: { \
- if (!cur_mpsv->data.d.todo) { \
- (void) kv_pop(mpstack); \
- cur_mpsv->data.d.dict->dv_copyID = copyID - 1; \
- CONV_DICT_END(); \
- continue; \
- } else if (cur_mpsv->data.d.todo \
- != cur_mpsv->data.d.dict->dv_hashtab.ht_used) { \
- CONV_DICT_BETWEEN_ITEMS(); \
- } \
- while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) { \
- cur_mpsv->data.d.hi++; \
- } \
- dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi); \
- cur_mpsv->data.d.todo--; \
- cur_mpsv->data.d.hi++; \
- CONV_STR_STRING(&di->di_key[0], STRLEN(&di->di_key[0])); \
- CONV_DICT_AFTER_KEY(); \
- cur_tv = &di->di_tv; \
- break; \
- } \
- case kMPConvList: { \
- if (cur_mpsv->data.l.li == NULL) { \
- (void) kv_pop(mpstack); \
- cur_mpsv->data.l.list->lv_copyID = copyID - 1; \
- CONV_LIST_END(cur_mpsv->data.l.list); \
- continue; \
- } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \
- CONV_LIST_BETWEEN_ITEMS(); \
- } \
- cur_tv = &cur_mpsv->data.l.li->li_tv; \
- cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \
- break; \
- } \
- case kMPConvPairs: { \
- if (cur_mpsv->data.l.li == NULL) { \
- (void) kv_pop(mpstack); \
- cur_mpsv->data.l.list->lv_copyID = copyID - 1; \
- CONV_DICT_END(); \
- continue; \
- } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \
- CONV_DICT_BETWEEN_ITEMS(); \
- } \
- const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; \
- CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair); \
- if (name##_convert_one_value(firstargname, &mpstack, \
- &kv_pair->lv_first->li_tv, copyID, \
- objname) == FAIL) { \
- goto encode_vim_to_##name##_error_ret; \
- } \
- CONV_DICT_AFTER_KEY(); \
- cur_tv = &kv_pair->lv_last->li_tv; \
- cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \
- break; \
- } \
- } \
- assert(cur_tv != NULL); \
- if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID, \
- objname) == FAIL) { \
- goto encode_vim_to_##name##_error_ret; \
- } \
- } \
- kv_destroy(mpstack); \
- return OK; \
-encode_vim_to_##name##_error_ret: \
- kv_destroy(mpstack); \
- return FAIL; \
-}
-
-#define CONV_STRING(buf, len) \
+#define TYPVAL_ENCODE_CONV_STRING(buf, len) \
do { \
const char *const buf_ = (const char *) buf; \
if (buf == NULL) { \
@@ -655,19 +273,19 @@ encode_vim_to_##name##_error_ret: \
} \
} while (0)
-#define CONV_STR_STRING(buf, len) \
- CONV_STRING(buf, len)
+#define TYPVAL_ENCODE_CONV_STR_STRING(buf, len) \
+ TYPVAL_ENCODE_CONV_STRING(buf, len)
-#define CONV_EXT_STRING(buf, len, type)
+#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type)
-#define CONV_NUMBER(num) \
+#define TYPVAL_ENCODE_CONV_NUMBER(num) \
do { \
char numbuf[NUMBUFLEN]; \
vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRId64, (int64_t) (num)); \
ga_concat(gap, numbuf); \
} while (0)
-#define CONV_FLOAT(flt) \
+#define TYPVAL_ENCODE_CONV_FLOAT(flt) \
do { \
const float_T flt_ = (flt); \
switch (fpclassify(flt_)) { \
@@ -690,51 +308,51 @@ encode_vim_to_##name##_error_ret: \
} \
} while (0)
-#define CONV_FUNC(fun) \
+#define TYPVAL_ENCODE_CONV_FUNC(fun) \
do { \
ga_concat(gap, "function("); \
- CONV_STRING(fun, STRLEN(fun)); \
+ TYPVAL_ENCODE_CONV_STRING(fun, STRLEN(fun)); \
ga_append(gap, ')'); \
} while (0)
-#define CONV_EMPTY_LIST() \
+#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \
ga_concat(gap, "[]")
-#define CONV_LIST_START(lst) \
+#define TYPVAL_ENCODE_CONV_LIST_START(len) \
ga_append(gap, '[')
-#define CONV_EMPTY_DICT() \
+#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \
ga_concat(gap, "{}")
-#define CONV_NIL() \
+#define TYPVAL_ENCODE_CONV_NIL() \
ga_concat(gap, "v:null")
-#define CONV_BOOL(num) \
+#define TYPVAL_ENCODE_CONV_BOOL(num) \
ga_concat(gap, ((num)? "v:true": "v:false"))
-#define CONV_UNSIGNED_NUMBER(num)
+#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num)
-#define CONV_DICT_START(len) \
+#define TYPVAL_ENCODE_CONV_DICT_START(len) \
ga_append(gap, '{')
-#define CONV_DICT_END() \
+#define TYPVAL_ENCODE_CONV_DICT_END() \
ga_append(gap, '}')
-#define CONV_DICT_AFTER_KEY() \
+#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() \
ga_concat(gap, ": ")
-#define CONV_DICT_BETWEEN_ITEMS() \
+#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() \
ga_concat(gap, ", ")
-#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair)
+#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair)
-#define CONV_LIST_END(lst) \
+#define TYPVAL_ENCODE_CONV_LIST_END() \
ga_append(gap, ']')
-#define CONV_LIST_BETWEEN_ITEMS() \
- CONV_DICT_BETWEEN_ITEMS()
+#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() \
+ TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS()
-#define CONV_RECURSE(val, conv_type) \
+#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \
do { \
if (!did_echo_string_emsg) { \
/* Only give this message once for a recursive call to avoid */ \
@@ -764,12 +382,12 @@ encode_vim_to_##name##_error_ret: \
return OK; \
} while (0)
-#define CONV_ALLOW_SPECIAL false
+#define TYPVAL_ENCODE_ALLOW_SPECIALS false
-DEFINE_VIML_CONV_FUNCTIONS(static, string, garray_T *const, gap)
+TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(static, string, garray_T *const, gap)
-#undef CONV_RECURSE
-#define CONV_RECURSE(val, conv_type) \
+#undef TYPVAL_ENCODE_CONV_RECURSE
+#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \
do { \
char ebuf[NUMBUFLEN + 7]; \
size_t backref = 0; \
@@ -796,10 +414,10 @@ DEFINE_VIML_CONV_FUNCTIONS(static, string, garray_T *const, gap)
return OK; \
} while (0)
-DEFINE_VIML_CONV_FUNCTIONS(, echo, garray_T *const, gap)
+TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(, echo, garray_T *const, gap)
-#undef CONV_RECURSE
-#define CONV_RECURSE(val, conv_type) \
+#undef TYPVAL_ENCODE_CONV_RECURSE
+#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \
do { \
if (!did_echo_string_emsg) { \
/* Only give this message once for a recursive call to avoid */ \
@@ -811,27 +429,27 @@ DEFINE_VIML_CONV_FUNCTIONS(, echo, garray_T *const, gap)
return OK; \
} while (0)
-#undef CONV_ALLOW_SPECIAL
-#define CONV_ALLOW_SPECIAL true
+#undef TYPVAL_ENCODE_ALLOW_SPECIALS
+#define TYPVAL_ENCODE_ALLOW_SPECIALS true
-#undef CONV_NIL
-#define CONV_NIL() \
+#undef TYPVAL_ENCODE_CONV_NIL
+#define TYPVAL_ENCODE_CONV_NIL() \
ga_concat(gap, "null")
-#undef CONV_BOOL
-#define CONV_BOOL(num) \
+#undef TYPVAL_ENCODE_CONV_BOOL
+#define TYPVAL_ENCODE_CONV_BOOL(num) \
ga_concat(gap, ((num)? "true": "false"))
-#undef CONV_UNSIGNED_NUMBER
-#define CONV_UNSIGNED_NUMBER(num) \
+#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
+#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) \
do { \
char numbuf[NUMBUFLEN]; \
vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRIu64, (num)); \
ga_concat(gap, numbuf); \
} while (0)
-#undef CONV_FLOAT
-#define CONV_FLOAT(flt) \
+#undef TYPVAL_ENCODE_CONV_FLOAT
+#define TYPVAL_ENCODE_CONV_FLOAT(flt) \
do { \
const float_T flt_ = (flt); \
switch (fpclassify(flt_)) { \
@@ -1019,24 +637,24 @@ static inline int convert_to_json_string(garray_T *const gap,
return OK;
}
-#undef CONV_STRING
-#define CONV_STRING(buf, len) \
+#undef TYPVAL_ENCODE_CONV_STRING
+#define TYPVAL_ENCODE_CONV_STRING(buf, len) \
do { \
if (convert_to_json_string(gap, (const char *) (buf), (len)) != OK) { \
return FAIL; \
} \
} while (0)
-#undef CONV_EXT_STRING
-#define CONV_EXT_STRING(buf, len, type) \
+#undef TYPVAL_ENCODE_CONV_EXT_STRING
+#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) \
do { \
xfree(buf); \
EMSG(_("E474: Unable to convert EXT string to JSON")); \
return FAIL; \
} while (0)
-#undef CONV_FUNC
-#define CONV_FUNC(fun) \
+#undef TYPVAL_ENCODE_CONV_FUNC
+#define TYPVAL_ENCODE_CONV_FUNC(fun) \
return conv_error(_("E474: Error while dumping %s, %s: " \
"attempt to dump function reference"), \
mpstack, objname)
@@ -1080,38 +698,38 @@ static inline bool check_json_key(const typval_T *const tv)
return true;
}
-#undef CONV_SPECIAL_DICT_KEY_CHECK
-#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair) \
+#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK
+#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair) \
do { \
if (!check_json_key(&kv_pair->lv_first->li_tv)) { \
EMSG(_("E474: Invalid key in special dictionary")); \
- goto encode_vim_to_##name##_error_ret; \
+ goto label; \
} \
} while (0)
-DEFINE_VIML_CONV_FUNCTIONS(static, json, garray_T *const, gap)
-
-#undef CONV_STRING
-#undef CONV_STR_STRING
-#undef CONV_EXT_STRING
-#undef CONV_NUMBER
-#undef CONV_FLOAT
-#undef CONV_FUNC
-#undef CONV_EMPTY_LIST
-#undef CONV_LIST_START
-#undef CONV_EMPTY_DICT
-#undef CONV_NIL
-#undef CONV_BOOL
-#undef CONV_UNSIGNED_NUMBER
-#undef CONV_DICT_START
-#undef CONV_DICT_END
-#undef CONV_DICT_AFTER_KEY
-#undef CONV_DICT_BETWEEN_ITEMS
-#undef CONV_SPECIAL_DICT_KEY_CHECK
-#undef CONV_LIST_END
-#undef CONV_LIST_BETWEEN_ITEMS
-#undef CONV_RECURSE
-#undef CONV_ALLOW_SPECIAL
+TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(static, json, garray_T *const, gap)
+
+#undef TYPVAL_ENCODE_CONV_STRING
+#undef TYPVAL_ENCODE_CONV_STR_STRING
+#undef TYPVAL_ENCODE_CONV_EXT_STRING
+#undef TYPVAL_ENCODE_CONV_NUMBER
+#undef TYPVAL_ENCODE_CONV_FLOAT
+#undef TYPVAL_ENCODE_CONV_FUNC
+#undef TYPVAL_ENCODE_CONV_EMPTY_LIST
+#undef TYPVAL_ENCODE_CONV_LIST_START
+#undef TYPVAL_ENCODE_CONV_EMPTY_DICT
+#undef TYPVAL_ENCODE_CONV_NIL
+#undef TYPVAL_ENCODE_CONV_BOOL
+#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
+#undef TYPVAL_ENCODE_CONV_DICT_START
+#undef TYPVAL_ENCODE_CONV_DICT_END
+#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
+#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
+#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK
+#undef TYPVAL_ENCODE_CONV_LIST_END
+#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS
+#undef TYPVAL_ENCODE_CONV_RECURSE
+#undef TYPVAL_ENCODE_ALLOW_SPECIALS
/// Return a string with the string representation of a variable.
/// Puts quotes around strings, so that they can be parsed back by eval().
@@ -1181,7 +799,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)
return (char *) ga.ga_data;
}
-#define CONV_STRING(buf, len) \
+#define TYPVAL_ENCODE_CONV_STRING(buf, len) \
do { \
if (buf == NULL) { \
msgpack_pack_bin(packer, 0); \
@@ -1192,7 +810,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)
} \
} while (0)
-#define CONV_STR_STRING(buf, len) \
+#define TYPVAL_ENCODE_CONV_STR_STRING(buf, len) \
do { \
if (buf == NULL) { \
msgpack_pack_str(packer, 0); \
@@ -1203,7 +821,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)
} \
} while (0)
-#define CONV_EXT_STRING(buf, len, type) \
+#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) \
do { \
if (buf == NULL) { \
msgpack_pack_ext(packer, 0, (int8_t) type); \
@@ -1214,30 +832,30 @@ char *encode_tv2json(typval_T *tv, size_t *len)
} \
} while (0)
-#define CONV_NUMBER(num) \
+#define TYPVAL_ENCODE_CONV_NUMBER(num) \
msgpack_pack_int64(packer, (int64_t) (num))
-#define CONV_FLOAT(flt) \
+#define TYPVAL_ENCODE_CONV_FLOAT(flt) \
msgpack_pack_double(packer, (double) (flt))
-#define CONV_FUNC(fun) \
+#define TYPVAL_ENCODE_CONV_FUNC(fun) \
return conv_error(_("E951: Error while dumping %s, %s: " \
"attempt to dump function reference"), \
mpstack, objname)
-#define CONV_EMPTY_LIST() \
+#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \
msgpack_pack_array(packer, 0)
-#define CONV_LIST_START(lst) \
- msgpack_pack_array(packer, (size_t) (lst)->lv_len)
+#define TYPVAL_ENCODE_CONV_LIST_START(len) \
+ msgpack_pack_array(packer, (size_t) (len))
-#define CONV_EMPTY_DICT() \
+#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \
msgpack_pack_map(packer, 0)
-#define CONV_NIL() \
+#define TYPVAL_ENCODE_CONV_NIL() \
msgpack_pack_nil(packer)
-#define CONV_BOOL(num) \
+#define TYPVAL_ENCODE_CONV_BOOL(num) \
do { \
if ((num)) { \
msgpack_pack_true(packer); \
@@ -1246,51 +864,51 @@ char *encode_tv2json(typval_T *tv, size_t *len)
} \
} while (0)
-#define CONV_UNSIGNED_NUMBER(num) \
+#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) \
msgpack_pack_uint64(packer, (num))
-#define CONV_DICT_START(len) \
+#define TYPVAL_ENCODE_CONV_DICT_START(len) \
msgpack_pack_map(packer, (size_t) (len))
-#define CONV_DICT_END()
+#define TYPVAL_ENCODE_CONV_DICT_END()
-#define CONV_DICT_AFTER_KEY()
+#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY()
-#define CONV_DICT_BETWEEN_ITEMS()
+#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS()
-#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair)
+#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair)
-#define CONV_LIST_END(lst)
+#define TYPVAL_ENCODE_CONV_LIST_END()
-#define CONV_LIST_BETWEEN_ITEMS()
+#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS()
-#define CONV_RECURSE(val, conv_type) \
+#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \
return conv_error(_("E952: Unable to dump %s: " \
"container references itself in %s"), \
mpstack, objname)
-#define CONV_ALLOW_SPECIAL true
-
-DEFINE_VIML_CONV_FUNCTIONS(, msgpack, msgpack_packer *const, packer)
-
-#undef CONV_STRING
-#undef CONV_STR_STRING
-#undef CONV_EXT_STRING
-#undef CONV_NUMBER
-#undef CONV_FLOAT
-#undef CONV_FUNC
-#undef CONV_EMPTY_LIST
-#undef CONV_LIST_START
-#undef CONV_EMPTY_DICT
-#undef CONV_NIL
-#undef CONV_BOOL
-#undef CONV_UNSIGNED_NUMBER
-#undef CONV_DICT_START
-#undef CONV_DICT_END
-#undef CONV_DICT_AFTER_KEY
-#undef CONV_DICT_BETWEEN_ITEMS
-#undef CONV_SPECIAL_DICT_KEY_CHECK
-#undef CONV_LIST_END
-#undef CONV_LIST_BETWEEN_ITEMS
-#undef CONV_RECURSE
-#undef CONV_ALLOW_SPECIAL
+#define TYPVAL_ENCODE_ALLOW_SPECIALS true
+
+TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(, msgpack, msgpack_packer *const, packer)
+
+#undef TYPVAL_ENCODE_CONV_STRING
+#undef TYPVAL_ENCODE_CONV_STR_STRING
+#undef TYPVAL_ENCODE_CONV_EXT_STRING
+#undef TYPVAL_ENCODE_CONV_NUMBER
+#undef TYPVAL_ENCODE_CONV_FLOAT
+#undef TYPVAL_ENCODE_CONV_FUNC
+#undef TYPVAL_ENCODE_CONV_EMPTY_LIST
+#undef TYPVAL_ENCODE_CONV_LIST_START
+#undef TYPVAL_ENCODE_CONV_EMPTY_DICT
+#undef TYPVAL_ENCODE_CONV_NIL
+#undef TYPVAL_ENCODE_CONV_BOOL
+#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
+#undef TYPVAL_ENCODE_CONV_DICT_START
+#undef TYPVAL_ENCODE_CONV_DICT_END
+#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
+#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
+#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK
+#undef TYPVAL_ENCODE_CONV_LIST_END
+#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS
+#undef TYPVAL_ENCODE_CONV_RECURSE
+#undef TYPVAL_ENCODE_ALLOW_SPECIALS
diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h
new file mode 100644
index 0000000000..f70a6c9e94
--- /dev/null
+++ b/src/nvim/eval/typval_encode.h
@@ -0,0 +1,563 @@
+/// @file eval/typval_convert.h
+///
+/// Contains set of macros used to convert (possibly recursive) typval_T into
+/// something else. For these macros to work the following macros must be
+/// defined:
+
+/// @def TYPVAL_ENCODE_CONV_NIL
+/// @brief Macros used to convert NIL value
+///
+/// Is called both for special dictionary (unless #TYPVAL_ENCODE_ALLOW_SPECIALS
+/// is false) and `v:null`. Accepts no arguments, but still must be
+/// a function-like macros.
+
+/// @def TYPVAL_ENCODE_CONV_BOOL
+/// @brief Macros used to convert boolean value
+///
+/// Is called both for special dictionary (unless #TYPVAL_ENCODE_ALLOW_SPECIALS
+/// is false) and `v:true`/`v:false`.
+///
+/// @param num Boolean value to convert. Value is an expression which
+/// evaluates to some integer.
+
+/// @def TYPVAL_ENCODE_CONV_NUMBER
+/// @brief Macros used to convert integer
+///
+/// @param num Integer to convert, must accept both varnumber_T and int64_t.
+
+/// @def TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
+/// @brief Macros used to convert unsigned integer
+///
+/// Not used if #TYPVAL_ENCODE_ALLOW_SPECIALS is false, but still must be
+/// defined.
+///
+/// @param num Integer to convert, must accept uint64_t.
+
+/// @def TYPVAL_ENCODE_CONV_FLOAT
+/// @brief Macros used to convert floating-point number
+///
+/// @param flt Number to convert, must accept float_T.
+
+/// @def TYPVAL_ENCODE_CONV_STRING
+/// @brief Macros used to convert plain string
+///
+/// Is used to convert VAR_STRING objects as well as BIN strings represented as
+/// special dictionary.
+///
+/// @param buf String to convert. Is a char[] buffer, not NUL-terminated.
+/// @param len String length.
+
+/// @def TYPVAL_ENCODE_CONV_STR_STRING
+/// @brief Like #TYPVAL_ENCODE_CONV_STRING, but for STR strings
+///
+/// Is used to convert dictionary keys and STR strings represented as special
+/// dictionaries.
+
+/// @def TYPVAL_ENCODE_CONV_EXT_STRING
+/// @brief Macros used to convert EXT string
+///
+/// Is used to convert EXT strings represented as special dictionaries. Never
+/// actually used if #TYPVAL_ENCODE_ALLOW_SPECIALS is false, but still must be
+/// defined.
+///
+/// @param buf String to convert. Is a char[] buffer, not NUL-terminated.
+/// @param len String length.
+/// @param type EXT type.
+
+/// @def TYPVAL_ENCODE_CONV_FUNC
+/// @brief Macros used to convert a function reference
+///
+/// @param fun Function name.
+
+/// @def TYPVAL_ENCODE_CONV_EMPTY_LIST
+/// @brief Macros used to convert an empty list
+///
+/// Accepts no arguments, but still must be a function-like macros.
+
+/// @def TYPVAL_ENCODE_CONV_EMPTY_DICT
+/// @brief Macros used to convert an empty dictionary
+///
+/// Accepts no arguments, but still must be a function-like macros.
+
+/// @def TYPVAL_ENCODE_CONV_LIST_START
+/// @brief Macros used before starting to convert non-empty list
+///
+/// @param len List length. Is an expression which evaluates to an integer.
+
+/// @def TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS
+/// @brief Macros used after finishing converting non-last list item
+///
+/// Accepts no arguments, but still must be a function-like macros.
+
+/// @def TYPVAL_ENCODE_CONV_LIST_END
+/// @brief Macros used after converting non-empty list
+///
+/// Accepts no arguments, but still must be a function-like macros.
+
+/// @def TYPVAL_ENCODE_CONV_DICT_START
+/// @brief Macros used before starting to convert non-empty dictionary
+///
+/// @param len Dictionary length. Is an expression which evaluates to an
+/// integer.
+
+/// @def TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK
+/// @brief Macros used to check special dictionary key
+///
+/// @param label Label for goto in case check was not successfull.
+/// @param kv_pair List with two elements: key and value.
+
+/// @def TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
+/// @brief Macros used after finishing converting dictionary key
+///
+/// Accepts no arguments, but still must be a function-like macros.
+
+/// @def TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
+/// @brief Macros used after finishing converting non-last dictionary value
+///
+/// Accepts no arguments, but still must be a function-like macros.
+
+/// @def TYPVAL_ENCODE_CONV_DICT_END
+/// @brief Macros used after converting non-empty dictionary
+///
+/// Accepts no arguments, but still must be a function-like macros.
+
+/// @def TYPVAL_ENCODE_CONV_RECURSE
+/// @brief Macros used when self-containing container is detected
+///
+/// @param val Container for which this situation was detected.
+/// @param conv_type Type of the stack entry, @see MPConvStackValType.
+
+/// @def TYPVAL_ENCODE_ALLOW_SPECIALS
+/// @brief Macros that specifies whether special dictionaries are special
+///
+/// Must be something that evaluates to boolean, most likely `true` or `false`.
+/// If it is false then special dictionaries are not treated specially.
+#ifndef NVIM_EVAL_TYPVAL_ENCODE_H
+#define NVIM_EVAL_TYPVAL_ENCODE_H
+
+#include <stddef.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "nvim/lib/kvec.h"
+#include "nvim/eval_defs.h"
+#include "nvim/eval/encode.h"
+#include "nvim/func_attr.h"
+
+/// Type of the stack entry
+typedef enum {
+ kMPConvDict, ///< Convert dict_T *dictionary.
+ kMPConvList, ///< Convert list_T *list.
+ kMPConvPairs, ///< Convert mapping represented as a list_T* of pairs.
+} MPConvStackValType;
+
+/// Structure representing current VimL to messagepack conversion state
+typedef struct {
+ MPConvStackValType type; ///< Type of the stack entry.
+ union {
+ struct {
+ dict_T *dict; ///< Currently converted dictionary.
+ hashitem_T *hi; ///< Currently converted dictionary item.
+ size_t todo; ///< Amount of items left to process.
+ } d; ///< State of dictionary conversion.
+ struct {
+ list_T *list; ///< Currently converted list.
+ listitem_T *li; ///< Currently converted list item.
+ } l; ///< State of list or generic mapping conversion.
+ } data; ///< Data to convert.
+} MPConvStackVal;
+
+/// Stack used to convert VimL values to messagepack.
+typedef kvec_t(MPConvStackVal) MPConvStack;
+
+// Defines for MPConvStack
+#define _mp_size kv_size
+#define _mp_init kv_init
+#define _mp_destroy kv_destroy
+#define _mp_push kv_push
+#define _mp_pop kv_pop
+#define _mp_last kv_last
+
+/// Code for checking whether container references itself
+///
+/// @param[in,out] val Container to check.
+/// @param copyID_attr Name of the container attribute that holds copyID.
+/// After checking whether value of this attribute is
+/// copyID (variable) it is set to copyID.
+#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val, copyID_attr, conv_type) \
+ do { \
+ if ((val)->copyID_attr == copyID) { \
+ TYPVAL_ENCODE_CONV_RECURSE((val), conv_type); \
+ } \
+ (val)->copyID_attr = copyID; \
+ } while (0)
+
+/// Length of the string stored in typval_T
+///
+/// @param[in] tv String for which to compute length for. Must be typval_T
+/// with VAR_STRING.
+///
+/// @return Length of the string stored in typval_T, including 0 for NULL
+/// string.
+static inline size_t tv_strlen(const typval_T *const tv)
+ FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_NONNULL_ALL
+{
+ assert(tv->v_type == VAR_STRING);
+ return (tv->vval.v_string == NULL
+ ? 0
+ : strlen((char *) tv->vval.v_string));
+}
+
+/// Define functions which convert VimL value to something else
+///
+/// Creates function `vim_to_{name}(firstargtype firstargname, typval_T *const
+/// tv)` which returns OK or FAIL and helper functions.
+///
+/// @param scope Scope of the main function: either nothing or `static`.
+/// @param firstargtype Type of the first argument. It will be used to return
+/// the results.
+/// @param firstargname Name of the first argument.
+/// @param name Name of the target converter.
+#define TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(scope, name, firstargtype, \
+ firstargname) \
+static int name##_convert_one_value(firstargtype firstargname, \
+ MPConvStack *const mpstack, \
+ typval_T *const tv, \
+ const int copyID, \
+ const char *const objname) \
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \
+{ \
+ switch (tv->v_type) { \
+ case VAR_STRING: { \
+ TYPVAL_ENCODE_CONV_STRING(tv->vval.v_string, tv_strlen(tv)); \
+ break; \
+ } \
+ case VAR_NUMBER: { \
+ TYPVAL_ENCODE_CONV_NUMBER(tv->vval.v_number); \
+ break; \
+ } \
+ case VAR_FLOAT: { \
+ TYPVAL_ENCODE_CONV_FLOAT(tv->vval.v_float); \
+ break; \
+ } \
+ case VAR_FUNC: { \
+ TYPVAL_ENCODE_CONV_FUNC(tv->vval.v_string); \
+ break; \
+ } \
+ case VAR_LIST: { \
+ if (tv->vval.v_list == NULL || tv->vval.v_list->lv_len == 0) { \
+ TYPVAL_ENCODE_CONV_EMPTY_LIST(); \
+ break; \
+ } \
+ _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, \
+ kMPConvList); \
+ TYPVAL_ENCODE_CONV_LIST_START(tv->vval.v_list->lv_len); \
+ _mp_push(*mpstack, ((MPConvStackVal) { \
+ .type = kMPConvList, \
+ .data = { \
+ .l = { \
+ .list = tv->vval.v_list, \
+ .li = tv->vval.v_list->lv_first, \
+ }, \
+ }, \
+ })); \
+ break; \
+ } \
+ case VAR_SPECIAL: { \
+ switch (tv->vval.v_special) { \
+ case kSpecialVarNull: { \
+ TYPVAL_ENCODE_CONV_NIL(); \
+ break; \
+ } \
+ case kSpecialVarTrue: \
+ case kSpecialVarFalse: { \
+ TYPVAL_ENCODE_CONV_BOOL(tv->vval.v_special == kSpecialVarTrue); \
+ break; \
+ } \
+ } \
+ break; \
+ } \
+ case VAR_DICT: { \
+ if (tv->vval.v_dict == NULL \
+ || tv->vval.v_dict->dv_hashtab.ht_used == 0) { \
+ TYPVAL_ENCODE_CONV_EMPTY_DICT(); \
+ break; \
+ } \
+ const dictitem_T *type_di; \
+ const dictitem_T *val_di; \
+ if (TYPVAL_ENCODE_ALLOW_SPECIALS \
+ && tv->vval.v_dict->dv_hashtab.ht_used == 2 \
+ && (type_di = dict_find((dict_T *) tv->vval.v_dict, \
+ (char_u *) "_TYPE", -1)) != NULL \
+ && type_di->di_tv.v_type == VAR_LIST \
+ && (val_di = dict_find((dict_T *) tv->vval.v_dict, \
+ (char_u *) "_VAL", -1)) != NULL) { \
+ size_t i; \
+ for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) { \
+ if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) { \
+ break; \
+ } \
+ } \
+ if (i == ARRAY_SIZE(eval_msgpack_type_lists)) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ switch ((MessagePackType) i) { \
+ case kMPNil: { \
+ TYPVAL_ENCODE_CONV_NIL(); \
+ break; \
+ } \
+ case kMPBoolean: { \
+ if (val_di->di_tv.v_type != VAR_NUMBER) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ TYPVAL_ENCODE_CONV_BOOL(val_di->di_tv.vval.v_number); \
+ break; \
+ } \
+ case kMPInteger: { \
+ const list_T *val_list; \
+ varnumber_T sign; \
+ varnumber_T highest_bits; \
+ varnumber_T high_bits; \
+ varnumber_T low_bits; \
+ /* List of 4 integers; first is signed (should be 1 or -1, but */ \
+ /* this is not checked), second is unsigned and have at most */ \
+ /* one (sign is -1) or two (sign is 1) non-zero bits (number of */ \
+ /* bits is not checked), other unsigned and have at most 31 */ \
+ /* non-zero bits (number of bits is not checked).*/ \
+ if (val_di->di_tv.v_type != VAR_LIST \
+ || (val_list = val_di->di_tv.vval.v_list) == NULL \
+ || val_list->lv_len != 4 \
+ || val_list->lv_first->li_tv.v_type != VAR_NUMBER \
+ || (sign = val_list->lv_first->li_tv.vval.v_number) == 0 \
+ || val_list->lv_first->li_next->li_tv.v_type != VAR_NUMBER \
+ || (highest_bits = \
+ val_list->lv_first->li_next->li_tv.vval.v_number) < 0 \
+ || val_list->lv_last->li_prev->li_tv.v_type != VAR_NUMBER \
+ || (high_bits = \
+ val_list->lv_last->li_prev->li_tv.vval.v_number) < 0 \
+ || val_list->lv_last->li_tv.v_type != VAR_NUMBER \
+ || (low_bits = val_list->lv_last->li_tv.vval.v_number) < 0) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ uint64_t number = ((uint64_t) (((uint64_t) highest_bits) << 62) \
+ | (uint64_t) (((uint64_t) high_bits) << 31) \
+ | (uint64_t) low_bits); \
+ if (sign > 0) { \
+ TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(number); \
+ } else { \
+ TYPVAL_ENCODE_CONV_NUMBER(-number); \
+ } \
+ break; \
+ } \
+ case kMPFloat: { \
+ if (val_di->di_tv.v_type != VAR_FLOAT) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ TYPVAL_ENCODE_CONV_FLOAT(val_di->di_tv.vval.v_float); \
+ break; \
+ } \
+ case kMPString: \
+ case kMPBinary: { \
+ const bool is_string = ((MessagePackType) i == kMPString); \
+ if (val_di->di_tv.v_type != VAR_LIST) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ size_t len; \
+ char *buf; \
+ if (!encode_vim_list_to_buf(val_di->di_tv.vval.v_list, &len, \
+ &buf)) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ if (is_string) { \
+ TYPVAL_ENCODE_CONV_STR_STRING(buf, len); \
+ } else { \
+ TYPVAL_ENCODE_CONV_STRING(buf, len); \
+ } \
+ xfree(buf); \
+ break; \
+ } \
+ case kMPArray: { \
+ if (val_di->di_tv.v_type != VAR_LIST) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, \
+ lv_copyID, kMPConvList); \
+ TYPVAL_ENCODE_CONV_LIST_START(val_di->di_tv.vval.v_list->lv_len); \
+ _mp_push(*mpstack, ((MPConvStackVal) { \
+ .type = kMPConvList, \
+ .data = { \
+ .l = { \
+ .list = val_di->di_tv.vval.v_list, \
+ .li = val_di->di_tv.vval.v_list->lv_first, \
+ }, \
+ }, \
+ })); \
+ break; \
+ } \
+ case kMPMap: { \
+ if (val_di->di_tv.v_type != VAR_LIST) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ list_T *const val_list = val_di->di_tv.vval.v_list; \
+ if (val_list == NULL || val_list->lv_len == 0) { \
+ TYPVAL_ENCODE_CONV_EMPTY_DICT(); \
+ break; \
+ } \
+ for (const listitem_T *li = val_list->lv_first; li != NULL; \
+ li = li->li_next) { \
+ if (li->li_tv.v_type != VAR_LIST \
+ || li->li_tv.vval.v_list->lv_len != 2) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ } \
+ _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val_list, lv_copyID, \
+ kMPConvPairs); \
+ TYPVAL_ENCODE_CONV_DICT_START(val_list->lv_len); \
+ _mp_push(*mpstack, ((MPConvStackVal) { \
+ .type = kMPConvPairs, \
+ .data = { \
+ .l = { \
+ .list = val_list, \
+ .li = val_list->lv_first, \
+ }, \
+ }, \
+ })); \
+ break; \
+ } \
+ case kMPExt: { \
+ const list_T *val_list; \
+ varnumber_T type; \
+ if (val_di->di_tv.v_type != VAR_LIST \
+ || (val_list = val_di->di_tv.vval.v_list) == NULL \
+ || val_list->lv_len != 2 \
+ || (val_list->lv_first->li_tv.v_type != VAR_NUMBER) \
+ || (type = val_list->lv_first->li_tv.vval.v_number) > INT8_MAX \
+ || type < INT8_MIN \
+ || (val_list->lv_last->li_tv.v_type != VAR_LIST)) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ size_t len; \
+ char *buf; \
+ if (!encode_vim_list_to_buf(val_list->lv_last->li_tv.vval.v_list, \
+ &len, &buf)) { \
+ goto name##_convert_one_value_regular_dict; \
+ } \
+ TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type); \
+ xfree(buf); \
+ break; \
+ } \
+ } \
+ break; \
+ } \
+name##_convert_one_value_regular_dict: \
+ _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, \
+ kMPConvDict); \
+ TYPVAL_ENCODE_CONV_DICT_START(tv->vval.v_dict->dv_hashtab.ht_used); \
+ _mp_push(*mpstack, ((MPConvStackVal) { \
+ .type = kMPConvDict, \
+ .data = { \
+ .d = { \
+ .dict = tv->vval.v_dict, \
+ .hi = tv->vval.v_dict->dv_hashtab.ht_array, \
+ .todo = tv->vval.v_dict->dv_hashtab.ht_used, \
+ }, \
+ }, \
+ })); \
+ break; \
+ } \
+ case VAR_UNKNOWN: { \
+ EMSG2(_(e_intern2), #name "_convert_one_value()"); \
+ return FAIL; \
+ } \
+ } \
+ return OK; \
+} \
+\
+scope int encode_vim_to_##name(firstargtype firstargname, typval_T *const tv, \
+ const char *const objname) \
+ FUNC_ATTR_WARN_UNUSED_RESULT \
+{ \
+ const int copyID = get_copyID(); \
+ MPConvStack mpstack; \
+ _mp_init(mpstack); \
+ if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \
+ == FAIL) { \
+ goto encode_vim_to_##name##_error_ret; \
+ } \
+ while (_mp_size(mpstack)) { \
+ MPConvStackVal *cur_mpsv = &_mp_last(mpstack); \
+ typval_T *cur_tv = NULL; \
+ switch (cur_mpsv->type) { \
+ case kMPConvDict: { \
+ if (!cur_mpsv->data.d.todo) { \
+ (void) _mp_pop(mpstack); \
+ cur_mpsv->data.d.dict->dv_copyID = copyID - 1; \
+ TYPVAL_ENCODE_CONV_DICT_END(); \
+ continue; \
+ } else if (cur_mpsv->data.d.todo \
+ != cur_mpsv->data.d.dict->dv_hashtab.ht_used) { \
+ TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(); \
+ } \
+ while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) { \
+ cur_mpsv->data.d.hi++; \
+ } \
+ dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi); \
+ cur_mpsv->data.d.todo--; \
+ cur_mpsv->data.d.hi++; \
+ TYPVAL_ENCODE_CONV_STR_STRING(&di->di_key[0], \
+ strlen((char *) &di->di_key[0])); \
+ TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(); \
+ cur_tv = &di->di_tv; \
+ break; \
+ } \
+ case kMPConvList: { \
+ if (cur_mpsv->data.l.li == NULL) { \
+ (void) _mp_pop(mpstack); \
+ cur_mpsv->data.l.list->lv_copyID = copyID - 1; \
+ TYPVAL_ENCODE_CONV_LIST_END(); \
+ continue; \
+ } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \
+ TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(); \
+ } \
+ cur_tv = &cur_mpsv->data.l.li->li_tv; \
+ cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \
+ break; \
+ } \
+ case kMPConvPairs: { \
+ if (cur_mpsv->data.l.li == NULL) { \
+ (void) _mp_pop(mpstack); \
+ cur_mpsv->data.l.list->lv_copyID = copyID - 1; \
+ TYPVAL_ENCODE_CONV_DICT_END(); \
+ continue; \
+ } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \
+ TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(); \
+ } \
+ const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; \
+ TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK( \
+ encode_vim_to_##name##_error_ret, kv_pair); \
+ if (name##_convert_one_value(firstargname, &mpstack, \
+ &kv_pair->lv_first->li_tv, copyID, \
+ objname) == FAIL) { \
+ goto encode_vim_to_##name##_error_ret; \
+ } \
+ TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(); \
+ cur_tv = &kv_pair->lv_last->li_tv; \
+ cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \
+ break; \
+ } \
+ } \
+ assert(cur_tv != NULL); \
+ if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID, \
+ objname) == FAIL) { \
+ goto encode_vim_to_##name##_error_ret; \
+ } \
+ } \
+ _mp_destroy(mpstack); \
+ return OK; \
+encode_vim_to_##name##_error_ret: \
+ _mp_destroy(mpstack); \
+ return FAIL; \
+}
+
+#endif // NVIM_EVAL_TYPVAL_ENCODE_H
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 59962c153b..dd096af6b3 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -6992,7 +6992,7 @@ void do_sleep(long msec)
ui_flush(); // flush before waiting
for (long left = msec; !got_int && left > 0; left -= 1000L) {
int next = left > 1000l ? 1000 : (int)left;
- LOOP_PROCESS_EVENTS_UNTIL(&loop, loop.events, (int)next, got_int);
+ LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, (int)next, got_int);
os_breakcheck();
}
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index db21fddedb..65144dace8 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -358,7 +358,7 @@ static int command_line_execute(VimState *state, int key)
s->c = key;
if (s->c == K_EVENT) {
- queue_process_events(loop.events);
+ queue_process_events(main_loop.events);
redrawcmdline();
return 1;
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index dafb75ca87..f618e5ffc4 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -1243,7 +1243,6 @@ EXTERN char *ignoredp;
// If a msgpack-rpc channel should be started over stdin/stdout
EXTERN bool embedded_mode INIT(= false);
-EXTERN Loop loop;
/// Used to track the status of external functions.
/// Currently only used for iconv().
diff --git a/src/nvim/lib/kvec.h b/src/nvim/lib/kvec.h
index b41ef0cc9f..36c91c86b2 100644
--- a/src/nvim/lib/kvec.h
+++ b/src/nvim/lib/kvec.h
@@ -1,59 +1,61 @@
-/* The MIT License
-
- Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk>
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-*/
-
-/*
- An example:
-
-#include "kvec.h"
-int main() {
- kvec_t(int) array;
- kv_init(array);
- kv_push(int, array, 10); // append
- kv_a(int, array, 20) = 5; // dynamic
- kv_A(array, 20) = 4; // static
- kv_destroy(array);
- return 0;
-}
-*/
-
-/*
- 2008-09-22 (0.1.0):
+// The MIT License
+//
+// Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk>
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+// An example:
+//
+// #include "kvec.h"
+// int main() {
+// kvec_t(int) array = KV_INITIAL_VALUE;
+// kv_push(array, 10); // append
+// kv_a(array, 20) = 5; // dynamic
+// kv_A(array, 20) = 4; // static
+// kv_destroy(array);
+// return 0;
+// }
+
+#ifndef NVIM_LIB_KVEC_H
+#define NVIM_LIB_KVEC_H
- * The initial version.
+#include <stdlib.h>
+#include <string.h>
-*/
+#include "nvim/memory.h"
-#ifndef AC_KVEC_H
-#define AC_KVEC_H
+#define kv_roundup32(x) \
+ ((--(x)), \
+ ((x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16), \
+ (++(x)))
-#include <stdlib.h>
-#include "nvim/memory.h"
+#define KV_INITIAL_VALUE { .size = 0, .capacity = 0, .items = NULL }
-#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
+#define kvec_t(type) \
+ struct { \
+ size_t size; \
+ size_t capacity; \
+ type *items; \
+ }
-#define kvec_t(type) struct { size_t size, capacity; type *items; }
#define kv_init(v) ((v).size = (v).capacity = 0, (v).items = 0)
#define kv_destroy(v) xfree((v).items)
#define kv_A(v, i) ((v).items[(i)])
@@ -62,31 +64,130 @@ int main() {
#define kv_max(v) ((v).capacity)
#define kv_last(v) kv_A(v, kv_size(v) - 1)
-#define kv_resize(type, v, s) ((v).capacity = (s), (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity))
-
-#define kv_copy(type, v1, v0) do { \
- if ((v1).capacity < (v0).size) kv_resize(type, v1, (v0).size); \
- (v1).size = (v0).size; \
- memcpy((v1).items, (v0).items, sizeof(type) * (v0).size); \
- } while (0) \
-
-#define kv_push(type, v, x) do { \
- if ((v).size == (v).capacity) { \
- (v).capacity = (v).capacity? (v).capacity<<1 : 8; \
- (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity); \
- } \
- (v).items[(v).size++] = (x); \
- } while (0)
-
-#define kv_pushp(type, v) ((((v).size == (v).capacity)? \
- ((v).capacity = ((v).capacity? (v).capacity<<1 : 8), \
- (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity), 0) \
- : 0), ((v).items + ((v).size++)))
-
-#define kv_a(type, v, i) (((v).capacity <= (size_t)(i)? \
- ((v).capacity = (v).size = (i) + 1, kv_roundup32((v).capacity), \
- (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity), 0) \
- : (v).size <= (size_t)(i)? (v).size = (i) + 1 \
- : 0), (v).items[(i)])
-
-#endif
+#define kv_resize(v, s) \
+ ((v).capacity = (s), \
+ (v).items = xrealloc((v).items, sizeof((v).items[0]) * (v).capacity))
+
+#define kv_resize_full(v) \
+ kv_resize(v, (v).capacity ? (v).capacity << 1 : 8)
+
+#define kv_copy(v1, v0) \
+ do { \
+ if ((v1).capacity < (v0).size) { \
+ kv_resize(v1, (v0).size); \
+ } \
+ (v1).size = (v0).size; \
+ memcpy((v1).items, (v0).items, sizeof((v1).items[0]) * (v0).size); \
+ } while (0) \
+
+#define kv_pushp(v) \
+ ((((v).size == (v).capacity) ? (kv_resize_full(v), 0) : 0), \
+ ((v).items + ((v).size++)))
+
+#define kv_push(v, x) \
+ (*kv_pushp(v) = (x))
+
+#define kv_a(v, i) \
+ (((v).capacity <= (size_t) (i) \
+ ? ((v).capacity = (v).size = (i) + 1, \
+ kv_roundup32((v).capacity), \
+ kv_resize((v), (v).capacity), 0) \
+ : ((v).size <= (size_t) (i) \
+ ? (v).size = (i) + 1 \
+ : 0)), \
+ (v).items[(i)])
+
+/// Type of a vector with a few first members allocated on stack
+///
+/// Is compatible with #kv_A, #kv_pop, #kv_size, #kv_max, #kv_last.
+/// Is not compatible with #kv_resize, #kv_resize_full, #kv_copy, #kv_push,
+/// #kv_pushp, #kv_a, #kv_destroy.
+///
+/// @param[in] type Type of vector elements.
+/// @param[in] init_size Number of the elements in the initial array.
+#define kvec_withinit_t(type, INIT_SIZE) \
+ struct { \
+ size_t size; \
+ size_t capacity; \
+ type *items; \
+ type init_array[INIT_SIZE]; \
+ }
+
+/// Initialize vector with preallocated array
+///
+/// @param[out] v Vector to initialize.
+#define kvi_init(v) \
+ ((v).capacity = ARRAY_SIZE((v).init_array), \
+ (v).size = 0, \
+ (v).items = (v).init_array)
+
+/// Move data to a new destination and free source
+static inline void *_memcpy_free(void *const restrict dest,
+ void *const restrict src,
+ const size_t size)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE
+{
+ memcpy(dest, src, size);
+ xfree(src);
+ return dest;
+}
+
+/// Resize vector with preallocated array
+///
+/// @param[out] v Vector to resize.
+/// @param[in] s New size.
+#define kvi_resize(v, s) \
+ ((v).capacity = ((s) > ARRAY_SIZE((v).init_array) \
+ ? (s) \
+ : ARRAY_SIZE((v).init_array)), \
+ (v).items = ((v).capacity == ARRAY_SIZE((v).init_array) \
+ ? ((v).items == (v).init_array \
+ ? (v).items \
+ : _memcpy_free((v).init_array, (v).items, \
+ (v).size * sizeof((v).items[0]))) \
+ : ((v).items == (v).init_array \
+ ? memcpy(xmalloc((v).capacity * sizeof((v).items[0])), \
+ (v).items, \
+ (v).size * sizeof((v).items[0])) \
+ : xrealloc((v).items, \
+ (v).capacity * sizeof((v).items[0])))))
+
+/// Resize vector with preallocated array when it is full
+///
+/// @param[out] v Vector to resize.
+#define kvi_resize_full(v) \
+ /* ARRAY_SIZE((v).init_array) is the minimal capacity of this vector. */ \
+ /* Thus when vector is full capacity may not be zero and it is safe */ \
+ /* not to bother with checking whether (v).capacity is 0. But now */ \
+ /* capacity is not guaranteed to have size that is a power of 2. */ \
+ kvi_resize(v, ((v).capacity == ARRAY_SIZE((v).init_array) \
+ ? ((v).capacity++, kv_roundup32((v).capacity)) \
+ : (v).capacity << 1))
+
+/// Get location where to store new element to a vector with preallocated array
+///
+/// @param[in,out] v Vector to push to.
+///
+/// @return Pointer to the place where new value should be stored.
+#define kvi_pushp(v) \
+ ((((v).size == (v).capacity) ? (kvi_resize_full(v), 0) : 0), \
+ ((v).items + ((v).size++)))
+
+/// Push value to a vector with preallocated array
+///
+/// @param[out] v Vector to push to.
+/// @param[in] x Value to push.
+#define kvi_push(v, x) \
+ (*kvi_pushp(v) = (x))
+
+/// Free array of elements of a vector with preallocated array if needed
+///
+/// @param[out] v Vector to free.
+#define kvi_destroy(v) \
+ do { \
+ if ((v).items != (v).init_array) { \
+ xfree((v).items); \
+ } \
+ } while (0)
+
+#endif // NVIM_LIB_KVEC_H
diff --git a/src/nvim/lib/queue.h b/src/nvim/lib/queue.h
index fe02b454ea..fc322978b0 100644
--- a/src/nvim/lib/queue.h
+++ b/src/nvim/lib/queue.h
@@ -1,92 +1,94 @@
-/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
+// Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#ifndef QUEUE_H_
-#define QUEUE_H_
+#ifndef NVIM_LIB_QUEUE_H
+#define NVIM_LIB_QUEUE_H
-typedef void *QUEUE[2];
+#include <stddef.h>
-/* Private macros. */
-#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0]))
-#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1]))
-#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q)))
-#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q)))
+#include "nvim/func_attr.h"
-/* Public macros. */
-#define QUEUE_DATA(ptr, type, field) \
- ((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field)))
+typedef struct _queue {
+ struct _queue *next;
+ struct _queue *prev;
+} QUEUE;
-#define QUEUE_FOREACH(q, h) \
- for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
+// Public macros.
+#define QUEUE_DATA(ptr, type, field) \
+ ((type *)((char *)(ptr) - offsetof(type, field)))
-#define QUEUE_EMPTY(q) \
- ((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q))
+#define QUEUE_FOREACH(q, h) \
+ for ( /* NOLINT(readability/braces) */ \
+ (q) = (h)->next; (q) != (h); (q) = (q)->next)
-#define QUEUE_HEAD(q) \
- (QUEUE_NEXT(q))
+// ffi.cdef is unable to swallow `bool` in place of `int` here.
+static inline int QUEUE_EMPTY(const QUEUE *const q)
+ FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return q == q->next;
+}
-#define QUEUE_INIT(q) \
- do { \
- QUEUE_NEXT(q) = (q); \
- QUEUE_PREV(q) = (q); \
- } \
- while (0)
+#define QUEUE_HEAD(q) (q)->next
-#define QUEUE_ADD(h, n) \
- do { \
- QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \
- QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \
- QUEUE_PREV(h) = QUEUE_PREV(n); \
- QUEUE_PREV_NEXT(h) = (h); \
- } \
- while (0)
+static inline void QUEUE_INIT(QUEUE *const q) FUNC_ATTR_ALWAYS_INLINE
+{
+ q->next = q;
+ q->prev = q;
+}
-#define QUEUE_SPLIT(h, q, n) \
- do { \
- QUEUE_PREV(n) = QUEUE_PREV(h); \
- QUEUE_PREV_NEXT(n) = (n); \
- QUEUE_NEXT(n) = (q); \
- QUEUE_PREV(h) = QUEUE_PREV(q); \
- QUEUE_PREV_NEXT(h) = (h); \
- QUEUE_PREV(q) = (n); \
- } \
- while (0)
+static inline void QUEUE_ADD(QUEUE *const h, QUEUE *const n)
+ FUNC_ATTR_ALWAYS_INLINE
+{
+ h->prev->next = n->next;
+ n->next->prev = h->prev;
+ h->prev = n->prev;
+ h->prev->next = h;
+}
-#define QUEUE_INSERT_HEAD(h, q) \
- do { \
- QUEUE_NEXT(q) = QUEUE_NEXT(h); \
- QUEUE_PREV(q) = (h); \
- QUEUE_NEXT_PREV(q) = (q); \
- QUEUE_NEXT(h) = (q); \
- } \
- while (0)
+static inline void QUEUE_SPLIT(QUEUE *const h, QUEUE *const q, QUEUE *const n)
+ FUNC_ATTR_ALWAYS_INLINE
+{
+ n->prev = h->prev;
+ n->prev->next = n;
+ n->next = q;
+ h->prev = q->prev;
+ h->prev->next = h;
+ q->prev = n;
+}
-#define QUEUE_INSERT_TAIL(h, q) \
- do { \
- QUEUE_NEXT(q) = (h); \
- QUEUE_PREV(q) = QUEUE_PREV(h); \
- QUEUE_PREV_NEXT(q) = (q); \
- QUEUE_PREV(h) = (q); \
- } \
- while (0)
+static inline void QUEUE_INSERT_HEAD(QUEUE *const h, QUEUE *const q)
+ FUNC_ATTR_ALWAYS_INLINE
+{
+ q->next = h->next;
+ q->prev = h;
+ q->next->prev = q;
+ h->next = q;
+}
-#define QUEUE_REMOVE(q) \
- do { \
- QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \
- QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \
- } \
- while (0)
+static inline void QUEUE_INSERT_TAIL(QUEUE *const h, QUEUE *const q)
+ FUNC_ATTR_ALWAYS_INLINE
+{
+ q->next = h;
+ q->prev = h->prev;
+ q->prev->next = q;
+ h->prev = q;
+}
-#endif /* QUEUE_H_ */
+static inline void QUEUE_REMOVE(QUEUE *const q) FUNC_ATTR_ALWAYS_INLINE
+{
+ q->prev->next = q->next;
+ q->next->prev = q->prev;
+}
+
+#endif // NVIM_LIB_QUEUE_H
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 71a972e8f6..2b14e6a777 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -120,6 +120,8 @@ typedef struct {
# include "main.c.generated.h"
#endif
+Loop main_loop;
+
static char *argv0;
// Error messages
@@ -133,7 +135,7 @@ static const char *err_extra_cmd =
void event_init(void)
{
- loop_init(&loop, NULL);
+ loop_init(&main_loop, NULL);
// early msgpack-rpc initialization
msgpack_rpc_init_method_table();
msgpack_rpc_helpers_init();
@@ -151,19 +153,19 @@ void event_init(void)
void event_teardown(void)
{
- if (!loop.events) {
+ if (!main_loop.events) {
return;
}
- queue_process_events(loop.events);
+ queue_process_events(main_loop.events);
input_stop();
channel_teardown();
- process_teardown(&loop);
+ process_teardown(&main_loop);
server_teardown();
signal_teardown();
terminal_teardown();
- loop_close(&loop);
+ loop_close(&main_loop);
}
/// Performs early initialization.
diff --git a/src/nvim/main.h b/src/nvim/main.h
index 084e247b7e..86d25fe657 100644
--- a/src/nvim/main.h
+++ b/src/nvim/main.h
@@ -2,6 +2,9 @@
#define NVIM_MAIN_H
#include "nvim/normal.h"
+#include "nvim/event/loop.h"
+
+extern Loop main_loop;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "main.h.generated.h"
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 3a6d7c1434..0d7d5a247e 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -16,6 +16,7 @@
#include "nvim/event/socket.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/vim.h"
+#include "nvim/main.h"
#include "nvim/ascii.h"
#include "nvim/memory.h"
#include "nvim/os_unix.h"
@@ -119,7 +120,7 @@ void channel_teardown(void)
uint64_t channel_from_process(char **argv)
{
Channel *channel = register_channel(kChannelTypeProc);
- channel->data.process.uvproc = libuv_process_init(&loop, channel);
+ channel->data.process.uvproc = libuv_process_init(&main_loop, channel);
Process *proc = &channel->data.process.uvproc.process;
proc->argv = argv;
proc->in = &channel->data.process.in;
@@ -127,7 +128,7 @@ uint64_t channel_from_process(char **argv)
proc->err = &channel->data.process.err;
proc->cb = process_exit;
if (!process_spawn(proc)) {
- loop_poll_events(&loop, 0);
+ loop_poll_events(&main_loop, 0);
decref(channel);
return 0;
}
@@ -179,7 +180,7 @@ bool channel_send_event(uint64_t id, char *name, Array args)
// Pending request, queue the notification for later sending.
String method = cstr_as_string(name);
WBuffer *buffer = serialize_request(id, 0, method, args, &out_buffer, 1);
- kv_push(WBuffer *, channel->delayed_notifications, buffer);
+ kv_push(channel->delayed_notifications, buffer);
} else {
send_event(channel, name, args);
}
@@ -217,10 +218,10 @@ Object channel_send_call(uint64_t id,
send_request(channel, request_id, method_name, args);
// Push the frame
- ChannelCallFrame frame = {request_id, false, false, NIL};
- kv_push(ChannelCallFrame *, channel->call_stack, &frame);
+ ChannelCallFrame frame = { request_id, false, false, NIL };
+ kv_push(channel->call_stack, &frame);
channel->pending_requests++;
- LOOP_PROCESS_EVENTS_UNTIL(&loop, channel->events, -1, frame.returned);
+ LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned);
(void)kv_pop(channel->call_stack);
channel->pending_requests--;
@@ -316,11 +317,11 @@ void channel_from_stdio(void)
Channel *channel = register_channel(kChannelTypeStdio);
incref(channel); // stdio channels are only closed on exit
// read stream
- rstream_init_fd(&loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE,
- channel);
+ rstream_init_fd(&main_loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE,
+ channel);
rstream_start(&channel->data.std.in, parse_msgpack);
// write stream
- wstream_init_fd(&loop, &channel->data.std.out, 1, 0, NULL);
+ wstream_init_fd(&main_loop, &channel->data.std.out, 1, 0, NULL);
}
static void forward_stderr(Stream *stream, RBuffer *rbuf, size_t count,
@@ -574,13 +575,12 @@ static void send_event(Channel *channel,
static void broadcast_event(char *name, Array args)
{
- kvec_t(Channel *) subscribed;
- kv_init(subscribed);
+ kvec_t(Channel *) subscribed = KV_INITIAL_VALUE;
Channel *channel;
map_foreach_value(channels, channel, {
if (pmap_has(cstr_t)(channel->subscribed_events, name)) {
- kv_push(Channel *, subscribed, channel);
+ kv_push(subscribed, channel);
}
});
@@ -600,7 +600,7 @@ static void broadcast_event(char *name, Array args)
for (size_t i = 0; i < kv_size(subscribed); i++) {
Channel *channel = kv_A(subscribed, i);
if (channel->pending_requests) {
- kv_push(WBuffer *, channel->delayed_notifications, buffer);
+ kv_push(channel->delayed_notifications, buffer);
} else {
channel_write(channel, buffer);
}
@@ -647,7 +647,7 @@ static void close_channel(Channel *channel)
case kChannelTypeStdio:
stream_close(&channel->data.std.in, NULL);
stream_close(&channel->data.std.out, NULL);
- queue_put(loop.fast_events, exit_event, 1, channel);
+ queue_put(main_loop.fast_events, exit_event, 1, channel);
return;
default:
abort();
@@ -692,7 +692,7 @@ static void close_cb(Stream *stream, void *data)
static Channel *register_channel(ChannelType type)
{
Channel *rv = xmalloc(sizeof(Channel));
- rv->events = queue_new_child(loop.events);
+ rv->events = queue_new_child(main_loop.events);
rv->type = type;
rv->refcount = 1;
rv->closed = false;
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index 6cc56ba3dd..abbd3e8aff 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -12,6 +12,7 @@
#include "nvim/eval.h"
#include "nvim/garray.h"
#include "nvim/vim.h"
+#include "nvim/main.h"
#include "nvim/memory.h"
#include "nvim/log.h"
#include "nvim/fileio.h"
@@ -108,7 +109,7 @@ int server_start(const char *endpoint)
}
SocketWatcher *watcher = xmalloc(sizeof(SocketWatcher));
- socket_watcher_init(&loop, watcher, endpoint, NULL);
+ socket_watcher_init(&main_loop, watcher, endpoint, NULL);
// Check if a watcher for the endpoint already exists
for (int i = 0; i < watchers.ga_len; i++) {
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 382c4943ff..cc604352e1 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -7879,7 +7879,7 @@ static void nv_event(cmdarg_T *cap)
// not safe to perform garbage collection because there could be unreferenced
// lists or dicts being used.
may_garbage_collect = false;
- queue_process_events(loop.events);
+ queue_process_events(main_loop.events);
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
}
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 7687b14f02..0c46dc96ee 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -60,7 +60,7 @@ void input_start(int fd)
}
global_fd = fd;
- rstream_init_fd(&loop, &read_stream, fd, READ_BUFFER_SIZE, NULL);
+ rstream_init_fd(&main_loop, &read_stream, fd, READ_BUFFER_SIZE, NULL);
rstream_start(&read_stream, read_cb);
}
@@ -87,8 +87,8 @@ static void create_cursorhold_event(void)
// have been called(inbuf_poll would return kInputAvail)
// TODO(tarruda): Cursorhold should be implemented as a timer set during the
// `state_check` callback for the states where it can be triggered.
- assert(!events_enabled || queue_empty(loop.events));
- queue_put(loop.events, cursorhold_event, 0);
+ assert(!events_enabled || queue_empty(main_loop.events));
+ queue_put(main_loop.events, cursorhold_event, 0);
}
// Low level input function
@@ -147,7 +147,7 @@ bool os_char_avail(void)
void os_breakcheck(void)
{
if (!got_int) {
- loop_poll_events(&loop, 0);
+ loop_poll_events(&main_loop, 0);
}
}
@@ -322,7 +322,7 @@ static bool input_poll(int ms)
prof_inchar_enter();
}
- LOOP_PROCESS_EVENTS_UNTIL(&loop, NULL, ms, input_ready() || input_eof);
+ LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, input_ready() || input_eof);
if (do_profiling == PROF_YES && ms) {
prof_inchar_exit();
@@ -419,5 +419,5 @@ static void read_error_exit(void)
static bool pending_events(void)
{
- return events_enabled && !queue_empty(loop.events);
+ return events_enabled && !queue_empty(main_loop.events);
}
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index f5a1637c94..988620b145 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -14,6 +14,7 @@
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
#include "nvim/types.h"
+#include "nvim/main.h"
#include "nvim/vim.h"
#include "nvim/message.h"
#include "nvim/memory.h"
@@ -205,16 +206,16 @@ static int do_os_system(char **argv,
xstrlcpy(prog, argv[0], MAXPATHL);
Stream in, out, err;
- LibuvProcess uvproc = libuv_process_init(&loop, &buf);
+ LibuvProcess uvproc = libuv_process_init(&main_loop, &buf);
Process *proc = &uvproc.process;
- Queue *events = queue_new_child(loop.events);
+ Queue *events = queue_new_child(main_loop.events);
proc->events = events;
proc->argv = argv;
proc->in = input != NULL ? &in : NULL;
proc->out = &out;
proc->err = &err;
if (!process_spawn(proc)) {
- loop_poll_events(&loop, 0);
+ loop_poll_events(&main_loop, 0);
// Failed, probably due to `sh` not being executable
if (!silent) {
MSG_PUTS(_("\nCannot execute "));
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index 0ff6016e32..4abc9cfc36 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -8,6 +8,7 @@
#include "nvim/globals.h"
#include "nvim/memline.h"
#include "nvim/eval.h"
+#include "nvim/main.h"
#include "nvim/memory.h"
#include "nvim/misc1.h"
#include "nvim/misc2.h"
@@ -28,10 +29,10 @@ static bool rejecting_deadly;
void signal_init(void)
{
- signal_watcher_init(&loop, &spipe, NULL);
- signal_watcher_init(&loop, &shup, NULL);
- signal_watcher_init(&loop, &squit, NULL);
- signal_watcher_init(&loop, &sterm, NULL);
+ signal_watcher_init(&main_loop, &spipe, NULL);
+ signal_watcher_init(&main_loop, &shup, NULL);
+ signal_watcher_init(&main_loop, &squit, NULL);
+ signal_watcher_init(&main_loop, &sterm, NULL);
#ifdef SIGPIPE
signal_watcher_start(&spipe, on_signal, SIGPIPE);
#endif
@@ -41,7 +42,7 @@ void signal_init(void)
#endif
signal_watcher_start(&sterm, on_signal, SIGTERM);
#ifdef SIGPWR
- signal_watcher_init(&loop, &spwr, NULL);
+ signal_watcher_init(&main_loop, &spwr, NULL);
signal_watcher_start(&spwr, on_signal, SIGPWR);
#endif
}
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c
index 188f0802c9..2205ad0958 100644
--- a/src/nvim/os/time.c
+++ b/src/nvim/os/time.c
@@ -9,6 +9,7 @@
#include "nvim/os/time.h"
#include "nvim/event/loop.h"
#include "nvim/vim.h"
+#include "nvim/main.h"
static uv_mutex_t delay_mutex;
static uv_cond_t delay_cond;
@@ -43,7 +44,7 @@ void os_delay(uint64_t milliseconds, bool ignoreinput)
if (milliseconds > INT_MAX) {
milliseconds = INT_MAX;
}
- LOOP_PROCESS_EVENTS_UNTIL(&loop, NULL, (int)milliseconds, got_int);
+ LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, (int)milliseconds, got_int);
} else {
os_microdelay(milliseconds * 1000);
}
diff --git a/src/nvim/state.c b/src/nvim/state.c
index b2f3f0bebe..30133e2201 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -4,6 +4,7 @@
#include "nvim/state.h"
#include "nvim/vim.h"
+#include "nvim/main.h"
#include "nvim/getchar.h"
#include "nvim/ui.h"
#include "nvim/os/input.h"
@@ -32,7 +33,7 @@ getkey:
// processing. Characters can come from mappings, scripts and other
// sources, so this scenario is very common.
key = safe_vgetc();
- } else if (!queue_empty(loop.events)) {
+ } else if (!queue_empty(main_loop.events)) {
// Event was made available after the last queue_process_events call
key = K_EVENT;
} else {
@@ -45,7 +46,7 @@ getkey:
// directly.
(void)os_inchar(NULL, 0, -1, 0);
input_disable_events();
- key = !queue_empty(loop.events) ? K_EVENT : safe_vgetc();
+ key = !queue_empty(main_loop.events) ? K_EVENT : safe_vgetc();
}
if (key == K_EVENT) {
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 104cc47cda..df5e03880a 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -63,6 +63,7 @@
#include "nvim/map.h"
#include "nvim/misc1.h"
#include "nvim/move.h"
+#include "nvim/main.h"
#include "nvim/state.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_cmds.h"
@@ -163,9 +164,9 @@ static VTermColor default_vt_bg_rgb;
void terminal_init(void)
{
invalidated_terminals = pmap_new(ptr_t)();
- time_watcher_init(&loop, &refresh_timer, NULL);
+ time_watcher_init(&main_loop, &refresh_timer, NULL);
// refresh_timer_cb will redraw the screen which can call vimscript
- refresh_timer.events = queue_new_child(loop.events);
+ refresh_timer.events = queue_new_child(main_loop.events);
// initialize a rgb->color index map for cterm attributes(VTermScreenCell
// only has RGB information and we need color indexes for terminal UIs)
@@ -452,7 +453,7 @@ static int terminal_execute(VimState *state, int key)
case K_EVENT:
// We cannot let an event free the terminal yet. It is still needed.
s->term->refcount++;
- queue_process_events(loop.events);
+ queue_process_events(main_loop.events);
s->term->refcount--;
if (s->term->buf_handle == 0) {
s->close = true;
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 99eb230a88..f374c6dc7a 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -4,6 +4,7 @@
#include "nvim/api/vim.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
+#include "nvim/main.h"
#include "nvim/misc2.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
@@ -92,7 +93,7 @@ static void flush_input(TermInput *input, bool wait_until_empty)
size_t drain_boundary = wait_until_empty ? 0 : 0xff;
do {
uv_mutex_lock(&input->key_buffer_mutex);
- loop_schedule(&loop, event_create(1, wait_input_enqueue, 1, input));
+ loop_schedule(&main_loop, event_create(1, wait_input_enqueue, 1, input));
input->waiting = true;
while (input->waiting) {
uv_cond_wait(&input->key_buffer_cond, &input->key_buffer_mutex);
@@ -336,7 +337,7 @@ static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
stream_close(&input->read_stream, NULL);
queue_put(input->loop->fast_events, restart_reading, 1, input);
} else {
- loop_schedule(&loop, event_create(1, input_done_event, 0));
+ loop_schedule(&main_loop, event_create(1, input_done_event, 0));
}
return;
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 62bc81ba64..50558e644a 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -11,6 +11,7 @@
#include "nvim/vim.h"
#include "nvim/ui.h"
#include "nvim/map.h"
+#include "nvim/main.h"
#include "nvim/memory.h"
#include "nvim/api/vim.h"
#include "nvim/api/private/helpers.h"
@@ -261,7 +262,7 @@ static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
UI *ui = data;
update_size(ui);
// run refresh_event in nvim main loop
- loop_schedule(&loop, event_create(1, refresh_event, 0));
+ loop_schedule(&main_loop, event_create(1, refresh_event, 0));
}
static bool attrs_differ(HlAttrs a1, HlAttrs a2)
@@ -681,7 +682,7 @@ static void invalidate(UI *ui, int top, int bot, int left, int right)
intersects->right = MAX(right, intersects->right);
} else {
// Else just add a new entry;
- kv_push(Rect, data->invalid_regions, ((Rect){top, bot, left, right}));
+ kv_push(data->invalid_regions, ((Rect) { top, bot, left, right }));
}
}
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index d17fa4a782..41d35684b1 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -5,6 +5,7 @@
#include <stdio.h>
#include <limits.h>
+#include "nvim/main.h"
#include "nvim/vim.h"
#include "nvim/ui.h"
#include "nvim/memory.h"
@@ -100,7 +101,7 @@ static void ui_bridge_stop(UI *b)
if (stopped) {
break;
}
- loop_poll_events(&loop, 10);
+ loop_poll_events(&main_loop, 10);
}
uv_thread_join(&bridge->ui_thread);
uv_mutex_destroy(&bridge->mutex);