refactor: format #15702

This commit is contained in:
dundargoc
2021-09-18 18:34:23 +02:00
committed by GitHub
parent 6cad86fffd
commit 51a98aa0c2
16 changed files with 4697 additions and 4954 deletions

View File

@@ -3,40 +3,39 @@
// Some of this code was adapted from 'if_py_both.h' from the original // Some of this code was adapted from 'if_py_both.h' from the original
// vim source // vim source
#include <lauxlib.h>
#include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include <lauxlib.h>
#include "nvim/api/buffer.h" #include "nvim/api/buffer.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h" #include "nvim/api/private/defs.h"
#include "nvim/lua/executor.h" #include "nvim/api/private/helpers.h"
#include "nvim/vim.h"
#include "nvim/buffer.h" #include "nvim/buffer.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h" #include "nvim/change.h"
#include "nvim/charset.h" #include "nvim/charset.h"
#include "nvim/cursor.h" #include "nvim/cursor.h"
#include "nvim/decoration.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/getchar.h" #include "nvim/getchar.h"
#include "nvim/lua/executor.h"
#include "nvim/map.h"
#include "nvim/map_defs.h"
#include "nvim/mark.h"
#include "nvim/memline.h" #include "nvim/memline.h"
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/misc1.h" #include "nvim/misc1.h"
#include "nvim/ex_cmds.h"
#include "nvim/map_defs.h"
#include "nvim/map.h"
#include "nvim/mark.h"
#include "nvim/ops.h"
#include "nvim/extmark.h"
#include "nvim/decoration.h"
#include "nvim/fileio.h"
#include "nvim/move.h" #include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/syntax.h" #include "nvim/syntax.h"
#include "nvim/window.h"
#include "nvim/undo.h" #include "nvim/undo.h"
#include "nvim/ex_docmd.h" #include "nvim/vim.h"
#include "nvim/buffer_updates.h" #include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/buffer.c.generated.h" # include "api/buffer.c.generated.h"
@@ -149,11 +148,8 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// @return False if attach failed (invalid parameter, or buffer isn't loaded); /// @return False if attach failed (invalid parameter, or buffer isn't loaded);
/// otherwise True. TODO: LUA_API_NO_EVAL /// otherwise True. TODO: LUA_API_NO_EVAL
Boolean nvim_buf_attach(uint64_t channel_id, Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer,
Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
Boolean send_buffer,
DictionaryOf(LuaRef) opts,
Error *err)
FUNC_API_SINCE(4) FUNC_API_SINCE(4)
{ {
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -237,9 +233,7 @@ error:
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// @return False if detach failed (because the buffer isn't loaded); /// @return False if detach failed (because the buffer isn't loaded);
/// otherwise True. /// otherwise True.
Boolean nvim_buf_detach(uint64_t channel_id, Boolean nvim_buf_detach(uint64_t channel_id, Buffer buffer, Error *err)
Buffer buffer,
Error *err)
FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY
{ {
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -252,8 +246,7 @@ Boolean nvim_buf_detach(uint64_t channel_id,
return true; return true;
} }
void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err)
Error *err)
FUNC_API_LUA_ONLY FUNC_API_LUA_ONLY
{ {
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -376,13 +369,8 @@ static bool check_string_array(Array arr, bool disallow_nl, Error *err)
/// @param strict_indexing Whether out-of-bounds should be an error. /// @param strict_indexing Whether out-of-bounds should be an error.
/// @param replacement Array of lines to use as replacement /// @param replacement Array of lines to use as replacement
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_buf_set_lines(uint64_t channel_id, void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integer end,
Buffer buffer, Boolean strict_indexing, ArrayOf(String) replacement, Error *err)
Integer start,
Integer end,
Boolean strict_indexing,
ArrayOf(String) replacement,
Error *err)
FUNC_API_SINCE(1) FUNC_API_SINCE(1)
FUNC_API_CHECK_TEXTLOCK FUNC_API_CHECK_TEXTLOCK
{ {
@@ -554,10 +542,8 @@ end:
/// @param end_column Last column /// @param end_column Last column
/// @param replacement Array of lines to use as replacement /// @param replacement Array of lines to use as replacement
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, Integer start_col,
Integer start_row, Integer start_col, Integer end_row, Integer end_col, ArrayOf(String) replacement, Error *err)
Integer end_row, Integer end_col,
ArrayOf(String) replacement, Error *err)
FUNC_API_SINCE(7) FUNC_API_SINCE(7)
{ {
FIXED_TEMP_ARRAY(scratch, 1); FIXED_TEMP_ARRAY(scratch, 1);
@@ -617,17 +603,17 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer,
// calculate byte size of old region before it gets modified/deleted // calculate byte size of old region before it gets modified/deleted
if (start_row == end_row) { if (start_row == end_row) {
old_byte = (bcount_t)end_col - start_col; old_byte = (bcount_t)end_col - start_col;
} else { } else {
const char *bufline; const char *bufline;
old_byte += (bcount_t)strlen(str_at_start) - start_col; old_byte += (bcount_t)strlen(str_at_start) - start_col;
for (int64_t i = 1; i < end_row - start_row; i++) { for (int64_t i = 1; i < end_row - start_row; i++) {
int64_t lnum = start_row + i; int64_t lnum = start_row + i;
bufline = (char *)ml_get_buf(buf, lnum, false); bufline = (char *)ml_get_buf(buf, lnum, false);
old_byte += (bcount_t)(strlen(bufline))+1; old_byte += (bcount_t)(strlen(bufline))+1;
} }
old_byte += (bcount_t)end_col+1; old_byte += (bcount_t)end_col+1;
} }
String first_item = replacement.items[0].data.string; String first_item = replacement.items[0].data.string;
@@ -824,7 +810,7 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err)
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) { if (!buf) {
return (Object) OBJECT_INIT; return (Object)OBJECT_INIT;
} }
return dict_get_value(buf->b_vars, name, err); return dict_get_value(buf->b_vars, name, err);
@@ -872,8 +858,8 @@ ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err)
/// @see |nvim_set_keymap()| /// @see |nvim_set_keymap()|
/// ///
/// @param buffer Buffer handle, or 0 for current buffer /// @param buffer Buffer handle, or 0 for current buffer
void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs, void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs, Dictionary opts,
Dictionary opts, Error *err) Error *err)
FUNC_API_SINCE(6) FUNC_API_SINCE(6)
{ {
modify_keymap(buffer, false, mode, lhs, rhs, opts, err); modify_keymap(buffer, false, mode, lhs, rhs, opts, err);
@@ -980,7 +966,7 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) { if (!buf) {
return (Object) OBJECT_INIT; return (Object)OBJECT_INIT;
} }
return get_option_from(buf, SREQ_BUF, name, err); return get_option_from(buf, SREQ_BUF, name, err);
@@ -994,8 +980,7 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
/// @param name Option name /// @param name Option name
/// @param value Option value /// @param value Option value
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, String name, Object value, Error *err)
String name, Object value, Error *err)
FUNC_API_SINCE(1) FUNC_API_SINCE(1)
{ {
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -1044,7 +1029,7 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err)
// Using aucmd_*: autocommands will be executed by rename_buffer // Using aucmd_*: autocommands will be executed by rename_buffer
aco_save_T aco; aco_save_T aco;
aucmd_prepbuf(&aco, buf); aucmd_prepbuf(&aco, buf);
int ren_ret = rename_buffer((char_u *) name.data); int ren_ret = rename_buffer((char_u *)name.data);
aucmd_restbuf(&aco); aucmd_restbuf(&aco);
if (try_end(err)) { if (try_end(err)) {
@@ -1105,12 +1090,11 @@ void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err)
return; return;
} }
int result = do_buffer( int result = do_buffer(unload ? DOBUF_UNLOAD : DOBUF_WIPE,
unload ? DOBUF_UNLOAD : DOBUF_WIPE, DOBUF_FIRST,
DOBUF_FIRST, FORWARD,
FORWARD, buf->handle,
buf->handle, force);
force);
if (result == FAIL) { if (result == FAIL) {
api_set_error(err, kErrorTypeException, "Failed to unload buffer."); api_set_error(err, kErrorTypeException, "Failed to unload buffer.");
@@ -1213,8 +1197,7 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict)
ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text))); ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text)));
if (vtc->hl_id > 0) { if (vtc->hl_id > 0) {
ADD(chunk, ADD(chunk,
STRING_OBJ(cstr_to_string( STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id))));
(const char *)syn_id2name(vtc->hl_id))));
} }
ADD(chunks, ARRAY_OBJ(chunk)); ADD(chunks, ARRAY_OBJ(chunk));
} }
@@ -1330,9 +1313,8 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
/// - details Whether to include the details dict /// - details Whether to include the details dict
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// @return List of [extmark_id, row, col] tuples in "traversal order". /// @return List of [extmark_id, row, col] tuples in "traversal order".
Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end, Dictionary opts,
Object start, Object end, Error *err)
Dictionary opts, Error *err)
FUNC_API_SINCE(7) FUNC_API_SINCE(7)
{ {
Array rv = ARRAY_DICT_INIT; Array rv = ARRAY_DICT_INIT;
@@ -1480,8 +1462,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
/// example treesitter highlighting uses a value of 100. /// example treesitter highlighting uses a value of 100.
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// @return Id of the created/updated extmark /// @return Id of the created/updated extmark
Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col,
Integer line, Integer col,
Dictionary opts, Error *err) Dictionary opts, Error *err)
FUNC_API_SINCE(7) FUNC_API_SINCE(7)
{ {
@@ -1546,19 +1527,18 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
} else if (strequal("hl_group", k.data)) { } else if (strequal("hl_group", k.data)) {
String hl_group; String hl_group;
switch (v->type) { switch (v->type) {
case kObjectTypeString: case kObjectTypeString:
hl_group = v->data.string; hl_group = v->data.string;
decor.hl_id = syn_check_group( decor.hl_id = syn_check_group((char_u *)(hl_group.data),
(char_u *)(hl_group.data), (int)hl_group.size);
(int)hl_group.size); break;
break; case kObjectTypeInteger:
case kObjectTypeInteger: decor.hl_id = (int)v->data.integer;
decor.hl_id = (int)v->data.integer; break;
break; default:
default: api_set_error(err, kErrorTypeValidation,
api_set_error(err, kErrorTypeValidation, "hl_group is not valid.");
"hl_group is not valid."); goto error;
goto error;
} }
} else if (strequal("virt_text", k.data)) { } else if (strequal("virt_text", k.data)) {
if (v->type != kObjectTypeArray) { if (v->type != kObjectTypeArray) {
@@ -1692,8 +1672,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
if (col2 >= 0) { if (col2 >= 0) {
if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) { if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
len = ephemeral ? MAXCOL : STRLEN( len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false));
ml_get_buf(buf, (linenr_T)line2 + 1, false));
} else if (line2 == buf->b_ml.ml_line_count) { } else if (line2 == buf->b_ml.ml_line_count) {
// We are trying to add an extmark past final newline // We are trying to add an extmark past final newline
len = 0; len = 0;
@@ -1713,7 +1692,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
decor.col = 0; decor.col = 0;
for (size_t i = 0; i < kv_size(decor.virt_text); i++) { for (size_t i = 0; i < kv_size(decor.virt_text); i++) {
decor.col decor.col
+= (int)mb_string2cells((char_u *)kv_A(decor.virt_text, i).text); += (int)mb_string2cells((char_u *)kv_A(decor.virt_text, i).text);
} }
} }
@@ -1761,10 +1740,7 @@ error:
/// @param id Extmark id /// @param id Extmark id
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// @return true if the extmark was found, else false /// @return true if the extmark was found, else false
Boolean nvim_buf_del_extmark(Buffer buffer, Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *err)
Integer ns_id,
Integer id,
Error *err)
FUNC_API_SINCE(7) FUNC_API_SINCE(7)
{ {
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -1810,13 +1786,8 @@ Boolean nvim_buf_del_extmark(Buffer buffer,
/// or -1 to highlight to end of line /// or -1 to highlight to end of line
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// @return The ns_id that was used /// @return The ns_id that was used
Integer nvim_buf_add_highlight(Buffer buffer, Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, Integer line,
Integer ns_id, Integer col_start, Integer col_end, Error *err)
String hl_group,
Integer line,
Integer col_start,
Integer col_end,
Error *err)
FUNC_API_SINCE(1) FUNC_API_SINCE(1)
{ {
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -1875,10 +1846,7 @@ Integer nvim_buf_add_highlight(Buffer buffer,
/// @param line_end End of range of lines to clear (exclusive) or -1 to clear /// @param line_end End of range of lines to clear (exclusive) or -1 to clear
/// to end of buffer. /// to end of buffer.
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_buf_clear_namespace(Buffer buffer, void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, Integer line_end,
Integer ns_id,
Integer line_start,
Integer line_end,
Error *err) Error *err)
FUNC_API_SINCE(5) FUNC_API_SINCE(5)
{ {

View File

@@ -1,18 +1,18 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check // 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 // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include "nvim/api/deprecated.h"
#include "nvim/api/buffer.h" #include "nvim/api/buffer.h"
#include "nvim/api/vim.h" #include "nvim/api/deprecated.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h" #include "nvim/api/private/defs.h"
#include "nvim/lua/executor.h" #include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/extmark.h" #include "nvim/extmark.h"
#include "nvim/lua/executor.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/deprecated.c.generated.h" # include "api/deprecated.c.generated.h"
@@ -69,10 +69,7 @@ Integer nvim_buf_get_number(Buffer buffer, Error *err)
/// @param line_end End of range of lines to clear (exclusive) or -1 to clear /// @param line_end End of range of lines to clear (exclusive) or -1 to clear
/// to end of file. /// to end of file.
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_buf_clear_highlight(Buffer buffer, void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start, Integer line_end,
Integer ns_id,
Integer line_start,
Integer line_end,
Error *err) Error *err)
FUNC_API_SINCE(1) FUNC_API_SINCE(1)
FUNC_API_DEPRECATED_SINCE(7) FUNC_API_DEPRECATED_SINCE(7)
@@ -111,12 +108,8 @@ void nvim_buf_clear_highlight(Buffer buffer,
/// @param opts Optional parameters. Currently not used. /// @param opts Optional parameters. Currently not used.
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// @return The ns_id that was used /// @return The ns_id that was used
Integer nvim_buf_set_virtual_text(Buffer buffer, Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, Array chunks,
Integer src_id, Dictionary opts, Error *err)
Integer line,
Array chunks,
Dictionary opts,
Error *err)
FUNC_API_SINCE(5) FUNC_API_SINCE(5)
FUNC_API_DEPRECATED_SINCE(8) FUNC_API_DEPRECATED_SINCE(8)
{ {
@@ -171,10 +164,7 @@ Integer nvim_buf_set_virtual_text(Buffer buffer,
/// the end of the buffer. /// the end of the buffer.
/// @param lines Array of lines /// @param lines Array of lines
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void buffer_insert(Buffer buffer, void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *err)
Integer lnum,
ArrayOf(String) lines,
Error *err)
{ {
// "lnum" will be the index of the line after inserting, // "lnum" will be the index of the line after inserting,
// no matter if it is negative or not // no matter if it is negative or not
@@ -268,7 +258,7 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
{ {
start = convert_index(start) + !include_start; start = convert_index(start) + !include_start;
end = convert_index(end) + include_end; end = convert_index(end) + include_end;
return nvim_buf_get_lines(0, buffer, start , end, false, err); return nvim_buf_get_lines(0, buffer, start, end, false, err);
} }
/// Replaces a line range on the buffer /// Replaces a line range on the buffer
@@ -286,13 +276,8 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
/// @param replacement Array of lines to use as replacement (0-length /// @param replacement Array of lines to use as replacement (0-length
// array will delete the line range) // array will delete the line range)
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void buffer_set_line_slice(Buffer buffer, void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean include_start,
Integer start, Boolean include_end, ArrayOf(String) replacement, Error *err)
Integer end,
Boolean include_start,
Boolean include_end,
ArrayOf(String) replacement,
Error *err)
{ {
start = convert_index(start) + !include_start; start = convert_index(start) + !include_start;
end = convert_index(end) + include_end; end = convert_index(end) + include_end;

View File

@@ -1,38 +1,35 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check // 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 // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <inttypes.h>
#include <stdbool.h>
#include <assert.h> #include <assert.h>
#include <inttypes.h>
#include <msgpack.h> #include <msgpack.h>
#include <stdbool.h>
#include "nvim/map.h"
#include "nvim/log.h"
#include "nvim/vim.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/buffer.h" #include "nvim/api/buffer.h"
#include "nvim/api/deprecated.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/tabpage.h" #include "nvim/api/tabpage.h"
#include "nvim/api/ui.h" #include "nvim/api/ui.h"
#include "nvim/api/vim.h" #include "nvim/api/vim.h"
#include "nvim/api/window.h" #include "nvim/api/window.h"
#include "nvim/api/deprecated.h" #include "nvim/log.h"
#include "nvim/map.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/vim.h"
static Map(String, MsgpackRpcRequestHandler) methods = MAP_INIT; static Map(String, MsgpackRpcRequestHandler) methods = MAP_INIT;
static void msgpack_rpc_add_method_handler(String method, static void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandler handler)
MsgpackRpcRequestHandler handler)
{ {
map_put(String, MsgpackRpcRequestHandler)(&methods, method, handler); map_put(String, MsgpackRpcRequestHandler)(&methods, method, handler);
} }
/// @param name API method name /// @param name API method name
/// @param name_len name size (includes terminating NUL) /// @param name_len name size (includes terminating NUL)
MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, size_t name_len,
size_t name_len,
Error *error) Error *error)
{ {
String m = { .data = (char *)name, .size = name_len }; String m = { .data = (char *)name, .size = name_len };

View File

@@ -7,33 +7,33 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h" #include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h" #include "nvim/api/vim.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/lua/executor.h"
#include "nvim/ascii.h" #include "nvim/ascii.h"
#include "nvim/assert.h" #include "nvim/assert.h"
#include "nvim/charset.h"
#include "nvim/syntax.h"
#include "nvim/vim.h"
#include "nvim/buffer.h" #include "nvim/buffer.h"
#include "nvim/window.h" #include "nvim/charset.h"
#include "nvim/memline.h" #include "nvim/decoration.h"
#include "nvim/memory.h"
#include "nvim/eval.h" #include "nvim/eval.h"
#include "nvim/eval/typval.h" #include "nvim/eval/typval.h"
#include "nvim/map_defs.h"
#include "nvim/map.h"
#include "nvim/extmark.h" #include "nvim/extmark.h"
#include "nvim/decoration.h" #include "nvim/fileio.h"
#include "nvim/getchar.h"
#include "nvim/lib/kvec.h"
#include "nvim/lua/executor.h"
#include "nvim/map.h"
#include "nvim/map_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/option.h" #include "nvim/option.h"
#include "nvim/option_defs.h" #include "nvim/option_defs.h"
#include "nvim/version.h" #include "nvim/syntax.h"
#include "nvim/lib/kvec.h"
#include "nvim/getchar.h"
#include "nvim/fileio.h"
#include "nvim/ui.h" #include "nvim/ui.h"
#include "nvim/version.h"
#include "nvim/vim.h"
#include "nvim/window.h"
/// Helper structure for vim_to_object /// Helper structure for vim_to_object
typedef struct { typedef struct {
@@ -41,8 +41,8 @@ typedef struct {
} EncodedData; } EncodedData;
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/helpers.c.generated.h"
# include "api/private/funcs_metadata.generated.h" # include "api/private/funcs_metadata.generated.h"
# include "api/private/helpers.c.generated.h"
# include "api/private/ui_events_metadata.generated.h" # include "api/private/ui_events_metadata.generated.h"
#endif #endif
@@ -210,8 +210,7 @@ dictitem_T *dict_check_writable(dict_T *dict, String key, bool del, Error *err)
/// @param retval If true the old value will be converted and returned. /// @param retval If true the old value will be converted and returned.
/// @param[out] err Details of an error that may have occurred /// @param[out] err Details of an error that may have occurred
/// @return The old value if `retval` is true and the key was present, else NIL /// @return The old value if `retval` is true and the key was present, else NIL
Object dict_set_var(dict_T *dict, String key, Object value, bool del, Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retval, Error *err)
bool retval, Error *err)
{ {
Object rv = OBJECT_INIT; Object rv = OBJECT_INIT;
dictitem_T *di = dict_check_writable(dict, key, del, err); dictitem_T *di = dict_check_writable(dict, key, del, err);
@@ -326,8 +325,7 @@ Object get_option_from(void *from, int type, String name, Error *err)
/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF` /// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
/// @param name The option name /// @param name The option name
/// @param[out] err Details of an error that may have occurred /// @param[out] err Details of an error that may have occurred
void set_option_to(uint64_t channel_id, void *to, int type, void set_option_to(uint64_t channel_id, void *to, int type, String name, Object value, Error *err)
String name, Object value, Error *err)
{ {
if (name.size == 0) { if (name.size == 0) {
api_set_error(err, kErrorTypeValidation, "Empty option name"); api_set_error(err, kErrorTypeValidation, "Empty option name");
@@ -418,61 +416,60 @@ void set_option_to(uint64_t channel_id, void *to, int type,
#define TYPVAL_ENCODE_ALLOW_SPECIALS false #define TYPVAL_ENCODE_ALLOW_SPECIALS false
#define TYPVAL_ENCODE_CONV_NIL(tv) \ #define TYPVAL_ENCODE_CONV_NIL(tv) \
kvi_push(edata->stack, NIL) kvi_push(edata->stack, NIL)
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
kvi_push(edata->stack, BOOLEAN_OBJ((Boolean)(num))) kvi_push(edata->stack, BOOLEAN_OBJ((Boolean)(num)))
#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ #define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \
kvi_push(edata->stack, INTEGER_OBJ((Integer)(num))) kvi_push(edata->stack, INTEGER_OBJ((Integer)(num)))
#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER
#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
kvi_push(edata->stack, FLOAT_OBJ((Float)(flt))) kvi_push(edata->stack, FLOAT_OBJ((Float)(flt)))
#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \ #define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \
do { \ do { \
const size_t len_ = (size_t)(len); \ const size_t len_ = (size_t)(len); \
const char *const str_ = (const char *)(str); \ const char *const str_ = (const char *)(str); \
assert(len_ == 0 || str_ != NULL); \ assert(len_ == 0 || str_ != NULL); \
kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \ kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \
} while (0) } while (0)
#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING #define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING
#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, str, len, type) \ #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, str, len, type) \
TYPVAL_ENCODE_CONV_NIL(tv) TYPVAL_ENCODE_CONV_NIL(tv)
#define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ #define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \
do { \ do { \
const size_t len_ = (size_t)(len); \ const size_t len_ = (size_t)(len); \
const blob_T *const blob_ = (blob); \ const blob_T *const blob_ = (blob); \
kvi_push(edata->stack, STRING_OBJ(((String) { \ kvi_push(edata->stack, STRING_OBJ(((String) { \
.data = len_ != 0 ? xmemdup(blob_->bv_ga.ga_data, len_) : NULL, \ .data = len_ != 0 ? xmemdup(blob_->bv_ga.ga_data, len_) : NULL, \
.size = len_ \ .size = len_ \
}))); \ }))); \
} while (0) } while (0)
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
do { \ do { \
TYPVAL_ENCODE_CONV_NIL(tv); \ TYPVAL_ENCODE_CONV_NIL(tv); \
goto typval_encode_stop_converting_one_item; \ goto typval_encode_stop_converting_one_item; \
} while (0) } while (0)
#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len)
#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len)
#define TYPVAL_ENCODE_CONV_FUNC_END(tv) #define TYPVAL_ENCODE_CONV_FUNC_END(tv)
#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ #define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
kvi_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 }))) kvi_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 })))
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
kvi_push(edata->stack, \ kvi_push(edata->stack, \
DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 }))) DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 })))
static inline void typval_encode_list_start(EncodedData *const edata, static inline void typval_encode_list_start(EncodedData *const edata, const size_t len)
const size_t len)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
{ {
kvi_push(edata->stack, ARRAY_OBJ(((Array) { kvi_push(edata->stack, ARRAY_OBJ(((Array) {
@@ -483,7 +480,7 @@ static inline void typval_encode_list_start(EncodedData *const edata,
} }
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ #define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
typval_encode_list_start(edata, (size_t)(len)) typval_encode_list_start(edata, (size_t)(len))
#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) #define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv)
@@ -498,7 +495,7 @@ static inline void typval_encode_between_list_items(EncodedData *const edata)
} }
#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \ #define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \
typval_encode_between_list_items(edata) typval_encode_between_list_items(edata)
static inline void typval_encode_list_end(EncodedData *const edata) static inline void typval_encode_list_end(EncodedData *const edata)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
@@ -511,22 +508,21 @@ static inline void typval_encode_list_end(EncodedData *const edata)
} }
#define TYPVAL_ENCODE_CONV_LIST_END(tv) \ #define TYPVAL_ENCODE_CONV_LIST_END(tv) \
typval_encode_list_end(edata) typval_encode_list_end(edata)
static inline void typval_encode_dict_start(EncodedData *const edata, static inline void typval_encode_dict_start(EncodedData *const edata, const size_t len)
const size_t len)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
{ {
kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) { kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) {
.capacity = len, .capacity = len,
.size = 0, .size = 0,
.items = xmalloc(len * sizeof( .items = xmalloc(len * sizeof(
*((Object)OBJECT_INIT).data.dictionary.items)), *((Object)OBJECT_INIT).data.dictionary.items)),
}))); })));
} }
#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \
typval_encode_dict_start(edata, (size_t)(len)) typval_encode_dict_start(edata, (size_t)(len))
#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) #define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv)
@@ -541,16 +537,16 @@ static inline void typval_encode_after_key(EncodedData *const edata)
assert(dict->data.dictionary.size < dict->data.dictionary.capacity); assert(dict->data.dictionary.size < dict->data.dictionary.capacity);
if (key.type == kObjectTypeString) { if (key.type == kObjectTypeString) {
dict->data.dictionary.items[dict->data.dictionary.size].key dict->data.dictionary.items[dict->data.dictionary.size].key
= key.data.string; = key.data.string;
} else { } else {
api_free_object(key); api_free_object(key);
dict->data.dictionary.items[dict->data.dictionary.size].key dict->data.dictionary.items[dict->data.dictionary.size].key
= STATIC_CSTR_TO_STRING("__INVALID_KEY__"); = STATIC_CSTR_TO_STRING("__INVALID_KEY__");
} }
} }
#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \ #define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \
typval_encode_after_key(edata) typval_encode_after_key(edata)
static inline void typval_encode_between_dict_items(EncodedData *const edata) static inline void typval_encode_between_dict_items(EncodedData *const edata)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
@@ -563,7 +559,7 @@ static inline void typval_encode_between_dict_items(EncodedData *const edata)
} }
#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ #define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \
typval_encode_between_dict_items(edata) typval_encode_between_dict_items(edata)
static inline void typval_encode_dict_end(EncodedData *const edata) static inline void typval_encode_dict_end(EncodedData *const edata)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
@@ -576,10 +572,10 @@ static inline void typval_encode_dict_end(EncodedData *const edata)
} }
#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ #define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \
typval_encode_dict_end(edata) typval_encode_dict_end(edata)
#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \
TYPVAL_ENCODE_CONV_NIL(val) TYPVAL_ENCODE_CONV_NIL(val)
#define TYPVAL_ENCODE_SCOPE static #define TYPVAL_ENCODE_SCOPE static
#define TYPVAL_ENCODE_NAME object #define TYPVAL_ENCODE_NAME object
@@ -708,15 +704,15 @@ String cchar_to_string(char c)
/// empty String is returned /// empty String is returned
String cstr_to_string(const char *str) String cstr_to_string(const char *str)
{ {
if (str == NULL) { if (str == NULL) {
return (String)STRING_INIT; return (String)STRING_INIT;
} }
size_t len = strlen(str); size_t len = strlen(str);
return (String){ return (String){
.data = xmemdupz(str, len), .data = xmemdupz(str, len),
.size = len, .size = len,
}; };
} }
/// Copies buffer to an allocated String. /// Copies buffer to an allocated String.
@@ -817,8 +813,8 @@ Array string_to_array(const String input, bool crlf)
/// @param buffer Buffer handle for a specific buffer, or 0 for the current /// @param buffer Buffer handle for a specific buffer, or 0 for the current
/// buffer, or -1 to signify global behavior ("all buffers") /// buffer, or -1 to signify global behavior ("all buffers")
/// @param is_unmap When true, removes the mapping that matches {lhs}. /// @param is_unmap When true, removes the mapping that matches {lhs}.
void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs, void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs, String rhs,
String rhs, Dictionary opts, Error *err) Dictionary opts, Error *err)
{ {
char *err_msg = NULL; // the error message to report, if any char *err_msg = NULL; // the error message to report, if any
char *err_arg = NULL; // argument for the error message format string char *err_arg = NULL; // argument for the error message format string
@@ -916,21 +912,21 @@ void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs,
} }
switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) { switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) {
case 0: case 0:
break; break;
case 1: case 1:
api_set_error(err, kErrorTypeException, (char *)e_invarg, 0); api_set_error(err, kErrorTypeException, (char *)e_invarg, 0);
goto fail_and_free; goto fail_and_free;
case 2: case 2:
api_set_error(err, kErrorTypeException, (char *)e_nomap, 0); api_set_error(err, kErrorTypeException, (char *)e_nomap, 0);
goto fail_and_free; goto fail_and_free;
case 5: case 5:
api_set_error(err, kErrorTypeException, api_set_error(err, kErrorTypeException,
"E227: mapping already exists for %s", parsed_args.lhs); "E227: mapping already exists for %s", parsed_args.lhs);
goto fail_and_free; goto fail_and_free;
default: default:
assert(false && "Unrecognized return code!"); assert(false && "Unrecognized return code!");
goto fail_and_free; goto fail_and_free;
} // switch } // switch
xfree(lhs_buf); xfree(lhs_buf);
@@ -986,44 +982,44 @@ Integer parse_keymap_opts(Dictionary opts, MapArguments *out, Error *err)
bool was_valid_opt = false; bool was_valid_opt = false;
switch (optname[0]) { switch (optname[0]) {
// note: strncmp up to and including the null terminator, so that // note: strncmp up to and including the null terminator, so that
// "nowaitFoobar" won't match against "nowait" // "nowaitFoobar" won't match against "nowait"
// don't recognize 'buffer' as a key; user shouldn't provide <buffer> // don't recognize 'buffer' as a key; user shouldn't provide <buffer>
// when calling nvim_set_keymap or nvim_buf_set_keymap, since it can be // when calling nvim_set_keymap or nvim_buf_set_keymap, since it can be
// inferred from which function they called // inferred from which function they called
case 'n': case 'n':
if (STRNCMP(optname, "noremap", 8) == 0) { if (STRNCMP(optname, "noremap", 8) == 0) {
was_valid_opt = true; was_valid_opt = true;
out->noremap = key_and_val->value.data.boolean; out->noremap = key_and_val->value.data.boolean;
} else if (STRNCMP(optname, "nowait", 7) == 0) { } else if (STRNCMP(optname, "nowait", 7) == 0) {
was_valid_opt = true; was_valid_opt = true;
out->nowait = key_and_val->value.data.boolean; out->nowait = key_and_val->value.data.boolean;
} }
break; break;
case 's': case 's':
if (STRNCMP(optname, "silent", 7) == 0) { if (STRNCMP(optname, "silent", 7) == 0) {
was_valid_opt = true; was_valid_opt = true;
out->silent = key_and_val->value.data.boolean; out->silent = key_and_val->value.data.boolean;
} else if (STRNCMP(optname, "script", 7) == 0) { } else if (STRNCMP(optname, "script", 7) == 0) {
was_valid_opt = true; was_valid_opt = true;
out->script = key_and_val->value.data.boolean; out->script = key_and_val->value.data.boolean;
} }
break; break;
case 'e': case 'e':
if (STRNCMP(optname, "expr", 5) == 0) { if (STRNCMP(optname, "expr", 5) == 0) {
was_valid_opt = true; was_valid_opt = true;
out->expr = key_and_val->value.data.boolean; out->expr = key_and_val->value.data.boolean;
} }
break; break;
case 'u': case 'u':
if (STRNCMP(optname, "unique", 7) == 0) { if (STRNCMP(optname, "unique", 7) == 0) {
was_valid_opt = true; was_valid_opt = true;
out->unique = key_and_val->value.data.boolean; out->unique = key_and_val->value.data.boolean;
} }
break; break;
default: default:
break; break;
} // switch } // switch
if (!was_valid_opt) { if (!was_valid_opt) {
err_msg = "Invalid key: %s"; err_msg = "Invalid key: %s";
@@ -1050,8 +1046,7 @@ fail_with_message:
/// @param[out] l Lines are copied here /// @param[out] l Lines are copied here
/// @param err[out] Error, if any /// @param err[out] Error, if any
/// @return true unless `err` was set /// @return true unless `err` was set
bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Array *l, Error *err)
Array *l, Error *err)
{ {
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
int64_t lnum = start + (int64_t)i; int64_t lnum = start + (int64_t)i;
@@ -1089,96 +1084,96 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
tv->v_lock = VAR_UNLOCKED; tv->v_lock = VAR_UNLOCKED;
switch (obj.type) { switch (obj.type) {
case kObjectTypeNil: case kObjectTypeNil:
tv->v_type = VAR_SPECIAL; tv->v_type = VAR_SPECIAL;
tv->vval.v_special = kSpecialVarNull; tv->vval.v_special = kSpecialVarNull;
break; break;
case kObjectTypeBoolean: case kObjectTypeBoolean:
tv->v_type = VAR_BOOL; tv->v_type = VAR_BOOL;
tv->vval.v_bool = obj.data.boolean? kBoolVarTrue: kBoolVarFalse; tv->vval.v_bool = obj.data.boolean? kBoolVarTrue: kBoolVarFalse;
break; break;
case kObjectTypeBuffer: case kObjectTypeBuffer:
case kObjectTypeWindow: case kObjectTypeWindow:
case kObjectTypeTabpage: case kObjectTypeTabpage:
case kObjectTypeInteger: case kObjectTypeInteger:
STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T), STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T),
"Integer size must be <= VimL number size"); "Integer size must be <= VimL number size");
tv->v_type = VAR_NUMBER; tv->v_type = VAR_NUMBER;
tv->vval.v_number = (varnumber_T)obj.data.integer; tv->vval.v_number = (varnumber_T)obj.data.integer;
break; break;
case kObjectTypeFloat: case kObjectTypeFloat:
tv->v_type = VAR_FLOAT; tv->v_type = VAR_FLOAT;
tv->vval.v_float = obj.data.floating; tv->vval.v_float = obj.data.floating;
break; break;
case kObjectTypeString: case kObjectTypeString:
tv->v_type = VAR_STRING; tv->v_type = VAR_STRING;
if (obj.data.string.data == NULL) { if (obj.data.string.data == NULL) {
tv->vval.v_string = NULL; tv->vval.v_string = NULL;
} else { } else {
tv->vval.v_string = xmemdupz(obj.data.string.data, tv->vval.v_string = xmemdupz(obj.data.string.data,
obj.data.string.size); obj.data.string.size);
}
break;
case kObjectTypeArray: {
list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size);
for (uint32_t i = 0; i < obj.data.array.size; i++) {
Object item = obj.data.array.items[i];
typval_T li_tv;
if (!object_to_vim(item, &li_tv, err)) {
tv_list_free(list);
return false;
}
tv_list_append_owned_tv(list, li_tv);
}
tv_list_ref(list);
tv->v_type = VAR_LIST;
tv->vval.v_list = list;
break;
} }
break;
case kObjectTypeDictionary: { case kObjectTypeArray: {
dict_T *const dict = tv_dict_alloc(); list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size);
for (uint32_t i = 0; i < obj.data.dictionary.size; i++) { for (uint32_t i = 0; i < obj.data.array.size; i++) {
KeyValuePair item = obj.data.dictionary.items[i]; Object item = obj.data.array.items[i];
String key = item.key; typval_T li_tv;
if (key.size == 0) { if (!object_to_vim(item, &li_tv, err)) {
api_set_error(err, kErrorTypeValidation, tv_list_free(list);
"Empty dictionary keys aren't allowed"); return false;
// cleanup
tv_dict_free(dict);
return false;
}
dictitem_T *const di = tv_dict_item_alloc(key.data);
if (!object_to_vim(item.value, &di->di_tv, err)) {
// cleanup
tv_dict_item_free(di);
tv_dict_free(dict);
return false;
}
tv_dict_add(dict, di);
} }
dict->dv_refcount++;
tv->v_type = VAR_DICT; tv_list_append_owned_tv(list, li_tv);
tv->vval.v_dict = dict;
break;
} }
default: tv_list_ref(list);
abort();
tv->v_type = VAR_LIST;
tv->vval.v_list = list;
break;
}
case kObjectTypeDictionary: {
dict_T *const dict = tv_dict_alloc();
for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
KeyValuePair item = obj.data.dictionary.items[i];
String key = item.key;
if (key.size == 0) {
api_set_error(err, kErrorTypeValidation,
"Empty dictionary keys aren't allowed");
// cleanup
tv_dict_free(dict);
return false;
}
dictitem_T *const di = tv_dict_item_alloc(key.data);
if (!object_to_vim(item.value, &di->di_tv, err)) {
// cleanup
tv_dict_item_free(di);
tv_dict_free(dict);
return false;
}
tv_dict_add(dict, di);
}
dict->dv_refcount++;
tv->v_type = VAR_DICT;
tv->vval.v_dict = dict;
break;
}
default:
abort();
} }
return true; return true;
@@ -1196,33 +1191,33 @@ void api_free_string(String value)
void api_free_object(Object value) void api_free_object(Object value)
{ {
switch (value.type) { switch (value.type) {
case kObjectTypeNil: case kObjectTypeNil:
case kObjectTypeBoolean: case kObjectTypeBoolean:
case kObjectTypeInteger: case kObjectTypeInteger:
case kObjectTypeFloat: case kObjectTypeFloat:
case kObjectTypeBuffer: case kObjectTypeBuffer:
case kObjectTypeWindow: case kObjectTypeWindow:
case kObjectTypeTabpage: case kObjectTypeTabpage:
break; break;
case kObjectTypeString: case kObjectTypeString:
api_free_string(value.data.string); api_free_string(value.data.string);
break; break;
case kObjectTypeArray: case kObjectTypeArray:
api_free_array(value.data.array); api_free_array(value.data.array);
break; break;
case kObjectTypeDictionary: case kObjectTypeDictionary:
api_free_dictionary(value.data.dictionary); api_free_dictionary(value.data.dictionary);
break; break;
case kObjectTypeLuaRef: case kObjectTypeLuaRef:
api_free_luaref(value.data.luaref); api_free_luaref(value.data.luaref);
break; break;
default: default:
abort(); abort();
} }
} }
@@ -1385,36 +1380,30 @@ Dictionary copy_dictionary(Dictionary dict)
Object copy_object(Object obj) Object copy_object(Object obj)
{ {
switch (obj.type) { switch (obj.type) {
case kObjectTypeBuffer: case kObjectTypeBuffer:
case kObjectTypeTabpage: case kObjectTypeTabpage:
case kObjectTypeWindow: case kObjectTypeWindow:
case kObjectTypeNil: case kObjectTypeNil:
case kObjectTypeBoolean: case kObjectTypeBoolean:
case kObjectTypeInteger: case kObjectTypeInteger:
case kObjectTypeFloat: case kObjectTypeFloat:
return obj; return obj;
case kObjectTypeString: case kObjectTypeString:
return STRING_OBJ(copy_string(obj.data.string)); return STRING_OBJ(copy_string(obj.data.string));
case kObjectTypeArray: case kObjectTypeArray:
return ARRAY_OBJ(copy_array(obj.data.array)); return ARRAY_OBJ(copy_array(obj.data.array));
case kObjectTypeDictionary: { case kObjectTypeDictionary:
return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary)); return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary));
} default:
default: abort();
abort();
} }
} }
static void set_option_value_for(char *key, static void set_option_value_for(char *key, int numval, char *stringval, int opt_flags,
int numval, int opt_type, void *from, Error *err)
char *stringval,
int opt_flags,
int opt_type,
void *from,
Error *err)
{ {
win_T *save_curwin = NULL; win_T *save_curwin = NULL;
tabpage_T *save_curtab = NULL; tabpage_T *save_curtab = NULL;
@@ -1423,29 +1412,28 @@ static void set_option_value_for(char *key,
try_start(); try_start();
switch (opt_type) switch (opt_type)
{ {
case SREQ_WIN: case SREQ_WIN:
if (switch_win(&save_curwin, &save_curtab, (win_T *)from, if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
win_find_tabpage((win_T *)from), false) == FAIL) win_find_tabpage((win_T *)from), false) == FAIL) {
{ if (try_end(err)) {
if (try_end(err)) {
return;
}
api_set_error(err,
kErrorTypeException,
"Problem while switching windows");
return; return;
} }
set_option_value_err(key, numval, stringval, opt_flags, err); api_set_error(err,
restore_win(save_curwin, save_curtab, true); kErrorTypeException,
break; "Problem while switching windows");
case SREQ_BUF: return;
aucmd_prepbuf(&aco, (buf_T *)from); }
set_option_value_err(key, numval, stringval, opt_flags, err); set_option_value_err(key, numval, stringval, opt_flags, err);
aucmd_restbuf(&aco); restore_win(save_curwin, save_curtab, true);
break; break;
case SREQ_GLOBAL: case SREQ_BUF:
set_option_value_err(key, numval, stringval, opt_flags, err); aucmd_prepbuf(&aco, (buf_T *)from);
break; set_option_value_err(key, numval, stringval, opt_flags, err);
aucmd_restbuf(&aco);
break;
case SREQ_GLOBAL:
set_option_value_err(key, numval, stringval, opt_flags, err);
break;
} }
if (ERROR_SET(err)) { if (ERROR_SET(err)) {
@@ -1456,11 +1444,7 @@ static void set_option_value_for(char *key,
} }
static void set_option_value_err(char *key, static void set_option_value_err(char *key, int numval, char *stringval, int opt_flags, Error *err)
int numval,
char *stringval,
int opt_flags,
Error *err)
{ {
char *errmsg; char *errmsg;
@@ -1519,8 +1503,7 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf)
// Check for correct mode // Check for correct mode
if (int_mode & current_maphash->m_mode) { if (int_mode & current_maphash->m_mode) {
mapblock_fill_dict(dict, current_maphash, buffer_value, false); mapblock_fill_dict(dict, current_maphash, buffer_value, false);
ADD(mappings, vim_to_object( ADD(mappings, vim_to_object((typval_T[]) { { .v_type = VAR_DICT, .vval.v_dict = dict } }));
(typval_T[]) { { .v_type = VAR_DICT, .vval.v_dict = dict } }));
tv_dict_clear(dict); tv_dict_clear(dict);
} }
@@ -1556,13 +1539,13 @@ bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, int
if (obj.type == kObjectTypeInteger) { if (obj.type == kObjectTypeInteger) {
Integer id = obj.data.integer; Integer id = obj.data.integer;
if (id == 0) { if (id == 0) {
*row = 0; *row = 0;
*col = 0; *col = 0;
return true; return true;
} else if (id == -1) { } else if (id == -1) {
*row = MAXLNUM; *row = MAXLNUM;
*col = MAXCOL; *col = MAXCOL;
return true; return true;
} else if (id < 0) { } else if (id < 0) {
api_set_error(err, kErrorTypeValidation, "Mark id must be positive"); api_set_error(err, kErrorTypeValidation, "Mark id must be positive");
return false; return false;
@@ -1578,7 +1561,7 @@ bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, int
return false; return false;
} }
// Check if it is a position // Check if it is a position
} else if (obj.type == kObjectTypeArray) { } else if (obj.type == kObjectTypeArray) {
Array pos = obj.data.array; Array pos = obj.data.array;
if (pos.size != 2 if (pos.size != 2
@@ -1662,8 +1645,7 @@ free_exit:
/// @param what The name of the object, used for error message /// @param what The name of the object, used for error message
/// @param nil_value What to return if the type is nil. /// @param nil_value What to return if the type is nil.
/// @param err Set if there was an error in converting to a bool /// @param err Set if there was an error in converting to a bool
bool api_object_to_bool(Object obj, const char *what, bool api_object_to_bool(Object obj, const char *what, bool nil_value, Error *err)
bool nil_value, Error *err)
{ {
if (obj.type == kObjectTypeBoolean) { if (obj.type == kObjectTypeBoolean) {
return obj.data.boolean; return obj.data.boolean;
@@ -1766,7 +1748,7 @@ static bool parse_float_relative(String relative, FloatRelative *out)
char *str = relative.data; char *str = relative.data;
if (striequal(str, "editor")) { if (striequal(str, "editor")) {
*out = kFloatRelativeEditor; *out = kFloatRelativeEditor;
} else if (striequal(str, "win")) { } else if (striequal(str, "win")) {
*out = kFloatRelativeWindow; *out = kFloatRelativeWindow;
} else if (striequal(str, "cursor")) { } else if (striequal(str, "cursor")) {
*out = kFloatRelativeCursor; *out = kFloatRelativeCursor;
@@ -1800,7 +1782,7 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
{ "shadow", { "", "", " ", " ", " ", " ", " ", "" }, true }, { "shadow", { "", "", " ", " ", " ", " ", " ", "" }, true },
{ "rounded", { "", "", "", "", "", "", "", "" }, false }, { "rounded", { "", "", "", "", "", "", "", "" }, false },
{ "solid", { " ", " ", " ", " ", " ", " ", " ", " " }, false }, { "solid", { " ", " ", " ", " ", " ", " ", " ", " " }, false },
{ NULL, { { NUL } } , false }, { NULL, { { NUL } }, false },
}; };
schar_T *chars = fconfig->border_chars; schar_T *chars = fconfig->border_chars;
@@ -1837,7 +1819,6 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
return; return;
} }
} }
} else if (iytem.type == kObjectTypeString) { } else if (iytem.type == kObjectTypeString) {
string = iytem.data.string; string = iytem.data.string;
} else { } else {
@@ -1896,8 +1877,8 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
} }
} }
bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf, bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf, bool new_win,
bool new_win, Error *err) Error *err)
{ {
// TODO(bfredl): use a get/has_key interface instead and get rid of extra // TODO(bfredl): use a get/has_key interface instead and get rid of extra
// flags // flags
@@ -1998,13 +1979,13 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
has_bufpos = true; has_bufpos = true;
} else if (!strcmp(key, "external")) { } else if (!strcmp(key, "external")) {
has_external = fconfig->external has_external = fconfig->external
= api_object_to_bool(val, "'external' key", false, err); = api_object_to_bool(val, "'external' key", false, err);
if (ERROR_SET(err)) { if (ERROR_SET(err)) {
return false; return false;
} }
} else if (!strcmp(key, "focusable")) { } else if (!strcmp(key, "focusable")) {
fconfig->focusable fconfig->focusable
= api_object_to_bool(val, "'focusable' key", true, err); = api_object_to_bool(val, "'focusable' key", true, err);
if (ERROR_SET(err)) { if (ERROR_SET(err)) {
return false; return false;
} }
@@ -2031,13 +2012,13 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
fconfig->style = kWinStyleUnused; fconfig->style = kWinStyleUnused;
} else if (striequal(val.data.string.data, "minimal")) { } else if (striequal(val.data.string.data, "minimal")) {
fconfig->style = kWinStyleMinimal; fconfig->style = kWinStyleMinimal;
} else { } else {
api_set_error(err, kErrorTypeValidation, api_set_error(err, kErrorTypeValidation,
"Invalid value of 'style' key"); "Invalid value of 'style' key");
} }
} else if (strequal(key, "noautocmd") && new_win) { } else if (strequal(key, "noautocmd") && new_win) {
fconfig->noautocmd fconfig->noautocmd
= api_object_to_bool(val, "'noautocmd' key", false, err); = api_object_to_bool(val, "'noautocmd' key", false, err);
if (ERROR_SET(err)) { if (ERROR_SET(err)) {
return false; return false;
} }

View File

@@ -5,10 +5,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "nvim/api/tabpage.h"
#include "nvim/api/vim.h"
#include "nvim/api/private/defs.h" #include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h" #include "nvim/api/private/helpers.h"
#include "nvim/api/tabpage.h"
#include "nvim/api/vim.h"
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/window.h" #include "nvim/window.h"
@@ -53,7 +53,7 @@ Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err)
tabpage_T *tab = find_tab_by_handle(tabpage, err); tabpage_T *tab = find_tab_by_handle(tabpage, err);
if (!tab) { if (!tab) {
return (Object) OBJECT_INIT; return (Object)OBJECT_INIT;
} }
return dict_get_value(tab->tp_vars, name, err); return dict_get_value(tab->tp_vars, name, err);
@@ -65,10 +65,7 @@ Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err)
/// @param name Variable name /// @param name Variable name
/// @param value Variable value /// @param value Variable value
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_tabpage_set_var(Tabpage tabpage, void nvim_tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
String name,
Object value,
Error *err)
FUNC_API_SINCE(1) FUNC_API_SINCE(1)
{ {
tabpage_T *tab = find_tab_by_handle(tabpage, err); tabpage_T *tab = find_tab_by_handle(tabpage, err);

View File

@@ -2,22 +2,22 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h> #include <assert.h>
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "nvim/vim.h"
#include "nvim/ui.h"
#include "nvim/memory.h"
#include "nvim/map.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/api/ui.h"
#include "nvim/api/private/defs.h" #include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h" #include "nvim/api/private/helpers.h"
#include "nvim/popupmnu.h" #include "nvim/api/ui.h"
#include "nvim/cursor_shape.h" #include "nvim/cursor_shape.h"
#include "nvim/highlight.h" #include "nvim/highlight.h"
#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h" #include "nvim/screen.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
#include "nvim/window.h" #include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -85,8 +85,8 @@ void remote_ui_wait_for_attach(void)
/// @param height Requested screen rows /// @param height Requested screen rows
/// @param options |ui-option| map /// @param options |ui-option| map
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictionary options,
Dictionary options, Error *err) Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{ {
if (pmap_has(uint64_t)(&connected_uis, channel_id)) { if (pmap_has(uint64_t)(&connected_uis, channel_id)) {
@@ -171,8 +171,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
} }
/// @deprecated /// @deprecated
void ui_attach(uint64_t channel_id, Integer width, Integer height, void ui_attach(uint64_t channel_id, Integer width, Integer height, Boolean enable_rgb, Error *err)
Boolean enable_rgb, Error *err)
{ {
Dictionary opts = ARRAY_DICT_INIT; Dictionary opts = ARRAY_DICT_INIT;
PUT(opts, "rgb", BOOLEAN_OBJ(enable_rgb)); PUT(opts, "rgb", BOOLEAN_OBJ(enable_rgb));
@@ -198,8 +197,7 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
} }
void nvim_ui_try_resize(uint64_t channel_id, Integer width, void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Error *err)
Integer height, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{ {
if (!pmap_has(uint64_t)(&connected_uis, channel_id)) { if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
@@ -220,8 +218,7 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width,
ui_refresh(); ui_refresh();
} }
void nvim_ui_set_option(uint64_t channel_id, String name, void nvim_ui_set_option(uint64_t channel_id, String name, Object value, Error *error)
Object value, Error *error)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{ {
if (!pmap_has(uint64_t)(&connected_uis, channel_id)) { if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
@@ -234,8 +231,7 @@ void nvim_ui_set_option(uint64_t channel_id, String name,
ui_set_option(ui, false, name, value, error); ui_set_option(ui, false, name, value, error);
} }
static void ui_set_option(UI *ui, bool init, String name, Object value, static void ui_set_option(UI *ui, bool init, String name, Object value, Error *error)
Error *error)
{ {
if (strequal(name.data, "override")) { if (strequal(name.data, "override")) {
if (value.type != kObjectTypeBoolean) { if (value.type != kObjectTypeBoolean) {
@@ -300,8 +296,8 @@ static void ui_set_option(UI *ui, bool init, String name, Object value,
/// @param width The new requested width. /// @param width The new requested width.
/// @param height The new requested height. /// @param height The new requested height.
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, Integer height,
Integer height, Error *err) Error *err)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY
{ {
if (!pmap_has(uint64_t)(&connected_uis, channel_id)) { if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
@@ -359,8 +355,8 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err)
/// @param row Popupmenu row. /// @param row Popupmenu row.
/// @param col Popupmenu height. /// @param col Popupmenu height.
/// @param[out] err Error details, if any. /// @param[out] err Error details, if any.
void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Float row, Float col,
Float row, Float col, Error *err) Error *err)
FUNC_API_SINCE(7) FUNC_API_REMOTE_ONLY FUNC_API_SINCE(7) FUNC_API_REMOTE_ONLY
{ {
if (!pmap_has(uint64_t)(&connected_uis, channel_id)) { if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
@@ -424,8 +420,7 @@ static void remote_ui_grid_clear(UI *ui, Integer grid)
push_call(ui, name, args); push_call(ui, name, args);
} }
static void remote_ui_grid_resize(UI *ui, Integer grid, static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
Integer width, Integer height)
{ {
Array args = ARRAY_DICT_INIT; Array args = ARRAY_DICT_INIT;
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
@@ -437,9 +432,8 @@ static void remote_ui_grid_resize(UI *ui, Integer grid,
push_call(ui, name, args); push_call(ui, name, args);
} }
static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left,
Integer bot, Integer left, Integer right, Integer right, Integer rows, Integer cols)
Integer rows, Integer cols)
{ {
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
Array args = ARRAY_DICT_INIT; Array args = ARRAY_DICT_INIT;
@@ -474,8 +468,7 @@ static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top,
} }
} }
static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
Integer rgb_bg, Integer rgb_sp,
Integer cterm_fg, Integer cterm_bg) Integer cterm_fg, Integer cterm_bg)
{ {
if (!ui->ui_ext[kUITermColors]) { if (!ui->ui_ext[kUITermColors]) {
@@ -505,8 +498,8 @@ static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg,
} }
} }
static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
HlAttrs cterm_attrs, Array info) Array info)
{ {
if (!ui->ui_ext[kUILinegrid]) { if (!ui->ui_ext[kUILinegrid]) {
return; return;
@@ -543,8 +536,7 @@ static void remote_ui_highlight_set(UI *ui, int id)
} }
/// "true" cursor used only for input focus /// "true" cursor used only for input focus
static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col)
Integer col)
{ {
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
Array args = ARRAY_DICT_INIT; Array args = ARRAY_DICT_INIT;
@@ -584,11 +576,9 @@ static void remote_ui_put(UI *ui, const char *cell)
push_call(ui, "put", args); push_call(ui, "put", args);
} }
static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
Integer startcol, Integer endcol, Integer clearcol, Integer clearattr, LineFlags flags,
Integer clearcol, Integer clearattr, const schar_T *chunk, const sattr_T *attrs)
LineFlags flags, const schar_T *chunk,
const sattr_T *attrs)
{ {
UIData *data = ui->data; UIData *data = ui->data;
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
@@ -729,7 +719,7 @@ static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed)
if (ui->ui_ext[kUIWildmenu]) { if (ui->ui_ext[kUIWildmenu]) {
if (strequal(name, "popupmenu_show")) { if (strequal(name, "popupmenu_show")) {
data->wildmenu_active = (args.items[4].data.integer == -1) data->wildmenu_active = (args.items[4].data.integer == -1)
|| !ui->ui_ext[kUIPopupmenu]; || !ui->ui_ext[kUIPopupmenu];
if (data->wildmenu_active) { if (data->wildmenu_active) {
Array new_args = ARRAY_DICT_INIT; Array new_args = ARRAY_DICT_INIT;
Array items = args.items[0].data.array; Array items = args.items[0].data.array;

View File

@@ -3,54 +3,54 @@
#include <assert.h> #include <assert.h>
#include <inttypes.h> #include <inttypes.h>
#include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include "nvim/api/vim.h" #include "nvim/api/buffer.h"
#include "nvim/ascii.h" #include "nvim/api/deprecated.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h" #include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h" #include "nvim/api/private/dispatch.h"
#include "nvim/api/buffer.h" #include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/api/window.h" #include "nvim/api/window.h"
#include "nvim/api/deprecated.h" #include "nvim/ascii.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/lua/executor.h"
#include "nvim/vim.h"
#include "nvim/buffer.h" #include "nvim/buffer.h"
#include "nvim/context.h" #include "nvim/context.h"
#include "nvim/file_search.h" #include "nvim/decoration.h"
#include "nvim/highlight.h"
#include "nvim/window.h"
#include "nvim/types.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
#include "nvim/screen.h"
#include "nvim/memline.h"
#include "nvim/mark.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/popupmnu.h"
#include "nvim/edit.h" #include "nvim/edit.h"
#include "nvim/eval.h" #include "nvim/eval.h"
#include "nvim/eval/typval.h" #include "nvim/eval/typval.h"
#include "nvim/eval/userfunc.h" #include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
#include "nvim/file_search.h"
#include "nvim/fileio.h" #include "nvim/fileio.h"
#include "nvim/getchar.h"
#include "nvim/highlight.h"
#include "nvim/lua/executor.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h" #include "nvim/move.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/ops.h" #include "nvim/ops.h"
#include "nvim/option.h" #include "nvim/option.h"
#include "nvim/state.h"
#include "nvim/decoration.h"
#include "nvim/syntax.h"
#include "nvim/getchar.h"
#include "nvim/os/input.h" #include "nvim/os/input.h"
#include "nvim/os/process.h" #include "nvim/os/process.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h"
#include "nvim/state.h"
#include "nvim/syntax.h"
#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
#include "nvim/viml/parser/expressions.h" #include "nvim/viml/parser/expressions.h"
#include "nvim/viml/parser/parser.h" #include "nvim/viml/parser/parser.h"
#include "nvim/ui.h" #include "nvim/window.h"
#define LINE_BUFFER_SIZE 4096 #define LINE_BUFFER_SIZE 4096
@@ -301,12 +301,18 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
for (size_t i = 0; i < mode.size; ++i) { for (size_t i = 0; i < mode.size; ++i) {
switch (mode.data[i]) { switch (mode.data[i]) {
case 'n': remap = false; break; case 'n':
case 'm': remap = true; break; remap = false; break;
case 't': typed = true; break; case 'm':
case 'i': insert = true; break; remap = true; break;
case 'x': execute = true; break; case 't':
case '!': dangerous = true; break; typed = true; break;
case 'i':
insert = true; break;
case 'x':
execute = true; break;
case '!':
dangerous = true; break;
} }
} }
@@ -316,11 +322,11 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
char *keys_esc; char *keys_esc;
if (escape_csi) { if (escape_csi) {
// Need to escape K_SPECIAL and CSI before putting the string in the // Need to escape K_SPECIAL and CSI before putting the string in the
// typeahead buffer. // typeahead buffer.
keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data);
} else { } else {
keys_esc = keys.data; keys_esc = keys.data;
} }
ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE), ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE),
insert ? 0 : typebuf.tb_len, !typed, false); insert ? 0 : typebuf.tb_len, !typed, false);
@@ -329,7 +335,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
} }
if (escape_csi) { if (escape_csi) {
xfree(keys_esc); xfree(keys_esc);
} }
if (execute) { if (execute) {
@@ -391,8 +397,8 @@ Integer nvim_input(String keys)
/// @param row Mouse row-position (zero-based, like redraw events) /// @param row Mouse row-position (zero-based, like redraw events)
/// @param col Mouse column-position (zero-based, like redraw events) /// @param col Mouse column-position (zero-based, like redraw events)
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_input_mouse(String button, String action, String modifier, void nvim_input_mouse(String button, String action, String modifier, Integer grid, Integer row,
Integer grid, Integer row, Integer col, Error *err) Integer col, Error *err)
FUNC_API_SINCE(6) FUNC_API_FAST FUNC_API_SINCE(6) FUNC_API_FAST
{ {
if (button.data == NULL || action.data == NULL) { if (button.data == NULL || action.data == NULL) {
@@ -469,8 +475,7 @@ error:
/// @param special Replace |keycodes|, e.g. <CR> becomes a "\n" char. /// @param special Replace |keycodes|, e.g. <CR> becomes a "\n" char.
/// @see replace_termcodes /// @see replace_termcodes
/// @see cpoptions /// @see cpoptions
String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special)
Boolean special)
FUNC_API_SINCE(1) FUNC_API_SINCE(1)
{ {
if (str.size == 0) { if (str.size == 0) {
@@ -499,32 +504,32 @@ Object nvim_eval(String expr, Error *err)
Object rv = OBJECT_INIT; Object rv = OBJECT_INIT;
TRY_WRAP({ TRY_WRAP({
// Initialize `force_abort` and `suppress_errthrow` at the top level. // Initialize `force_abort` and `suppress_errthrow` at the top level.
if (!recursive) { if (!recursive) {
force_abort = false; force_abort = false;
suppress_errthrow = false; suppress_errthrow = false;
current_exception = NULL; current_exception = NULL;
// `did_emsg` is set by emsg(), which cancels execution. // `did_emsg` is set by emsg(), which cancels execution.
did_emsg = false; did_emsg = false;
}
recursive++;
try_start();
typval_T rettv;
int ok = eval0((char_u *)expr.data, &rettv, NULL, true);
if (!try_end(err)) {
if (ok == FAIL) {
// Should never happen, try_end() should get the error. #8371
api_set_error(err, kErrorTypeException,
"Failed to evaluate expression: '%.*s'", 256, expr.data);
} else {
rv = vim_to_object(&rettv);
} }
} recursive++;
try_start();
tv_clear(&rettv); typval_T rettv;
recursive--; int ok = eval0((char_u *)expr.data, &rettv, NULL, true);
if (!try_end(err)) {
if (ok == FAIL) {
// Should never happen, try_end() should get the error. #8371
api_set_error(err, kErrorTypeException,
"Failed to evaluate expression: '%.*s'", 256, expr.data);
} else {
rv = vim_to_object(&rettv);
}
}
tv_clear(&rettv);
recursive--;
}); });
return rv; return rv;
@@ -597,31 +602,31 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err)
} }
TRY_WRAP({ TRY_WRAP({
// Initialize `force_abort` and `suppress_errthrow` at the top level. // Initialize `force_abort` and `suppress_errthrow` at the top level.
if (!recursive) { if (!recursive) {
force_abort = false; force_abort = false;
suppress_errthrow = false; suppress_errthrow = false;
current_exception = NULL; current_exception = NULL;
// `did_emsg` is set by emsg(), which cancels execution. // `did_emsg` is set by emsg(), which cancels execution.
did_emsg = false; did_emsg = false;
} }
recursive++; recursive++;
try_start(); try_start();
typval_T rettv; typval_T rettv;
funcexe_T funcexe = FUNCEXE_INIT; funcexe_T funcexe = FUNCEXE_INIT;
funcexe.firstline = curwin->w_cursor.lnum; funcexe.firstline = curwin->w_cursor.lnum;
funcexe.lastline = curwin->w_cursor.lnum; funcexe.lastline = curwin->w_cursor.lnum;
funcexe.evaluate = true; funcexe.evaluate = true;
funcexe.selfdict = self; funcexe.selfdict = self;
// call_func() retval is deceptive, ignore it. Instead we set `msg_list` // call_func() retval is deceptive, ignore it. Instead we set `msg_list`
// (see above) to capture abort-causing non-exception errors. // (see above) to capture abort-causing non-exception errors.
(void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size, (void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size,
vim_args, &funcexe); vim_args, &funcexe);
if (!try_end(err)) { if (!try_end(err)) {
rv = vim_to_object(&rettv); rv = vim_to_object(&rettv);
} }
tv_clear(&rettv); tv_clear(&rettv);
recursive--; recursive--;
}); });
free_vim_args: free_vim_args:
@@ -663,31 +668,28 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err)
typval_T rettv; typval_T rettv;
bool mustfree = false; bool mustfree = false;
switch (dict.type) { switch (dict.type) {
case kObjectTypeString: { case kObjectTypeString:
try_start(); try_start();
if (eval0((char_u *)dict.data.string.data, &rettv, NULL, true) == FAIL) { if (eval0((char_u *)dict.data.string.data, &rettv, NULL, true) == FAIL) {
api_set_error(err, kErrorTypeException, api_set_error(err, kErrorTypeException,
"Failed to evaluate dict expression"); "Failed to evaluate dict expression");
}
if (try_end(err)) {
return rv;
}
// Evaluation of the string arg created a new dict or increased the
// refcount of a dict. Not necessary for a RPC dict.
mustfree = true;
break;
} }
case kObjectTypeDictionary: { if (try_end(err)) {
if (!object_to_vim(dict, &rettv, err)) {
goto end;
}
break;
}
default: {
api_set_error(err, kErrorTypeValidation,
"dict argument type must be String or Dictionary");
return rv; return rv;
} }
// Evaluation of the string arg created a new dict or increased the
// refcount of a dict. Not necessary for a RPC dict.
mustfree = true;
break;
case kObjectTypeDictionary:
if (!object_to_vim(dict, &rettv, err)) {
goto end;
}
break;
default:
api_set_error(err, kErrorTypeValidation,
"dict argument type must be String or Dictionary");
return rv;
} }
dict_T *self_dict = rettv.vval.v_dict; dict_T *self_dict = rettv.vval.v_dict;
if (rettv.v_type != VAR_DICT || !self_dict) { if (rettv.v_type != VAR_DICT || !self_dict) {
@@ -1420,8 +1422,7 @@ void nvim_chan_send(Integer chan, String data, Error *err)
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// ///
/// @return Window handle, or 0 on error /// @return Window handle, or 0 on error
Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config, Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config, Error *err)
Error *err)
FUNC_API_SINCE(6) FUNC_API_SINCE(6)
FUNC_API_CHECK_TEXTLOCK FUNC_API_CHECK_TEXTLOCK
{ {
@@ -1579,7 +1580,7 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
bool cancel = false; bool cancel = false;
if (phase < -1 || phase > 3) { if (phase < -1 || phase > 3) {
api_set_error(err, kErrorTypeValidation, "Invalid phase: %"PRId64, phase); api_set_error(err, kErrorTypeValidation, "Invalid phase: %" PRId64, phase);
return false; return false;
} }
Array args = ARRAY_DICT_INIT; Array args = ARRAY_DICT_INIT;
@@ -1643,8 +1644,7 @@ theend:
/// @param after If true insert after cursor (like |p|), or before (like |P|). /// @param after If true insert after cursor (like |p|), or before (like |P|).
/// @param follow If true place cursor at end of inserted text. /// @param follow If true place cursor at end of inserted text.
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_put(ArrayOf(String) lines, String type, Boolean after, void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Error *err)
Boolean follow, Error *err)
FUNC_API_SINCE(6) FUNC_API_SINCE(6)
FUNC_API_CHECK_TEXTLOCK FUNC_API_CHECK_TEXTLOCK
{ {
@@ -1885,8 +1885,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// as keys excluding |<buffer>| but including |noremap|. /// as keys excluding |<buffer>| but including |noremap|.
/// Values are Booleans. Unknown key is an error. /// Values are Booleans. Unknown key is an error.
/// @param[out] err Error details, if any. /// @param[out] err Error details, if any.
void nvim_set_keymap(String mode, String lhs, String rhs, void nvim_set_keymap(String mode, String lhs, String rhs, Dictionary opts, Error *err)
Dictionary opts, Error *err)
FUNC_API_SINCE(6) FUNC_API_SINCE(6)
{ {
modify_keymap(-1, false, mode, lhs, rhs, opts, err); modify_keymap(-1, false, mode, lhs, rhs, opts, err);
@@ -1983,10 +1982,8 @@ Array nvim_get_api_info(uint64_t channel_id)
/// .png or .svg format is preferred. /// .png or .svg format is preferred.
/// ///
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_set_client_info(uint64_t channel_id, String name, void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, String type,
Dictionary version, String type, Dictionary methods, Dictionary attributes, Error *err)
Dictionary methods, Dictionary attributes,
Error *err)
FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY
{ {
Dictionary info = ARRAY_DICT_INIT; Dictionary info = ARRAY_DICT_INIT;
@@ -2114,9 +2111,9 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
Array args = call.items[1].data.array; Array args = call.items[1].data.array;
MsgpackRpcRequestHandler handler = MsgpackRpcRequestHandler handler =
msgpack_rpc_get_handler_for(name.data, msgpack_rpc_get_handler_for(name.data,
name.size, name.size,
&nested_error); &nested_error);
if (ERROR_SET(&nested_error)) { if (ERROR_SET(&nested_error)) {
break; break;
@@ -2232,26 +2229,26 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// - "svalue": String, value for "SingleQuotedString" and /// - "svalue": String, value for "SingleQuotedString" and
/// "DoubleQuotedString" nodes. /// "DoubleQuotedString" nodes.
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Error *err)
Error *err)
FUNC_API_SINCE(4) FUNC_API_FAST FUNC_API_SINCE(4) FUNC_API_FAST
{ {
int pflags = 0; int pflags = 0;
for (size_t i = 0 ; i < flags.size ; i++) { for (size_t i = 0 ; i < flags.size ; i++) {
switch (flags.data[i]) { switch (flags.data[i]) {
case 'm': { pflags |= kExprFlagsMulti; break; } case 'm':
case 'E': { pflags |= kExprFlagsDisallowEOC; break; } pflags |= kExprFlagsMulti; break;
case 'l': { pflags |= kExprFlagsParseLet; break; } case 'E':
case NUL: { pflags |= kExprFlagsDisallowEOC; break;
api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", case 'l':
(unsigned)flags.data[i]); pflags |= kExprFlagsParseLet; break;
return (Dictionary)ARRAY_DICT_INIT; case NUL:
} api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)",
default: { (unsigned)flags.data[i]);
api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", return (Dictionary)ARRAY_DICT_INIT;
flags.data[i], (unsigned)flags.data[i]); default:
return (Dictionary)ARRAY_DICT_INIT; api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)",
} flags.data[i], (unsigned)flags.data[i]);
return (Dictionary)ARRAY_DICT_INIT;
} }
} }
ParserLine parser_lines[] = { ParserLine parser_lines[] = {
@@ -2267,15 +2264,14 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
kvi_init(colors); kvi_init(colors);
ParserHighlight *const colors_p = (highlight ? &colors : NULL); ParserHighlight *const colors_p = (highlight ? &colors : NULL);
ParserState pstate; ParserState pstate;
viml_parser_init( viml_parser_init(&pstate, parser_simple_get_line, &plines_p, colors_p);
&pstate, parser_simple_get_line, &plines_p, colors_p);
ExprAST east = viml_pexpr_parse(&pstate, pflags); ExprAST east = viml_pexpr_parse(&pstate, pflags);
const size_t ret_size = ( const size_t ret_size = (
2 // "ast", "len" 2 // "ast", "len"
+ (size_t)(east.err.msg != NULL) // "error" + (size_t)(east.err.msg != NULL) // "error"
+ (size_t)highlight // "highlight" + (size_t)highlight // "highlight"
+ 0); + 0);
Dictionary ret = { Dictionary ret = {
.items = xmalloc(ret_size * sizeof(ret.items[0])), .items = xmalloc(ret_size * sizeof(ret.items[0])),
.size = 0, .size = 0,
@@ -2362,23 +2358,23 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
} else { } else {
if (cur_item.ret_node_p->type == kObjectTypeNil) { if (cur_item.ret_node_p->type == kObjectTypeNil) {
const size_t ret_node_items_size = (size_t)( const size_t ret_node_items_size = (size_t)(
3 // "type", "start" and "len" 3 // "type", "start" and "len"
+ (node->children != NULL) // "children" + (node->children != NULL) // "children"
+ (node->type == kExprNodeOption + (node->type == kExprNodeOption
|| node->type == kExprNodePlainIdentifier) // "scope" || node->type == kExprNodePlainIdentifier) // "scope"
+ (node->type == kExprNodeOption + (node->type == kExprNodeOption
|| node->type == kExprNodePlainIdentifier || node->type == kExprNodePlainIdentifier
|| node->type == kExprNodePlainKey || node->type == kExprNodePlainKey
|| node->type == kExprNodeEnvironment) // "ident" || node->type == kExprNodeEnvironment) // "ident"
+ (node->type == kExprNodeRegister) // "name" + (node->type == kExprNodeRegister) // "name"
+ (3 // "cmp_type", "ccs_strategy", "invert" + (3 // "cmp_type", "ccs_strategy", "invert"
* (node->type == kExprNodeComparison)) * (node->type == kExprNodeComparison))
+ (node->type == kExprNodeInteger) // "ivalue" + (node->type == kExprNodeInteger) // "ivalue"
+ (node->type == kExprNodeFloat) // "fvalue" + (node->type == kExprNodeFloat) // "fvalue"
+ (node->type == kExprNodeDoubleQuotedString + (node->type == kExprNodeDoubleQuotedString
|| node->type == kExprNodeSingleQuotedString) // "svalue" || node->type == kExprNodeSingleQuotedString) // "svalue"
+ (node->type == kExprNodeAssignment) // "augmentation" + (node->type == kExprNodeAssignment) // "augmentation"
+ 0); + 0);
Dictionary ret_node = { Dictionary ret_node = {
.items = xmalloc(ret_node_items_size * sizeof(ret_node.items[0])), .items = xmalloc(ret_node_items_size * sizeof(ret_node.items[0])),
.capacity = ret_node_items_size, .capacity = ret_node_items_size,
@@ -2432,151 +2428,138 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
.value = INTEGER_OBJ((Integer)node->len), .value = INTEGER_OBJ((Integer)node->len),
}; };
switch (node->type) { switch (node->type) {
case kExprNodeDoubleQuotedString: case kExprNodeDoubleQuotedString:
case kExprNodeSingleQuotedString: { case kExprNodeSingleQuotedString:
ret_node->items[ret_node->size++] = (KeyValuePair) { ret_node->items[ret_node->size++] = (KeyValuePair) {
.key = STATIC_CSTR_TO_STRING("svalue"), .key = STATIC_CSTR_TO_STRING("svalue"),
.value = STRING_OBJ(((String) { .value = STRING_OBJ(((String) {
.data = node->data.str.value, .data = node->data.str.value,
.size = node->data.str.size, .size = node->data.str.size,
})), })),
}; };
break; break;
} case kExprNodeOption:
case kExprNodeOption: { ret_node->items[ret_node->size++] = (KeyValuePair) {
ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("scope"),
.key = STATIC_CSTR_TO_STRING("scope"), .value = INTEGER_OBJ(node->data.opt.scope),
.value = INTEGER_OBJ(node->data.opt.scope), };
}; ret_node->items[ret_node->size++] = (KeyValuePair) {
ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("ident"),
.key = STATIC_CSTR_TO_STRING("ident"), .value = STRING_OBJ(((String) {
.value = STRING_OBJ(((String) { .data = xmemdupz(node->data.opt.ident,
.data = xmemdupz(node->data.opt.ident, node->data.opt.ident_len),
node->data.opt.ident_len), .size = node->data.opt.ident_len,
.size = node->data.opt.ident_len, })),
})), };
}; break;
break; case kExprNodePlainIdentifier:
} ret_node->items[ret_node->size++] = (KeyValuePair) {
case kExprNodePlainIdentifier: { .key = STATIC_CSTR_TO_STRING("scope"),
ret_node->items[ret_node->size++] = (KeyValuePair) { .value = INTEGER_OBJ(node->data.var.scope),
.key = STATIC_CSTR_TO_STRING("scope"), };
.value = INTEGER_OBJ(node->data.var.scope), ret_node->items[ret_node->size++] = (KeyValuePair) {
}; .key = STATIC_CSTR_TO_STRING("ident"),
ret_node->items[ret_node->size++] = (KeyValuePair) { .value = STRING_OBJ(((String) {
.key = STATIC_CSTR_TO_STRING("ident"), .data = xmemdupz(node->data.var.ident,
.value = STRING_OBJ(((String) { node->data.var.ident_len),
.data = xmemdupz(node->data.var.ident, .size = node->data.var.ident_len,
node->data.var.ident_len), })),
.size = node->data.var.ident_len, };
})), break;
}; case kExprNodePlainKey:
break; ret_node->items[ret_node->size++] = (KeyValuePair) {
} .key = STATIC_CSTR_TO_STRING("ident"),
case kExprNodePlainKey: { .value = STRING_OBJ(((String) {
ret_node->items[ret_node->size++] = (KeyValuePair) { .data = xmemdupz(node->data.var.ident,
.key = STATIC_CSTR_TO_STRING("ident"), node->data.var.ident_len),
.value = STRING_OBJ(((String) { .size = node->data.var.ident_len,
.data = xmemdupz(node->data.var.ident, })),
node->data.var.ident_len), };
.size = node->data.var.ident_len, break;
})), case kExprNodeEnvironment:
}; ret_node->items[ret_node->size++] = (KeyValuePair) {
break; .key = STATIC_CSTR_TO_STRING("ident"),
} .value = STRING_OBJ(((String) {
case kExprNodeEnvironment: { .data = xmemdupz(node->data.env.ident,
ret_node->items[ret_node->size++] = (KeyValuePair) { node->data.env.ident_len),
.key = STATIC_CSTR_TO_STRING("ident"), .size = node->data.env.ident_len,
.value = STRING_OBJ(((String) { })),
.data = xmemdupz(node->data.env.ident, };
node->data.env.ident_len), break;
.size = node->data.env.ident_len, case kExprNodeRegister:
})), ret_node->items[ret_node->size++] = (KeyValuePair) {
}; .key = STATIC_CSTR_TO_STRING("name"),
break; .value = INTEGER_OBJ(node->data.reg.name),
} };
case kExprNodeRegister: { break;
ret_node->items[ret_node->size++] = (KeyValuePair) { case kExprNodeComparison:
.key = STATIC_CSTR_TO_STRING("name"), ret_node->items[ret_node->size++] = (KeyValuePair) {
.value = INTEGER_OBJ(node->data.reg.name), .key = STATIC_CSTR_TO_STRING("cmp_type"),
}; .value = STRING_OBJ(cstr_to_string(eltkn_cmp_type_tab[node->data.cmp.type])),
break; };
} ret_node->items[ret_node->size++] = (KeyValuePair) {
case kExprNodeComparison: { .key = STATIC_CSTR_TO_STRING("ccs_strategy"),
ret_node->items[ret_node->size++] = (KeyValuePair) { .value = STRING_OBJ(cstr_to_string(ccs_tab[node->data.cmp.ccs])),
.key = STATIC_CSTR_TO_STRING("cmp_type"), };
.value = STRING_OBJ(cstr_to_string( ret_node->items[ret_node->size++] = (KeyValuePair) {
eltkn_cmp_type_tab[node->data.cmp.type])), .key = STATIC_CSTR_TO_STRING("invert"),
}; .value = BOOLEAN_OBJ(node->data.cmp.inv),
ret_node->items[ret_node->size++] = (KeyValuePair) { };
.key = STATIC_CSTR_TO_STRING("ccs_strategy"), break;
.value = STRING_OBJ(cstr_to_string( case kExprNodeFloat:
ccs_tab[node->data.cmp.ccs])), ret_node->items[ret_node->size++] = (KeyValuePair) {
}; .key = STATIC_CSTR_TO_STRING("fvalue"),
ret_node->items[ret_node->size++] = (KeyValuePair) { .value = FLOAT_OBJ(node->data.flt.value),
.key = STATIC_CSTR_TO_STRING("invert"), };
.value = BOOLEAN_OBJ(node->data.cmp.inv), break;
}; case kExprNodeInteger:
break; ret_node->items[ret_node->size++] = (KeyValuePair) {
} .key = STATIC_CSTR_TO_STRING("ivalue"),
case kExprNodeFloat: { .value = INTEGER_OBJ((Integer)(
ret_node->items[ret_node->size++] = (KeyValuePair) { node->data.num.value > API_INTEGER_MAX
.key = STATIC_CSTR_TO_STRING("fvalue"),
.value = FLOAT_OBJ(node->data.flt.value),
};
break;
}
case kExprNodeInteger: {
ret_node->items[ret_node->size++] = (KeyValuePair) {
.key = STATIC_CSTR_TO_STRING("ivalue"),
.value = INTEGER_OBJ((Integer)(
node->data.num.value > API_INTEGER_MAX
? API_INTEGER_MAX ? API_INTEGER_MAX
: (Integer)node->data.num.value)), : (Integer)node->data.num.value)),
}; };
break; break;
} case kExprNodeAssignment: {
case kExprNodeAssignment: { const ExprAssignmentType asgn_type = node->data.ass.type;
const ExprAssignmentType asgn_type = node->data.ass.type; ret_node->items[ret_node->size++] = (KeyValuePair) {
ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("augmentation"),
.key = STATIC_CSTR_TO_STRING("augmentation"), .value = STRING_OBJ(asgn_type == kExprAsgnPlain
.value = STRING_OBJ(
asgn_type == kExprAsgnPlain
? (String)STRING_INIT ? (String)STRING_INIT
: cstr_to_string(expr_asgn_type_tab[asgn_type])), : cstr_to_string(expr_asgn_type_tab[asgn_type])),
}; };
break; break;
} }
case kExprNodeMissing: case kExprNodeMissing:
case kExprNodeOpMissing: case kExprNodeOpMissing:
case kExprNodeTernary: case kExprNodeTernary:
case kExprNodeTernaryValue: case kExprNodeTernaryValue:
case kExprNodeSubscript: case kExprNodeSubscript:
case kExprNodeListLiteral: case kExprNodeListLiteral:
case kExprNodeUnaryPlus: case kExprNodeUnaryPlus:
case kExprNodeBinaryPlus: case kExprNodeBinaryPlus:
case kExprNodeNested: case kExprNodeNested:
case kExprNodeCall: case kExprNodeCall:
case kExprNodeComplexIdentifier: case kExprNodeComplexIdentifier:
case kExprNodeUnknownFigure: case kExprNodeUnknownFigure:
case kExprNodeLambda: case kExprNodeLambda:
case kExprNodeDictLiteral: case kExprNodeDictLiteral:
case kExprNodeCurlyBracesIdentifier: case kExprNodeCurlyBracesIdentifier:
case kExprNodeComma: case kExprNodeComma:
case kExprNodeColon: case kExprNodeColon:
case kExprNodeArrow: case kExprNodeArrow:
case kExprNodeConcat: case kExprNodeConcat:
case kExprNodeConcatOrSubscript: case kExprNodeConcatOrSubscript:
case kExprNodeOr: case kExprNodeOr:
case kExprNodeAnd: case kExprNodeAnd:
case kExprNodeUnaryMinus: case kExprNodeUnaryMinus:
case kExprNodeBinaryMinus: case kExprNodeBinaryMinus:
case kExprNodeNot: case kExprNodeNot:
case kExprNodeMultiplication: case kExprNodeMultiplication:
case kExprNodeDivision: case kExprNodeDivision:
case kExprNodeMod: { case kExprNodeMod:
break; break;
}
} }
assert(cur_item.ret_node_p->data.dictionary.size assert(cur_item.ret_node_p->data.dictionary.size
== cur_item.ret_node_p->data.dictionary.capacity); == cur_item.ret_node_p->data.dictionary.capacity);
@@ -2806,8 +2789,8 @@ Object nvim_get_proc(Integer pid, Error *err)
/// `insert`. /// `insert`.
/// @param opts Optional parameters. Reserved for future use. /// @param opts Optional parameters. Reserved for future use.
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Dictionary opts,
Dictionary opts, Error *err) Error *err)
FUNC_API_SINCE(6) FUNC_API_SINCE(6)
{ {
if (opts.size > 0) { if (opts.size > 0) {
@@ -2904,8 +2887,7 @@ void nvim__screenshot(String path)
/// ["win", winid, bufnr, row] /// ["win", winid, bufnr, row]
/// - on_end: called at the end of a redraw cycle /// - on_end: called at the end of a redraw cycle
/// ["end", tick] /// ["end", tick]
void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Error *err)
Error *err)
FUNC_API_SINCE(7) FUNC_API_LUA_ONLY FUNC_API_SINCE(7) FUNC_API_LUA_ONLY
{ {
DecorProvider *p = get_decor_provider((NS)ns_id, true); DecorProvider *p = get_decor_provider((NS)ns_id, true);

View File

@@ -1,25 +1,25 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check // 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 // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include "nvim/api/private/defs.h" #include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h" #include "nvim/api/private/helpers.h"
#include "nvim/lua/executor.h"
#include "nvim/ex_docmd.h"
#include "nvim/vim.h"
#include "nvim/api/window.h" #include "nvim/api/window.h"
#include "nvim/ascii.h" #include "nvim/ascii.h"
#include "nvim/buffer.h" #include "nvim/buffer.h"
#include "nvim/cursor.h" #include "nvim/cursor.h"
#include "nvim/ex_docmd.h"
#include "nvim/globals.h" #include "nvim/globals.h"
#include "nvim/lua/executor.h"
#include "nvim/move.h" #include "nvim/move.h"
#include "nvim/option.h" #include "nvim/option.h"
#include "nvim/screen.h" #include "nvim/screen.h"
#include "nvim/syntax.h" #include "nvim/syntax.h"
#include "nvim/vim.h"
#include "nvim/window.h" #include "nvim/window.h"
/// Gets the current buffer in a window /// Gets the current buffer in a window
@@ -222,7 +222,7 @@ Object nvim_win_get_var(Window window, String name, Error *err)
win_T *win = find_window_by_handle(window, err); win_T *win = find_window_by_handle(window, err);
if (!win) { if (!win) {
return (Object) OBJECT_INIT; return (Object)OBJECT_INIT;
} }
return dict_get_value(win->w_vars, name, err); return dict_get_value(win->w_vars, name, err);
@@ -275,7 +275,7 @@ Object nvim_win_get_option(Window window, String name, Error *err)
win_T *win = find_window_by_handle(window, err); win_T *win = find_window_by_handle(window, err);
if (!win) { if (!win) {
return (Object) OBJECT_INIT; return (Object)OBJECT_INIT;
} }
return get_option_from(win, SREQ_WIN, name, err); return get_option_from(win, SREQ_WIN, name, err);
@@ -289,8 +289,7 @@ Object nvim_win_get_option(Window window, String name, Error *err)
/// @param name Option name /// @param name Option name
/// @param value Option value /// @param value Option value
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_win_set_option(uint64_t channel_id, Window window, void nvim_win_set_option(uint64_t channel_id, Window window, String name, Object value, Error *err)
String name, Object value, Error *err)
FUNC_API_SINCE(1) FUNC_API_SINCE(1)
{ {
win_T *win = find_window_by_handle(window, err); win_T *win = find_window_by_handle(window, err);
@@ -452,8 +451,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
PUT(rv, "bufpos", ARRAY_OBJ(pos)); PUT(rv, "bufpos", ARRAY_OBJ(pos));
} }
} }
PUT(rv, "anchor", STRING_OBJ(cstr_to_string( PUT(rv, "anchor", STRING_OBJ(cstr_to_string(float_anchor_str[config->anchor])));
float_anchor_str[config->anchor])));
PUT(rv, "row", FLOAT_OBJ(config->row)); PUT(rv, "row", FLOAT_OBJ(config->row));
PUT(rv, "col", FLOAT_OBJ(config->col)); PUT(rv, "col", FLOAT_OBJ(config->col));
PUT(rv, "zindex", INTEGER_OBJ(config->zindex)); PUT(rv, "zindex", INTEGER_OBJ(config->zindex));
@@ -463,8 +461,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
for (size_t i = 0; i < 8; i++) { for (size_t i = 0; i < 8; i++) {
Array tuple = ARRAY_DICT_INIT; Array tuple = ARRAY_DICT_INIT;
String s = cstrn_to_string( String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T));
(const char *)config->border_chars[i], sizeof(schar_T));
int hi_id = config->border_hl_ids[i]; int hi_id = config->border_hl_ids[i];
char_u *hi_name = syn_id2name(hi_id); char_u *hi_name = syn_id2name(hi_id);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,12 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check // 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 // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "nvim/eval/typval.h"
#include "nvim/eval/executor.h"
#include "nvim/eval.h" #include "nvim/eval.h"
#include "nvim/eval/executor.h"
#include "nvim/eval/typval.h"
#include "nvim/globals.h"
#include "nvim/message.h" #include "nvim/message.h"
#include "nvim/vim.h" #include "nvim/vim.h"
#include "nvim/globals.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/executor.c.generated.h" # include "eval/executor.c.generated.h"
@@ -23,117 +23,124 @@ char *e_listidx = N_("E684: list index out of range: %" PRId64);
/// @param[in] op Used operator. /// @param[in] op Used operator.
/// ///
/// @return OK or FAIL. /// @return OK or FAIL.
int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *const op)
const char *const op)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NO_SANITIZE_UNDEFINED FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NO_SANITIZE_UNDEFINED
{ {
// Can't do anything with a Funcref, a Dict or special value on the right. // Can't do anything with a Funcref, a Dict or special value on the right.
if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
&& tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL) { && tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL) {
switch (tv1->v_type) { switch (tv1->v_type) {
case VAR_DICT: case VAR_DICT:
case VAR_FUNC: case VAR_FUNC:
case VAR_PARTIAL: case VAR_PARTIAL:
case VAR_BOOL: case VAR_BOOL:
case VAR_SPECIAL: { case VAR_SPECIAL:
break;
case VAR_BLOB:
if (*op != '+' || tv2->v_type != VAR_BLOB) {
break; break;
} }
case VAR_BLOB: { // Blob += Blob
if (*op != '+' || tv2->v_type != VAR_BLOB) { if (tv1->vval.v_blob != NULL && tv2->vval.v_blob != NULL) {
break; blob_T *const b1 = tv1->vval.v_blob;
} blob_T *const b2 = tv2->vval.v_blob;
// Blob += Blob for (int i = 0; i < tv_blob_len(b2); i++) {
if (tv1->vval.v_blob != NULL && tv2->vval.v_blob != NULL) { ga_append(&b1->bv_ga, (char)tv_blob_get(b2, i));
blob_T *const b1 = tv1->vval.v_blob; }
blob_T *const b2 = tv2->vval.v_blob;
for (int i = 0; i < tv_blob_len(b2); i++) {
ga_append(&b1->bv_ga, (char)tv_blob_get(b2, i));
}
}
return OK;
} }
case VAR_LIST: { return OK;
if (*op != '+' || tv2->v_type != VAR_LIST) { case VAR_LIST:
break; if (*op != '+' || tv2->v_type != VAR_LIST) {
} break;
// List += List
if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) {
tv_list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
}
return OK;
} }
case VAR_NUMBER: // List += List
case VAR_STRING: { if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) {
if (tv2->v_type == VAR_LIST) { tv_list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
break; }
} return OK;
if (vim_strchr((char_u *)"+-*/%", *op) != NULL) { case VAR_NUMBER:
// nr += nr or nr -= nr, nr *= nr, nr /= nr, nr %= nr case VAR_STRING:
varnumber_T n = tv_get_number(tv1); if (tv2->v_type == VAR_LIST) {
if (tv2->v_type == VAR_FLOAT) { break;
float_T f = (float_T)n; }
if (vim_strchr((char_u *)"+-*/%", *op) != NULL) {
// nr += nr or nr -= nr, nr *= nr, nr /= nr, nr %= nr
varnumber_T n = tv_get_number(tv1);
if (tv2->v_type == VAR_FLOAT) {
float_T f = (float_T)n;
if (*op == '%') { if (*op == '%') {
break;
}
switch (*op) {
case '+': f += tv2->vval.v_float; break;
case '-': f -= tv2->vval.v_float; break;
case '*': f *= tv2->vval.v_float; break;
case '/': f /= tv2->vval.v_float; break;
}
tv_clear(tv1);
tv1->v_type = VAR_FLOAT;
tv1->vval.v_float = f;
} else {
switch (*op) {
case '+': n += tv_get_number(tv2); break;
case '-': n -= tv_get_number(tv2); break;
case '*': n *= tv_get_number(tv2); break;
case '/': n = num_divide(n, tv_get_number(tv2)); break;
case '%': n = num_modulus(n, tv_get_number(tv2)); break;
}
tv_clear(tv1);
tv1->v_type = VAR_NUMBER;
tv1->vval.v_number = n;
}
} else {
// str .= str
if (tv2->v_type == VAR_FLOAT) {
break; break;
} }
const char *tvs = tv_get_string(tv1); switch (*op) {
char numbuf[NUMBUFLEN]; case '+':
char *const s = (char *)concat_str( f += tv2->vval.v_float; break;
(const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2, case '-':
numbuf)); f -= tv2->vval.v_float; break;
case '*':
f *= tv2->vval.v_float; break;
case '/':
f /= tv2->vval.v_float; break;
}
tv_clear(tv1); tv_clear(tv1);
tv1->v_type = VAR_STRING; tv1->v_type = VAR_FLOAT;
tv1->vval.v_string = (char_u *)s; tv1->vval.v_float = f;
} else {
switch (*op) {
case '+':
n += tv_get_number(tv2); break;
case '-':
n -= tv_get_number(tv2); break;
case '*':
n *= tv_get_number(tv2); break;
case '/':
n = num_divide(n, tv_get_number(tv2)); break;
case '%':
n = num_modulus(n, tv_get_number(tv2)); break;
}
tv_clear(tv1);
tv1->v_type = VAR_NUMBER;
tv1->vval.v_number = n;
} }
return OK; } else {
} // str .= str
case VAR_FLOAT: { if (tv2->v_type == VAR_FLOAT) {
if (*op == '%' || *op == '.'
|| (tv2->v_type != VAR_FLOAT
&& tv2->v_type != VAR_NUMBER
&& tv2->v_type != VAR_STRING)) {
break; break;
} }
const float_T f = (tv2->v_type == VAR_FLOAT const char *tvs = tv_get_string(tv1);
char numbuf[NUMBUFLEN];
char *const s =
(char *)concat_str((const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2,
numbuf));
tv_clear(tv1);
tv1->v_type = VAR_STRING;
tv1->vval.v_string = (char_u *)s;
}
return OK;
case VAR_FLOAT: {
if (*op == '%' || *op == '.'
|| (tv2->v_type != VAR_FLOAT
&& tv2->v_type != VAR_NUMBER
&& tv2->v_type != VAR_STRING)) {
break;
}
const float_T f = (tv2->v_type == VAR_FLOAT
? tv2->vval.v_float ? tv2->vval.v_float
: (float_T)tv_get_number(tv2)); : (float_T)tv_get_number(tv2));
switch (*op) { switch (*op) {
case '+': tv1->vval.v_float += f; break; case '+':
case '-': tv1->vval.v_float -= f; break; tv1->vval.v_float += f; break;
case '*': tv1->vval.v_float *= f; break; case '-':
case '/': tv1->vval.v_float /= f; break; tv1->vval.v_float -= f; break;
} case '*':
return OK; tv1->vval.v_float *= f; break;
} case '/':
case VAR_UNKNOWN: { tv1->vval.v_float /= f; break;
abort();
} }
return OK;
}
case VAR_UNKNOWN:
abort();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check // 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 // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "nvim/eval/typval.h"
#include "nvim/eval/gc.h" #include "nvim/eval/gc.h"
#include "nvim/eval/typval.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/gc.c.generated.h" # include "eval/gc.c.generated.h"

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,6 @@
#include "nvim/ex_cmds2.h" #include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h" #include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h" #include "nvim/ex_getln.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h" #include "nvim/fileio.h"
#include "nvim/getchar.h" #include "nvim/getchar.h"
#include "nvim/globals.h" #include "nvim/globals.h"
@@ -55,24 +54,23 @@ static funccall_T *current_funccal = NULL;
// item in it is still being used. // item in it is still being used.
static funccall_T *previous_funccal = NULL; static funccall_T *previous_funccal = NULL;
static char *e_funcexts = N_( static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");
"E122: Function %s already exists, add ! to replace it");
static char *e_funcdict = N_("E717: Dictionary entry already exists"); static char *e_funcdict = N_("E717: Dictionary entry already exists");
static char *e_funcref = N_("E718: Funcref required"); static char *e_funcref = N_("E718: Funcref required");
static char *e_nofunc = N_("E130: Unknown function: %s"); static char *e_nofunc = N_("E130: Unknown function: %s");
void func_init(void) void func_init(void)
{ {
hash_init(&func_hashtab); hash_init(&func_hashtab);
} }
/// Get function arguments. /// Get function arguments.
static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, int *varargs,
int *varargs, garray_T *default_args, bool skip) garray_T *default_args, bool skip)
{ {
bool mustend = false; bool mustend = false;
char_u *arg = *argp; char_u *arg = *argp;
char_u *p = arg; char_u *p = arg;
int c; int c;
int i; int i;
@@ -146,7 +144,7 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs,
*p = NUL; *p = NUL;
expr = vim_strsave(expr); expr = vim_strsave(expr);
((char_u **)(default_args->ga_data)) ((char_u **)(default_args->ga_data))
[default_args->ga_len] = expr; [default_args->ga_len] = expr;
default_args->ga_len++; default_args->ga_len++;
*p = c; *p = c;
} else { } else {
@@ -200,18 +198,18 @@ static void register_closure(ufunc_T *fp)
current_funccal->fc_refcount++; current_funccal->fc_refcount++;
ga_grow(&current_funccal->fc_funcs, 1); ga_grow(&current_funccal->fc_funcs, 1);
((ufunc_T **)current_funccal->fc_funcs.ga_data) ((ufunc_T **)current_funccal->fc_funcs.ga_data)
[current_funccal->fc_funcs.ga_len++] = fp; [current_funccal->fc_funcs.ga_len++] = fp;
} }
/// Get a name for a lambda. Returned in static memory. /// Get a name for a lambda. Returned in static memory.
char_u * get_lambda_name(void) char_u * get_lambda_name(void)
{ {
static char_u name[30]; static char_u name[30];
static int lambda_no = 0; static int lambda_no = 0;
snprintf((char *)name, sizeof(name), "<lambda>%d", ++lambda_no); snprintf((char *)name, sizeof(name), "<lambda>%d", ++lambda_no);
return name; return name;
} }
/// Parse a lambda expression and get a Funcref from "*arg". /// Parse a lambda expression and get a Funcref from "*arg".
@@ -220,14 +218,14 @@ char_u * get_lambda_name(void)
int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate)
{ {
garray_T newargs = GA_EMPTY_INIT_VALUE; garray_T newargs = GA_EMPTY_INIT_VALUE;
garray_T *pnewargs; garray_T *pnewargs;
ufunc_T *fp = NULL; ufunc_T *fp = NULL;
partial_T *pt = NULL; partial_T *pt = NULL;
int varargs; int varargs;
int ret; int ret;
char_u *start = skipwhite(*arg + 1); char_u *start = skipwhite(*arg + 1);
char_u *s, *e; char_u *s, *e;
bool *old_eval_lavars = eval_lavars_used; bool *old_eval_lavars = eval_lavars_used;
bool eval_lavars = false; bool eval_lavars = false;
// First, check if this is a lambda expression. "->" must exists. // First, check if this is a lambda expression. "->" must exists.
@@ -348,8 +346,7 @@ errret:
/// was not found. /// was not found.
/// ///
/// @return name of the function. /// @return name of the function.
char_u *deref_func_name(const char *name, int *lenp, char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp, bool no_autoload)
partial_T **const partialp, bool no_autoload)
FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_NONNULL_ARG(1, 2)
{ {
if (partialp != NULL) { if (partialp != NULL) {
@@ -409,19 +406,16 @@ void emsg_funcname(char *ermsg, const char_u *name)
* Allocate a variable for the result of a function. * Allocate a variable for the result of a function.
* Return OK or FAIL. * Return OK or FAIL.
*/ */
int int get_func_tv(const char_u *name, // name of the function
get_func_tv( int len, // length of "name" or -1 to use strlen()
const char_u *name, // name of the function typval_T *rettv, char_u **arg, // argument, pointing to the '('
int len, // length of "name" or -1 to use strlen() funcexe_T *funcexe // various values
typval_T *rettv, )
char_u **arg, // argument, pointing to the '('
funcexe_T *funcexe // various values
)
{ {
char_u *argp; char_u *argp;
int ret = OK; int ret = OK;
typval_T argvars[MAX_FUNC_ARGS + 1]; /* vars for arguments */ typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
int argcount = 0; /* number of arguments found */ int argcount = 0; // number of arguments found
/* /*
* Get the arguments. * Get the arguments.
@@ -438,13 +432,15 @@ get_func_tv(
break; break;
} }
++argcount; ++argcount;
if (*argp != ',') if (*argp != ',') {
break; break;
}
} }
if (*argp == ')') if (*argp == ')') {
++argp; ++argp;
else } else {
ret = FAIL; ret = FAIL;
}
if (ret == OK) { if (ret == OK) {
int i = 0; int i = 0;
@@ -512,8 +508,7 @@ static inline bool eval_fname_sid(const char *const name)
/// ///
/// @return transformed name: either `fname_buf` or a pointer to an allocated /// @return transformed name: either `fname_buf` or a pointer to an allocated
/// memory. /// memory.
static char_u *fname_trans_sid(const char_u *const name, static char_u *fname_trans_sid(const char_u *const name, char_u *const fname_buf,
char_u *const fname_buf,
char_u **const tofree, int *const error) char_u **const tofree, int *const error)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{ {
@@ -553,11 +548,12 @@ static char_u *fname_trans_sid(const char_u *const name,
/// @return NULL for unknown function. /// @return NULL for unknown function.
ufunc_T *find_func(const char_u *name) ufunc_T *find_func(const char_u *name)
{ {
hashitem_T *hi; hashitem_T *hi;
hi = hash_find(&func_hashtab, name); hi = hash_find(&func_hashtab, name);
if (!HASHITEM_EMPTY(hi)) if (!HASHITEM_EMPTY(hi)) {
return HI2UF(hi); return HI2UF(hi);
}
return NULL; return NULL;
} }
@@ -571,8 +567,9 @@ static void cat_func_name(char_u *buf, ufunc_T *fp)
if (fp->uf_name[0] == K_SPECIAL) { if (fp->uf_name[0] == K_SPECIAL) {
STRCPY(buf, "<SNR>"); STRCPY(buf, "<SNR>");
STRCAT(buf, fp->uf_name + 3); STRCAT(buf, fp->uf_name + 3);
} else } else {
STRCPY(buf, fp->uf_name); STRCPY(buf, fp->uf_name);
}
} }
/* /*
@@ -662,7 +659,6 @@ static void cleanup_function_call(funccall_T *fc)
if (may_free_fc && fc->l_varlist.lv_refcount // NOLINT(runtime/deprecated) if (may_free_fc && fc->l_varlist.lv_refcount // NOLINT(runtime/deprecated)
== DO_NOT_FREE_CNT) { == DO_NOT_FREE_CNT) {
fc->l_varlist.lv_first = NULL; // NOLINT(runtime/deprecated) fc->l_varlist.lv_first = NULL; // NOLINT(runtime/deprecated)
} else { } else {
free_fc = false; free_fc = false;
@@ -807,23 +803,22 @@ static void func_clear_free(ufunc_T *fp, bool force)
/// @param[in] firstline First line of range. /// @param[in] firstline First line of range.
/// @param[in] lastline Last line of range. /// @param[in] lastline Last line of range.
/// @param selfdict Dictionary for "self" for dictionary functions. /// @param selfdict Dictionary for "self" for dictionary functions.
void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv,
typval_T *rettv, linenr_T firstline, linenr_T lastline, linenr_T firstline, linenr_T lastline, dict_T *selfdict)
dict_T *selfdict)
FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_NONNULL_ARG(1, 3, 4)
{ {
char_u *save_sourcing_name; char_u *save_sourcing_name;
linenr_T save_sourcing_lnum; linenr_T save_sourcing_lnum;
bool using_sandbox = false; bool using_sandbox = false;
funccall_T *fc; funccall_T *fc;
int save_did_emsg; int save_did_emsg;
static int depth = 0; static int depth = 0;
dictitem_T *v; dictitem_T *v;
int fixvar_idx = 0; // index in fixvar[] int fixvar_idx = 0; // index in fixvar[]
int ai; int ai;
bool islambda = false; bool islambda = false;
char_u numbuf[NUMBUFLEN]; char_u numbuf[NUMBUFLEN];
char_u *name; char_u *name;
typval_T *tv_to_free[MAX_FUNC_ARGS]; typval_T *tv_to_free[MAX_FUNC_ARGS];
int tv_to_free_len = 0; int tv_to_free_len = 0;
proftime_T wait_start; proftime_T wait_start;
@@ -949,7 +944,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
def_rettv.vval.v_number = -1; def_rettv.vval.v_number = -1;
default_expr = ((char_u **)(fp->uf_def_args.ga_data)) default_expr = ((char_u **)(fp->uf_def_args.ga_data))
[ai + fp->uf_def_args.ga_len]; [ai + fp->uf_def_args.ga_len];
if (eval1(&default_expr, &def_rettv, true) == FAIL) { if (eval1(&default_expr, &def_rettv, true) == FAIL) {
default_arg_err = true; default_arg_err = true;
break; break;
@@ -1135,7 +1130,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
call_start = profile_sub_wait(wait_start, call_start); // -V614 call_start = profile_sub_wait(wait_start, call_start); // -V614
fp->uf_tm_total = profile_add(fp->uf_tm_total, call_start); fp->uf_tm_total = profile_add(fp->uf_tm_total, call_start);
fp->uf_tm_self = profile_self(fp->uf_tm_self, call_start, fp->uf_tm_self = profile_self(fp->uf_tm_self, call_start,
fp->uf_tm_children); fp->uf_tm_children);
if (fc->caller != NULL && fc->caller->func->uf_profiling) { if (fc->caller != NULL && fc->caller->func->uf_profiling) {
fc->caller->func->uf_tm_children = fc->caller->func->uf_tm_children =
profile_add(fc->caller->func->uf_tm_children, call_start); profile_add(fc->caller->func->uf_tm_children, call_start);
@@ -1153,19 +1148,19 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
++no_wait_return; ++no_wait_return;
verbose_enter_scroll(); verbose_enter_scroll();
if (aborting()) if (aborting()) {
smsg(_("%s aborted"), sourcing_name); smsg(_("%s aborted"), sourcing_name);
else if (fc->rettv->v_type == VAR_NUMBER) } else if (fc->rettv->v_type == VAR_NUMBER) {
smsg(_("%s returning #%" PRId64 ""), smsg(_("%s returning #%" PRId64 ""),
sourcing_name, (int64_t)fc->rettv->vval.v_number); sourcing_name, (int64_t)fc->rettv->vval.v_number);
else { } else {
char_u buf[MSG_BUF_LEN]; char_u buf[MSG_BUF_LEN];
// The value may be very long. Skip the middle part, so that we // The value may be very long. Skip the middle part, so that we
// have some idea how it starts and ends. smsg() would always // have some idea how it starts and ends. smsg() would always
// truncate it at the end. Don't want errors such as E724 here. // truncate it at the end. Don't want errors such as E724 here.
emsg_off++; emsg_off++;
char_u *s = (char_u *) encode_tv2string(fc->rettv, NULL); char_u *s = (char_u *)encode_tv2string(fc->rettv, NULL);
char_u *tofree = s; char_u *tofree = s;
emsg_off--; emsg_off--;
if (s != NULL) { if (s != NULL) {
@@ -1269,8 +1264,8 @@ void set_current_funccal(funccall_T *fc)
#if defined(EXITFREE) #if defined(EXITFREE)
void free_all_functions(void) void free_all_functions(void)
{ {
hashitem_T *hi; hashitem_T *hi;
ufunc_T *fp; ufunc_T *fp;
uint64_t skipped = 0; uint64_t skipped = 0;
uint64_t todo = 1; uint64_t todo = 1;
uint64_t used; uint64_t used;
@@ -1357,8 +1352,7 @@ static bool builtin_function(const char *name, int len)
return p == NULL; return p == NULL;
} }
int func_call(char_u *name, typval_T *args, partial_T *partial, int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv)
dict_T *selfdict, typval_T *rettv)
{ {
typval_T argv[MAX_FUNC_ARGS + 1]; typval_T argv[MAX_FUNC_ARGS + 1];
int argc = 0; int argc = 0;
@@ -1397,38 +1391,37 @@ static void user_func_error(int error, const char_u *name)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
switch (error) { switch (error) {
case ERROR_UNKNOWN: case ERROR_UNKNOWN:
emsg_funcname(N_("E117: Unknown function: %s"), name); emsg_funcname(N_("E117: Unknown function: %s"), name);
break; break;
case ERROR_NOTMETHOD: case ERROR_NOTMETHOD:
emsg_funcname(N_("E276: Cannot use function as a method: %s"), name); emsg_funcname(N_("E276: Cannot use function as a method: %s"), name);
break; break;
case ERROR_DELETED: case ERROR_DELETED:
emsg_funcname(N_("E933: Function was deleted: %s"), name); emsg_funcname(N_("E933: Function was deleted: %s"), name);
break; break;
case ERROR_TOOMANY: case ERROR_TOOMANY:
emsg_funcname(_(e_toomanyarg), name); emsg_funcname(_(e_toomanyarg), name);
break; break;
case ERROR_TOOFEW: case ERROR_TOOFEW:
emsg_funcname(N_("E119: Not enough arguments for function: %s"), emsg_funcname(N_("E119: Not enough arguments for function: %s"),
name); name);
break; break;
case ERROR_SCRIPT: case ERROR_SCRIPT:
emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), emsg_funcname(N_("E120: Using <SID> not in a script context: %s"),
name); name);
break; break;
case ERROR_DICT: case ERROR_DICT:
emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
name); name);
break; break;
} }
} }
/// Used by call_func to add a method base (if any) to a function argument list /// Used by call_func to add a method base (if any) to a function argument list
/// as the first argument. @see call_func /// as the first argument. @see call_func
static void argv_add_base(typval_T *const basetv, typval_T **const argvars, static void argv_add_base(typval_T *const basetv, typval_T **const argvars, int *const argcount,
int *const argcount, typval_T *const new_argvars, typval_T *const new_argvars, int *const argv_base)
int *const argv_base)
FUNC_ATTR_NONNULL_ARG(2, 3, 4, 5) FUNC_ATTR_NONNULL_ARG(2, 3, 4, 5)
{ {
if (basetv != NULL) { if (basetv != NULL) {
@@ -1446,16 +1439,14 @@ static void argv_add_base(typval_T *const basetv, typval_T **const argvars,
/// @return FAIL if function cannot be called, else OK (even if an error /// @return FAIL if function cannot be called, else OK (even if an error
/// occurred while executing the function! Set `msg_list` to capture /// occurred while executing the function! Set `msg_list` to capture
/// the error, see do_cmdline()). /// the error, see do_cmdline()).
int int call_func(const char_u *funcname, // name of the function
call_func( int len, // length of "name" or -1 to use strlen()
const char_u *funcname, // name of the function typval_T *rettv, // [out] value goes here
int len, // length of "name" or -1 to use strlen() int argcount_in, // number of "argvars"
typval_T *rettv, // [out] value goes here typval_T *argvars_in, // vars for arguments, must have "argcount"
int argcount_in, // number of "argvars" // PLUS ONE elements!
typval_T *argvars_in, // vars for arguments, must have "argcount" funcexe_T *funcexe // more arguments
// PLUS ONE elements! )
funcexe_T *funcexe // more arguments
)
FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6) FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6)
{ {
int ret = FAIL; int ret = FAIL;
@@ -1612,8 +1603,9 @@ call_func(
*/ */
update_force_abort(); update_force_abort();
} }
if (error == ERROR_NONE) if (error == ERROR_NONE) {
ret = OK; ret = OK;
}
theend: theend:
// Report an error unless the argument evaluation or function call has been // Report an error unless the argument evaluation or function call has been
@@ -1641,8 +1633,9 @@ theend:
static void list_func_head(ufunc_T *fp, int indent, bool force) static void list_func_head(ufunc_T *fp, int indent, bool force)
{ {
msg_start(); msg_start();
if (indent) if (indent) {
MSG_PUTS(" "); MSG_PUTS(" ");
}
MSG_PUTS(force ? "function! " : "function "); MSG_PUTS(force ? "function! " : "function ");
if (fp->uf_name[0] == K_SPECIAL) { if (fp->uf_name[0] == K_SPECIAL) {
MSG_PUTS_ATTR("<SNR>", HL_ATTR(HLF_8)); MSG_PUTS_ATTR("<SNR>", HL_ATTR(HLF_8));
@@ -1698,25 +1691,22 @@ static void list_func_head(ufunc_T *fp, int indent, bool force)
/// Advances "pp" to just after the function name (if no error). /// Advances "pp" to just after the function name (if no error).
/// ///
/// @return the function name in allocated memory, or NULL for failure. /// @return the function name in allocated memory, or NULL for failure.
char_u * char_u *trans_function_name(char_u **pp, bool skip, // only find the end, don't evaluate
trans_function_name( int flags, funcdict_T *fdp, // return: info about dictionary used
char_u **pp, partial_T **partial // return: partial of a FuncRef
bool skip, // only find the end, don't evaluate )
int flags,
funcdict_T *fdp, // return: info about dictionary used
partial_T **partial // return: partial of a FuncRef
)
FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(1)
{ {
char_u *name = NULL; char_u *name = NULL;
const char_u *start; const char_u *start;
const char_u *end; const char_u *end;
int lead; int lead;
int len; int len;
lval_T lv; lval_T lv;
if (fdp != NULL) if (fdp != NULL) {
memset(fdp, 0, sizeof(funcdict_T)); memset(fdp, 0, sizeof(funcdict_T));
}
start = *pp; start = *pp;
/* Check for hard coded <SNR>: already translated function ID (from a user /* Check for hard coded <SNR>: already translated function ID (from a user
@@ -1739,8 +1729,9 @@ trans_function_name(
end = get_lval((char_u *)start, NULL, &lv, false, skip, flags | GLV_READ_ONLY, end = get_lval((char_u *)start, NULL, &lv, false, skip, flags | GLV_READ_ONLY,
lead > 2 ? 0 : FNE_CHECK_START); lead > 2 ? 0 : FNE_CHECK_START);
if (end == start) { if (end == start) {
if (!skip) if (!skip) {
EMSG(_("E129: Function name required")); EMSG(_("E129: Function name required"));
}
goto theend; goto theend;
} }
if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range))) { if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range))) {
@@ -1806,7 +1797,7 @@ trans_function_name(
goto theend; goto theend;
} }
/* Check if the name is a Funcref. If so, use the value. */ // Check if the name is a Funcref. If so, use the value.
if (lv.ll_exp_name != NULL) { if (lv.ll_exp_name != NULL) {
len = (int)strlen(lv.ll_exp_name); len = (int)strlen(lv.ll_exp_name);
name = deref_func_name(lv.ll_exp_name, &len, partial, name = deref_func_name(lv.ll_exp_name, &len, partial,
@@ -1915,31 +1906,31 @@ theend:
*/ */
void ex_function(exarg_T *eap) void ex_function(exarg_T *eap)
{ {
char_u *theline; char_u *theline;
char_u *line_to_free = NULL; char_u *line_to_free = NULL;
int c; int c;
int saved_did_emsg; int saved_did_emsg;
bool saved_wait_return = need_wait_return; bool saved_wait_return = need_wait_return;
char_u *name = NULL; char_u *name = NULL;
char_u *p; char_u *p;
char_u *arg; char_u *arg;
char_u *line_arg = NULL; char_u *line_arg = NULL;
garray_T newargs; garray_T newargs;
garray_T default_args; garray_T default_args;
garray_T newlines; garray_T newlines;
int varargs = false; int varargs = false;
int flags = 0; int flags = 0;
ufunc_T *fp; ufunc_T *fp;
bool overwrite = false; bool overwrite = false;
int indent; int indent;
int nesting; int nesting;
dictitem_T *v; dictitem_T *v;
funcdict_T fudi; funcdict_T fudi;
static int func_nr = 0; // number for nameless function static int func_nr = 0; // number for nameless function
int paren; int paren;
hashtab_T *ht; hashtab_T *ht;
int todo; int todo;
hashitem_T *hi; hashitem_T *hi;
linenr_T sourcing_lnum_off; linenr_T sourcing_lnum_off;
linenr_T sourcing_lnum_top; linenr_T sourcing_lnum_top;
bool is_heredoc = false; bool is_heredoc = false;
@@ -1992,15 +1983,17 @@ void ex_function(exarg_T *eap)
--todo; --todo;
fp = HI2UF(hi); fp = HI2UF(hi);
if (!isdigit(*fp->uf_name) if (!isdigit(*fp->uf_name)
&& vim_regexec(&regmatch, fp->uf_name, 0)) && vim_regexec(&regmatch, fp->uf_name, 0)) {
list_func_head(fp, false, false); list_func_head(fp, false, false);
}
} }
} }
vim_regfree(regmatch.regprog); vim_regfree(regmatch.regprog);
} }
} }
if (*p == '/') if (*p == '/') {
++p; ++p;
}
eap->nextcmd = check_nextcmd(p); eap->nextcmd = check_nextcmd(p);
return; return;
} }
@@ -2034,8 +2027,9 @@ void ex_function(exarg_T *eap)
} }
xfree(fudi.fd_newkey); xfree(fudi.fd_newkey);
return; return;
} else } else {
eap->skip = TRUE; eap->skip = TRUE;
}
} }
/* An error in a function call during evaluation of an expression in magic /* An error in a function call during evaluation of an expression in magic
@@ -2055,8 +2049,9 @@ void ex_function(exarg_T *eap)
goto ret_free; goto ret_free;
} }
eap->nextcmd = check_nextcmd(p); eap->nextcmd = check_nextcmd(p);
if (eap->nextcmd != NULL) if (eap->nextcmd != NULL) {
*p = NUL; *p = NUL;
}
if (!eap->skip && !got_int) { if (!eap->skip && !got_int) {
fp = find_func(name); fp = find_func(name);
if (fp != NULL) { if (fp != NULL) {
@@ -2083,8 +2078,9 @@ void ex_function(exarg_T *eap)
msg_putchar('\n'); msg_putchar('\n');
msg_puts(eap->forceit ? "endfunction" : " endfunction"); msg_puts(eap->forceit ? "endfunction" : " endfunction");
} }
} else } else {
emsg_funcname(N_("E123: Undefined function: %s"), name); emsg_funcname(N_("E123: Undefined function: %s"), name);
}
} }
goto ret_free; goto ret_free;
} }
@@ -2111,17 +2107,20 @@ void ex_function(exarg_T *eap)
if (!eap->skip) { if (!eap->skip) {
/* Check the name of the function. Unless it's a dictionary function /* Check the name of the function. Unless it's a dictionary function
* (that we are overwriting). */ * (that we are overwriting). */
if (name != NULL) if (name != NULL) {
arg = name; arg = name;
else } else {
arg = fudi.fd_newkey; arg = fudi.fd_newkey;
}
if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) { if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) {
int j = (*arg == K_SPECIAL) ? 3 : 0; int j = (*arg == K_SPECIAL) ? 3 : 0;
while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j]) while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j])
: eval_isnamec(arg[j]))) : eval_isnamec(arg[j]))) {
++j; ++j;
if (arg[j] != NUL) }
if (arg[j] != NUL) {
emsg_funcname((char *)e_invarg2, arg); emsg_funcname((char *)e_invarg2, arg);
}
} }
// Disallow using the g: dict. // Disallow using the g: dict.
if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE) { if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE) {
@@ -2156,7 +2155,7 @@ void ex_function(exarg_T *eap)
p += 7; p += 7;
if (current_funccal == NULL) { if (current_funccal == NULL) {
emsg_funcname(N_ emsg_funcname(N_
("E932: Closure function should not be at top level: %s"), ("E932: Closure function should not be at top level: %s"),
name == NULL ? (char_u *)"" : name); name == NULL ? (char_u *)"" : name);
goto erret; goto erret;
} }
@@ -2181,14 +2180,16 @@ void ex_function(exarg_T *eap)
* whole function before telling him it doesn't work! For a script we * whole function before telling him it doesn't work! For a script we
* need to skip the body to be able to find what follows. */ * need to skip the body to be able to find what follows. */
if (!eap->skip && !eap->forceit) { if (!eap->skip && !eap->forceit) {
if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) {
EMSG(_(e_funcdict)); EMSG(_(e_funcdict));
else if (name != NULL && find_func(name) != NULL) } else if (name != NULL && find_func(name) != NULL) {
emsg_funcname(e_funcexts, name); emsg_funcname(e_funcexts, name);
}
} }
if (!eap->skip && did_emsg) if (!eap->skip && did_emsg) {
goto erret; goto erret;
}
if (!ui_has(kUICmdline)) { if (!ui_has(kUICmdline)) {
msg_putchar('\n'); // don't overwrite the function name msg_putchar('\n'); // don't overwrite the function name
@@ -2212,9 +2213,9 @@ void ex_function(exarg_T *eap)
// Use eap->arg, split up in parts by line breaks. // Use eap->arg, split up in parts by line breaks.
theline = line_arg; theline = line_arg;
p = vim_strchr(theline, '\n'); p = vim_strchr(theline, '\n');
if (p == NULL) if (p == NULL) {
line_arg += STRLEN(line_arg); line_arg += STRLEN(line_arg);
else { } else {
*p = NUL; *p = NUL;
line_arg = p + 1; line_arg = p + 1;
} }
@@ -2242,7 +2243,7 @@ void ex_function(exarg_T *eap)
// Detect line continuation: sourcing_lnum increased more than one. // Detect line continuation: sourcing_lnum increased more than one.
sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie); sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie);
if (sourcing_lnum < sourcing_lnum_off) { if (sourcing_lnum < sourcing_lnum_off) {
sourcing_lnum_off -= sourcing_lnum; sourcing_lnum_off -= sourcing_lnum;
} else { } else {
sourcing_lnum_off = 0; sourcing_lnum_off = 0;
} }
@@ -2306,13 +2307,14 @@ void ex_function(exarg_T *eap)
/* Increase indent inside "if", "while", "for" and "try", decrease /* Increase indent inside "if", "while", "for" and "try", decrease
* at "end". */ * at "end". */
if (indent > 2 && STRNCMP(p, "end", 3) == 0) if (indent > 2 && STRNCMP(p, "end", 3) == 0) {
indent -= 2; indent -= 2;
else if (STRNCMP(p, "if", 2) == 0 } else if (STRNCMP(p, "if", 2) == 0
|| STRNCMP(p, "wh", 2) == 0 || STRNCMP(p, "wh", 2) == 0
|| STRNCMP(p, "for", 3) == 0 || STRNCMP(p, "for", 3) == 0
|| STRNCMP(p, "try", 3) == 0) || STRNCMP(p, "try", 3) == 0) {
indent += 2; indent += 2;
}
// Check for defining a function inside this function. // Check for defining a function inside this function.
if (checkforcmd(&p, "function", 2)) { if (checkforcmd(&p, "function", 2)) {
@@ -2362,10 +2364,11 @@ void ex_function(exarg_T *eap)
&& (!ASCII_ISALPHA(p[2]) || p[2] == 's')))) { && (!ASCII_ISALPHA(p[2]) || p[2] == 's')))) {
// ":python <<" continues until a dot, like ":append" // ":python <<" continues until a dot, like ":append"
p = skipwhite(arg + 2); p = skipwhite(arg + 2);
if (*p == NUL) if (*p == NUL) {
skip_until = vim_strsave((char_u *)"."); skip_until = vim_strsave((char_u *)".");
else } else {
skip_until = vim_strsave(p); skip_until = vim_strsave(p);
}
} }
// Check for ":let v =<< [trim] EOF" // Check for ":let v =<< [trim] EOF"
@@ -2408,8 +2411,9 @@ void ex_function(exarg_T *eap)
/* Add NULL lines for continuation lines, so that the line count is /* Add NULL lines for continuation lines, so that the line count is
* equal to the index in the growarray. */ * equal to the index in the growarray. */
while (sourcing_lnum_off-- > 0) while (sourcing_lnum_off-- > 0) {
((char_u **)(newlines.ga_data))[newlines.ga_len++] = NULL; ((char_u **)(newlines.ga_data))[newlines.ga_len++] = NULL;
}
// Check for end of eap->arg. // Check for end of eap->arg.
if (line_arg != NULL && *line_arg == NUL) { if (line_arg != NULL && *line_arg == NUL) {
@@ -2419,8 +2423,9 @@ void ex_function(exarg_T *eap)
/* Don't define the function when skipping commands or when an error was /* Don't define the function when skipping commands or when an error was
* detected. */ * detected. */
if (eap->skip || did_emsg) if (eap->skip || did_emsg) {
goto erret; goto erret;
}
/* /*
* If there are no errors, add the function * If there are no errors, add the function
@@ -2429,7 +2434,7 @@ void ex_function(exarg_T *eap)
v = find_var((const char *)name, STRLEN(name), &ht, false); v = find_var((const char *)name, STRLEN(name), &ht, false);
if (v != NULL && v->di_tv.v_type == VAR_FUNC) { if (v != NULL && v->di_tv.v_type == VAR_FUNC) {
emsg_funcname(N_("E707: Function name conflicts with variable: %s"), emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
name); name);
goto erret; goto erret;
} }
@@ -2445,7 +2450,7 @@ void ex_function(exarg_T *eap)
} }
if (fp->uf_calls > 0) { if (fp->uf_calls > 0) {
emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"), emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"),
name); name);
goto erret; goto erret;
} }
if (fp->uf_refcount > 1) { if (fp->uf_refcount > 1) {
@@ -2493,7 +2498,7 @@ void ex_function(exarg_T *eap)
if (fp == NULL) { if (fp == NULL) {
if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) { if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) {
int slen, plen; int slen, plen;
char_u *scriptname; char_u *scriptname;
// Check that the autoload name matches the script name. // Check that the autoload name matches the script name.
int j = FAIL; int j = FAIL;
@@ -2503,14 +2508,14 @@ void ex_function(exarg_T *eap)
plen = (int)STRLEN(p); plen = (int)STRLEN(p);
slen = (int)STRLEN(sourcing_name); slen = (int)STRLEN(sourcing_name);
if (slen > plen && fnamecmp(p, if (slen > plen && fnamecmp(p,
sourcing_name + slen - plen) == 0) sourcing_name + slen - plen) == 0) {
j = OK; j = OK;
}
xfree(scriptname); xfree(scriptname);
} }
if (j == FAIL) { if (j == FAIL) {
EMSG2(_( EMSG2(_("E746: Function name does not match script file name: %s"),
"E746: Function name does not match script file name: %s"), name);
name);
goto erret; goto erret;
} }
} }
@@ -2651,8 +2656,8 @@ bool function_exists(const char *const name, bool no_deref)
char_u *get_user_func_name(expand_T *xp, int idx) char_u *get_user_func_name(expand_T *xp, int idx)
{ {
static size_t done; static size_t done;
static hashitem_T *hi; static hashitem_T *hi;
ufunc_T *fp; ufunc_T *fp;
if (idx == 0) { if (idx == 0) {
done = 0; done = 0;
@@ -2660,10 +2665,12 @@ char_u *get_user_func_name(expand_T *xp, int idx)
} }
assert(hi); assert(hi);
if (done < func_hashtab.ht_used) { if (done < func_hashtab.ht_used) {
if (done++ > 0) if (done++ > 0) {
++hi; ++hi;
while (HASHITEM_EMPTY(hi)) }
while (HASHITEM_EMPTY(hi)) {
++hi; ++hi;
}
fp = HI2UF(hi); fp = HI2UF(hi);
if ((fp->uf_flags & FC_DICT) if ((fp->uf_flags & FC_DICT)
@@ -2678,8 +2685,9 @@ char_u *get_user_func_name(expand_T *xp, int idx)
cat_func_name(IObuff, fp); cat_func_name(IObuff, fp);
if (xp->xp_context != EXPAND_USER_FUNC) { if (xp->xp_context != EXPAND_USER_FUNC) {
STRCAT(IObuff, "("); STRCAT(IObuff, "(");
if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) {
STRCAT(IObuff, ")"); STRCAT(IObuff, ")");
}
} }
return IObuff; return IObuff;
} }
@@ -2689,17 +2697,18 @@ char_u *get_user_func_name(expand_T *xp, int idx)
/// ":delfunction {name}" /// ":delfunction {name}"
void ex_delfunction(exarg_T *eap) void ex_delfunction(exarg_T *eap)
{ {
ufunc_T *fp = NULL; ufunc_T *fp = NULL;
char_u *p; char_u *p;
char_u *name; char_u *name;
funcdict_T fudi; funcdict_T fudi;
p = eap->arg; p = eap->arg;
name = trans_function_name(&p, eap->skip, 0, &fudi, NULL); name = trans_function_name(&p, eap->skip, 0, &fudi, NULL);
xfree(fudi.fd_newkey); xfree(fudi.fd_newkey);
if (name == NULL) { if (name == NULL) {
if (fudi.fd_dict != NULL && !eap->skip) if (fudi.fd_dict != NULL && !eap->skip) {
EMSG(_(e_funcref)); EMSG(_(e_funcref));
}
return; return;
} }
if (!ends_excmd(*skipwhite(p))) { if (!ends_excmd(*skipwhite(p))) {
@@ -2708,11 +2717,13 @@ void ex_delfunction(exarg_T *eap)
return; return;
} }
eap->nextcmd = check_nextcmd(p); eap->nextcmd = check_nextcmd(p);
if (eap->nextcmd != NULL) if (eap->nextcmd != NULL) {
*p = NUL; *p = NUL;
}
if (!eap->skip) if (!eap->skip) {
fp = find_func(name); fp = find_func(name);
}
xfree(name); xfree(name);
if (!eap->skip) { if (!eap->skip) {
@@ -2730,7 +2741,7 @@ void ex_delfunction(exarg_T *eap)
// the reference count, and 1 is the initial refcount. // the reference count, and 1 is the initial refcount.
if (fp->uf_refcount > 2) { if (fp->uf_refcount > 2) {
EMSG2(_("Cannot delete function %s: It is being used internally"), EMSG2(_("Cannot delete function %s: It is being used internally"),
eap->arg); eap->arg);
return; return;
} }
@@ -2778,8 +2789,8 @@ void func_unref(char_u *name)
abort(); abort();
} }
#else #else
internal_error("func_unref()"); internal_error("func_unref()");
abort(); abort();
#endif #endif
} }
func_ptr_unref(fp); func_ptr_unref(fp);
@@ -2860,7 +2871,7 @@ static int can_free_funccal(funccall_T *fc, int copyID)
*/ */
void ex_return(exarg_T *eap) void ex_return(exarg_T *eap)
{ {
char_u *arg = eap->arg; char_u *arg = eap->arg;
typval_T rettv; typval_T rettv;
int returning = FALSE; int returning = FALSE;
@@ -2869,8 +2880,9 @@ void ex_return(exarg_T *eap)
return; return;
} }
if (eap->skip) if (eap->skip) {
++emsg_skip; ++emsg_skip;
}
eap->nextcmd = NULL; eap->nextcmd = NULL;
if ((*arg != NUL && *arg != '|' && *arg != '\n') if ((*arg != NUL && *arg != '|' && *arg != '\n')
@@ -2900,21 +2912,22 @@ void ex_return(exarg_T *eap)
eap->nextcmd = check_nextcmd(arg); eap->nextcmd = check_nextcmd(arg);
} }
if (eap->skip) if (eap->skip) {
--emsg_skip; --emsg_skip;
}
} }
// TODO(ZyX-I): move to eval/ex_cmds // TODO(ZyX-I): move to eval/ex_cmds
/* /*
* ":1,25call func(arg1, arg2)" function call. * ":1,25call func(arg1, arg2)" function call.
*/ */
void ex_call(exarg_T *eap) void ex_call(exarg_T *eap)
{ {
char_u *arg = eap->arg; char_u *arg = eap->arg;
char_u *startarg; char_u *startarg;
char_u *name; char_u *name;
char_u *tofree; char_u *tofree;
int len; int len;
typval_T rettv; typval_T rettv;
linenr_T lnum; linenr_T lnum;
@@ -3063,12 +3076,12 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
if (idx >= 0) { if (idx >= 0) {
cstack->cs_pending[idx] = CSTP_RETURN; cstack->cs_pending[idx] = CSTP_RETURN;
if (!is_cmd && !reanimate) if (!is_cmd && !reanimate) {
/* A pending return again gets pending. "rettv" points to an /* A pending return again gets pending. "rettv" points to an
* allocated variable with the rettv of the original ":return"'s * allocated variable with the rettv of the original ":return"'s
* argument if present or is NULL else. */ * argument if present or is NULL else. */
cstack->cs_rettv[idx] = rettv; cstack->cs_rettv[idx] = rettv;
else { } else {
/* When undoing a return in order to make it pending, get the stored /* When undoing a return in order to make it pending, get the stored
* return rettv. */ * return rettv. */
if (reanimate) { if (reanimate) {
@@ -3080,8 +3093,9 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
// Store the value of the pending return. // Store the value of the pending return.
cstack->cs_rettv[idx] = xcalloc(1, sizeof(typval_T)); cstack->cs_rettv[idx] = xcalloc(1, sizeof(typval_T));
*(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv; *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
} else } else {
cstack->cs_rettv[idx] = NULL; cstack->cs_rettv[idx] = NULL;
}
if (reanimate) { if (reanimate) {
/* The pending return value could be overwritten by a ":return" /* The pending return value could be overwritten by a ":return"
@@ -3101,8 +3115,9 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
if (!reanimate && rettv != NULL) { if (!reanimate && rettv != NULL) {
tv_clear(current_funccal->rettv); tv_clear(current_funccal->rettv);
*current_funccal->rettv = *(typval_T *)rettv; *current_funccal->rettv = *(typval_T *)rettv;
if (!is_cmd) if (!is_cmd) {
xfree(rettv); xfree(rettv);
}
} }
} }
@@ -3119,7 +3134,7 @@ char_u *get_return_cmd(void *rettv)
char_u *tofree = NULL; char_u *tofree = NULL;
if (rettv != NULL) { if (rettv != NULL) {
tofree = s = (char_u *) encode_tv2echo((typval_T *) rettv, NULL); tofree = s = (char_u *)encode_tv2echo((typval_T *)rettv, NULL);
} }
if (s == NULL) { if (s == NULL) {
s = (char_u *)""; s = (char_u *)"";
@@ -3127,8 +3142,9 @@ char_u *get_return_cmd(void *rettv)
STRCPY(IObuff, ":return "); STRCPY(IObuff, ":return ");
STRLCPY(IObuff + 8, s, IOSIZE - 8); STRLCPY(IObuff + 8, s, IOSIZE - 8);
if (STRLEN(s) + 8 >= IOSIZE) if (STRLEN(s) + 8 >= IOSIZE) {
STRCPY(IObuff + IOSIZE - 4, "..."); STRCPY(IObuff + IOSIZE - 4, "...");
}
xfree(tofree); xfree(tofree);
return vim_strsave(IObuff); return vim_strsave(IObuff);
} }
@@ -3140,19 +3156,20 @@ char_u *get_return_cmd(void *rettv)
*/ */
char_u *get_func_line(int c, void *cookie, int indent, bool do_concat) char_u *get_func_line(int c, void *cookie, int indent, bool do_concat)
{ {
funccall_T *fcp = (funccall_T *)cookie; funccall_T *fcp = (funccall_T *)cookie;
ufunc_T *fp = fcp->func; ufunc_T *fp = fcp->func;
char_u *retval; char_u *retval;
garray_T *gap; // growarray with function lines garray_T *gap; // growarray with function lines
// If breakpoints have been added/deleted need to check for it. // If breakpoints have been added/deleted need to check for it.
if (fcp->dbg_tick != debug_tick) { if (fcp->dbg_tick != debug_tick) {
fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
sourcing_lnum); sourcing_lnum);
fcp->dbg_tick = debug_tick; fcp->dbg_tick = debug_tick;
} }
if (do_profiling == PROF_YES) if (do_profiling == PROF_YES) {
func_line_end(cookie); func_line_end(cookie);
}
gap = &fp->uf_lines; gap = &fp->uf_lines;
if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try()) if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
@@ -3169,8 +3186,9 @@ char_u *get_func_line(int c, void *cookie, int indent, bool do_concat)
} else { } else {
retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]); retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
sourcing_lnum = fcp->linenr; sourcing_lnum = fcp->linenr;
if (do_profiling == PROF_YES) if (do_profiling == PROF_YES) {
func_line_start(cookie); func_line_start(cookie);
}
} }
} }
@@ -3192,7 +3210,7 @@ char_u *get_func_line(int c, void *cookie, int indent, bool do_concat)
*/ */
int func_has_ended(void *cookie) int func_has_ended(void *cookie)
{ {
funccall_T *fcp = (funccall_T *)cookie; funccall_T *fcp = (funccall_T *)cookie;
/* Ignore the "abort" flag if the abortion behavior has been changed due to /* Ignore the "abort" flag if the abortion behavior has been changed due to
* an error inside a try conditional. */ * an error inside a try conditional. */
@@ -3448,8 +3466,7 @@ hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht)
} }
/// Search variable in parent scope. /// Search variable in parent scope.
dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, int no_autoload)
int no_autoload)
{ {
if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) { if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) {
return NULL; return NULL;
@@ -3560,7 +3577,7 @@ bool set_ref_in_func_args(int copyID)
for (int i = 0; i < funcargs.ga_len; i++) { for (int i = 0; i < funcargs.ga_len; i++) {
if (set_ref_in_item(((typval_T **)funcargs.ga_data)[i], if (set_ref_in_item(((typval_T **)funcargs.ga_data)[i],
copyID, NULL, NULL)) { copyID, NULL, NULL)) {
return true; return true;
} }
} }
return false; return false;

File diff suppressed because it is too large Load Diff