diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 22:39:54 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 22:39:54 +0000 |
commit | 21cb7d04c387e4198ca8098a884c78b56ffcf4c2 (patch) | |
tree | 84fe5690df1551f0bb2bdfe1a13aacd29ebc1de7 /src/nvim/msgpack_rpc | |
parent | d9c904f85a23a496df4eb6be42aa43f007b22d50 (diff) | |
parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
download | rneovim-colorcolchar.tar.gz rneovim-colorcolchar.tar.bz2 rneovim-colorcolchar.zip |
Merge remote-tracking branch 'upstream/master' into colorcolcharcolorcolchar
Diffstat (limited to 'src/nvim/msgpack_rpc')
-rw-r--r-- | src/nvim/msgpack_rpc/channel.c | 263 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/channel.h | 17 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/channel_defs.h | 21 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/helpers.c | 22 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/helpers.h | 5 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/server.c | 13 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/server.h | 6 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/unpacker.c | 118 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/unpacker.h | 9 |
9 files changed, 247 insertions, 227 deletions
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index d60e18590f..0fb1ebf931 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <assert.h> #include <inttypes.h> #include <msgpack/object.h> @@ -10,7 +7,6 @@ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <uv.h> #include "klib/kvec.h" #include "nvim/api/private/defs.h" @@ -24,9 +20,11 @@ #include "nvim/event/rstream.h" #include "nvim/event/stream.h" #include "nvim/event/wstream.h" +#include "nvim/func_attr.h" +#include "nvim/globals.h" #include "nvim/log.h" #include "nvim/main.h" -#include "nvim/map.h" +#include "nvim/map_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/msgpack_rpc/channel.h" @@ -35,16 +33,82 @@ #include "nvim/msgpack_rpc/unpacker.h" #include "nvim/os/input.h" #include "nvim/rbuffer.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/ui_client.h" -#if MIN_LOG_LEVEL > LOGLVL_DBG +#ifdef NVIM_LOG_DEBUG +# define REQ "[request] " +# define RES "[response] " +# define NOT "[notify] " +# define ERR "[error] " + +// Cannot define array with negative offsets, so this one is needed to be added +// to MSGPACK_UNPACK_\* values. +# define MUR_OFF 2 + +static const char *const msgpack_error_messages[] = { + [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found", + [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string", + [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error", + [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory", +}; + +static void log_close(FILE *f) +{ + fputc('\n', f); + fflush(f); + fclose(f); + log_unlock(); +} + +static void log_server_msg(uint64_t channel_id, msgpack_sbuffer *packed) +{ + msgpack_unpacked unpacked; + msgpack_unpacked_init(&unpacked); + DLOGN("RPC ->ch %" PRIu64 ": ", channel_id); + const msgpack_unpack_return result = + msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL); + switch (result) { + case MSGPACK_UNPACK_SUCCESS: { + uint64_t type = unpacked.data.via.array.ptr[0].via.u64; + log_lock(); + FILE *f = open_log_file(); + fprintf(f, type ? (type == 1 ? RES : NOT) : REQ); + msgpack_object_print(f, unpacked.data); + log_close(f); + msgpack_unpacked_destroy(&unpacked); + break; + } + case MSGPACK_UNPACK_EXTRA_BYTES: + case MSGPACK_UNPACK_CONTINUE: + case MSGPACK_UNPACK_PARSE_ERROR: + case MSGPACK_UNPACK_NOMEM_ERROR: { + log_lock(); + FILE *f = open_log_file(); + fprintf(f, ERR); + fprintf(f, "%s", msgpack_error_messages[result + MUR_OFF]); + log_close(f); + break; + } + } +} + +static void log_client_msg(uint64_t channel_id, bool is_request, const char *name) +{ + DLOGN("RPC <-ch %" PRIu64 ": ", channel_id); + log_lock(); + FILE *f = open_log_file(); + fprintf(f, "%s: %s", is_request ? REQ : RES, name); + log_close(f); +} + +#else # define log_client_msg(...) # define log_server_msg(...) #endif -static PMap(cstr_t) event_strings = MAP_INIT; +static Set(cstr_t) event_strings = SET_INIT; static msgpack_sbuffer out_buffer; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -71,7 +135,7 @@ void rpc_start(Channel *channel) if (channel->streamtype != kChannelStreamInternal) { Stream *out = channel_outstream(channel); -#if MIN_LOG_LEVEL <= LOGLVL_DBG +#ifdef NVIM_LOG_DEBUG Stream *in = channel_instream(channel); DLOG("rpc ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id, (void *)in, (void *)out); @@ -141,9 +205,15 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem // Push the frame ChannelCallFrame frame = { request_id, false, false, NIL, NULL }; kv_push(rpc->call_stack, &frame); - LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned); + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned || rpc->closed); (void)kv_pop(rpc->call_stack); + if (rpc->closed) { + api_set_error(err, kErrorTypeException, "Invalid channel: %" PRIu64, id); + channel_decref(channel); + return NIL; + } + if (frame.errored) { if (frame.result.type == kObjectTypeString) { api_set_error(err, kErrorTypeException, "%s", @@ -188,14 +258,12 @@ void rpc_subscribe(uint64_t id, char *event) abort(); } - char *event_string = pmap_get(cstr_t)(&event_strings, event); - - if (!event_string) { - event_string = xstrdup(event); - pmap_put(cstr_t)(&event_strings, event_string, event_string); + const char **key_alloc = NULL; + if (set_put_ref(cstr_t, &event_strings, event, &key_alloc)) { + *key_alloc = xstrdup(event); } - pmap_put(cstr_t)(channel->rpc.subscribed_events, event_string, event_string); + set_put(cstr_t, channel->rpc.subscribed_events, *key_alloc); } /// Unsubscribes to event broadcasts @@ -242,26 +310,43 @@ end: channel_decref(channel); } +static ChannelCallFrame *find_call_frame(RpcState *rpc, uint32_t request_id) +{ + for (size_t i = 0; i < kv_size(rpc->call_stack); i++) { + ChannelCallFrame *frame = kv_Z(rpc->call_stack, i); + if (frame->request_id == request_id) { + return frame; + } + } + return NULL; +} + static void parse_msgpack(Channel *channel) { Unpacker *p = channel->rpc.unpacker; while (unpacker_advance(p)) { if (p->type == kMessageTypeRedrawEvent) { - if (p->grid_line_event) { - ui_client_event_raw_line(p->grid_line_event); - } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) { - p->ui_handler.fn(p->result.data.array); + // When exiting, ui_client_stop() has already been called, so don't handle UI events. + if (ui_client_channel_id && !exiting) { + if (p->grid_line_event) { + ui_client_event_raw_line(p->grid_line_event); + } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) { + p->ui_handler.fn(p->result.data.array); + } } arena_mem_free(arena_finish(&p->arena)); } else if (p->type == kMessageTypeResponse) { - ChannelCallFrame *frame = kv_last(channel->rpc.call_stack); - if (p->request_id != frame->request_id) { + ChannelCallFrame *frame = channel->rpc.client_type == kClientTypeMsgpackRpc + ? find_call_frame(&channel->rpc, p->request_id) + : kv_last(channel->rpc.call_stack); + if (frame == NULL || p->request_id != frame->request_id) { char buf[256]; snprintf(buf, sizeof(buf), - "ch %" PRIu64 " returned a response with an unknown request " - "id. Ensure the client is properly synchronized", - channel->id); + "ch %" PRIu64 " (type=%" PRIu32 ") returned a response with an unknown request " + "id %" PRIu32 ". Ensure the client is properly synchronized", + channel->id, (unsigned)channel->rpc.client_type, p->request_id); chan_close_with_error(channel, buf, LOGLVL_ERR); + return; } frame->returned = true; frame->errored = (p->error.type != kObjectTypeNil); @@ -486,7 +571,7 @@ static void broadcast_event(const char *name, Array args) map_foreach_value(&channels, channel, { if (channel->is_rpc - && pmap_has(cstr_t)(channel->rpc.subscribed_events, name)) { + && set_has(cstr_t, channel->rpc.subscribed_events, name)) { kv_push(subscribed, channel); } }); @@ -514,24 +599,12 @@ end: static void unsubscribe(Channel *channel, char *event) { - char *event_string = pmap_get(cstr_t)(&event_strings, event); - if (!event_string) { + if (!set_has(cstr_t, &event_strings, event)) { WLOG("RPC: ch %" PRIu64 ": tried to unsubscribe unknown event '%s'", channel->id, event); return; } - pmap_del(cstr_t)(channel->rpc.subscribed_events, event_string); - - map_foreach_value(&channels, channel, { - if (channel->is_rpc - && pmap_has(cstr_t)(channel->rpc.subscribed_events, event_string)) { - return; - } - }); - - // Since the string is no longer used by other channels, release it's memory - pmap_del(cstr_t)(&event_strings, event_string); - xfree(event_string); + set_del(cstr_t, channel->rpc.subscribed_events, event); } /// Mark rpc state as closed, and release its reference to the channel. @@ -547,6 +620,10 @@ void rpc_close(Channel *channel) if (channel->streamtype == kChannelStreamStdio || (channel->id == ui_client_channel_id && channel->streamtype != kChannelStreamProc)) { + if (channel->streamtype == kChannelStreamStdio) { + // Avoid hanging when there are no other UIs and a prompt is triggered on exit. + remote_ui_disconnect(channel->id); + } exit_from_channel(0); } } @@ -557,13 +634,7 @@ void rpc_free(Channel *channel) unpacker_teardown(channel->rpc.unpacker); xfree(channel->rpc.unpacker); - // Unsubscribe from all events - char *event_string; - map_foreach_value(channel->rpc.subscribed_events, event_string, { - unsubscribe(channel, event_string); - }); - - pmap_destroy(cstr_t)(channel->rpc.subscribed_events); + set_destroy(cstr_t, channel->rpc.subscribed_events); kv_destroy(channel->rpc.call_stack); api_free_dictionary(channel->rpc.info); } @@ -575,7 +646,7 @@ static void chan_close_with_error(Channel *channel, char *msg, int loglevel) ChannelCallFrame *frame = kv_A(channel->rpc.call_stack, i); frame->returned = true; frame->errored = true; - frame->result = STRING_OBJ(cstr_to_string(msg)); + frame->result = CSTR_TO_OBJ(msg); } channel_close(channel->id, kChannelPartRpc, NULL); @@ -612,7 +683,7 @@ static WBuffer *serialize_response(uint64_t channel_id, MsgpackRpcRequestHandler } else { Array args = ARRAY_DICT_INIT; ADD(args, INTEGER_OBJ(err->type)); - ADD(args, STRING_OBJ(cstr_to_string(err->msg))); + ADD(args, CSTR_TO_OBJ(err->msg)); msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"), args, &pac); api_free_array(args); @@ -638,6 +709,25 @@ void rpc_set_client_info(uint64_t id, Dictionary info) api_free_dictionary(chan->rpc.info); chan->rpc.info = info; + + // Parse "type" on "info" and set "client_type" + const char *type = get_client_info(chan, "type"); + if (type == NULL || strequal(type, "remote")) { + chan->rpc.client_type = kClientTypeRemote; + } else if (strequal(type, "msgpack-rpc")) { + chan->rpc.client_type = kClientTypeMsgpackRpc; + } else if (strequal(type, "ui")) { + chan->rpc.client_type = kClientTypeUi; + } else if (strequal(type, "embedder")) { + chan->rpc.client_type = kClientTypeEmbedder; + } else if (strequal(type, "host")) { + chan->rpc.client_type = kClientTypeHost; + } else if (strequal(type, "plugin")) { + chan->rpc.client_type = kClientTypePlugin; + } else { + chan->rpc.client_type = kClientTypeUnknown; + } + channel_info_changed(chan, false); } @@ -646,14 +736,15 @@ Dictionary rpc_client_info(Channel *chan) return copy_dictionary(chan->rpc.info, NULL); } -const char *rpc_client_name(Channel *chan) +const char *get_client_info(Channel *chan, const char *key) + FUNC_ATTR_NONNULL_ALL { if (!chan->is_rpc) { return NULL; } Dictionary info = chan->rpc.info; for (size_t i = 0; i < info.size; i++) { - if (strequal("name", info.items[i].key.data) + if (strequal(key, info.items[i].key.data) && info.items[i].value.type == kObjectTypeString) { return info.items[i].value.data.string.data; } @@ -662,69 +753,11 @@ const char *rpc_client_name(Channel *chan) return NULL; } -#if MIN_LOG_LEVEL <= LOGLVL_DBG -# define REQ "[request] " -# define RES "[response] " -# define NOT "[notify] " -# define ERR "[error] " - -// Cannot define array with negative offsets, so this one is needed to be added -// to MSGPACK_UNPACK_\* values. -# define MUR_OFF 2 - -static const char *const msgpack_error_messages[] = { - [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found", - [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string", - [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error", - [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory", -}; - -static void log_server_msg(uint64_t channel_id, msgpack_sbuffer *packed) -{ - msgpack_unpacked unpacked; - msgpack_unpacked_init(&unpacked); - DLOGN("RPC ->ch %" PRIu64 ": ", channel_id); - const msgpack_unpack_return result = - msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL); - switch (result) { - case MSGPACK_UNPACK_SUCCESS: { - uint64_t type = unpacked.data.via.array.ptr[0].via.u64; - log_lock(); - FILE *f = open_log_file(); - fprintf(f, type ? (type == 1 ? RES : NOT) : REQ); - msgpack_object_print(f, unpacked.data); - log_close(f); - msgpack_unpacked_destroy(&unpacked); - break; - } - case MSGPACK_UNPACK_EXTRA_BYTES: - case MSGPACK_UNPACK_CONTINUE: - case MSGPACK_UNPACK_PARSE_ERROR: - case MSGPACK_UNPACK_NOMEM_ERROR: { - log_lock(); - FILE *f = open_log_file(); - fprintf(f, ERR); - fprintf(f, "%s", msgpack_error_messages[result + MUR_OFF]); - log_close(f); - break; - } - } -} - -static void log_client_msg(uint64_t channel_id, bool is_request, const char *name) +void rpc_free_all_mem(void) { - DLOGN("RPC <-ch %" PRIu64 ": ", channel_id); - log_lock(); - FILE *f = open_log_file(); - fprintf(f, "%s: %s", is_request ? REQ : RES, name); - log_close(f); -} - -static void log_close(FILE *f) -{ - fputc('\n', f); - fflush(f); - fclose(f); - log_unlock(); + cstr_t key; + set_foreach(&event_strings, key, { + xfree((void *)key); + }); + set_destroy(cstr_t, &event_strings); } -#endif diff --git a/src/nvim/msgpack_rpc/channel.h b/src/nvim/msgpack_rpc/channel.h index ce5806930c..818bee8318 100644 --- a/src/nvim/msgpack_rpc/channel.h +++ b/src/nvim/msgpack_rpc/channel.h @@ -1,25 +1,24 @@ -#ifndef NVIM_MSGPACK_RPC_CHANNEL_H -#define NVIM_MSGPACK_RPC_CHANNEL_H +#pragma once -#include <stdbool.h> -#include <uv.h> +#include <stdint.h> // IWYU pragma: keep -#include "nvim/api/private/defs.h" +#include "nvim/api/private/defs.h" // IWYU pragma: keep #include "nvim/channel.h" #include "nvim/event/multiqueue.h" #include "nvim/event/process.h" #include "nvim/event/socket.h" -#include "nvim/macros.h" -#include "nvim/vim.h" +#include "nvim/event/wstream.h" +#include "nvim/macros_defs.h" +#include "nvim/memory_defs.h" // IWYU pragma: keep +#include "nvim/msgpack_rpc/channel_defs.h" // IWYU pragma: export #define METHOD_MAXLEN 512 /// HACK: os/input.c drains this queue immediately before blocking for input. /// Events on this queue are async-safe, but they need the resolved state /// of os_inchar(), so they are processed "just-in-time". -EXTERN MultiQueue *ch_before_blocking_events INIT(= NULL); +EXTERN MultiQueue *ch_before_blocking_events INIT( = NULL); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/channel.h.generated.h" #endif -#endif // NVIM_MSGPACK_RPC_CHANNEL_H diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h index 404e68329a..20b8a89afb 100644 --- a/src/nvim/msgpack_rpc/channel_defs.h +++ b/src/nvim/msgpack_rpc/channel_defs.h @@ -1,19 +1,29 @@ -#ifndef NVIM_MSGPACK_RPC_CHANNEL_DEFS_H -#define NVIM_MSGPACK_RPC_CHANNEL_DEFS_H +#pragma once #include <msgpack.h> #include <stdbool.h> #include <uv.h> +#include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/event/process.h" #include "nvim/event/socket.h" -#include "nvim/vim.h" +#include "nvim/map_defs.h" typedef struct Channel Channel; typedef struct Unpacker Unpacker; +typedef enum { + kClientTypeUnknown = -1, + kClientTypeRemote = 0, + kClientTypeMsgpackRpc = 5, + kClientTypeUi = 1, + kClientTypeEmbedder = 2, + kClientTypeHost = 3, + kClientTypePlugin = 4, +} ClientType; + typedef struct { uint32_t request_id; bool returned, errored; @@ -31,12 +41,11 @@ typedef struct { } RequestEvent; typedef struct { - PMap(cstr_t) subscribed_events[1]; + Set(cstr_t) subscribed_events[1]; bool closed; Unpacker *unpacker; uint32_t next_request_id; kvec_t(ChannelCallFrame *) call_stack; Dictionary info; + ClientType client_type; } RpcState; - -#endif // NVIM_MSGPACK_RPC_CHANNEL_DEFS_H diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 5f0f03dd69..1fdfc9e536 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <msgpack/object.h> #include <msgpack/sbuffer.h> #include <msgpack/unpack.h> @@ -12,14 +9,13 @@ #include "klib/kvec.h" #include "msgpack/pack.h" #include "nvim/api/private/helpers.h" -#include "nvim/assert.h" -#include "nvim/event/wstream.h" +#include "nvim/assert_defs.h" +#include "nvim/func_attr.h" #include "nvim/memory.h" #include "nvim/msgpack_rpc/helpers.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "keysets.generated.h" // IWYU pragma: export # include "msgpack_rpc/helpers.c.generated.h" #endif @@ -84,12 +80,8 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) *cur.aobj = INTEGER_OBJ((Integer)cur.mobj->via.u64); } break; -#ifdef NVIM_MSGPACK_HAS_FLOAT32 case MSGPACK_OBJECT_FLOAT32: case MSGPACK_OBJECT_FLOAT64: -#else - case MSGPACK_OBJECT_FLOAT: -#endif { STATIC_ASSERT(sizeof(Float) == sizeof(cur.mobj->via.f64), "Msgpack floating-point size does not match API integer"); @@ -156,12 +148,8 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) case MSGPACK_OBJECT_BOOLEAN: case MSGPACK_OBJECT_POSITIVE_INTEGER: case MSGPACK_OBJECT_NEGATIVE_INTEGER: -#ifdef NVIM_MSGPACK_HAS_FLOAT32 case MSGPACK_OBJECT_FLOAT32: case MSGPACK_OBJECT_FLOAT64: -#else - case MSGPACK_OBJECT_FLOAT: -#endif case MSGPACK_OBJECT_EXT: case MSGPACK_OBJECT_MAP: case MSGPACK_OBJECT_ARRAY: @@ -484,8 +472,8 @@ msgpack_object *msgpack_rpc_method(msgpack_object *req) { msgpack_object *obj = req->via.array.ptr + (msgpack_rpc_is_notification(req) ? 1 : 2); - return obj->type == MSGPACK_OBJECT_STR || obj->type == MSGPACK_OBJECT_BIN ? - obj : NULL; + return obj->type == MSGPACK_OBJECT_STR || obj->type == MSGPACK_OBJECT_BIN + ? obj : NULL; } msgpack_object *msgpack_rpc_args(msgpack_object *req) diff --git a/src/nvim/msgpack_rpc/helpers.h b/src/nvim/msgpack_rpc/helpers.h index dab8a16b6b..dd2096f305 100644 --- a/src/nvim/msgpack_rpc/helpers.h +++ b/src/nvim/msgpack_rpc/helpers.h @@ -1,5 +1,4 @@ -#ifndef NVIM_MSGPACK_RPC_HELPERS_H -#define NVIM_MSGPACK_RPC_HELPERS_H +#pragma once #include <msgpack.h> #include <stdbool.h> @@ -19,5 +18,3 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/helpers.h.generated.h" #endif - -#endif // NVIM_MSGPACK_RPC_HELPERS_H diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 1d75c208be..f3627eaa61 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <inttypes.h> #include <stdbool.h> #include <stdio.h> @@ -10,6 +7,7 @@ #include "nvim/channel.h" #include "nvim/eval.h" #include "nvim/event/socket.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/log.h" #include "nvim/main.h" @@ -71,8 +69,8 @@ static void close_socket_watcher(SocketWatcher **watcher) static void set_vservername(garray_T *srvs) { char *default_server = (srvs->ga_len > 0) - ? ((SocketWatcher **)srvs->ga_data)[0]->addr - : NULL; + ? ((SocketWatcher **)srvs->ga_data)[0]->addr + : NULL; set_vim_var_string(VV_SEND_SERVER, default_server, -1); } @@ -91,13 +89,14 @@ char *server_address_new(const char *name) { static uint32_t count = 0; char fmt[ADDRESS_MAX_SIZE]; + const char *appname = get_appname(); #ifdef MSWIN int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32, - name ? name : "nvim", os_get_pid(), count++); + name ? name : appname, os_get_pid(), count++); #else char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir); int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32, - dir, name ? name : "nvim", os_get_pid(), count++); + dir, name ? name : appname, os_get_pid(), count++); xfree(dir); #endif if ((size_t)r >= sizeof(fmt)) { diff --git a/src/nvim/msgpack_rpc/server.h b/src/nvim/msgpack_rpc/server.h index 5446e40e0b..71b578a14b 100644 --- a/src/nvim/msgpack_rpc/server.h +++ b/src/nvim/msgpack_rpc/server.h @@ -1,9 +1,7 @@ -#ifndef NVIM_MSGPACK_RPC_SERVER_H -#define NVIM_MSGPACK_RPC_SERVER_H +#pragma once -#include <stdio.h> +#include <stddef.h> // IWYU pragma: keep #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/server.h.generated.h" #endif -#endif // NVIM_MSGPACK_RPC_SERVER_H diff --git a/src/nvim/msgpack_rpc/unpacker.c b/src/nvim/msgpack_rpc/unpacker.c index 44a16beb48..38263381bf 100644 --- a/src/nvim/msgpack_rpc/unpacker.c +++ b/src/nvim/msgpack_rpc/unpacker.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <assert.h> #include <stdbool.h> #include <stdlib.h> @@ -8,8 +5,9 @@ #include "klib/kvec.h" #include "mpack/conv.h" #include "nvim/api/private/helpers.h" -#include "nvim/ascii.h" -#include "nvim/macros.h" +#include "nvim/ascii_defs.h" +#include "nvim/grid.h" +#include "nvim/macros_defs.h" #include "nvim/memory.h" #include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/msgpack_rpc/helpers.h" @@ -87,7 +85,7 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node) *result = NIL; break; case MPACK_TOKEN_BOOLEAN: - *result = BOOL(mpack_unpack_boolean(node->tok)); + *result = BOOLEAN_OBJ(mpack_unpack_boolean(node->tok)); break; case MPACK_TOKEN_SINT: *result = INTEGER_OBJ(mpack_unpack_sint(node->tok)); @@ -172,14 +170,12 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node) node->data[0].p = result; break; } - - default: - abort(); } } static void api_parse_exit(mpack_parser_t *parser, mpack_node_t *node) -{} +{ +} void unpacker_init(Unpacker *p) { @@ -292,13 +288,13 @@ error: // objects. For the moment "redraw/grid_line" uses a hand-rolled decoder, // to avoid a blizzard of small objects for each screen cell. // -// <0>[2, "redraw", <10>[{11}["method", <12>[args], <12>[args], ...], <11>[...], ...]] +// <0>[2, "redraw", <10>[<11>["method", <12>[args], <12>[args], ...], <11>[...], ...]] // // Where [args] gets unpacked as an Array. Note: first {11} is not saved as a state. // // When method is "grid_line", we furthermore decode a cell at a time like: // -// <0>[2, "redraw", <10>[{11}["grid_line", <14>[g, r, c, [<15>[cell], <15>[cell], ...]], ...], <11>[...], ...]] +// <0>[2, "redraw", <10>[<11>["grid_line", <14>[g, r, c, [<15>[cell], <15>[cell], ...], <16>wrap]], <11>[...], ...]] // // where [cell] is [char, repeat, attr], where 'repeat' and 'attr' is optional @@ -323,7 +319,7 @@ bool unpacker_advance(Unpacker *p) return false; } - if (p->state == 15) { + if (p->state == 16) { // grid_line event already unpacked goto done; } else { @@ -358,10 +354,10 @@ done: p->state = 0; return true; case 13: - case 15: + case 16: p->ncalls--; if (p->ncalls > 0) { - p->state = (p->state == 15) ? 14 : 12; + p->state = (p->state == 16) ? 14 : 12; } else if (p->nevents > 0) { p->state = 11; } else { @@ -382,7 +378,6 @@ bool unpacker_parse_redraw(Unpacker *p) size_t size = p->read_size; GridLineEvent *g = p->grid_line_event; -// -V:NEXT_TYPE:501 #define NEXT_TYPE(tok, typ) \ result = mpack_rtoken(&data, &size, &tok); \ if (result == MPACK_EOF) { \ @@ -394,7 +389,6 @@ bool unpacker_parse_redraw(Unpacker *p) return false; \ } -redo: switch (p->state) { case 10: NEXT_TYPE(tok, MPACK_TOKEN_ARRAY); @@ -440,7 +434,7 @@ redo: case 14: NEXT_TYPE(tok, MPACK_TOKEN_ARRAY); int eventarrsize = (int)tok.length; - if (eventarrsize != 4) { + if (eventarrsize != 5) { p->state = -1; return false; } @@ -462,58 +456,64 @@ redo: FALLTHROUGH; case 15: - assert(g->icell < g->ncells); - - NEXT_TYPE(tok, MPACK_TOKEN_ARRAY); - int cellarrsize = (int)tok.length; - if (cellarrsize < 1 || cellarrsize > 3) { - p->state = -1; - return false; - } + for (; g->icell != g->ncells; g->icell++) { + assert(g->icell < g->ncells); + + NEXT_TYPE(tok, MPACK_TOKEN_ARRAY); + int cellarrsize = (int)tok.length; + if (cellarrsize < 1 || cellarrsize > 3) { + p->state = -1; + return false; + } - NEXT_TYPE(tok, MPACK_TOKEN_STR); - if (tok.length > size) { - return false; - } + NEXT_TYPE(tok, MPACK_TOKEN_STR); + if (tok.length > size) { + return false; + } - const char *cellbuf = data; - size_t cellsize = tok.length; - data += cellsize; - size -= cellsize; + const char *cellbuf = data; + size_t cellsize = tok.length; + data += cellsize; + size -= cellsize; - if (cellarrsize >= 2) { - NEXT_TYPE(tok, MPACK_TOKEN_SINT); - g->cur_attr = (int)tok.data.value.lo; - } + if (cellarrsize >= 2) { + NEXT_TYPE(tok, MPACK_TOKEN_SINT); + g->cur_attr = (int)tok.data.value.lo; + } - int repeat = 1; - if (cellarrsize >= 3) { - NEXT_TYPE(tok, MPACK_TOKEN_UINT); - repeat = (int)tok.data.value.lo; - } + int repeat = 1; + if (cellarrsize >= 3) { + NEXT_TYPE(tok, MPACK_TOKEN_UINT); + repeat = (int)tok.data.value.lo; + } - g->clear_width = 0; - if (g->icell == g->ncells - 1 && cellsize == 1 && cellbuf[0] == ' ' && repeat > 1) { - g->clear_width = repeat; - } else { - for (int r = 0; r < repeat; r++) { - if (g->coloff >= (int)grid_line_buf_size) { - p->state = -1; - return false; + g->clear_width = 0; + if (g->icell == g->ncells - 1 && cellsize == 1 && cellbuf[0] == ' ' && repeat > 1) { + g->clear_width = repeat; + } else { + schar_T sc = schar_from_buf(cellbuf, cellsize); + for (int r = 0; r < repeat; r++) { + if (g->coloff >= (int)grid_line_buf_size) { + p->state = -1; + return false; + } + grid_line_buf_char[g->coloff] = sc; + grid_line_buf_attr[g->coloff++] = g->cur_attr; } - memcpy(grid_line_buf_char[g->coloff], cellbuf, cellsize); - grid_line_buf_char[g->coloff][cellsize] = NUL; - grid_line_buf_attr[g->coloff++] = g->cur_attr; } + + p->read_ptr = data; + p->read_size = size; } + p->state = 16; + FALLTHROUGH; - g->icell++; + case 16: + NEXT_TYPE(tok, MPACK_TOKEN_BOOLEAN); + g->wrap = mpack_unpack_boolean(tok); p->read_ptr = data; p->read_size = size; - if (g->icell == g->ncells) { - return true; - } - goto redo; + return true; case 12: return true; diff --git a/src/nvim/msgpack_rpc/unpacker.h b/src/nvim/msgpack_rpc/unpacker.h index b8b2d38d3b..53af29761e 100644 --- a/src/nvim/msgpack_rpc/unpacker.h +++ b/src/nvim/msgpack_rpc/unpacker.h @@ -1,5 +1,4 @@ -#ifndef NVIM_MSGPACK_RPC_UNPACKER_H -#define NVIM_MSGPACK_RPC_UNPACKER_H +#pragma once #include <inttypes.h> #include <stdbool.h> @@ -11,9 +10,9 @@ #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/grid_defs.h" -#include "nvim/memory.h" +#include "nvim/memory_defs.h" #include "nvim/msgpack_rpc/channel_defs.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/ui_client.h" struct Unpacker { @@ -49,5 +48,3 @@ struct Unpacker { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/unpacker.h.generated.h" #endif - -#endif // NVIM_MSGPACK_RPC_UNPACKER_H |