diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/nvim/eval.c | 15 | ||||
-rw-r--r-- | src/nvim/eval_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 92 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/channel.c | 51 | ||||
-rw-r--r-- | src/nvim/option.c | 3 | ||||
-rw-r--r-- | src/nvim/os/env.c | 17 | ||||
-rw-r--r-- | src/nvim/os/wstream.c | 6 | ||||
-rw-r--r-- | src/nvim/terminal.c | 2 | ||||
-rw-r--r-- | src/nvim/version.c | 4 |
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 |