diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-30 20:35:25 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-30 20:35:25 +0000 |
commit | 1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch) | |
tree | cd08258054db80bb9a11b1061bb091c70b76926a /src/nvim/channel.c | |
parent | eaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff) | |
parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
download | rneovim-aucmd_textputpost.tar.gz rneovim-aucmd_textputpost.tar.bz2 rneovim-aucmd_textputpost.zip |
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'src/nvim/channel.c')
-rw-r--r-- | src/nvim/channel.c | 110 |
1 files changed, 58 insertions, 52 deletions
diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 65bb87bc2c..e8fe80a3b6 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -1,13 +1,11 @@ -// 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 <lauxlib.h> #include <stddef.h> #include <stdio.h> #include <string.h> -#include "lauxlib.h" +#include "klib/kvec.h" #include "nvim/api/private/converter.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" @@ -17,10 +15,10 @@ #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" -#include "nvim/event/loop.h" #include "nvim/event/rstream.h" #include "nvim/event/socket.h" #include "nvim/event/wstream.h" +#include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/log.h" @@ -32,12 +30,14 @@ #include "nvim/msgpack_rpc/server.h" #include "nvim/os/os_defs.h" #include "nvim/os/shell.h" +#include "nvim/path.h" #include "nvim/rbuffer.h" + #ifdef MSWIN +# include "nvim/os/fs.h" # include "nvim/os/os_win_console.h" # include "nvim/os/pty_conpty_win.h" #endif -#include "nvim/path.h" static bool did_stdio = false; @@ -79,7 +79,7 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error) // allow double close, even though we can't say what parts was valid. return true; } - *error = (const char *)e_invchan; + *error = e_invchan; return false; } @@ -89,19 +89,19 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error) if (chan->is_rpc) { rpc_close(chan); } else if (part == kChannelPartRpc) { - *error = (const char *)e_invstream; + *error = e_invstream; return false; } } else if ((part == kChannelPartStdin || part == kChannelPartStdout) && chan->is_rpc) { - *error = (const char *)e_invstreamrpc; + *error = e_invstreamrpc; return false; } switch (chan->streamtype) { case kChannelStreamSocket: if (!close_main) { - *error = (const char *)e_invstream; + *error = e_invstream; return false; } stream_may_close(&chan->stream.socket); @@ -132,14 +132,14 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error) stream_may_close(&chan->stream.stdio.out); } if (part == kChannelPartStderr) { - *error = (const char *)e_invstream; + *error = e_invstream; return false; } break; case kChannelStreamStderr: if (part != kChannelPartAll && part != kChannelPartStderr) { - *error = (const char *)e_invstream; + *error = e_invstream; return false; } if (!chan->stream.err.closed) { @@ -154,7 +154,7 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error) case kChannelStreamInternal: if (!close_main) { - *error = (const char *)e_invstream; + *error = e_invstream; return false; } if (chan->term) { @@ -166,9 +166,6 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error) channel_decref(chan); } break; - - default: - abort(); } return true; @@ -207,7 +204,7 @@ Channel *channel_alloc(ChannelStreamType type) void channel_create_event(Channel *chan, const char *ext_source) { -#if MIN_LOG_LEVEL <= LOGLVL_INF +#ifdef NVIM_LOG_DEBUG const char *source; if (ext_source) { @@ -216,7 +213,7 @@ void channel_create_event(Channel *chan, const char *ext_source) source = ext_source; } else { eval_fmt_source_name_line(IObuff, sizeof(IObuff)); - source = (const char *)IObuff; + source = IObuff; } assert(chan->id <= VARNUMBER_MAX); @@ -225,6 +222,7 @@ void channel_create_event(Channel *chan, const char *ext_source) // TODO(bfredl): do the conversion in one step. Also would be nice // to pretty print top level dict in defined order (void)object_to_vim(DICTIONARY_OBJ(info), &tv, NULL); + assert(tv.v_type == VAR_DICT); char *str = encode_tv2json(&tv, NULL); ILOG("new channel %" PRIu64 " (%s) : %s", chan->id, source, str); xfree(str); @@ -277,7 +275,7 @@ static void free_channel_event(void **argv) callback_reader_free(&chan->on_stderr); callback_free(&chan->on_exit); - pmap_del(uint64_t)(&channels, chan->id); + pmap_del(uint64_t)(&channels, chan->id, NULL); multiqueue_free(chan->events); xfree(chan); } @@ -287,7 +285,7 @@ static void channel_destroy_early(Channel *chan) if ((chan->id != --next_chan_id)) { abort(); } - pmap_del(uint64_t)(&channels, chan->id); + pmap_del(uint64_t)(&channels, chan->id, NULL); chan->id = 0; if ((--chan->refcount != 0)) { @@ -307,6 +305,7 @@ static void close_cb(Stream *stream, void *data) /// /// @param[in] argv Arguments vector specifying the command to run, /// NULL-terminated +/// @param[in] exepath The path to the executable. If NULL, use `argv[0]`. /// @param[in] on_stdout Callback to read the job's stdout /// @param[in] on_stderr Callback to read the job's stderr /// @param[in] on_exit Callback to receive the job's exit status @@ -328,10 +327,11 @@ static void close_cb(Stream *stream, void *data) /// < 0 if the job can't start /// /// @returns [allocated] channel -Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader on_stderr, - Callback on_exit, bool pty, bool rpc, bool overlapped, bool detach, - ChannelStdinMode stdin_mode, const char *cwd, uint16_t pty_width, - uint16_t pty_height, dict_T *env, varnumber_T *status_out) +Channel *channel_job_start(char **argv, const char *exepath, CallbackReader on_stdout, + CallbackReader on_stderr, Callback on_exit, bool pty, bool rpc, + bool overlapped, bool detach, ChannelStdinMode stdin_mode, + const char *cwd, uint16_t pty_width, uint16_t pty_height, dict_T *env, + varnumber_T *status_out) { Channel *chan = channel_alloc(kChannelStreamProc); chan->on_data = on_stdout; @@ -362,6 +362,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader Process *proc = &chan->stream.proc; proc->argv = argv; + proc->exepath = exepath; proc->cb = channel_process_exit_cb; proc->events = chan->events; proc->detach = detach; @@ -369,8 +370,8 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader proc->env = env; proc->overlapped = overlapped; - char *cmd = xstrdup(proc->argv[0]); - bool has_in, has_out, has_err; + char *cmd = xstrdup(process_get_exepath(proc)); + bool has_out, has_err; if (proc->type == kProcessTypePty) { has_out = true; has_err = false; @@ -380,14 +381,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader proc->fwd_err = chan->on_stderr.fwd_err; } - switch (stdin_mode) { - case kChannelStdinPipe: - has_in = true; - break; - case kChannelStdinNull: - has_in = false; - break; - } + bool has_in = stdin_mode == kChannelStdinPipe; int status = process_spawn(proc, has_in, has_out, has_err); if (status) { @@ -790,10 +784,9 @@ void channel_terminal_open(buf_T *buf, Channel *chan) topts.write_cb = term_write; topts.resize_cb = term_resize; topts.close_cb = term_close; - buf->b_p_channel = (long)chan->id; // 'channel' option - Terminal *term = terminal_open(buf, topts); - chan->term = term; + buf->b_p_channel = (OptInt)chan->id; // 'channel' option channel_incref(chan); + terminal_open(&chan->term, buf, topts); } static void term_write(char *buf, size_t size, void *data) @@ -836,13 +829,12 @@ static void term_close(void *data) multiqueue_put(chan->events, term_delayed_free, 1, data); } -void channel_info_changed(Channel *chan, bool new) +void channel_info_changed(Channel *chan, bool new_chan) { - event_T event = new ? EVENT_CHANOPEN : EVENT_CHANINFO; + event_T event = new_chan ? EVENT_CHANOPEN : EVENT_CHANINFO; if (has_event(event)) { channel_incref(chan); - multiqueue_put(main_loop.events, set_info_event, - 2, chan, event); + multiqueue_put(main_loop.events, set_info_event, 2, chan, event); } } @@ -856,6 +848,7 @@ static void set_info_event(void **argv) Dictionary info = channel_info(chan->id); typval_T retval; (void)object_to_vim(DICTIONARY_OBJ(info), &retval, NULL); + assert(retval.v_type == VAR_DICT); tv_dict_add_dict(dict, S_LEN("info"), retval.vval.v_dict); tv_dict_set_keys_readonly(dict); @@ -890,14 +883,14 @@ Dictionary channel_info(uint64_t id) stream_desc = "job"; if (chan->stream.proc.type == kProcessTypePty) { const char *name = pty_process_tty_name(&chan->stream.pty); - PUT(info, "pty", STRING_OBJ(cstr_to_string(name))); + PUT(info, "pty", CSTR_TO_OBJ(name)); } char **p = chan->stream.proc.argv; Array argv = ARRAY_DICT_INIT; if (p != NULL) { while (*p != NULL) { - ADD(argv, STRING_OBJ(cstr_to_string(*p))); + ADD(argv, CSTR_TO_OBJ(*p)); p++; } } @@ -920,11 +913,8 @@ Dictionary channel_info(uint64_t id) case kChannelStreamSocket: stream_desc = "socket"; break; - - default: - abort(); } - PUT(info, "stream", STRING_OBJ(cstr_to_string(stream_desc))); + PUT(info, "stream", CSTR_TO_OBJ(stream_desc)); if (chan->is_rpc) { mode_desc = "rpc"; @@ -935,17 +925,33 @@ Dictionary channel_info(uint64_t id) } else { mode_desc = "bytes"; } - PUT(info, "mode", STRING_OBJ(cstr_to_string(mode_desc))); + PUT(info, "mode", CSTR_TO_OBJ(mode_desc)); return info; } +/// Simple int64_t comparison function for use with qsort() +static int int64_t_cmp(const void *a, const void *b) +{ + int64_t diff = *(int64_t *)a - *(int64_t *)b; + return (diff < 0) ? -1 : (diff > 0); +} + Array channel_all_info(void) { - Channel *channel; - Array ret = ARRAY_DICT_INIT; - map_foreach_value(&channels, channel, { - ADD(ret, DICTIONARY_OBJ(channel_info(channel->id))); + // order the items in the array by channel number, for Determinismâ„¢ + kvec_t(int64_t) ids = KV_INITIAL_VALUE; + kv_resize(ids, map_size(&channels)); + uint64_t id; + map_foreach_key(&channels, id, { + kv_push(ids, (int64_t)id); }); + qsort(ids.items, ids.size, sizeof ids.items[0], int64_t_cmp); + + Array ret = ARRAY_DICT_INIT; + for (size_t i = 0; i < ids.size; i++) { + ADD(ret, DICTIONARY_OBJ(channel_info((uint64_t)ids.items[i]))); + } + kv_destroy(ids); return ret; } |