aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/CMakeLists.txt5
-rw-r--r--src/nvim/eval.c15
-rw-r--r--src/nvim/eval_defs.h2
-rw-r--r--src/nvim/ex_cmds.c92
-rw-r--r--src/nvim/msgpack_rpc/channel.c51
-rw-r--r--src/nvim/option.c3
-rw-r--r--src/nvim/os/env.c17
-rw-r--r--src/nvim/os/wstream.c6
-rw-r--r--src/nvim/terminal.c2
-rw-r--r--src/nvim/version.c4
10 files changed, 102 insertions, 95 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 92fbc0c8c9..47782e8b6b 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -106,7 +106,9 @@ foreach(gen_include ${gen_includes})
list(APPEND gen_cflags "-I${gen_include}")
endforeach()
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
-set(gen_cflags "${gen_cflags} ${CMAKE_C_FLAGS_${build_type}} ${CMAKE_C_FLAGS}")
+separate_arguments(C_FLAGS_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS})
+separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${build_type}})
+set(gen_cflags ${gen_cflags} ${C_FLAGS_${build_type}_ARRAY} ${C_FLAGS_ARRAY})
foreach(sfile ${NEOVIM_SOURCES}
"${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c")
@@ -121,7 +123,6 @@ foreach(sfile ${NEOVIM_SOURCES}
set(gf1 "${GENERATED_DIR}/${r}.c.generated.h")
set(gf2 "${GENERATED_INCLUDES_DIR}/${r}.h.generated.h")
set(gf3 "${GENERATED_DIR}/${r}.i")
- separate_arguments(C_FLAGS_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS})
add_custom_command(
OUTPUT "${gf1}" "${gf2}"
COMMAND ${CMAKE_C_COMPILER} ${sfile} -o ${gf3} ${gen_cflags} -E ${C_FLAGS_ARRAY}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 9d8421ef04..4ab31985b5 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -5560,8 +5560,10 @@ static int free_unref_items(int copyID)
bool did_free = false;
// Go through the list of dicts and free items without the copyID.
+ // Don't free dicts that are referenced internally.
for (dict_T *dd = first_dict; dd != NULL; ) {
- if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) {
+ if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
+ && !dd->internal_refcount) {
// Free the Dictionary and ordinary items it contains, but don't
// recurse into Lists and Dictionaries, they will be in the list
// of dicts or list of lists. */
@@ -5671,6 +5673,7 @@ dict_T *dict_alloc(void) FUNC_ATTR_NONNULL_RET
d->dv_scope = 0;
d->dv_refcount = 0;
d->dv_copyID = 0;
+ d->internal_refcount = 0;
return d;
}
@@ -10969,6 +10972,9 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
}
}
+ // poll to ensure any pending callbacks from the last job are invoked
+ event_poll(0);
+
for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) {
Job *job = NULL;
if (arg->li_tv.v_type != VAR_NUMBER
@@ -20064,6 +20070,7 @@ static inline void common_job_callbacks(dict_T *vopts, ufunc_T **on_stdout,
return;
}
+ vopts->internal_refcount++;
vopts->dv_refcount++;
}
@@ -20097,7 +20104,11 @@ static inline void free_term_job_data(TerminalJobData *data) {
if (data->on_exit) {
user_func_unref(data->on_exit);
}
- dict_unref(data->self);
+
+ if (data->self) {
+ data->self->internal_refcount--;
+ dict_unref(data->self);
+ }
free(data);
}
diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h
index d2de830d6c..34a36004d6 100644
--- a/src/nvim/eval_defs.h
+++ b/src/nvim/eval_defs.h
@@ -111,6 +111,8 @@ struct dictvar_S {
dict_T *dv_copydict; /* copied dict used by deepcopy() */
dict_T *dv_used_next; /* next dict in used dicts list */
dict_T *dv_used_prev; /* previous dict in used dicts list */
+ int internal_refcount; // number of internal references to
+ // prevent garbage collection
};
#endif // NVIM_EVAL_DEFS_H
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index e687eab3c4..c686c5effa 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -2790,51 +2790,13 @@ do_ecmd (
oldbuf = (flags & ECMD_OLDBUF);
}
+ buf = curbuf;
if ((flags & ECMD_SET_HELP) || keep_help_flag) {
- char_u *p;
-
- curbuf->b_help = true;
- set_string_option_direct((char_u *)"buftype", -1,
- (char_u *)"help", OPT_FREE|OPT_LOCAL, 0);
-
- /*
- * Always set these options after jumping to a help tag, because the
- * user may have an autocommand that gets in the way.
- * Accept all ASCII chars for keywords, except ' ', '*', '"', '|', and
- * latin1 word characters (for translated help files).
- * Only set it when needed, buf_init_chartab() is some work.
- */
- p =
- (char_u *)"!-~,^*,^|,^\",192-255";
- if (STRCMP(curbuf->b_p_isk, p) != 0) {
- set_string_option_direct((char_u *)"isk", -1, p,
- OPT_FREE|OPT_LOCAL, 0);
- check_buf_options(curbuf);
- (void)buf_init_chartab(curbuf, FALSE);
- }
-
- curbuf->b_p_ts = 8; /* 'tabstop' is 8 */
- curwin->w_p_list = FALSE; /* no list mode */
-
- curbuf->b_p_ma = FALSE; /* not modifiable */
- curbuf->b_p_bin = FALSE; /* reset 'bin' before reading file */
- curwin->w_p_nu = 0; /* no line numbers */
- curwin->w_p_rnu = 0; /* no relative line numbers */
- RESET_BINDING(curwin); /* no scroll or cursor binding */
- curwin->w_p_arab = FALSE; /* no arabic mode */
- curwin->w_p_rl = FALSE; /* help window is left-to-right */
- curwin->w_p_fen = FALSE; /* No folding in the help window */
- curwin->w_p_diff = FALSE; /* No 'diff' */
- curwin->w_p_spell = FALSE; /* No spell checking */
-
- buf = curbuf;
- set_buflisted(FALSE);
- } else {
- buf = curbuf;
- /* Don't make a buffer listed if it's a help buffer. Useful when
- * using CTRL-O to go back to a help file. */
- if (!curbuf->b_help)
- set_buflisted(TRUE);
+ prepare_help_buffer();
+ } else if (!curbuf->b_help) {
+ // Don't make a buffer listed if it's a help buffer. Useful when using
+ // CTRL-O to go back to a help file.
+ set_buflisted(TRUE);
}
/* If autocommands change buffers under our fingers, forget about
@@ -5046,6 +5008,46 @@ int find_help_tags(char_u *arg, int *num_matches, char_u ***matches, int keep_la
return OK;
}
+/// Called when starting to edit a buffer for a help file.
+static void prepare_help_buffer(void)
+{
+ curbuf->b_help = true;
+ set_string_option_direct((char_u *)"buftype", -1, (char_u *)"help",
+ OPT_FREE|OPT_LOCAL, 0);
+
+ // Always set these options after jumping to a help tag, because the
+ // user may have an autocommand that gets in the way.
+ // Accept all ASCII chars for keywords, except ' ', '*', '"', '|', and
+ // latin1 word characters (for translated help files).
+ // Only set it when needed, buf_init_chartab() is some work.
+ char_u *p = (char_u *)"!-~,^*,^|,^\",192-255";
+ if (STRCMP(curbuf->b_p_isk, p) != 0) {
+ set_string_option_direct((char_u *)"isk", -1, p, OPT_FREE|OPT_LOCAL, 0);
+ check_buf_options(curbuf);
+ (void)buf_init_chartab(curbuf, FALSE);
+ }
+
+ // Don't use the global foldmethod.
+ set_string_option_direct((char_u *)"fdm", -1, (char_u *)"manual",
+ OPT_FREE|OPT_LOCAL, 0);
+
+ curbuf->b_p_ts = 8; // 'tabstop' is 8.
+ curwin->w_p_list = FALSE; // No list mode.
+
+ curbuf->b_p_ma = FALSE; // Not modifiable.
+ curbuf->b_p_bin = FALSE; // Reset 'bin' before reading file.
+ curwin->w_p_nu = 0; // No line numbers.
+ curwin->w_p_rnu = 0; // No relative line numbers.
+ RESET_BINDING(curwin); // No scroll or cursor binding.
+ curwin->w_p_arab = FALSE; // No arabic mode.
+ curwin->w_p_rl = FALSE; // Help window is left-to-right.
+ curwin->w_p_fen = FALSE; // No folding in the help window.
+ curwin->w_p_diff = FALSE; // No 'diff'.
+ curwin->w_p_spell = FALSE; // No spell checking.
+
+ set_buflisted(FALSE);
+}
+
/*
* After reading a help file: May cleanup a help buffer when syntax
* highlighting is not used.
@@ -6316,5 +6318,3 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
}
}
}
-
-// vim: tabstop=8
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index b1f0798528..35549ce042 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -59,6 +59,7 @@ typedef struct {
} data;
uint64_t next_request_id;
kvec_t(ChannelCallFrame *) call_stack;
+ kvec_t(WBuffer *) delayed_notifications;
} Channel;
typedef struct {
@@ -68,18 +69,10 @@ typedef struct {
uint64_t request_id;
} RequestEvent;
-typedef struct {
- Channel *channel;
- String method;
- Array args;
-} DelayedNotification;
-
#define _noop(x)
KMEMPOOL_INIT(RequestEventPool, RequestEvent, _noop)
-KLIST_INIT(DelayedNotification, DelayedNotification, _noop)
-
static kmempool_t(RequestEventPool) *request_event_pool = NULL;
-static klist_t(DelayedNotification) *delayed_notifications = NULL;
+
static uint64_t next_id = 1;
static PMap(uint64_t) *channels = NULL;
static PMap(cstr_t) *event_strings = NULL;
@@ -93,7 +86,6 @@ static msgpack_sbuffer out_buffer;
void channel_init(void)
{
request_event_pool = kmp_init(RequestEventPool);
- delayed_notifications = kl_init(DelayedNotification);
channels = pmap_new(uint64_t)();
event_strings = pmap_new(cstr_t)();
msgpack_sbuffer_init(&out_buffer);
@@ -191,13 +183,10 @@ bool channel_send_event(uint64_t id, char *name, Array args)
if (channel) {
if (channel->pending_requests) {
- DelayedNotification p = {
- .channel = channel,
- .method = cstr_to_string(name),
- .args = args
- };
- // Pending request, queue the notification for sending later
- *kl_pushp(DelayedNotification, delayed_notifications) = p;
+ // 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);
} else {
send_event(channel, name, args);
}
@@ -248,7 +237,7 @@ Object channel_send_call(uint64_t id,
}
if (!channel->pending_requests) {
- send_delayed_notifications();
+ send_delayed_notifications(channel);
}
decref(channel);
@@ -506,6 +495,7 @@ static bool channel_write(Channel *channel, WBuffer *buffer)
bool success;
if (channel->closed) {
+ wstream_release_wbuffer(buffer);
return false;
}
@@ -593,7 +583,12 @@ static void broadcast_event(char *name, Array args)
kv_size(subscribed));
for (size_t i = 0; i < kv_size(subscribed); i++) {
- channel_write(kv_A(subscribed, i), buffer);
+ Channel *channel = kv_A(subscribed, i);
+ if (channel->pending_requests) {
+ kv_push(WBuffer *, channel->delayed_notifications, buffer);
+ } else {
+ channel_write(channel, buffer);
+ }
}
end:
@@ -666,6 +661,7 @@ static void free_channel(Channel *channel)
pmap_free(cstr_t)(channel->subscribed_events);
kv_destroy(channel->call_stack);
+ kv_destroy(channel->delayed_notifications);
free(channel);
}
@@ -686,6 +682,7 @@ static Channel *register_channel(void)
rv->subscribed_events = pmap_new(cstr_t)();
rv->next_request_id = 1;
kv_init(rv->call_stack);
+ kv_init(rv->delayed_notifications);
pmap_put(uint64_t)(channels, rv->id, rv);
return rv;
}
@@ -773,18 +770,14 @@ static WBuffer *serialize_response(uint64_t channel_id,
return rv;
}
-static void send_delayed_notifications(void)
+static void send_delayed_notifications(Channel* channel)
{
- DelayedNotification p;
-
- while (kl_shift(DelayedNotification, delayed_notifications, &p) == 0) {
- if (p.channel) {
- send_event(p.channel, p.method.data, p.args);
- } else {
- broadcast_event(p.method.data, p.args);
- }
- free(p.method.data);
+ for (size_t i = 0; i < kv_size(channel->delayed_notifications); i++) {
+ WBuffer *buffer = kv_A(channel->delayed_notifications, i);
+ channel_write(channel, buffer);
}
+
+ kv_size(channel->delayed_notifications) = 0;
}
static void incref(Channel *channel)
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 4f955fee4e..2d016d8350 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -5354,6 +5354,9 @@ set_num_option (
if (p_hi < 0) {
errmsg = e_positive;
p_hi = 0;
+ } else if (p_hi > 10000) {
+ errmsg = e_invarg;
+ p_hi = 10000;
}
if (p_re < 0 || p_re > 2) {
errmsg = e_invarg;
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 3bea2908d5..30e44341a9 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -243,19 +243,16 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
// Verify that we have found the end of a UNIX ${VAR} style variable
if (src[1] == '{' && *tail != '}') {
var = NULL;
- } else if (src[1] == '{') {
- ++tail;
- }
-#elif defined(MSWIN)
- // Verify that we have found the end of a Windows %VAR% style variable
- if (src[0] == '%' && *tail != '%') {
- var = NULL;
- } else if (src[0] == '%') {
- ++tail;
- }
+ } else {
+ if (src[1] == '{') {
+ ++tail;
+ }
#endif
*var = NUL;
var = vim_getenv(dst, &mustfree);
+#if defined(UNIX)
+ }
+#endif
} else if ( src[1] == NUL /* home directory */
|| vim_ispathsep(src[1])
|| vim_strchr((char_u *)" ,\t\n", src[1]) != NULL) {
diff --git a/src/nvim/os/wstream.c b/src/nvim/os/wstream.c
index 90d4ebeec8..13c6c0429f 100644
--- a/src/nvim/os/wstream.c
+++ b/src/nvim/os/wstream.c
@@ -181,7 +181,7 @@ bool wstream_write(WStream *wstream, WBuffer *buffer)
return true;
err:
- release_wbuffer(buffer);
+ wstream_release_wbuffer(buffer);
return false;
}
@@ -217,7 +217,7 @@ static void write_cb(uv_write_t *req, int status)
data->wstream->curmem -= data->buffer->size;
- release_wbuffer(data->buffer);
+ wstream_release_wbuffer(data->buffer);
if (data->wstream->cb) {
data->wstream->cb(data->wstream,
@@ -239,7 +239,7 @@ static void write_cb(uv_write_t *req, int status)
kmp_free(WRequestPool, wrequest_pool, data);
}
-static void release_wbuffer(WBuffer *buffer)
+void wstream_release_wbuffer(WBuffer *buffer)
{
if (!--buffer->refcount) {
if (buffer->cb) {
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 87b2d8ff99..daba7b943f 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -1126,4 +1126,4 @@ static int get_config_int(Terminal *term, char *key)
// }}}
-// vim: foldmethod=marker foldenable
+// vim: foldmethod=marker
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 45e3a73a69..8cdc06dba5 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -225,7 +225,7 @@ static int included_patches[] = {
518,
517,
516,
- //515,
+ 515,
514,
513,
//512 NA
@@ -404,7 +404,7 @@ static int included_patches[] = {
339,
338,
337,
- //336,
+ 336,
335,
334,
//333 NA