diff options
author | dundargoc <33953936+dundargoc@users.noreply.github.com> | 2021-09-18 18:34:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-18 09:34:23 -0700 |
commit | 51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6 (patch) | |
tree | b0a582d67883864eda3231bce45dc7c159cbe97f | |
parent | 6cad86fffdb91d3997a707ff6adb0b5991587b3e (diff) | |
download | rneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.tar.gz rneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.tar.bz2 rneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.zip |
refactor: format #15702
-rw-r--r-- | src/nvim/api/buffer.c | 164 | ||||
-rw-r--r-- | src/nvim/api/deprecated.c | 39 | ||||
-rw-r--r-- | src/nvim/api/private/dispatch.c | 25 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 585 | ||||
-rw-r--r-- | src/nvim/api/tabpage.c | 11 | ||||
-rw-r--r-- | src/nvim/api/ui.c | 68 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 598 | ||||
-rw-r--r-- | src/nvim/api/window.c | 21 | ||||
-rw-r--r-- | src/nvim/eval/decode.c | 946 | ||||
-rw-r--r-- | src/nvim/eval/encode.c | 830 | ||||
-rw-r--r-- | src/nvim/eval/executor.c | 193 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 1341 | ||||
-rw-r--r-- | src/nvim/eval/gc.c | 2 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 1030 | ||||
-rw-r--r-- | src/nvim/eval/userfunc.c | 399 | ||||
-rw-r--r-- | src/nvim/viml/parser/expressions.c | 3267 |
16 files changed, 4631 insertions, 4888 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 3808f601d9..8973f8fef6 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -3,40 +3,39 @@ // Some of this code was adapted from 'if_py_both.h' from the original // vim source +#include <lauxlib.h> +#include <limits.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> -#include <limits.h> - -#include <lauxlib.h> #include "nvim/api/buffer.h" -#include "nvim/api/private/helpers.h" #include "nvim/api/private/defs.h" -#include "nvim/lua/executor.h" -#include "nvim/vim.h" +#include "nvim/api/private/helpers.h" #include "nvim/buffer.h" +#include "nvim/buffer_updates.h" #include "nvim/change.h" #include "nvim/charset.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/lua/executor.h" +#include "nvim/map.h" +#include "nvim/map_defs.h" +#include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.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/ops.h" #include "nvim/syntax.h" -#include "nvim/window.h" #include "nvim/undo.h" -#include "nvim/ex_docmd.h" -#include "nvim/buffer_updates.h" +#include "nvim/vim.h" +#include "nvim/window.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # 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 /// @return False if attach failed (invalid parameter, or buffer isn't loaded); /// otherwise True. TODO: LUA_API_NO_EVAL -Boolean nvim_buf_attach(uint64_t channel_id, - Buffer buffer, - Boolean send_buffer, - DictionaryOf(LuaRef) opts, - Error *err) +Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer, + DictionaryOf(LuaRef) opts, Error *err) FUNC_API_SINCE(4) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -237,9 +233,7 @@ error: /// @param[out] err Error details, if any /// @return False if detach failed (because the buffer isn't loaded); /// otherwise True. -Boolean nvim_buf_detach(uint64_t channel_id, - Buffer buffer, - Error *err) +Boolean nvim_buf_detach(uint64_t channel_id, Buffer buffer, Error *err) FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -252,8 +246,7 @@ Boolean nvim_buf_detach(uint64_t channel_id, return true; } -void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, - Error *err) +void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err) FUNC_API_LUA_ONLY { 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 replacement Array of lines to use as replacement /// @param[out] err Error details, if any -void nvim_buf_set_lines(uint64_t channel_id, - Buffer buffer, - Integer start, - Integer end, - Boolean strict_indexing, - ArrayOf(String) replacement, - Error *err) +void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integer end, + Boolean strict_indexing, ArrayOf(String) replacement, Error *err) FUNC_API_SINCE(1) FUNC_API_CHECK_TEXTLOCK { @@ -554,10 +542,8 @@ end: /// @param end_column Last column /// @param replacement Array of lines to use as replacement /// @param[out] err Error details, if any -void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, - Integer start_row, Integer start_col, - Integer end_row, Integer end_col, - ArrayOf(String) replacement, Error *err) +void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, Integer start_col, + Integer end_row, Integer end_col, ArrayOf(String) replacement, Error *err) FUNC_API_SINCE(7) { 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 if (start_row == end_row) { - old_byte = (bcount_t)end_col - start_col; + old_byte = (bcount_t)end_col - start_col; } else { - const char *bufline; - old_byte += (bcount_t)strlen(str_at_start) - start_col; - for (int64_t i = 1; i < end_row - start_row; i++) { - int64_t lnum = start_row + i; + const char *bufline; + old_byte += (bcount_t)strlen(str_at_start) - start_col; + for (int64_t i = 1; i < end_row - start_row; i++) { + int64_t lnum = start_row + i; - bufline = (char *)ml_get_buf(buf, lnum, false); - old_byte += (bcount_t)(strlen(bufline))+1; - } - old_byte += (bcount_t)end_col+1; + bufline = (char *)ml_get_buf(buf, lnum, false); + old_byte += (bcount_t)(strlen(bufline))+1; + } + old_byte += (bcount_t)end_col+1; } 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); if (!buf) { - return (Object) OBJECT_INIT; + return (Object)OBJECT_INIT; } 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()| /// /// @param buffer Buffer handle, or 0 for current buffer -void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs, - Dictionary opts, Error *err) +void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs, Dictionary opts, + Error *err) FUNC_API_SINCE(6) { 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); if (!buf) { - return (Object) OBJECT_INIT; + return (Object)OBJECT_INIT; } 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 value Option value /// @param[out] err Error details, if any -void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, - String name, Object value, Error *err) +void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, String name, Object value, Error *err) FUNC_API_SINCE(1) { 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 aco_save_T aco; 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); if (try_end(err)) { @@ -1105,12 +1090,11 @@ void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err) return; } - int result = do_buffer( - unload ? DOBUF_UNLOAD : DOBUF_WIPE, - DOBUF_FIRST, - FORWARD, - buf->handle, - force); + int result = do_buffer(unload ? DOBUF_UNLOAD : DOBUF_WIPE, + DOBUF_FIRST, + FORWARD, + buf->handle, + force); if (result == FAIL) { 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))); if (vtc->hl_id > 0) { ADD(chunk, - STRING_OBJ(cstr_to_string( - (const char *)syn_id2name(vtc->hl_id)))); + STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id)))); } 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 /// @param[out] err Error details, if any /// @return List of [extmark_id, row, col] tuples in "traversal order". -Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, - Object start, Object end, - Dictionary opts, Error *err) +Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end, Dictionary opts, + Error *err) FUNC_API_SINCE(7) { 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. /// @param[out] err Error details, if any /// @return Id of the created/updated extmark -Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, - Integer line, Integer col, +Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col, Dictionary opts, Error *err) 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)) { String hl_group; switch (v->type) { - case kObjectTypeString: - hl_group = v->data.string; - decor.hl_id = syn_check_group( - (char_u *)(hl_group.data), - (int)hl_group.size); - break; - case kObjectTypeInteger: - decor.hl_id = (int)v->data.integer; - break; - default: - api_set_error(err, kErrorTypeValidation, - "hl_group is not valid."); - goto error; + case kObjectTypeString: + hl_group = v->data.string; + decor.hl_id = syn_check_group((char_u *)(hl_group.data), + (int)hl_group.size); + break; + case kObjectTypeInteger: + decor.hl_id = (int)v->data.integer; + break; + default: + api_set_error(err, kErrorTypeValidation, + "hl_group is not valid."); + goto error; } } else if (strequal("virt_text", k.data)) { if (v->type != kObjectTypeArray) { @@ -1692,8 +1672,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, if (col2 >= 0) { if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) { - len = ephemeral ? MAXCOL : STRLEN( - ml_get_buf(buf, (linenr_T)line2 + 1, false)); + len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false)); } else if (line2 == buf->b_ml.ml_line_count) { // We are trying to add an extmark past final newline len = 0; @@ -1713,7 +1692,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, decor.col = 0; for (size_t i = 0; i < kv_size(decor.virt_text); i++) { 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[out] err Error details, if any /// @return true if the extmark was found, else false -Boolean nvim_buf_del_extmark(Buffer buffer, - Integer ns_id, - Integer id, - Error *err) +Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *err) FUNC_API_SINCE(7) { 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 /// @param[out] err Error details, if any /// @return The ns_id that was used -Integer nvim_buf_add_highlight(Buffer buffer, - Integer ns_id, - String hl_group, - Integer line, - Integer col_start, - Integer col_end, - Error *err) +Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, Integer line, + Integer col_start, Integer col_end, Error *err) FUNC_API_SINCE(1) { 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 /// to end of buffer. /// @param[out] err Error details, if any -void nvim_buf_clear_namespace(Buffer buffer, - Integer ns_id, - Integer line_start, - Integer line_end, +void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, Integer line_end, Error *err) FUNC_API_SINCE(5) { diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index 554966e266..21b9db85c0 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -1,18 +1,18 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +#include <limits.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> -#include <limits.h> -#include "nvim/api/deprecated.h" #include "nvim/api/buffer.h" -#include "nvim/api/vim.h" -#include "nvim/api/private/helpers.h" +#include "nvim/api/deprecated.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/lua/executor.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # 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 /// to end of file. /// @param[out] err Error details, if any -void nvim_buf_clear_highlight(Buffer buffer, - Integer ns_id, - Integer line_start, - Integer line_end, +void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start, Integer line_end, Error *err) FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(7) @@ -111,12 +108,8 @@ void nvim_buf_clear_highlight(Buffer buffer, /// @param opts Optional parameters. Currently not used. /// @param[out] err Error details, if any /// @return The ns_id that was used -Integer nvim_buf_set_virtual_text(Buffer buffer, - Integer src_id, - Integer line, - Array chunks, - Dictionary opts, - Error *err) +Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, Array chunks, + Dictionary opts, Error *err) FUNC_API_SINCE(5) FUNC_API_DEPRECATED_SINCE(8) { @@ -171,10 +164,7 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, /// the end of the buffer. /// @param lines Array of lines /// @param[out] err Error details, if any -void buffer_insert(Buffer buffer, - Integer lnum, - ArrayOf(String) lines, - Error *err) +void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *err) { // "lnum" will be the index of the line after inserting, // 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; 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 @@ -286,13 +276,8 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer, /// @param replacement Array of lines to use as replacement (0-length // array will delete the line range) /// @param[out] err Error details, if any -void buffer_set_line_slice(Buffer buffer, - Integer start, - Integer end, - Boolean include_start, - Boolean include_end, - ArrayOf(String) replacement, - Error *err) +void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean include_start, + Boolean include_end, ArrayOf(String) replacement, Error *err) { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c index 9f16da4078..38ce7ca78c 100644 --- a/src/nvim/api/private/dispatch.c +++ b/src/nvim/api/private/dispatch.c @@ -1,38 +1,35 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include <inttypes.h> -#include <stdbool.h> #include <assert.h> +#include <inttypes.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/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/private/defs.h" - -#include "nvim/api/buffer.h" #include "nvim/api/tabpage.h" #include "nvim/api/ui.h" #include "nvim/api/vim.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 void msgpack_rpc_add_method_handler(String method, - MsgpackRpcRequestHandler handler) +static void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandler handler) { map_put(String, MsgpackRpcRequestHandler)(&methods, method, handler); } /// @param name API method name /// @param name_len name size (includes terminating NUL) -MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, - size_t name_len, +MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, size_t name_len, Error *error) { String m = { .data = (char *)name, .size = name_len }; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index ecbd4e13a3..541793e528 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -7,33 +7,33 @@ #include <stdlib.h> #include <string.h> -#include "nvim/api/private/helpers.h" #include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" -#include "nvim/msgpack_rpc/helpers.h" -#include "nvim/lua/executor.h" #include "nvim/ascii.h" #include "nvim/assert.h" -#include "nvim/charset.h" -#include "nvim/syntax.h" -#include "nvim/vim.h" #include "nvim/buffer.h" -#include "nvim/window.h" -#include "nvim/memline.h" -#include "nvim/memory.h" +#include "nvim/charset.h" +#include "nvim/decoration.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" -#include "nvim/map_defs.h" -#include "nvim/map.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_defs.h" -#include "nvim/version.h" -#include "nvim/lib/kvec.h" -#include "nvim/getchar.h" -#include "nvim/fileio.h" +#include "nvim/syntax.h" #include "nvim/ui.h" +#include "nvim/version.h" +#include "nvim/vim.h" +#include "nvim/window.h" /// Helper structure for vim_to_object typedef struct { @@ -41,8 +41,8 @@ typedef struct { } EncodedData; #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "api/private/helpers.c.generated.h" # include "api/private/funcs_metadata.generated.h" +# include "api/private/helpers.c.generated.h" # include "api/private/ui_events_metadata.generated.h" #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[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 -Object dict_set_var(dict_T *dict, String key, Object value, bool del, - bool retval, Error *err) +Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retval, Error *err) { Object rv = OBJECT_INIT; 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 name The option name /// @param[out] err Details of an error that may have occurred -void set_option_to(uint64_t channel_id, void *to, int type, - String name, Object value, Error *err) +void set_option_to(uint64_t channel_id, void *to, int type, String name, Object value, Error *err) { if (name.size == 0) { 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_CONV_NIL(tv) \ - kvi_push(edata->stack, NIL) + kvi_push(edata->stack, NIL) #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) \ - 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_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) \ - do { \ - const size_t len_ = (size_t)(len); \ - const char *const str_ = (const char *)(str); \ - assert(len_ == 0 || str_ != NULL); \ - kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \ - } while (0) + do { \ + const size_t len_ = (size_t)(len); \ + const char *const str_ = (const char *)(str); \ + assert(len_ == 0 || str_ != NULL); \ + kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \ + } while (0) #define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING #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) \ - do { \ - const size_t len_ = (size_t)(len); \ - const blob_T *const blob_ = (blob); \ - kvi_push(edata->stack, STRING_OBJ(((String) { \ - .data = len_ != 0 ? xmemdup(blob_->bv_ga.ga_data, len_) : NULL, \ - .size = len_ \ - }))); \ - } while (0) + do { \ + const size_t len_ = (size_t)(len); \ + const blob_T *const blob_ = (blob); \ + kvi_push(edata->stack, STRING_OBJ(((String) { \ + .data = len_ != 0 ? xmemdup(blob_->bv_ga.ga_data, len_) : NULL, \ + .size = len_ \ + }))); \ + } while (0) #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ - do { \ - TYPVAL_ENCODE_CONV_NIL(tv); \ - goto typval_encode_stop_converting_one_item; \ - } while (0) + do { \ + TYPVAL_ENCODE_CONV_NIL(tv); \ + goto typval_encode_stop_converting_one_item; \ + } while (0) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) #define TYPVAL_ENCODE_CONV_FUNC_END(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) \ - kvi_push(edata->stack, \ - DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 }))) + kvi_push(edata->stack, \ + DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 }))) -static inline void typval_encode_list_start(EncodedData *const edata, - const size_t len) +static inline void typval_encode_list_start(EncodedData *const edata, const size_t len) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL { 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) \ - 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) @@ -498,7 +495,7 @@ static inline void typval_encode_between_list_items(EncodedData *const edata) } #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) 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) \ - typval_encode_list_end(edata) + typval_encode_list_end(edata) -static inline void typval_encode_dict_start(EncodedData *const edata, - const size_t len) +static inline void typval_encode_dict_start(EncodedData *const edata, const size_t len) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL { kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) { .capacity = len, .size = 0, .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) \ - 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) @@ -541,16 +537,16 @@ static inline void typval_encode_after_key(EncodedData *const edata) assert(dict->data.dictionary.size < dict->data.dictionary.capacity); if (key.type == kObjectTypeString) { dict->data.dictionary.items[dict->data.dictionary.size].key - = key.data.string; + = key.data.string; } else { api_free_object(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) \ - typval_encode_after_key(edata) + typval_encode_after_key(edata) static inline void typval_encode_between_dict_items(EncodedData *const edata) 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) \ - typval_encode_between_dict_items(edata) + typval_encode_between_dict_items(edata) static inline void typval_encode_dict_end(EncodedData *const edata) 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) \ - typval_encode_dict_end(edata) + typval_encode_dict_end(edata) #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_NAME object @@ -708,15 +704,15 @@ String cchar_to_string(char c) /// empty String is returned String cstr_to_string(const char *str) { - if (str == NULL) { - return (String)STRING_INIT; - } + if (str == NULL) { + return (String)STRING_INIT; + } - size_t len = strlen(str); - return (String){ - .data = xmemdupz(str, len), - .size = len, - }; + size_t len = strlen(str); + return (String){ + .data = xmemdupz(str, len), + .size = len, + }; } /// 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 /// buffer, or -1 to signify global behavior ("all buffers") /// @param is_unmap When true, removes the mapping that matches {lhs}. -void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs, - String rhs, Dictionary opts, Error *err) +void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs, String rhs, + Dictionary opts, Error *err) { char *err_msg = NULL; // the error message to report, if any 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)) { - case 0: - break; - case 1: - api_set_error(err, kErrorTypeException, (char *)e_invarg, 0); - goto fail_and_free; - case 2: - api_set_error(err, kErrorTypeException, (char *)e_nomap, 0); - goto fail_and_free; - case 5: - api_set_error(err, kErrorTypeException, - "E227: mapping already exists for %s", parsed_args.lhs); - goto fail_and_free; - default: - assert(false && "Unrecognized return code!"); - goto fail_and_free; + case 0: + break; + case 1: + api_set_error(err, kErrorTypeException, (char *)e_invarg, 0); + goto fail_and_free; + case 2: + api_set_error(err, kErrorTypeException, (char *)e_nomap, 0); + goto fail_and_free; + case 5: + api_set_error(err, kErrorTypeException, + "E227: mapping already exists for %s", parsed_args.lhs); + goto fail_and_free; + default: + assert(false && "Unrecognized return code!"); + goto fail_and_free; } // switch xfree(lhs_buf); @@ -986,44 +982,44 @@ Integer parse_keymap_opts(Dictionary opts, MapArguments *out, Error *err) bool was_valid_opt = false; switch (optname[0]) { - // note: strncmp up to and including the null terminator, so that - // "nowaitFoobar" won't match against "nowait" - - // 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 - // inferred from which function they called - case 'n': - if (STRNCMP(optname, "noremap", 8) == 0) { - was_valid_opt = true; - out->noremap = key_and_val->value.data.boolean; - } else if (STRNCMP(optname, "nowait", 7) == 0) { - was_valid_opt = true; - out->nowait = key_and_val->value.data.boolean; - } - break; - case 's': - if (STRNCMP(optname, "silent", 7) == 0) { - was_valid_opt = true; - out->silent = key_and_val->value.data.boolean; - } else if (STRNCMP(optname, "script", 7) == 0) { - was_valid_opt = true; - out->script = key_and_val->value.data.boolean; - } - break; - case 'e': - if (STRNCMP(optname, "expr", 5) == 0) { - was_valid_opt = true; - out->expr = key_and_val->value.data.boolean; - } - break; - case 'u': - if (STRNCMP(optname, "unique", 7) == 0) { - was_valid_opt = true; - out->unique = key_and_val->value.data.boolean; - } - break; - default: - break; + // note: strncmp up to and including the null terminator, so that + // "nowaitFoobar" won't match against "nowait" + + // 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 + // inferred from which function they called + case 'n': + if (STRNCMP(optname, "noremap", 8) == 0) { + was_valid_opt = true; + out->noremap = key_and_val->value.data.boolean; + } else if (STRNCMP(optname, "nowait", 7) == 0) { + was_valid_opt = true; + out->nowait = key_and_val->value.data.boolean; + } + break; + case 's': + if (STRNCMP(optname, "silent", 7) == 0) { + was_valid_opt = true; + out->silent = key_and_val->value.data.boolean; + } else if (STRNCMP(optname, "script", 7) == 0) { + was_valid_opt = true; + out->script = key_and_val->value.data.boolean; + } + break; + case 'e': + if (STRNCMP(optname, "expr", 5) == 0) { + was_valid_opt = true; + out->expr = key_and_val->value.data.boolean; + } + break; + case 'u': + if (STRNCMP(optname, "unique", 7) == 0) { + was_valid_opt = true; + out->unique = key_and_val->value.data.boolean; + } + break; + default: + break; } // switch if (!was_valid_opt) { err_msg = "Invalid key: %s"; @@ -1050,8 +1046,7 @@ fail_with_message: /// @param[out] l Lines are copied here /// @param err[out] Error, if any /// @return true unless `err` was set -bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, - Array *l, Error *err) +bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Array *l, Error *err) { for (size_t i = 0; i < n; 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; switch (obj.type) { - case kObjectTypeNil: - tv->v_type = VAR_SPECIAL; - tv->vval.v_special = kSpecialVarNull; - break; - - case kObjectTypeBoolean: - tv->v_type = VAR_BOOL; - tv->vval.v_bool = obj.data.boolean? kBoolVarTrue: kBoolVarFalse; - break; - - case kObjectTypeBuffer: - case kObjectTypeWindow: - case kObjectTypeTabpage: - case kObjectTypeInteger: - STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T), - "Integer size must be <= VimL number size"); - tv->v_type = VAR_NUMBER; - tv->vval.v_number = (varnumber_T)obj.data.integer; - break; - - case kObjectTypeFloat: - tv->v_type = VAR_FLOAT; - tv->vval.v_float = obj.data.floating; - break; - - case kObjectTypeString: - tv->v_type = VAR_STRING; - if (obj.data.string.data == NULL) { - tv->vval.v_string = NULL; - } else { - tv->vval.v_string = xmemdupz(obj.data.string.data, - obj.data.string.size); - } - break; - - case kObjectTypeArray: { - list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size); + case kObjectTypeNil: + tv->v_type = VAR_SPECIAL; + tv->vval.v_special = kSpecialVarNull; + break; + + case kObjectTypeBoolean: + tv->v_type = VAR_BOOL; + tv->vval.v_bool = obj.data.boolean? kBoolVarTrue: kBoolVarFalse; + break; + + case kObjectTypeBuffer: + case kObjectTypeWindow: + case kObjectTypeTabpage: + case kObjectTypeInteger: + STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T), + "Integer size must be <= VimL number size"); + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T)obj.data.integer; + break; + + case kObjectTypeFloat: + tv->v_type = VAR_FLOAT; + tv->vval.v_float = obj.data.floating; + break; + + case kObjectTypeString: + tv->v_type = VAR_STRING; + if (obj.data.string.data == NULL) { + tv->vval.v_string = NULL; + } else { + tv->vval.v_string = xmemdupz(obj.data.string.data, + obj.data.string.size); + } + break; - for (uint32_t i = 0; i < obj.data.array.size; i++) { - Object item = obj.data.array.items[i]; - typval_T li_tv; + case kObjectTypeArray: { + list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size); - if (!object_to_vim(item, &li_tv, err)) { - tv_list_free(list); - return false; - } + for (uint32_t i = 0; i < obj.data.array.size; i++) { + Object item = obj.data.array.items[i]; + typval_T li_tv; - tv_list_append_owned_tv(list, li_tv); + if (!object_to_vim(item, &li_tv, err)) { + tv_list_free(list); + return false; } - tv_list_ref(list); - tv->v_type = VAR_LIST; - tv->vval.v_list = list; - break; + tv_list_append_owned_tv(list, li_tv); } + tv_list_ref(list); - case kObjectTypeDictionary: { - dict_T *const dict = tv_dict_alloc(); + tv->v_type = VAR_LIST; + tv->vval.v_list = list; + break; + } - for (uint32_t i = 0; i < obj.data.dictionary.size; i++) { - KeyValuePair item = obj.data.dictionary.items[i]; - String key = item.key; + case kObjectTypeDictionary: { + dict_T *const dict = tv_dict_alloc(); - if (key.size == 0) { - api_set_error(err, kErrorTypeValidation, - "Empty dictionary keys aren't allowed"); - // cleanup - tv_dict_free(dict); - return false; - } + for (uint32_t i = 0; i < obj.data.dictionary.size; i++) { + KeyValuePair item = obj.data.dictionary.items[i]; + String key = item.key; - dictitem_T *const di = tv_dict_item_alloc(key.data); + if (key.size == 0) { + api_set_error(err, kErrorTypeValidation, + "Empty dictionary keys aren't allowed"); + // cleanup + tv_dict_free(dict); + return false; + } - if (!object_to_vim(item.value, &di->di_tv, err)) { - // cleanup - tv_dict_item_free(di); - tv_dict_free(dict); - return false; - } + dictitem_T *const di = tv_dict_item_alloc(key.data); - tv_dict_add(dict, di); + if (!object_to_vim(item.value, &di->di_tv, err)) { + // cleanup + tv_dict_item_free(di); + tv_dict_free(dict); + return false; } - dict->dv_refcount++; - tv->v_type = VAR_DICT; - tv->vval.v_dict = dict; - break; + tv_dict_add(dict, di); } - default: - abort(); + dict->dv_refcount++; + + tv->v_type = VAR_DICT; + tv->vval.v_dict = dict; + break; + } + default: + abort(); } return true; @@ -1196,33 +1191,33 @@ void api_free_string(String value) void api_free_object(Object value) { switch (value.type) { - case kObjectTypeNil: - case kObjectTypeBoolean: - case kObjectTypeInteger: - case kObjectTypeFloat: - case kObjectTypeBuffer: - case kObjectTypeWindow: - case kObjectTypeTabpage: - break; - - case kObjectTypeString: - api_free_string(value.data.string); - break; - - case kObjectTypeArray: - api_free_array(value.data.array); - break; - - case kObjectTypeDictionary: - api_free_dictionary(value.data.dictionary); - break; - - case kObjectTypeLuaRef: - api_free_luaref(value.data.luaref); - break; - - default: - abort(); + case kObjectTypeNil: + case kObjectTypeBoolean: + case kObjectTypeInteger: + case kObjectTypeFloat: + case kObjectTypeBuffer: + case kObjectTypeWindow: + case kObjectTypeTabpage: + break; + + case kObjectTypeString: + api_free_string(value.data.string); + break; + + case kObjectTypeArray: + api_free_array(value.data.array); + break; + + case kObjectTypeDictionary: + api_free_dictionary(value.data.dictionary); + break; + + case kObjectTypeLuaRef: + api_free_luaref(value.data.luaref); + break; + + default: + abort(); } } @@ -1385,36 +1380,30 @@ Dictionary copy_dictionary(Dictionary dict) Object copy_object(Object obj) { switch (obj.type) { - case kObjectTypeBuffer: - case kObjectTypeTabpage: - case kObjectTypeWindow: - case kObjectTypeNil: - case kObjectTypeBoolean: - case kObjectTypeInteger: - case kObjectTypeFloat: - return obj; - - case kObjectTypeString: - return STRING_OBJ(copy_string(obj.data.string)); - - case kObjectTypeArray: - return ARRAY_OBJ(copy_array(obj.data.array)); - - case kObjectTypeDictionary: { - return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary)); - } - default: - abort(); + case kObjectTypeBuffer: + case kObjectTypeTabpage: + case kObjectTypeWindow: + case kObjectTypeNil: + case kObjectTypeBoolean: + case kObjectTypeInteger: + case kObjectTypeFloat: + return obj; + + case kObjectTypeString: + return STRING_OBJ(copy_string(obj.data.string)); + + case kObjectTypeArray: + return ARRAY_OBJ(copy_array(obj.data.array)); + + case kObjectTypeDictionary: + return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary)); + default: + abort(); } } -static void set_option_value_for(char *key, - int numval, - char *stringval, - int opt_flags, - int opt_type, - void *from, - Error *err) +static void set_option_value_for(char *key, int numval, char *stringval, int opt_flags, + int opt_type, void *from, Error *err) { win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; @@ -1423,29 +1412,28 @@ static void set_option_value_for(char *key, try_start(); switch (opt_type) { - case SREQ_WIN: - if (switch_win(&save_curwin, &save_curtab, (win_T *)from, - win_find_tabpage((win_T *)from), false) == FAIL) - { - if (try_end(err)) { - return; - } - api_set_error(err, - kErrorTypeException, - "Problem while switching windows"); + case SREQ_WIN: + if (switch_win(&save_curwin, &save_curtab, (win_T *)from, + win_find_tabpage((win_T *)from), false) == FAIL) { + if (try_end(err)) { return; } - set_option_value_err(key, numval, stringval, opt_flags, err); - restore_win(save_curwin, save_curtab, true); - break; - case SREQ_BUF: - aucmd_prepbuf(&aco, (buf_T *)from); - 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; + api_set_error(err, + kErrorTypeException, + "Problem while switching windows"); + return; + } + set_option_value_err(key, numval, stringval, opt_flags, err); + restore_win(save_curwin, save_curtab, true); + break; + case SREQ_BUF: + aucmd_prepbuf(&aco, (buf_T *)from); + 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)) { @@ -1456,11 +1444,7 @@ static void set_option_value_for(char *key, } -static void set_option_value_err(char *key, - int numval, - char *stringval, - int opt_flags, - Error *err) +static void set_option_value_err(char *key, int numval, char *stringval, int opt_flags, Error *err) { char *errmsg; @@ -1519,8 +1503,7 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf) // Check for correct mode if (int_mode & current_maphash->m_mode) { mapblock_fill_dict(dict, current_maphash, buffer_value, false); - ADD(mappings, vim_to_object( - (typval_T[]) { { .v_type = VAR_DICT, .vval.v_dict = dict } })); + ADD(mappings, vim_to_object((typval_T[]) { { .v_type = VAR_DICT, .vval.v_dict = 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) { Integer id = obj.data.integer; if (id == 0) { - *row = 0; - *col = 0; - return true; + *row = 0; + *col = 0; + return true; } else if (id == -1) { - *row = MAXLNUM; - *col = MAXCOL; - return true; + *row = MAXLNUM; + *col = MAXCOL; + return true; } else if (id < 0) { api_set_error(err, kErrorTypeValidation, "Mark id must be positive"); return false; @@ -1578,7 +1561,7 @@ bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, int return false; } - // Check if it is a position + // Check if it is a position } else if (obj.type == kObjectTypeArray) { Array pos = obj.data.array; if (pos.size != 2 @@ -1662,8 +1645,7 @@ free_exit: /// @param what The name of the object, used for error message /// @param nil_value What to return if the type is nil. /// @param err Set if there was an error in converting to a bool -bool api_object_to_bool(Object obj, const char *what, - bool nil_value, Error *err) +bool api_object_to_bool(Object obj, const char *what, bool nil_value, Error *err) { if (obj.type == kObjectTypeBoolean) { return obj.data.boolean; @@ -1766,7 +1748,7 @@ static bool parse_float_relative(String relative, FloatRelative *out) char *str = relative.data; if (striequal(str, "editor")) { *out = kFloatRelativeEditor; - } else if (striequal(str, "win")) { + } else if (striequal(str, "win")) { *out = kFloatRelativeWindow; } else if (striequal(str, "cursor")) { *out = kFloatRelativeCursor; @@ -1800,7 +1782,7 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) { "shadow", { "", "", " ", " ", " ", " ", " ", "" }, true }, { "rounded", { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, false }, { "solid", { " ", " ", " ", " ", " ", " ", " ", " " }, false }, - { NULL, { { NUL } } , false }, + { NULL, { { NUL } }, false }, }; schar_T *chars = fconfig->border_chars; @@ -1837,7 +1819,6 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) return; } } - } else if (iytem.type == kObjectTypeString) { string = iytem.data.string; } 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 new_win, Error *err) +bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf, bool new_win, + Error *err) { // TODO(bfredl): use a get/has_key interface instead and get rid of extra // flags @@ -1998,13 +1979,13 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf, has_bufpos = true; } else if (!strcmp(key, "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)) { return false; } } else if (!strcmp(key, "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)) { return false; } @@ -2031,13 +2012,13 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf, fconfig->style = kWinStyleUnused; } else if (striequal(val.data.string.data, "minimal")) { fconfig->style = kWinStyleMinimal; - } else { + } else { api_set_error(err, kErrorTypeValidation, "Invalid value of 'style' key"); } } else if (strequal(key, "noautocmd") && new_win) { fconfig->noautocmd - = api_object_to_bool(val, "'noautocmd' key", false, err); + = api_object_to_bool(val, "'noautocmd' key", false, err); if (ERROR_SET(err)) { return false; } diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c index 5f727dbc38..14b6be8eeb 100644 --- a/src/nvim/api/tabpage.c +++ b/src/nvim/api/tabpage.c @@ -5,10 +5,10 @@ #include <stdint.h> #include <stdlib.h> -#include "nvim/api/tabpage.h" -#include "nvim/api/vim.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/tabpage.h" +#include "nvim/api/vim.h" #include "nvim/memory.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); if (!tab) { - return (Object) OBJECT_INIT; + return (Object)OBJECT_INIT; } 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 value Variable value /// @param[out] err Error details, if any -void nvim_tabpage_set_var(Tabpage tabpage, - String name, - Object value, - Error *err) +void nvim_tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) FUNC_API_SINCE(1) { tabpage_T *tab = find_tab_by_handle(tabpage, err); diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 713980ca68..9b200dcba2 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -2,22 +2,22 @@ // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com #include <assert.h> +#include <stdbool.h> #include <stddef.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/helpers.h" -#include "nvim/popupmnu.h" +#include "nvim/api/ui.h" #include "nvim/cursor_shape.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/ui.h" +#include "nvim/vim.h" #include "nvim/window.h" #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -85,8 +85,8 @@ void remote_ui_wait_for_attach(void) /// @param height Requested screen rows /// @param options |ui-option| map /// @param[out] err Error details, if any -void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, - Dictionary options, Error *err) +void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictionary options, + Error *err) FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { 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 -void ui_attach(uint64_t channel_id, Integer width, Integer height, - Boolean enable_rgb, Error *err) +void ui_attach(uint64_t channel_id, Integer width, Integer height, Boolean enable_rgb, Error *err) { Dictionary opts = ARRAY_DICT_INIT; 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, - Integer height, Error *err) +void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Error *err) FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { 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(); } -void nvim_ui_set_option(uint64_t channel_id, String name, - Object value, Error *error) +void nvim_ui_set_option(uint64_t channel_id, String name, Object value, Error *error) FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { 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); } -static void ui_set_option(UI *ui, bool init, String name, Object value, - Error *error) +static void ui_set_option(UI *ui, bool init, String name, Object value, Error *error) { if (strequal(name.data, "override")) { 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 height The new requested height. /// @param[out] err Error details, if any -void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, - Integer height, Error *err) +void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, Integer height, + Error *err) FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY { 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 col Popupmenu height. /// @param[out] err Error details, if any. -void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, - Float row, Float col, Error *err) +void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Float row, Float col, + Error *err) FUNC_API_SINCE(7) FUNC_API_REMOTE_ONLY { 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); } -static void remote_ui_grid_resize(UI *ui, Integer grid, - Integer width, Integer height) +static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height) { Array args = ARRAY_DICT_INIT; if (ui->ui_ext[kUILinegrid]) { @@ -437,9 +432,8 @@ static void remote_ui_grid_resize(UI *ui, Integer grid, push_call(ui, name, args); } -static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, - Integer bot, Integer left, Integer right, - Integer rows, Integer cols) +static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left, + Integer right, Integer rows, Integer cols) { if (ui->ui_ext[kUILinegrid]) { 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, - Integer rgb_bg, Integer rgb_sp, +static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, Integer cterm_fg, Integer cterm_bg) { 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, - HlAttrs cterm_attrs, Array info) +static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, + Array info) { if (!ui->ui_ext[kUILinegrid]) { return; @@ -543,8 +536,7 @@ static void remote_ui_highlight_set(UI *ui, int id) } /// "true" cursor used only for input focus -static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, - Integer col) +static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col) { if (ui->ui_ext[kUILinegrid]) { Array args = ARRAY_DICT_INIT; @@ -584,11 +576,9 @@ static void remote_ui_put(UI *ui, const char *cell) push_call(ui, "put", args); } -static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, - Integer startcol, Integer endcol, - Integer clearcol, Integer clearattr, - LineFlags flags, const schar_T *chunk, - const sattr_T *attrs) +static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol, + Integer clearcol, Integer clearattr, LineFlags flags, + const schar_T *chunk, const sattr_T *attrs) { UIData *data = ui->data; 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 (strequal(name, "popupmenu_show")) { data->wildmenu_active = (args.items[4].data.integer == -1) - || !ui->ui_ext[kUIPopupmenu]; + || !ui->ui_ext[kUIPopupmenu]; if (data->wildmenu_active) { Array new_args = ARRAY_DICT_INIT; Array items = args.items[0].data.array; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index e764c45f0e..3be45d0cf7 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -3,54 +3,54 @@ #include <assert.h> #include <inttypes.h> +#include <limits.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> -#include <limits.h> -#include "nvim/api/vim.h" -#include "nvim/ascii.h" -#include "nvim/api/private/helpers.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/buffer.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/vim.h" #include "nvim/api/window.h" -#include "nvim/api/deprecated.h" -#include "nvim/msgpack_rpc/channel.h" -#include "nvim/msgpack_rpc/helpers.h" -#include "nvim/lua/executor.h" -#include "nvim/vim.h" +#include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/context.h" -#include "nvim/file_search.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/decoration.h" #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/typval.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/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/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/helpers.h" #include "nvim/ops.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/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/parser.h" -#include "nvim/ui.h" +#include "nvim/window.h" #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) { switch (mode.data[i]) { - case 'n': remap = false; break; - case 'm': remap = true; break; - case 't': typed = true; break; - case 'i': insert = true; break; - case 'x': execute = true; break; - case '!': dangerous = true; break; + case 'n': + remap = false; break; + case 'm': + remap = true; break; + case 't': + 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; if (escape_csi) { - // Need to escape K_SPECIAL and CSI before putting the string in the - // typeahead buffer. - keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); + // Need to escape K_SPECIAL and CSI before putting the string in the + // typeahead buffer. + keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); } else { - keys_esc = keys.data; + keys_esc = keys.data; } ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE), insert ? 0 : typebuf.tb_len, !typed, false); @@ -329,7 +335,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) } if (escape_csi) { - xfree(keys_esc); + xfree(keys_esc); } if (execute) { @@ -391,8 +397,8 @@ Integer nvim_input(String keys) /// @param row Mouse row-position (zero-based, like redraw events) /// @param col Mouse column-position (zero-based, like redraw events) /// @param[out] err Error details, if any -void nvim_input_mouse(String button, String action, String modifier, - Integer grid, Integer row, Integer col, Error *err) +void nvim_input_mouse(String button, String action, String modifier, Integer grid, Integer row, + Integer col, Error *err) FUNC_API_SINCE(6) FUNC_API_FAST { if (button.data == NULL || action.data == NULL) { @@ -469,8 +475,7 @@ error: /// @param special Replace |keycodes|, e.g. <CR> becomes a "\n" char. /// @see replace_termcodes /// @see cpoptions -String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, - Boolean special) +String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) FUNC_API_SINCE(1) { if (str.size == 0) { @@ -499,32 +504,32 @@ Object nvim_eval(String expr, Error *err) Object rv = OBJECT_INIT; TRY_WRAP({ - // Initialize `force_abort` and `suppress_errthrow` at the top level. - if (!recursive) { - force_abort = false; - suppress_errthrow = false; - current_exception = NULL; - // `did_emsg` is set by emsg(), which cancels execution. - did_emsg = false; - } - recursive++; - try_start(); + // Initialize `force_abort` and `suppress_errthrow` at the top level. + if (!recursive) { + force_abort = false; + suppress_errthrow = false; + current_exception = NULL; + // `did_emsg` is set by emsg(), which cancels execution. + did_emsg = false; + } + recursive++; + try_start(); - typval_T rettv; - int ok = eval0((char_u *)expr.data, &rettv, NULL, true); + 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); + 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--; + tv_clear(&rettv); + recursive--; }); return rv; @@ -597,31 +602,31 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err) } TRY_WRAP({ - // Initialize `force_abort` and `suppress_errthrow` at the top level. - if (!recursive) { - force_abort = false; - suppress_errthrow = false; - current_exception = NULL; - // `did_emsg` is set by emsg(), which cancels execution. - did_emsg = false; - } - recursive++; - try_start(); - typval_T rettv; - funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; - funcexe.selfdict = self; - // call_func() retval is deceptive, ignore it. Instead we set `msg_list` - // (see above) to capture abort-causing non-exception errors. - (void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size, - vim_args, &funcexe); - if (!try_end(err)) { - rv = vim_to_object(&rettv); - } - tv_clear(&rettv); - recursive--; + // Initialize `force_abort` and `suppress_errthrow` at the top level. + if (!recursive) { + force_abort = false; + suppress_errthrow = false; + current_exception = NULL; + // `did_emsg` is set by emsg(), which cancels execution. + did_emsg = false; + } + recursive++; + try_start(); + typval_T rettv; + funcexe_T funcexe = FUNCEXE_INIT; + funcexe.firstline = curwin->w_cursor.lnum; + funcexe.lastline = curwin->w_cursor.lnum; + funcexe.evaluate = true; + funcexe.selfdict = self; + // call_func() retval is deceptive, ignore it. Instead we set `msg_list` + // (see above) to capture abort-causing non-exception errors. + (void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size, + vim_args, &funcexe); + if (!try_end(err)) { + rv = vim_to_object(&rettv); + } + tv_clear(&rettv); + recursive--; }); free_vim_args: @@ -663,31 +668,28 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err) typval_T rettv; bool mustfree = false; switch (dict.type) { - case kObjectTypeString: { - try_start(); - if (eval0((char_u *)dict.data.string.data, &rettv, NULL, true) == FAIL) { - api_set_error(err, kErrorTypeException, - "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 (!object_to_vim(dict, &rettv, err)) { - goto end; - } - break; + case kObjectTypeString: + try_start(); + if (eval0((char_u *)dict.data.string.data, &rettv, NULL, true) == FAIL) { + api_set_error(err, kErrorTypeException, + "Failed to evaluate dict expression"); } - default: { - api_set_error(err, kErrorTypeValidation, - "dict argument type must be String or Dictionary"); + 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 (!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; 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 /// /// @return Window handle, or 0 on error -Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config, - Error *err) +Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config, Error *err) FUNC_API_SINCE(6) FUNC_API_CHECK_TEXTLOCK { @@ -1579,7 +1580,7 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err) bool cancel = false; 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; } Array args = ARRAY_DICT_INIT; @@ -1643,8 +1644,7 @@ theend: /// @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[out] err Error details, if any -void nvim_put(ArrayOf(String) lines, String type, Boolean after, - Boolean follow, Error *err) +void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Error *err) FUNC_API_SINCE(6) FUNC_API_CHECK_TEXTLOCK { @@ -1885,8 +1885,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode) /// as keys excluding |<buffer>| but including |noremap|. /// Values are Booleans. Unknown key is an error. /// @param[out] err Error details, if any. -void nvim_set_keymap(String mode, String lhs, String rhs, - Dictionary opts, Error *err) +void nvim_set_keymap(String mode, String lhs, String rhs, Dictionary opts, Error *err) FUNC_API_SINCE(6) { 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. /// /// @param[out] err Error details, if any -void nvim_set_client_info(uint64_t channel_id, String name, - Dictionary version, String type, - Dictionary methods, Dictionary attributes, - Error *err) +void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, String type, + Dictionary methods, Dictionary attributes, Error *err) FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY { 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; MsgpackRpcRequestHandler handler = - msgpack_rpc_get_handler_for(name.data, - name.size, - &nested_error); + msgpack_rpc_get_handler_for(name.data, + name.size, + &nested_error); if (ERROR_SET(&nested_error)) { break; @@ -2232,26 +2229,26 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// - "svalue": String, value for "SingleQuotedString" and /// "DoubleQuotedString" nodes. /// @param[out] err Error details, if any -Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, - Error *err) +Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Error *err) FUNC_API_SINCE(4) FUNC_API_FAST { int pflags = 0; for (size_t i = 0 ; i < flags.size ; i++) { switch (flags.data[i]) { - case 'm': { pflags |= kExprFlagsMulti; break; } - case 'E': { pflags |= kExprFlagsDisallowEOC; break; } - case 'l': { pflags |= kExprFlagsParseLet; break; } - case NUL: { - api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", - (unsigned)flags.data[i]); - return (Dictionary)ARRAY_DICT_INIT; - } - default: { - api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", - flags.data[i], (unsigned)flags.data[i]); - return (Dictionary)ARRAY_DICT_INIT; - } + case 'm': + pflags |= kExprFlagsMulti; break; + case 'E': + pflags |= kExprFlagsDisallowEOC; break; + case 'l': + pflags |= kExprFlagsParseLet; break; + case NUL: + api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", + (unsigned)flags.data[i]); + return (Dictionary)ARRAY_DICT_INIT; + default: + api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", + flags.data[i], (unsigned)flags.data[i]); + return (Dictionary)ARRAY_DICT_INIT; } } ParserLine parser_lines[] = { @@ -2267,15 +2264,14 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, kvi_init(colors); ParserHighlight *const colors_p = (highlight ? &colors : NULL); ParserState pstate; - viml_parser_init( - &pstate, parser_simple_get_line, &plines_p, colors_p); + viml_parser_init(&pstate, parser_simple_get_line, &plines_p, colors_p); ExprAST east = viml_pexpr_parse(&pstate, pflags); const size_t ret_size = ( - 2 // "ast", "len" - + (size_t)(east.err.msg != NULL) // "error" - + (size_t)highlight // "highlight" - + 0); + 2 // "ast", "len" + + (size_t)(east.err.msg != NULL) // "error" + + (size_t)highlight // "highlight" + + 0); Dictionary ret = { .items = xmalloc(ret_size * sizeof(ret.items[0])), .size = 0, @@ -2362,23 +2358,23 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, } else { if (cur_item.ret_node_p->type == kObjectTypeNil) { const size_t ret_node_items_size = (size_t)( - 3 // "type", "start" and "len" - + (node->children != NULL) // "children" - + (node->type == kExprNodeOption - || node->type == kExprNodePlainIdentifier) // "scope" - + (node->type == kExprNodeOption - || node->type == kExprNodePlainIdentifier - || node->type == kExprNodePlainKey - || node->type == kExprNodeEnvironment) // "ident" - + (node->type == kExprNodeRegister) // "name" - + (3 // "cmp_type", "ccs_strategy", "invert" - * (node->type == kExprNodeComparison)) - + (node->type == kExprNodeInteger) // "ivalue" - + (node->type == kExprNodeFloat) // "fvalue" - + (node->type == kExprNodeDoubleQuotedString - || node->type == kExprNodeSingleQuotedString) // "svalue" - + (node->type == kExprNodeAssignment) // "augmentation" - + 0); + 3 // "type", "start" and "len" + + (node->children != NULL) // "children" + + (node->type == kExprNodeOption + || node->type == kExprNodePlainIdentifier) // "scope" + + (node->type == kExprNodeOption + || node->type == kExprNodePlainIdentifier + || node->type == kExprNodePlainKey + || node->type == kExprNodeEnvironment) // "ident" + + (node->type == kExprNodeRegister) // "name" + + (3 // "cmp_type", "ccs_strategy", "invert" + * (node->type == kExprNodeComparison)) + + (node->type == kExprNodeInteger) // "ivalue" + + (node->type == kExprNodeFloat) // "fvalue" + + (node->type == kExprNodeDoubleQuotedString + || node->type == kExprNodeSingleQuotedString) // "svalue" + + (node->type == kExprNodeAssignment) // "augmentation" + + 0); Dictionary ret_node = { .items = xmalloc(ret_node_items_size * sizeof(ret_node.items[0])), .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), }; switch (node->type) { - case kExprNodeDoubleQuotedString: - case kExprNodeSingleQuotedString: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("svalue"), - .value = STRING_OBJ(((String) { - .data = node->data.str.value, - .size = node->data.str.size, - })), - }; - break; - } - case kExprNodeOption: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("scope"), - .value = INTEGER_OBJ(node->data.opt.scope), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.opt.ident, - node->data.opt.ident_len), - .size = node->data.opt.ident_len, - })), - }; - break; - } - case kExprNodePlainIdentifier: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .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"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.var.ident, - node->data.var.ident_len), - .size = node->data.var.ident_len, - })), - }; - break; - } - case kExprNodePlainKey: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .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) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.env.ident, - node->data.env.ident_len), - .size = node->data.env.ident_len, - })), - }; - break; - } - case kExprNodeRegister: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("name"), - .value = INTEGER_OBJ(node->data.reg.name), - }; - break; - } - case kExprNodeComparison: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("cmp_type"), - .value = STRING_OBJ(cstr_to_string( - eltkn_cmp_type_tab[node->data.cmp.type])), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ccs_strategy"), - .value = STRING_OBJ(cstr_to_string( - ccs_tab[node->data.cmp.ccs])), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("invert"), - .value = BOOLEAN_OBJ(node->data.cmp.inv), - }; - break; - } - case kExprNodeFloat: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .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 + case kExprNodeDoubleQuotedString: + case kExprNodeSingleQuotedString: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("svalue"), + .value = STRING_OBJ(((String) { + .data = node->data.str.value, + .size = node->data.str.size, + })), + }; + break; + case kExprNodeOption: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("scope"), + .value = INTEGER_OBJ(node->data.opt.scope), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.opt.ident, + node->data.opt.ident_len), + .size = node->data.opt.ident_len, + })), + }; + break; + case kExprNodePlainIdentifier: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .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"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.var.ident, + node->data.var.ident_len), + .size = node->data.var.ident_len, + })), + }; + break; + case kExprNodePlainKey: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .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) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.env.ident, + node->data.env.ident_len), + .size = node->data.env.ident_len, + })), + }; + break; + case kExprNodeRegister: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("name"), + .value = INTEGER_OBJ(node->data.reg.name), + }; + break; + case kExprNodeComparison: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("cmp_type"), + .value = STRING_OBJ(cstr_to_string(eltkn_cmp_type_tab[node->data.cmp.type])), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ccs_strategy"), + .value = STRING_OBJ(cstr_to_string(ccs_tab[node->data.cmp.ccs])), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("invert"), + .value = BOOLEAN_OBJ(node->data.cmp.inv), + }; + break; + case kExprNodeFloat: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .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 : (Integer)node->data.num.value)), - }; - break; - } - case kExprNodeAssignment: { - const ExprAssignmentType asgn_type = node->data.ass.type; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("augmentation"), - .value = STRING_OBJ( - asgn_type == kExprAsgnPlain + }; + break; + case kExprNodeAssignment: { + const ExprAssignmentType asgn_type = node->data.ass.type; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("augmentation"), + .value = STRING_OBJ(asgn_type == kExprAsgnPlain ? (String)STRING_INIT : cstr_to_string(expr_asgn_type_tab[asgn_type])), - }; - break; - } - case kExprNodeMissing: - case kExprNodeOpMissing: - case kExprNodeTernary: - case kExprNodeTernaryValue: - case kExprNodeSubscript: - case kExprNodeListLiteral: - case kExprNodeUnaryPlus: - case kExprNodeBinaryPlus: - case kExprNodeNested: - case kExprNodeCall: - case kExprNodeComplexIdentifier: - case kExprNodeUnknownFigure: - case kExprNodeLambda: - case kExprNodeDictLiteral: - case kExprNodeCurlyBracesIdentifier: - case kExprNodeComma: - case kExprNodeColon: - case kExprNodeArrow: - case kExprNodeConcat: - case kExprNodeConcatOrSubscript: - case kExprNodeOr: - case kExprNodeAnd: - case kExprNodeUnaryMinus: - case kExprNodeBinaryMinus: - case kExprNodeNot: - case kExprNodeMultiplication: - case kExprNodeDivision: - case kExprNodeMod: { - break; - } + }; + break; + } + case kExprNodeMissing: + case kExprNodeOpMissing: + case kExprNodeTernary: + case kExprNodeTernaryValue: + case kExprNodeSubscript: + case kExprNodeListLiteral: + case kExprNodeUnaryPlus: + case kExprNodeBinaryPlus: + case kExprNodeNested: + case kExprNodeCall: + case kExprNodeComplexIdentifier: + case kExprNodeUnknownFigure: + case kExprNodeLambda: + case kExprNodeDictLiteral: + case kExprNodeCurlyBracesIdentifier: + case kExprNodeComma: + case kExprNodeColon: + case kExprNodeArrow: + case kExprNodeConcat: + case kExprNodeConcatOrSubscript: + case kExprNodeOr: + case kExprNodeAnd: + case kExprNodeUnaryMinus: + case kExprNodeBinaryMinus: + case kExprNodeNot: + case kExprNodeMultiplication: + case kExprNodeDivision: + case kExprNodeMod: + break; } assert(cur_item.ret_node_p->data.dictionary.size == cur_item.ret_node_p->data.dictionary.capacity); @@ -2806,8 +2789,8 @@ Object nvim_get_proc(Integer pid, Error *err) /// `insert`. /// @param opts Optional parameters. Reserved for future use. /// @param[out] err Error details, if any -void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, - Dictionary opts, Error *err) +void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Dictionary opts, + Error *err) FUNC_API_SINCE(6) { if (opts.size > 0) { @@ -2904,8 +2887,7 @@ void nvim__screenshot(String path) /// ["win", winid, bufnr, row] /// - on_end: called at the end of a redraw cycle /// ["end", tick] -void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, - Error *err) +void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Error *err) FUNC_API_SINCE(7) FUNC_API_LUA_ONLY { DecorProvider *p = get_decor_provider((NS)ns_id, true); diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 069dfae233..99ba297111 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -1,25 +1,25 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +#include <limits.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> -#include <limits.h> #include "nvim/api/private/defs.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/ascii.h" #include "nvim/buffer.h" #include "nvim/cursor.h" +#include "nvim/ex_docmd.h" #include "nvim/globals.h" +#include "nvim/lua/executor.h" #include "nvim/move.h" #include "nvim/option.h" #include "nvim/screen.h" #include "nvim/syntax.h" +#include "nvim/vim.h" #include "nvim/window.h" /// 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); if (!win) { - return (Object) OBJECT_INIT; + return (Object)OBJECT_INIT; } 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); if (!win) { - return (Object) OBJECT_INIT; + return (Object)OBJECT_INIT; } 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 value Option value /// @param[out] err Error details, if any -void nvim_win_set_option(uint64_t channel_id, Window window, - String name, Object value, Error *err) +void nvim_win_set_option(uint64_t channel_id, Window window, String name, Object value, Error *err) FUNC_API_SINCE(1) { 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, "anchor", STRING_OBJ(cstr_to_string( - float_anchor_str[config->anchor]))); + PUT(rv, "anchor", STRING_OBJ(cstr_to_string(float_anchor_str[config->anchor]))); PUT(rv, "row", FLOAT_OBJ(config->row)); PUT(rv, "col", FLOAT_OBJ(config->col)); 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++) { Array tuple = ARRAY_DICT_INIT; - String s = cstrn_to_string( - (const char *)config->border_chars[i], sizeof(schar_T)); + String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T)); int hi_id = config->border_hl_ids[i]; char_u *hi_name = syn_id2name(hi_id); diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 5c03f55621..c8734c9b9c 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -1,20 +1,19 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include <stddef.h> - #include <msgpack.h> +#include <stddef.h> -#include "nvim/eval/typval.h" +#include "nvim/ascii.h" +#include "nvim/charset.h" // vim_str2nr #include "nvim/eval.h" #include "nvim/eval/decode.h" #include "nvim/eval/encode.h" -#include "nvim/ascii.h" -#include "nvim/macros.h" -#include "nvim/message.h" +#include "nvim/eval/typval.h" #include "nvim/globals.h" -#include "nvim/charset.h" // vim_str2nr #include "nvim/lib/kvec.h" +#include "nvim/macros.h" +#include "nvim/message.h" #include "nvim/vim.h" // OK, FAIL /// Helper structure for container_struct @@ -52,8 +51,7 @@ typedef kvec_t(ContainerStackItem) ContainerStack; /// @param[out] rettv Location where created dictionary will be saved. /// @param[in] type Type of the dictionary. /// @param[in] val Value associated with the _VAL key. -static inline void create_special_dict(typval_T *const rettv, - const MessagePackType type, +static inline void create_special_dict(typval_T *const rettv, const MessagePackType type, typval_T val) FUNC_ATTR_NONNULL_ALL { @@ -97,12 +95,9 @@ static inline void create_special_dict(typval_T *const rettv, /// value when decoder is restarted, otherwise unused. /// /// @return OK in case of success, FAIL in case of error. -static inline int json_decoder_pop(ValuesStackItem obj, - ValuesStack *const stack, - ContainerStack *const container_stack, - const char **const pp, - bool *const next_map_special, - bool *const didcomma, +static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack, + ContainerStack *const container_stack, const char **const pp, + bool *const next_map_special, bool *const didcomma, bool *const didcolon) FUNC_ATTR_NONNULL_ALL { @@ -114,9 +109,9 @@ static inline int json_decoder_pop(ValuesStackItem obj, const char *val_location = *pp; if (obj.val.v_type == last_container.container.v_type // vval.v_list and vval.v_dict should have the same size and offset - && ((void *) obj.val.vval.v_list - == (void *) last_container.container.vval.v_list)) { - (void) kv_pop(*container_stack); + && ((void *)obj.val.vval.v_list + == (void *)last_container.container.vval.v_list)) { + (void)kv_pop(*container_stack); val_location = last_container.s; last_container = kv_last(*container_stack); } @@ -142,8 +137,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, assert(!(key.is_special_string || key.val.vval.v_string == NULL || *key.val.vval.v_string == NUL)); - dictitem_T *const obj_di = tv_dict_item_alloc( - (const char *)key.val.vval.v_string); + dictitem_T *const obj_di = tv_dict_item_alloc((const char *)key.val.vval.v_string); tv_clear(&key.val); if (tv_dict_add(last_container.container.vval.v_dict, obj_di) == FAIL) { @@ -179,9 +173,9 @@ static inline int json_decoder_pop(ValuesStackItem obj, tv_clear(&obj.val); // Restart - (void) kv_pop(*container_stack); + (void)kv_pop(*container_stack); ValuesStackItem last_container_val = - kv_A(*stack, last_container.stack_index); + kv_A(*stack, last_container.stack_index); while (kv_size(*stack) > last_container.stack_index) { tv_clear(&(kv_pop(*stack).val)); } @@ -197,7 +191,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, } #define LENP(p, e) \ - ((int) ((e) - (p))), (p) + ((int)((e) - (p))), (p) #define OBJ(obj_tv, is_sp_string, didcomma_, didcolon_) \ ((ValuesStackItem) { \ .is_special_string = (is_sp_string), \ @@ -229,8 +223,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, /// /// @return [allocated] list which should contain key-value pairs. Return value /// may be safely ignored. -list_T *decode_create_map_special_dict(typval_T *const ret_tv, - const ptrdiff_t len) +list_T *decode_create_map_special_dict(typval_T *const ret_tv, const ptrdiff_t len) FUNC_ATTR_NONNULL_ALL { list_T *const list = tv_list_alloc(len); @@ -260,9 +253,8 @@ list_T *decode_create_map_special_dict(typval_T *const ret_tv, /// will be freed. /// /// @return Decoded string. -typval_T decode_string(const char *const s, const size_t len, - const TriState hasnul, const bool binary, - const bool s_allocated) +typval_T decode_string(const char *const s, const size_t len, const TriState hasnul, + const bool binary, const bool s_allocated) FUNC_ATTR_WARN_UNUSED_RESULT { assert(s != NULL || len == 0); @@ -280,10 +272,10 @@ typval_T decode_string(const char *const s, const size_t len, tv_list_ref(list); create_special_dict(&tv, kMPString, ((typval_T){ - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + })); const int elw_ret = encode_list_write((void *)list, s, len); if (s_allocated) { xfree((void *)s); @@ -299,7 +291,7 @@ typval_T decode_string(const char *const s, const size_t len, .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, .vval = { .v_string = (char_u *)( - (s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) }, + (s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) }, }; } } @@ -323,11 +315,9 @@ typval_T decode_string(const char *const s, const size_t len, /// /// @return OK in case of success, FAIL in case of error. static inline int parse_json_string(const char *const buf, const size_t buf_len, - const char **const pp, - ValuesStack *const stack, + const char **const pp, ValuesStack *const stack, ContainerStack *const container_stack, - bool *const next_map_special, - bool *const didcomma, + bool *const next_map_special, bool *const didcomma, bool *const didcolon) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { @@ -341,55 +331,52 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, p++; if (p == e) { emsgf(_("E474: Unfinished escape sequence: %.*s"), - (int) buf_len, buf); + (int)buf_len, buf); goto parse_json_string_fail; } switch (*p) { - case 'u': { - if (p + 4 >= e) { - emsgf(_("E474: Unfinished unicode escape sequence: %.*s"), - (int) buf_len, buf); - goto parse_json_string_fail; - } else if (!ascii_isxdigit(p[1]) - || !ascii_isxdigit(p[2]) - || !ascii_isxdigit(p[3]) - || !ascii_isxdigit(p[4])) { - emsgf(_("E474: Expected four hex digits after \\u: %.*s"), - LENP(p - 1, e)); - goto parse_json_string_fail; - } - // One UTF-8 character below U+10000 can take up to 3 bytes, - // above up to 6, but they are encoded using two \u escapes. - len += 3; - p += 5; - break; - } - case '\\': - case '/': - case '"': - case 't': - case 'b': - case 'n': - case 'r': - case 'f': { - len++; - p++; - break; - } - default: { - emsgf(_("E474: Unknown escape sequence: %.*s"), LENP(p - 1, e)); + case 'u': + if (p + 4 >= e) { + emsgf(_("E474: Unfinished unicode escape sequence: %.*s"), + (int)buf_len, buf); + goto parse_json_string_fail; + } else if (!ascii_isxdigit(p[1]) + || !ascii_isxdigit(p[2]) + || !ascii_isxdigit(p[3]) + || !ascii_isxdigit(p[4])) { + emsgf(_("E474: Expected four hex digits after \\u: %.*s"), + LENP(p - 1, e)); goto parse_json_string_fail; } + // One UTF-8 character below U+10000 can take up to 3 bytes, + // above up to 6, but they are encoded using two \u escapes. + len += 3; + p += 5; + break; + case '\\': + case '/': + case '"': + case 't': + case 'b': + case 'n': + case 'r': + case 'f': + len++; + p++; + break; + default: + emsgf(_("E474: Unknown escape sequence: %.*s"), LENP(p - 1, e)); + goto parse_json_string_fail; } } else { - uint8_t p_byte = (uint8_t) *p; + uint8_t p_byte = (uint8_t)*p; // unescaped = %x20-21 / %x23-5B / %x5D-10FFFF if (p_byte < 0x20) { emsgf(_("E474: ASCII control characters cannot be present " "inside string: %.*s"), LENP(p, e)); goto parse_json_string_fail; } - const int ch = utf_ptr2char((char_u *) p); + const int ch = utf_ptr2char((char_u *)p); // All characters above U+007F are encoded using two or more bytes // and thus cannot possibly be equal to *p. But utf_ptr2char({0xFF, // 0}) will return 0xFF, even though 0xFF cannot start any UTF-8 @@ -397,7 +384,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, // // The only exception is U+00C3 which is represented as 0xC3 0x83. if (ch >= 0x80 && p_byte == ch - && !(ch == 0xC3 && p + 1 < e && (uint8_t) p[1] == 0x83)) { + && !(ch == 0xC3 && p + 1 < e && (uint8_t)p[1] == 0x83)) { emsgf(_("E474: Only UTF-8 strings allowed: %.*s"), LENP(p, e)); goto parse_json_string_fail; } else if (ch > 0x10FFFF) { @@ -405,14 +392,14 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, "are allowed to appear unescaped: %.*s"), LENP(p, e)); goto parse_json_string_fail; } - const size_t ch_len = (size_t) utf_char2len(ch); - assert(ch_len == (size_t) (ch ? utf_ptr2len((char_u *) p) : 1)); + const size_t ch_len = (size_t)utf_char2len(ch); + assert(ch_len == (size_t)(ch ? utf_ptr2len((char_u *)p) : 1)); len += ch_len; p += ch_len; } } if (p == e || *p != '"') { - emsgf(_("E474: Expected string end: %.*s"), (int) buf_len, buf); + emsgf(_("E474: Expected string end: %.*s"), (int)buf_len, buf); goto parse_json_string_fail; } if (len == 0) { @@ -429,7 +416,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, #define PUT_FST_IN_PAIR(fst_in_pair, str_end) \ do { \ if (fst_in_pair != 0) { \ - str_end += utf_char2bytes(fst_in_pair, (char_u *) str_end); \ + str_end += utf_char2bytes(fst_in_pair, (char_u *)str_end); \ fst_in_pair = 0; \ } \ } while (0) @@ -440,56 +427,55 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, if (*t == '\\') { t++; switch (*t) { - case 'u': { - const char ubuf[] = { t[1], t[2], t[3], t[4] }; - t += 4; - uvarnumber_T ch; - vim_str2nr((char_u *)ubuf, NULL, NULL, - STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true); - if (ch == 0) { - hasnul = true; - } - if (SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) { - PUT_FST_IN_PAIR(fst_in_pair, str_end); - fst_in_pair = (int) ch; - } else if (SURROGATE_LO_START <= ch && ch <= SURROGATE_LO_END - && fst_in_pair != 0) { - const int full_char = ( - (int) (ch - SURROGATE_LO_START) - + ((fst_in_pair - SURROGATE_HI_START) << 10) - + SURROGATE_FIRST_CHAR); - str_end += utf_char2bytes(full_char, (char_u *) str_end); - fst_in_pair = 0; - } else { - PUT_FST_IN_PAIR(fst_in_pair, str_end); - str_end += utf_char2bytes((int) ch, (char_u *) str_end); - } - break; + case 'u': { + const char ubuf[] = { t[1], t[2], t[3], t[4] }; + t += 4; + uvarnumber_T ch; + vim_str2nr((char_u *)ubuf, NULL, NULL, + STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true); + if (ch == 0) { + hasnul = true; } - case '\\': - case '/': - case '"': - case 't': - case 'b': - case 'n': - case 'r': - case 'f': { - static const char escapes[] = { - ['\\'] = '\\', - ['/'] = '/', - ['"'] = '"', - ['t'] = TAB, - ['b'] = BS, - ['n'] = NL, - ['r'] = CAR, - ['f'] = FF, - }; - *str_end++ = escapes[(int) *t]; - break; - } - default: { - abort(); + if (SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) { + PUT_FST_IN_PAIR(fst_in_pair, str_end); + fst_in_pair = (int)ch; + } else if (SURROGATE_LO_START <= ch && ch <= SURROGATE_LO_END + && fst_in_pair != 0) { + const int full_char = ( + (int)(ch - SURROGATE_LO_START) + + ((fst_in_pair - SURROGATE_HI_START) << 10) + + SURROGATE_FIRST_CHAR); + str_end += utf_char2bytes(full_char, (char_u *)str_end); + fst_in_pair = 0; + } else { + PUT_FST_IN_PAIR(fst_in_pair, str_end); + str_end += utf_char2bytes((int)ch, (char_u *)str_end); } + break; + } + case '\\': + case '/': + case '"': + case 't': + case 'b': + case 'n': + case 'r': + case 'f': { + static const char escapes[] = { + ['\\'] = '\\', + ['/'] = '/', + ['"'] = '"', + ['t'] = TAB, + ['b'] = BS, + ['n'] = NL, + ['r'] = CAR, + ['f'] = FF, + }; + *str_end++ = escapes[(int)*t]; + break; + } + default: + abort(); } } else { *str_end++ = *t; @@ -498,8 +484,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, PUT_FST_IN_PAIR(fst_in_pair, str_end); #undef PUT_FST_IN_PAIR *str_end = NUL; - typval_T obj = decode_string( - str, (size_t)(str_end - str), hasnul ? kTrue : kFalse, false, true); + typval_T obj = decode_string(str, (size_t)(str_end - str), hasnul ? kTrue : kFalse, false, true); if (obj.v_type == VAR_UNKNOWN) { goto parse_json_string_fail; } @@ -536,11 +521,9 @@ parse_json_string_ret: /// /// @return OK in case of success, FAIL in case of error. static inline int parse_json_number(const char *const buf, const size_t buf_len, - const char **const pp, - ValuesStack *const stack, + const char **const pp, ValuesStack *const stack, ContainerStack *const container_stack, - bool *const next_map_special, - bool *const didcomma, + bool *const next_map_special, bool *const didcomma, bool *const didcolon) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { @@ -605,14 +588,14 @@ parse_json_number_check: .v_type = VAR_NUMBER, .v_lock = VAR_UNLOCKED, }; - const size_t exp_num_len = (size_t) (p - s); + const size_t exp_num_len = (size_t)(p - s); if (fracs || exps) { // Convert floating-point number const size_t num_len = string2float(s, &tv.vval.v_float); if (exp_num_len != num_len) { emsgf(_("E685: internal error: while converting number \"%.*s\" " "to float string2float consumed %zu bytes in place of %zu"), - (int) exp_num_len, s, num_len, exp_num_len); + (int)exp_num_len, s, num_len, exp_num_len); } tv.v_type = VAR_FLOAT; } else { @@ -623,7 +606,7 @@ parse_json_number_check: if ((int)exp_num_len != num_len) { emsgf(_("E685: internal error: while converting number \"%.*s\" " "to integer vim_str2nr consumed %i bytes in place of %zu"), - (int) exp_num_len, s, num_len, exp_num_len); + (int)exp_num_len, s, num_len, exp_num_len); } tv.vval.v_number = nr; } @@ -664,8 +647,7 @@ parse_json_number_ret: /// @param[out] rettv Location where to save results. /// /// @return OK in case of success, FAIL otherwise. -int json_decode_string(const char *const buf, const size_t buf_len, - typval_T *const rettv) +int json_decode_string(const char *const buf, const size_t buf_len, typval_T *const rettv) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { const char *p = buf; @@ -688,219 +670,212 @@ int json_decode_string(const char *const buf, const size_t buf_len, json_decode_string_cycle_start: assert(*p == '{' || next_map_special == false); switch (*p) { - case '}': - case ']': { - if (kv_size(container_stack) == 0) { - emsgf(_("E474: No container to close: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } - ContainerStackItem last_container = kv_last(container_stack); - if (*p == '}' && last_container.container.v_type != VAR_DICT) { - emsgf(_("E474: Closing list with curly bracket: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (*p == ']' && last_container.container.v_type != VAR_LIST) { - emsgf(_("E474: Closing dictionary with square bracket: %.*s"), - LENP(p, e)); - goto json_decode_string_fail; - } else if (didcomma) { - emsgf(_("E474: Trailing comma: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (didcolon) { - emsgf(_("E474: Expected value after colon: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (last_container.stack_index != kv_size(stack) - 1) { - assert(last_container.stack_index < kv_size(stack) - 1); - emsgf(_("E474: Expected value: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } - if (kv_size(stack) == 1) { - p++; - (void) kv_pop(container_stack); - goto json_decode_string_after_cycle; - } else { - if (json_decoder_pop(kv_pop(stack), &stack, &container_stack, &p, - &next_map_special, &didcomma, &didcolon) - == FAIL) { - goto json_decode_string_fail; - } - assert(!next_map_special); - break; - } + case '}': + case ']': { + if (kv_size(container_stack) == 0) { + emsgf(_("E474: No container to close: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } - case ',': { - if (kv_size(container_stack) == 0) { - emsgf(_("E474: Comma not inside container: %.*s"), LENP(p, e)); + ContainerStackItem last_container = kv_last(container_stack); + if (*p == '}' && last_container.container.v_type != VAR_DICT) { + emsgf(_("E474: Closing list with curly bracket: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (*p == ']' && last_container.container.v_type != VAR_LIST) { + emsgf(_("E474: Closing dictionary with square bracket: %.*s"), + LENP(p, e)); + goto json_decode_string_fail; + } else if (didcomma) { + emsgf(_("E474: Trailing comma: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (didcolon) { + emsgf(_("E474: Expected value after colon: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (last_container.stack_index != kv_size(stack) - 1) { + assert(last_container.stack_index < kv_size(stack) - 1); + emsgf(_("E474: Expected value: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } + if (kv_size(stack) == 1) { + p++; + (void)kv_pop(container_stack); + goto json_decode_string_after_cycle; + } else { + if (json_decoder_pop(kv_pop(stack), &stack, &container_stack, &p, + &next_map_special, &didcomma, &didcolon) + == FAIL) { goto json_decode_string_fail; } - ContainerStackItem last_container = kv_last(container_stack); - if (didcomma) { - emsgf(_("E474: Duplicate comma: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (didcolon) { - emsgf(_("E474: Comma after colon: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (last_container.container.v_type == VAR_DICT - && last_container.stack_index != kv_size(stack) - 1) { - emsgf(_("E474: Using comma in place of colon: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (last_container.special_val == NULL + assert(!next_map_special); + break; + } + } + case ',': { + if (kv_size(container_stack) == 0) { + emsgf(_("E474: Comma not inside container: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } + ContainerStackItem last_container = kv_last(container_stack); + if (didcomma) { + emsgf(_("E474: Duplicate comma: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (didcolon) { + emsgf(_("E474: Comma after colon: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (last_container.container.v_type == VAR_DICT + && last_container.stack_index != kv_size(stack) - 1) { + emsgf(_("E474: Using comma in place of colon: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (last_container.special_val == NULL ? (last_container.container.v_type == VAR_DICT ? (DICT_LEN(last_container.container.vval.v_dict) == 0) : (tv_list_len(last_container.container.vval.v_list) == 0)) - : (tv_list_len(last_container.special_val) == 0)) { - emsgf(_("E474: Leading comma: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } - didcomma = true; - continue; + : (tv_list_len(last_container.special_val) == 0)) { + emsgf(_("E474: Leading comma: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } - case ':': { - if (kv_size(container_stack) == 0) { - emsgf(_("E474: Colon not inside container: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } - ContainerStackItem last_container = kv_last(container_stack); - if (last_container.container.v_type != VAR_DICT) { - emsgf(_("E474: Using colon not in dictionary: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (last_container.stack_index != kv_size(stack) - 2) { - emsgf(_("E474: Unexpected colon: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (didcomma) { - emsgf(_("E474: Colon after comma: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } else if (didcolon) { - emsgf(_("E474: Duplicate colon: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } - didcolon = true; - continue; + didcomma = true; + continue; + } + case ':': { + if (kv_size(container_stack) == 0) { + emsgf(_("E474: Colon not inside container: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } - case ' ': - case TAB: - case NL: - case CAR: { - continue; + ContainerStackItem last_container = kv_last(container_stack); + if (last_container.container.v_type != VAR_DICT) { + emsgf(_("E474: Using colon not in dictionary: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (last_container.stack_index != kv_size(stack) - 2) { + emsgf(_("E474: Unexpected colon: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (didcomma) { + emsgf(_("E474: Colon after comma: %.*s"), LENP(p, e)); + goto json_decode_string_fail; + } else if (didcolon) { + emsgf(_("E474: Duplicate colon: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } - case 'n': { - if ((p + 3) >= e || strncmp(p + 1, "ull", 3) != 0) { - emsgf(_("E474: Expected null: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } - p += 3; - POP(((typval_T) { - .v_type = VAR_SPECIAL, - .v_lock = VAR_UNLOCKED, - .vval = { .v_special = kSpecialVarNull }, - }), false); - break; + didcolon = true; + continue; + } + case ' ': + case TAB: + case NL: + case CAR: + continue; + case 'n': + if ((p + 3) >= e || strncmp(p + 1, "ull", 3) != 0) { + emsgf(_("E474: Expected null: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } - case 't': { - if ((p + 3) >= e || strncmp(p + 1, "rue", 3) != 0) { - emsgf(_("E474: Expected true: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } - p += 3; - POP(((typval_T) { - .v_type = VAR_BOOL, - .v_lock = VAR_UNLOCKED, - .vval = { .v_bool = kBoolVarTrue }, - }), false); - break; + p += 3; + POP(((typval_T) { + .v_type = VAR_SPECIAL, + .v_lock = VAR_UNLOCKED, + .vval = { .v_special = kSpecialVarNull }, + }), false); + break; + case 't': + if ((p + 3) >= e || strncmp(p + 1, "rue", 3) != 0) { + emsgf(_("E474: Expected true: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } - case 'f': { - if ((p + 4) >= e || strncmp(p + 1, "alse", 4) != 0) { - emsgf(_("E474: Expected false: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } - p += 4; - POP(((typval_T) { - .v_type = VAR_BOOL, - .v_lock = VAR_UNLOCKED, - .vval = { .v_bool = kBoolVarFalse }, - }), false); - break; + p += 3; + POP(((typval_T) { + .v_type = VAR_BOOL, + .v_lock = VAR_UNLOCKED, + .vval = { .v_bool = kBoolVarTrue }, + }), false); + break; + case 'f': + if ((p + 4) >= e || strncmp(p + 1, "alse", 4) != 0) { + emsgf(_("E474: Expected false: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } - case '"': { - if (parse_json_string(buf, buf_len, &p, &stack, &container_stack, - &next_map_special, &didcomma, &didcolon) - == FAIL) { - // Error message was already given - goto json_decode_string_fail; - } - if (next_map_special) { - goto json_decode_string_cycle_start; - } - break; + p += 4; + POP(((typval_T) { + .v_type = VAR_BOOL, + .v_lock = VAR_UNLOCKED, + .vval = { .v_bool = kBoolVarFalse }, + }), false); + break; + case '"': + if (parse_json_string(buf, buf_len, &p, &stack, &container_stack, + &next_map_special, &didcomma, &didcolon) + == FAIL) { + // Error message was already given + goto json_decode_string_fail; } - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - if (parse_json_number(buf, buf_len, &p, &stack, &container_stack, - &next_map_special, &didcomma, &didcolon) - == FAIL) { - // Error message was already given - goto json_decode_string_fail; - } - if (next_map_special) { - goto json_decode_string_cycle_start; - } - break; + if (next_map_special) { + goto json_decode_string_cycle_start; } - case '[': { - list_T *list = tv_list_alloc(kListLenMayKnow); - tv_list_ref(list); - typval_T tv = { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - }; - kv_push(container_stack, ((ContainerStackItem) { + break; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (parse_json_number(buf, buf_len, &p, &stack, &container_stack, + &next_map_special, &didcomma, &didcolon) + == FAIL) { + // Error message was already given + goto json_decode_string_fail; + } + if (next_map_special) { + goto json_decode_string_cycle_start; + } + break; + case '[': { + list_T *list = tv_list_alloc(kListLenMayKnow); + tv_list_ref(list); + typval_T tv = { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + }; + kv_push(container_stack, ((ContainerStackItem) { .stack_index = kv_size(stack), .s = p, .container = tv, .special_val = NULL, })); - kv_push(stack, OBJ(tv, false, didcomma, didcolon)); - break; + kv_push(stack, OBJ(tv, false, didcomma, didcolon)); + break; + } + case '{': { + typval_T tv; + list_T *val_list = NULL; + if (next_map_special) { + next_map_special = false; + val_list = decode_create_map_special_dict(&tv, kListLenMayKnow); + } else { + dict_T *dict = tv_dict_alloc(); + dict->dv_refcount++; + tv = (typval_T) { + .v_type = VAR_DICT, + .v_lock = VAR_UNLOCKED, + .vval = { .v_dict = dict }, + }; } - case '{': { - typval_T tv; - list_T *val_list = NULL; - if (next_map_special) { - next_map_special = false; - val_list = decode_create_map_special_dict(&tv, kListLenMayKnow); - } else { - dict_T *dict = tv_dict_alloc(); - dict->dv_refcount++; - tv = (typval_T) { - .v_type = VAR_DICT, - .v_lock = VAR_UNLOCKED, - .vval = { .v_dict = dict }, - }; - } - kv_push(container_stack, ((ContainerStackItem) { + kv_push(container_stack, ((ContainerStackItem) { .stack_index = kv_size(stack), .s = p, .container = tv, .special_val = val_list, })); - kv_push(stack, OBJ(tv, false, didcomma, didcolon)); - break; - } - default: { - emsgf(_("E474: Unidentified byte: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } + kv_push(stack, OBJ(tv, false, didcomma, didcolon)); + break; + } + default: + emsgf(_("E474: Unidentified byte: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } didcomma = false; didcolon = false; @@ -912,23 +887,21 @@ json_decode_string_cycle_start: json_decode_string_after_cycle: for (; p < e; p++) { switch (*p) { - case NL: - case ' ': - case TAB: - case CAR: { - break; - } - default: { - emsgf(_("E474: Trailing characters: %.*s"), LENP(p, e)); - goto json_decode_string_fail; - } + case NL: + case ' ': + case TAB: + case CAR: + break; + default: + emsgf(_("E474: Trailing characters: %.*s"), LENP(p, e)); + goto json_decode_string_fail; } } if (kv_size(stack) == 1 && kv_size(container_stack) == 0) { *rettv = kv_pop(stack).val; goto json_decode_string_ret; } - emsgf(_("E474: Unexpected end of input: %.*s"), (int) buf_len, buf); + emsgf(_("E474: Unexpected end of input: %.*s"), (int)buf_len, buf); json_decode_string_fail: ret = FAIL; while (kv_size(stack)) { @@ -952,192 +925,183 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { switch (mobj.type) { - case MSGPACK_OBJECT_NIL: { + case MSGPACK_OBJECT_NIL: + *rettv = (typval_T) { + .v_type = VAR_SPECIAL, + .v_lock = VAR_UNLOCKED, + .vval = { .v_special = kSpecialVarNull }, + }; + break; + case MSGPACK_OBJECT_BOOLEAN: + *rettv = (typval_T) { + .v_type = VAR_BOOL, + .v_lock = VAR_UNLOCKED, + .vval = { + .v_bool = mobj.via.boolean ? kBoolVarTrue : kBoolVarFalse + }, + }; + break; + case MSGPACK_OBJECT_POSITIVE_INTEGER: + if (mobj.via.u64 <= VARNUMBER_MAX) { *rettv = (typval_T) { - .v_type = VAR_SPECIAL, + .v_type = VAR_NUMBER, .v_lock = VAR_UNLOCKED, - .vval = { .v_special = kSpecialVarNull }, + .vval = { .v_number = (varnumber_T)mobj.via.u64 }, }; - break; + } else { + list_T *const list = tv_list_alloc(4); + tv_list_ref(list); + create_special_dict(rettv, kMPInteger, ((typval_T) { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + })); + uint64_t n = mobj.via.u64; + tv_list_append_number(list, 1); + tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3)); + tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF)); + tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); } - case MSGPACK_OBJECT_BOOLEAN: { + break; + case MSGPACK_OBJECT_NEGATIVE_INTEGER: + if (mobj.via.i64 >= VARNUMBER_MIN) { // -V547 *rettv = (typval_T) { - .v_type = VAR_BOOL, + .v_type = VAR_NUMBER, .v_lock = VAR_UNLOCKED, - .vval = { - .v_bool = mobj.via.boolean ? kBoolVarTrue : kBoolVarFalse - }, + .vval = { .v_number = (varnumber_T)mobj.via.i64 }, }; - break; - } - case MSGPACK_OBJECT_POSITIVE_INTEGER: { - if (mobj.via.u64 <= VARNUMBER_MAX) { - *rettv = (typval_T) { - .v_type = VAR_NUMBER, - .v_lock = VAR_UNLOCKED, - .vval = { .v_number = (varnumber_T) mobj.via.u64 }, - }; - } else { - list_T *const list = tv_list_alloc(4); - tv_list_ref(list); - create_special_dict(rettv, kMPInteger, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); - uint64_t n = mobj.via.u64; - tv_list_append_number(list, 1); - tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3)); - tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF)); - tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); - } - break; - } - case MSGPACK_OBJECT_NEGATIVE_INTEGER: { - if (mobj.via.i64 >= VARNUMBER_MIN) { // -V547 - *rettv = (typval_T) { - .v_type = VAR_NUMBER, - .v_lock = VAR_UNLOCKED, - .vval = { .v_number = (varnumber_T) mobj.via.i64 }, - }; - } else { - list_T *const list = tv_list_alloc(4); - tv_list_ref(list); - create_special_dict(rettv, kMPInteger, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); - uint64_t n = -((uint64_t)mobj.via.i64); - tv_list_append_number(list, -1); - tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3)); - tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF)); - tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); - } - break; + } else { + list_T *const list = tv_list_alloc(4); + tv_list_ref(list); + create_special_dict(rettv, kMPInteger, ((typval_T) { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + })); + uint64_t n = -((uint64_t)mobj.via.i64); + tv_list_append_number(list, -1); + tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3)); + tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF)); + tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); } + break; #ifdef NVIM_MSGPACK_HAS_FLOAT32 - case MSGPACK_OBJECT_FLOAT32: - case MSGPACK_OBJECT_FLOAT64: + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: #else - case MSGPACK_OBJECT_FLOAT: + case MSGPACK_OBJECT_FLOAT: #endif - { - *rettv = (typval_T) { - .v_type = VAR_FLOAT, - .v_lock = VAR_UNLOCKED, - .vval = { .v_float = mobj.via.f64 }, - }; - break; + *rettv = (typval_T) { + .v_type = VAR_FLOAT, + .v_lock = VAR_UNLOCKED, + .vval = { .v_float = mobj.via.f64 }, + }; + break; + case MSGPACK_OBJECT_STR: + *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kTrue, false, + false); + if (rettv->v_type == VAR_UNKNOWN) { + return FAIL; } - case MSGPACK_OBJECT_STR: { - *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kTrue, false, - false); - if (rettv->v_type == VAR_UNKNOWN) { - return FAIL; - } - break; + break; + case MSGPACK_OBJECT_BIN: + *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kNone, true, + false); + if (rettv->v_type == VAR_UNKNOWN) { + return FAIL; } - case MSGPACK_OBJECT_BIN: { - *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kNone, true, - false); - if (rettv->v_type == VAR_UNKNOWN) { + break; + case MSGPACK_OBJECT_ARRAY: { + list_T *const list = tv_list_alloc((ptrdiff_t)mobj.via.array.size); + tv_list_ref(list); + *rettv = (typval_T) { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + }; + for (size_t i = 0; i < mobj.via.array.size; i++) { + // Not populated yet, need to create list item to push. + tv_list_append_owned_tv(list, (typval_T) { .v_type = VAR_UNKNOWN }); + if (msgpack_to_vim(mobj.via.array.ptr[i], + TV_LIST_ITEM_TV(tv_list_last(list))) + == FAIL) { return FAIL; } - break; } - case MSGPACK_OBJECT_ARRAY: { - list_T *const list = tv_list_alloc((ptrdiff_t)mobj.via.array.size); - tv_list_ref(list); - *rettv = (typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - }; - for (size_t i = 0; i < mobj.via.array.size; i++) { - // Not populated yet, need to create list item to push. - tv_list_append_owned_tv(list, (typval_T) { .v_type = VAR_UNKNOWN }); - if (msgpack_to_vim(mobj.via.array.ptr[i], - TV_LIST_ITEM_TV(tv_list_last(list))) - == FAIL) { - return FAIL; - } + break; + } + case MSGPACK_OBJECT_MAP: { + for (size_t i = 0; i < mobj.via.map.size; i++) { + if (mobj.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR + || mobj.via.map.ptr[i].key.via.str.size == 0 + || memchr(mobj.via.map.ptr[i].key.via.str.ptr, NUL, + mobj.via.map.ptr[i].key.via.str.size) != NULL) { + goto msgpack_to_vim_generic_map; } - break; } - case MSGPACK_OBJECT_MAP: { - for (size_t i = 0; i < mobj.via.map.size; i++) { - if (mobj.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR - || mobj.via.map.ptr[i].key.via.str.size == 0 - || memchr(mobj.via.map.ptr[i].key.via.str.ptr, NUL, - mobj.via.map.ptr[i].key.via.str.size) != NULL) { - goto msgpack_to_vim_generic_map; - } + dict_T *const dict = tv_dict_alloc(); + dict->dv_refcount++; + *rettv = (typval_T) { + .v_type = VAR_DICT, + .v_lock = VAR_UNLOCKED, + .vval = { .v_dict = dict }, + }; + for (size_t i = 0; i < mobj.via.map.size; i++) { + dictitem_T *const di = xmallocz(offsetof(dictitem_T, di_key) + + mobj.via.map.ptr[i].key.via.str.size); + memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr, + mobj.via.map.ptr[i].key.via.str.size); + di->di_tv.v_type = VAR_UNKNOWN; + if (tv_dict_add(dict, di) == FAIL) { + // Duplicate key: fallback to generic map + tv_clear(rettv); + xfree(di); + goto msgpack_to_vim_generic_map; } - dict_T *const dict = tv_dict_alloc(); - dict->dv_refcount++; - *rettv = (typval_T) { - .v_type = VAR_DICT, - .v_lock = VAR_UNLOCKED, - .vval = { .v_dict = dict }, - }; - for (size_t i = 0; i < mobj.via.map.size; i++) { - dictitem_T *const di = xmallocz(offsetof(dictitem_T, di_key) - + mobj.via.map.ptr[i].key.via.str.size); - memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr, - mobj.via.map.ptr[i].key.via.str.size); - di->di_tv.v_type = VAR_UNKNOWN; - if (tv_dict_add(dict, di) == FAIL) { - // Duplicate key: fallback to generic map - tv_clear(rettv); - xfree(di); - goto msgpack_to_vim_generic_map; - } - if (msgpack_to_vim(mobj.via.map.ptr[i].val, &di->di_tv) == FAIL) { - return FAIL; - } + if (msgpack_to_vim(mobj.via.map.ptr[i].val, &di->di_tv) == FAIL) { + return FAIL; } - break; + } + break; msgpack_to_vim_generic_map: {} - list_T *const list = decode_create_map_special_dict( - rettv, (ptrdiff_t)mobj.via.map.size); - for (size_t i = 0; i < mobj.via.map.size; i++) { - list_T *const kv_pair = tv_list_alloc(2); - tv_list_append_list(list, kv_pair); + list_T *const list = decode_create_map_special_dict(rettv, (ptrdiff_t)mobj.via.map.size); + for (size_t i = 0; i < mobj.via.map.size; i++) { + list_T *const kv_pair = tv_list_alloc(2); + tv_list_append_list(list, kv_pair); - typval_T key_tv = { .v_type = VAR_UNKNOWN }; - if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_tv) == FAIL) { - tv_clear(&key_tv); - return FAIL; - } - tv_list_append_owned_tv(kv_pair, key_tv); + typval_T key_tv = { .v_type = VAR_UNKNOWN }; + if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_tv) == FAIL) { + tv_clear(&key_tv); + return FAIL; + } + tv_list_append_owned_tv(kv_pair, key_tv); - typval_T val_tv = { .v_type = VAR_UNKNOWN }; - if (msgpack_to_vim(mobj.via.map.ptr[i].val, &val_tv) == FAIL) { - tv_clear(&val_tv); - return FAIL; - } - tv_list_append_owned_tv(kv_pair, val_tv); + typval_T val_tv = { .v_type = VAR_UNKNOWN }; + if (msgpack_to_vim(mobj.via.map.ptr[i].val, &val_tv) == FAIL) { + tv_clear(&val_tv); + return FAIL; } - break; + tv_list_append_owned_tv(kv_pair, val_tv); } - case MSGPACK_OBJECT_EXT: { - list_T *const list = tv_list_alloc(2); - tv_list_ref(list); - tv_list_append_number(list, mobj.via.ext.type); - list_T *const ext_val_list = tv_list_alloc(kListLenMayKnow); - tv_list_append_list(list, ext_val_list); - create_special_dict(rettv, kMPExt, ((typval_T) { + break; + } + case MSGPACK_OBJECT_EXT: { + list_T *const list = tv_list_alloc(2); + tv_list_ref(list); + tv_list_append_number(list, mobj.via.ext.type); + list_T *const ext_val_list = tv_list_alloc(kListLenMayKnow); + tv_list_append_list(list, ext_val_list); + create_special_dict(rettv, kMPExt, ((typval_T) { .v_type = VAR_LIST, .v_lock = VAR_UNLOCKED, .vval = { .v_list = list }, })); - if (encode_list_write((void *) ext_val_list, mobj.via.ext.ptr, - mobj.via.ext.size) == -1) { - return FAIL; - } - break; + if (encode_list_write((void *)ext_val_list, mobj.via.ext.ptr, + mobj.via.ext.size) == -1) { + return FAIL; } + break; + } } return OK; } diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index b5e50e7ef5..1c0afc89f5 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -7,27 +7,27 @@ /// /// Split out from eval.c. -#include <msgpack.h> -#include <inttypes.h> -#include <stddef.h> #include <assert.h> +#include <inttypes.h> #include <math.h> +#include <msgpack.h> +#include <stddef.h> -#include "nvim/eval/encode.h" +#include "nvim/ascii.h" #include "nvim/buffer_defs.h" +#include "nvim/charset.h" // vim_isprintc() #include "nvim/eval.h" +#include "nvim/eval/encode.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_encode.h" #include "nvim/garray.h" -#include "nvim/mbyte.h" +#include "nvim/lib/kvec.h" +#include "nvim/macros.h" #include "nvim/math.h" -#include "nvim/message.h" +#include "nvim/mbyte.h" #include "nvim/memory.h" -#include "nvim/charset.h" // vim_isprintc() -#include "nvim/macros.h" -#include "nvim/ascii.h" +#include "nvim/message.h" #include "nvim/vim.h" // For _() -#include "nvim/lib/kvec.h" -#include "nvim/eval/typval_encode.h" #define ga_concat(a, b) ga_concat(a, (char_u *)b) #define utf_ptr2char(b) utf_ptr2char((char_u *)b) @@ -62,7 +62,7 @@ int encode_list_write(void *const data, const char *const buf, const size_t len) if (len == 0) { return 0; } - list_T *const list = (list_T *) data; + list_T *const list = (list_T *)data; const char *const end = buf + len; const char *line_end = buf; listitem_T *li = tv_list_last(list); @@ -74,8 +74,7 @@ int encode_list_write(void *const data, const char *const buf, const size_t len) const size_t line_length = (size_t)(line_end - buf); char *str = (char *)TV_LIST_ITEM_TV(li)->vval.v_string; const size_t li_len = (str == NULL ? 0 : strlen(str)); - TV_LIST_ITEM_TV(li)->vval.v_string = xrealloc( - str, li_len + line_length + 1); + TV_LIST_ITEM_TV(li)->vval.v_string = xrealloc(str, li_len + line_length + 1); str = (char *)TV_LIST_ITEM_TV(li)->vval.v_string + li_len; memcpy(str, buf, line_length); str[line_length] = 0; @@ -86,7 +85,7 @@ int encode_list_write(void *const data, const char *const buf, const size_t len) while (line_end < end) { const char *line_start = line_end; - line_end = xmemscan(line_start, NL, (size_t) (end - line_start)); + line_end = xmemscan(line_start, NL, (size_t)(end - line_start)); char *str = NULL; if (line_end != line_start) { const size_t line_length = (size_t)(line_end - line_start); @@ -133,75 +132,70 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, } MPConvStackVal v = kv_A(*mpstack, i); switch (v.type) { - case kMPConvDict: { - typval_T key_tv = { - .v_type = VAR_STRING, - .vval = { .v_string = (v.data.d.hi == NULL + case kMPConvDict: { + typval_T key_tv = { + .v_type = VAR_STRING, + .vval = { .v_string = (v.data.d.hi == NULL ? v.data.d.dict->dv_hashtab.ht_array : (v.data.d.hi - 1))->hi_key }, - }; - char *const key = encode_tv2string(&key_tv, NULL); - vim_snprintf((char *) IObuff, IOSIZE, key_msg, key); - xfree(key); - ga_concat(&msg_ga, IObuff); - break; - } - case kMPConvPairs: - case kMPConvList: { - const int idx = (v.data.l.li == tv_list_first(v.data.l.list) + }; + char *const key = encode_tv2string(&key_tv, NULL); + vim_snprintf((char *)IObuff, IOSIZE, key_msg, key); + xfree(key); + ga_concat(&msg_ga, IObuff); + break; + } + case kMPConvPairs: + case kMPConvList: { + const int idx = (v.data.l.li == tv_list_first(v.data.l.list) ? 0 : (v.data.l.li == NULL ? tv_list_len(v.data.l.list) - 1 - : (int)tv_list_idx_of_item( - v.data.l.list, - TV_LIST_ITEM_PREV(v.data.l.list, - v.data.l.li)))); - const listitem_T *const li = (v.data.l.li == NULL + : (int)tv_list_idx_of_item(v.data.l.list, + TV_LIST_ITEM_PREV(v.data.l.list, + v.data.l.li)))); + const listitem_T *const li = (v.data.l.li == NULL ? tv_list_last(v.data.l.list) : TV_LIST_ITEM_PREV(v.data.l.list, v.data.l.li)); - if (v.type == kMPConvList - || li == NULL - || (TV_LIST_ITEM_TV(li)->v_type != VAR_LIST - && tv_list_len(TV_LIST_ITEM_TV(li)->vval.v_list) <= 0)) { - vim_snprintf((char *)IObuff, IOSIZE, idx_msg, idx); - ga_concat(&msg_ga, IObuff); - } else { - assert(li != NULL); - listitem_T *const first_item = - tv_list_first(TV_LIST_ITEM_TV(li)->vval.v_list); - assert(first_item != NULL); - typval_T key_tv = *TV_LIST_ITEM_TV(first_item); - char *const key = encode_tv2echo(&key_tv, NULL); - vim_snprintf((char *) IObuff, IOSIZE, key_pair_msg, key, idx); - xfree(key); - ga_concat(&msg_ga, IObuff); - } - break; + if (v.type == kMPConvList + || li == NULL + || (TV_LIST_ITEM_TV(li)->v_type != VAR_LIST + && tv_list_len(TV_LIST_ITEM_TV(li)->vval.v_list) <= 0)) { + vim_snprintf((char *)IObuff, IOSIZE, idx_msg, idx); + ga_concat(&msg_ga, IObuff); + } else { + assert(li != NULL); + listitem_T *const first_item = + tv_list_first(TV_LIST_ITEM_TV(li)->vval.v_list); + assert(first_item != NULL); + typval_T key_tv = *TV_LIST_ITEM_TV(first_item); + char *const key = encode_tv2echo(&key_tv, NULL); + vim_snprintf((char *)IObuff, IOSIZE, key_pair_msg, key, idx); + xfree(key); + ga_concat(&msg_ga, IObuff); } - case kMPConvPartial: { - switch (v.data.p.stage) { - case kMPConvPartialArgs: { - abort(); - break; - } - case kMPConvPartialSelf: { - ga_concat(&msg_ga, partial_arg_msg); - break; - } - case kMPConvPartialEnd: { - ga_concat(&msg_ga, partial_self_msg); - break; - } - } + break; + } + case kMPConvPartial: + switch (v.data.p.stage) { + case kMPConvPartialArgs: + abort(); break; - } - case kMPConvPartialList: { - const int idx = (int)(v.data.a.arg - v.data.a.argv) - 1; - vim_snprintf((char *)IObuff, IOSIZE, partial_arg_i_msg, idx); - ga_concat(&msg_ga, IObuff); + case kMPConvPartialSelf: + ga_concat(&msg_ga, partial_arg_msg); + break; + case kMPConvPartialEnd: + ga_concat(&msg_ga, partial_self_msg); break; } + break; + case kMPConvPartialList: { + const int idx = (int)(v.data.a.arg - v.data.a.argv) - 1; + vim_snprintf((char *)IObuff, IOSIZE, partial_arg_i_msg, idx); + ga_concat(&msg_ga, IObuff); + break; + } } } emsgf(msg, _(objname), (kv_size(*mpstack) == 0 @@ -219,8 +213,7 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, /// zero. /// /// @return true in case of success, false in case of failure. -bool encode_vim_list_to_buf(const list_T *const list, size_t *const ret_len, - char **const ret_buf) +bool encode_vim_list_to_buf(const list_T *const list, size_t *const ret_len, char **const ret_buf) FUNC_ATTR_NONNULL_ARG(2, 3) FUNC_ATTR_WARN_UNUSED_RESULT { size_t len = 0; @@ -264,8 +257,8 @@ bool encode_vim_list_to_buf(const list_T *const list, size_t *const ret_len, /// @return OK when reading was finished, FAIL in case of error (i.e. list item /// was not a string), NOTDONE if reading was successful, but there are /// more bytes to read. -int encode_read_from_list(ListReaderState *const state, char *const buf, - const size_t nbuf, size_t *const read_bytes) +int encode_read_from_list(ListReaderState *const state, char *const buf, const size_t nbuf, + size_t *const read_bytes) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { char *const buf_end = buf + nbuf; @@ -276,13 +269,13 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, for (size_t i = state->offset; i < state->li_length && p < buf_end; i++) { assert(TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL); const char ch = (char)( - TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]); + TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]); *p++ = (char)((char)ch == (char)NL ? (char)NUL : (char)ch); } if (p < buf_end) { state->li = TV_LIST_ITEM_NEXT(state->list, state->li); if (state->li == NULL) { - *read_bytes = (size_t) (p - buf); + *read_bytes = (size_t)(p - buf); return OK; } *p++ = NL; @@ -304,181 +297,181 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, } #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ - do { \ - const char *const buf_ = (const char *) buf; \ - if (buf == NULL) { \ - ga_concat(gap, "''"); \ - } else { \ - const size_t len_ = (len); \ - ga_grow(gap, (int) (2 + len_ + memcnt(buf_, '\'', len_))); \ - ga_append(gap, '\''); \ - for (size_t i_ = 0; i_ < len_; i_++) { \ - if (buf_[i_] == '\'') { \ - ga_append(gap, '\''); \ - } \ - ga_append(gap, buf_[i_]); \ + do { \ + const char *const buf_ = (const char *)buf; \ + if (buf == NULL) { \ + ga_concat(gap, "''"); \ + } else { \ + const size_t len_ = (len); \ + ga_grow(gap, (int)(2 + len_ + memcnt(buf_, '\'', len_))); \ + ga_append(gap, '\''); \ + for (size_t i_ = 0; i_ < len_; i_++) { \ + if (buf_[i_] == '\'') { \ + ga_append(gap, '\''); \ } \ - ga_append(gap, '\''); \ + ga_append(gap, buf_[i_]); \ } \ - } while (0) + ga_append(gap, '\''); \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) \ - TYPVAL_ENCODE_CONV_STRING(tv, buf, len) + TYPVAL_ENCODE_CONV_STRING(tv, buf, len) #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) #define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ - do { \ - const blob_T *const blob_ = (blob); \ - const int len_ = (len); \ - if (len_ == 0) { \ - ga_concat(gap, "0z"); \ - } else { \ - /* Allocate space for "0z", the two hex chars per byte, and a */ \ - /* "." separator after every eight hex chars. */ \ - /* Example: "0z00112233.44556677.8899" */ \ - ga_grow(gap, 2 + 2 * len_ + (len_ - 1) / 4); \ - ga_concat(gap, "0z"); \ - char numbuf[NUMBUFLEN]; \ - for (int i_ = 0; i_ < len_; i_++) { \ - if (i_ > 0 && (i_ & 3) == 0) { \ - ga_append(gap, '.'); \ - } \ - vim_snprintf((char *)numbuf, ARRAY_SIZE(numbuf), "%02X", \ - (int)tv_blob_get(blob_, i_)); \ - ga_concat(gap, numbuf); \ + do { \ + const blob_T *const blob_ = (blob); \ + const int len_ = (len); \ + if (len_ == 0) { \ + ga_concat(gap, "0z"); \ + } else { \ + /* Allocate space for "0z", the two hex chars per byte, and a */ \ + /* "." separator after every eight hex chars. */ \ + /* Example: "0z00112233.44556677.8899" */ \ + ga_grow(gap, 2 + 2 * len_ + (len_ - 1) / 4); \ + ga_concat(gap, "0z"); \ + char numbuf[NUMBUFLEN]; \ + for (int i_ = 0; i_ < len_; i_++) { \ + if (i_ > 0 && (i_ & 3) == 0) { \ + ga_append(gap, '.'); \ } \ + vim_snprintf((char *)numbuf, ARRAY_SIZE(numbuf), "%02X", \ + (int)tv_blob_get(blob_, i_)); \ + ga_concat(gap, numbuf); \ } \ - } while (0) + } \ + } while (0) #define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ - do { \ - char numbuf[NUMBUFLEN]; \ - vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRId64, (int64_t) (num)); \ - ga_concat(gap, numbuf); \ - } while (0) + do { \ + char numbuf[NUMBUFLEN]; \ + vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRId64, (int64_t)(num)); \ + ga_concat(gap, numbuf); \ + } while (0) #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - do { \ - const float_T flt_ = (flt); \ - switch (xfpclassify(flt_)) { \ - case FP_NAN: { \ - ga_concat(gap, (char_u *) "str2float('nan')"); \ - break; \ - } \ - case FP_INFINITE: { \ - if (flt_ < 0) { \ - ga_append(gap, '-'); \ - } \ - ga_concat(gap, (char_u *) "str2float('inf')"); \ - break; \ - } \ - default: { \ - char numbuf[NUMBUFLEN]; \ - vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%g", flt_); \ - ga_concat(gap, (char_u *) numbuf); \ - } \ + do { \ + const float_T flt_ = (flt); \ + switch (xfpclassify(flt_)) { \ + case FP_NAN: { \ + ga_concat(gap, (char_u *)"str2float('nan')"); \ + break; \ + } \ + case FP_INFINITE: { \ + if (flt_ < 0) { \ + ga_append(gap, '-'); \ } \ - } while (0) + ga_concat(gap, (char_u *)"str2float('inf')"); \ + break; \ + } \ + default: { \ + char numbuf[NUMBUFLEN]; \ + vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%g", flt_); \ + ga_concat(gap, (char_u *)numbuf); \ + } \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ - do { \ - const char *const fun_ = (const char *)(fun); \ - if (fun_ == NULL) { \ - internal_error("string(): NULL function name"); \ - ga_concat(gap, "function(NULL"); \ - } else { \ - ga_concat(gap, "function("); \ - TYPVAL_ENCODE_CONV_STRING(tv, fun_, strlen(fun_)); \ - }\ - } while (0) + do { \ + const char *const fun_ = (const char *)(fun); \ + if (fun_ == NULL) { \ + internal_error("string(): NULL function name"); \ + ga_concat(gap, "function(NULL"); \ + } else { \ + ga_concat(gap, "function("); \ + TYPVAL_ENCODE_CONV_STRING(tv, fun_, strlen(fun_)); \ + }\ + } while (0) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) \ - do { \ - if (len != 0) { \ - ga_concat(gap, ", "); \ - } \ - } while (0) + do { \ + if (len != 0) { \ + ga_concat(gap, ", "); \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) \ - do { \ - if ((ptrdiff_t)len != -1) { \ - ga_concat(gap, ", "); \ - } \ - } while (0) + do { \ + if ((ptrdiff_t)len != -1) { \ + ga_concat(gap, ", "); \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_FUNC_END(tv) \ - ga_append(gap, ')') + ga_append(gap, ')') #define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ - ga_concat(gap, "[]") + ga_concat(gap, "[]") #define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ - ga_append(gap, '[') + ga_append(gap, '[') #define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ - ga_concat(gap, "{}") + ga_concat(gap, "{}") #define TYPVAL_ENCODE_CONV_NIL(tv) \ - ga_concat(gap, "v:null") + ga_concat(gap, "v:null") #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - ga_concat(gap, ((num)? "v:true": "v:false")) + ga_concat(gap, ((num)? "v:true": "v:false")) #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ - ga_append(gap, '{') + ga_append(gap, '{') #define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) #define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ - ga_append(gap, '}') + ga_append(gap, '}') #define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \ - ga_concat(gap, ": ") + ga_concat(gap, ": ") #define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ - ga_concat(gap, ", ") + ga_concat(gap, ", ") #define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key) #define TYPVAL_ENCODE_CONV_LIST_END(tv) \ - ga_append(gap, ']') + ga_append(gap, ']') #define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \ - TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, NULL) + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, NULL) #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ - do { \ - if (!did_echo_string_emsg) { \ - /* Only give this message once for a recursive call to avoid */ \ - /* flooding the user with errors. */ \ - did_echo_string_emsg = true; \ - EMSG(_("E724: unable to correctly dump variable " \ - "with self-referencing container")); \ - } \ - char ebuf[NUMBUFLEN + 7]; \ - size_t backref = 0; \ - for (; backref < kv_size(*mpstack); backref++) { \ - const MPConvStackVal mpval = kv_A(*mpstack, backref); \ - if (mpval.type == conv_type) { \ - if (conv_type == kMPConvDict) { \ - if ((void *) mpval.data.d.dict == (void *) (val)) { \ - break; \ - } \ - } else if (conv_type == kMPConvList) { \ - if ((void *) mpval.data.l.list == (void *) (val)) { \ - break; \ - } \ + do { \ + if (!did_echo_string_emsg) { \ + /* Only give this message once for a recursive call to avoid */ \ + /* flooding the user with errors. */ \ + did_echo_string_emsg = true; \ + EMSG(_("E724: unable to correctly dump variable " \ + "with self-referencing container")); \ + } \ + char ebuf[NUMBUFLEN + 7]; \ + size_t backref = 0; \ + for (; backref < kv_size(*mpstack); backref++) { \ + const MPConvStackVal mpval = kv_A(*mpstack, backref); \ + if (mpval.type == conv_type) { \ + if (conv_type == kMPConvDict) { \ + if ((void *)mpval.data.d.dict == (void *)(val)) { \ + break; \ + } \ + } else if (conv_type == kMPConvList) { \ + if ((void *)mpval.data.l.list == (void *)(val)) { \ + break; \ } \ } \ } \ - vim_snprintf(ebuf, ARRAY_SIZE(ebuf), "{E724@%zu}", backref); \ - ga_concat(gap, &ebuf[0]); \ - } while (0) + } \ + vim_snprintf(ebuf, ARRAY_SIZE(ebuf), "{E724@%zu}", backref); \ + ga_concat(gap, &ebuf[0]); \ + } while (0) #define TYPVAL_ENCODE_ALLOW_SPECIALS false @@ -494,31 +487,31 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, #undef TYPVAL_ENCODE_CONV_RECURSE #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ - do { \ - char ebuf[NUMBUFLEN + 7]; \ - size_t backref = 0; \ - for (; backref < kv_size(*mpstack); backref++) { \ - const MPConvStackVal mpval = kv_A(*mpstack, backref); \ - if (mpval.type == conv_type) { \ - if (conv_type == kMPConvDict) { \ - if ((void *) mpval.data.d.dict == (void *) val) { \ - break; \ - } \ - } else if (conv_type == kMPConvList) { \ - if ((void *) mpval.data.l.list == (void *) val) { \ - break; \ - } \ + do { \ + char ebuf[NUMBUFLEN + 7]; \ + size_t backref = 0; \ + for (; backref < kv_size(*mpstack); backref++) { \ + const MPConvStackVal mpval = kv_A(*mpstack, backref); \ + if (mpval.type == conv_type) { \ + if (conv_type == kMPConvDict) { \ + if ((void *)mpval.data.d.dict == (void *)val) { \ + break; \ + } \ + } else if (conv_type == kMPConvList) { \ + if ((void *)mpval.data.l.list == (void *)val) { \ + break; \ } \ } \ } \ - if (conv_type == kMPConvDict) { \ - vim_snprintf(ebuf, ARRAY_SIZE(ebuf), "{...@%zu}", backref); \ - } else { \ - vim_snprintf(ebuf, ARRAY_SIZE(ebuf), "[...@%zu]", backref); \ - } \ - ga_concat(gap, &ebuf[0]); \ - return OK; \ - } while (0) + } \ + if (conv_type == kMPConvDict) { \ + vim_snprintf(ebuf, ARRAY_SIZE(ebuf), "{...@%zu}", backref); \ + } else { \ + vim_snprintf(ebuf, ARRAY_SIZE(ebuf), "[...@%zu]", backref); \ + } \ + ga_concat(gap, &ebuf[0]); \ + return OK; \ + } while (0) #define TYPVAL_ENCODE_SCOPE #define TYPVAL_ENCODE_NAME echo @@ -532,56 +525,56 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, #undef TYPVAL_ENCODE_CONV_RECURSE #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ - do { \ - if (!did_echo_string_emsg) { \ - /* Only give this message once for a recursive call to avoid */ \ - /* flooding the user with errors. */ \ - did_echo_string_emsg = true; \ - EMSG(_("E724: unable to correctly dump variable " \ - "with self-referencing container")); \ - } \ - } while (0) + do { \ + if (!did_echo_string_emsg) { \ + /* Only give this message once for a recursive call to avoid */ \ + /* flooding the user with errors. */ \ + did_echo_string_emsg = true; \ + EMSG(_("E724: unable to correctly dump variable " \ + "with self-referencing container")); \ + } \ + } while (0) #undef TYPVAL_ENCODE_ALLOW_SPECIALS #define TYPVAL_ENCODE_ALLOW_SPECIALS true #undef TYPVAL_ENCODE_CONV_NIL #define TYPVAL_ENCODE_CONV_NIL(tv) \ - ga_concat(gap, "null") + ga_concat(gap, "null") #undef TYPVAL_ENCODE_CONV_BOOL #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - ga_concat(gap, ((num)? "true": "false")) + ga_concat(gap, ((num)? "true": "false")) #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \ - do { \ - char numbuf[NUMBUFLEN]; \ - vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRIu64, (num)); \ - ga_concat(gap, numbuf); \ - } while (0) + do { \ + char numbuf[NUMBUFLEN]; \ + vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRIu64, (num)); \ + ga_concat(gap, numbuf); \ + } while (0) #undef TYPVAL_ENCODE_CONV_FLOAT #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - do { \ - const float_T flt_ = (flt); \ - switch (xfpclassify(flt_)) { \ - case FP_NAN: { \ - EMSG(_("E474: Unable to represent NaN value in JSON")); \ - return FAIL; \ - } \ - case FP_INFINITE: { \ - EMSG(_("E474: Unable to represent infinity in JSON")); \ - return FAIL; \ - } \ - default: { \ - char numbuf[NUMBUFLEN]; \ - vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%g", flt_); \ - ga_concat(gap, (char_u *) numbuf); \ - break; \ - } \ - } \ - } while (0) + do { \ + const float_T flt_ = (flt); \ + switch (xfpclassify(flt_)) { \ + case FP_NAN: { \ + EMSG(_("E474: Unable to represent NaN value in JSON")); \ + return FAIL; \ + } \ + case FP_INFINITE: { \ + EMSG(_("E474: Unable to represent infinity in JSON")); \ + return FAIL; \ + } \ + default: { \ + char numbuf[NUMBUFLEN]; \ + vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%g", flt_); \ + ga_concat(gap, (char_u *)numbuf); \ + break; \ + } \ + } \ + } while (0) /// Escape sequences used in JSON static const char escapes[][3] = { @@ -603,8 +596,7 @@ static const char xdigits[] = "0123456789ABCDEF"; /// @param[in] len Converted string length. /// /// @return OK in case of success, FAIL otherwise. -static inline int convert_to_json_string(garray_T *const gap, - const char *const buf, +static inline int convert_to_json_string(garray_T *const gap, const char *const buf, const size_t len) FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_ALWAYS_INLINE { @@ -622,49 +614,47 @@ static inline int convert_to_json_string(garray_T *const gap, // This is done to make resulting values displayable on screen also not from // Neovim. #define ENCODE_RAW(ch) \ - (ch >= 0x20 && utf_printable(ch)) + (ch >= 0x20 && utf_printable(ch)) for (size_t i = 0; i < utf_len;) { const int ch = utf_ptr2char(utf_buf + i); const size_t shift = (ch == 0? 1: utf_ptr2len(utf_buf + i)); assert(shift > 0); i += shift; switch (ch) { - case BS: - case TAB: - case NL: - case FF: - case CAR: - case '"': - case '\\': { - str_len += 2; - break; - } - default: { - if (ch > 0x7F && shift == 1) { - emsgf(_("E474: String \"%.*s\" contains byte that does not start " - "any UTF-8 character"), - (int)(utf_len - (i - shift)), utf_buf + i - shift); - xfree(tofree); - return FAIL; - } else if ((SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) - || (SURROGATE_LO_START <= ch && ch <= SURROGATE_LO_END)) { - emsgf(_("E474: UTF-8 string contains code point which belongs " - "to a surrogate pair: %.*s"), - (int)(utf_len - (i - shift)), utf_buf + i - shift); - xfree(tofree); - return FAIL; - } else if (ENCODE_RAW(ch)) { - str_len += shift; - } else { - str_len += ((sizeof("\\u1234") - 1) - * (size_t) (1 + (ch >= SURROGATE_FIRST_CHAR))); - } - break; + case BS: + case TAB: + case NL: + case FF: + case CAR: + case '"': + case '\\': + str_len += 2; + break; + default: + if (ch > 0x7F && shift == 1) { + emsgf(_("E474: String \"%.*s\" contains byte that does not start " + "any UTF-8 character"), + (int)(utf_len - (i - shift)), utf_buf + i - shift); + xfree(tofree); + return FAIL; + } else if ((SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) + || (SURROGATE_LO_START <= ch && ch <= SURROGATE_LO_END)) { + emsgf(_("E474: UTF-8 string contains code point which belongs " + "to a surrogate pair: %.*s"), + (int)(utf_len - (i - shift)), utf_buf + i - shift); + xfree(tofree); + return FAIL; + } else if (ENCODE_RAW(ch)) { + str_len += shift; + } else { + str_len += ((sizeof("\\u1234") - 1) + * (size_t)(1 + (ch >= SURROGATE_FIRST_CHAR))); } + break; } } ga_append(gap, '"'); - ga_grow(gap, (int) str_len); + ga_grow(gap, (int)str_len); for (size_t i = 0; i < utf_len;) { const int ch = utf_ptr2char(utf_buf + i); const size_t shift = (ch == 0? 1: utf_char2len(ch)); @@ -672,46 +662,44 @@ static inline int convert_to_json_string(garray_T *const gap, // Is false on invalid unicode, but this should already be handled. assert(ch == 0 || shift == utf_ptr2len(utf_buf + i)); switch (ch) { - case BS: - case TAB: - case NL: - case FF: - case CAR: - case '"': - case '\\': { - ga_concat_len(gap, escapes[ch], 2); - break; - } - default: { - if (ENCODE_RAW(ch)) { - ga_concat_len(gap, utf_buf + i, shift); - } else if (ch < SURROGATE_FIRST_CHAR) { - ga_concat_len(gap, ((const char[]) { - '\\', 'u', - xdigits[(ch >> (4 * 3)) & 0xF], - xdigits[(ch >> (4 * 2)) & 0xF], - xdigits[(ch >> (4 * 1)) & 0xF], - xdigits[(ch >> (4 * 0)) & 0xF], - }), sizeof("\\u1234") - 1); - } else { - const int tmp = ch - SURROGATE_FIRST_CHAR; - const int hi = SURROGATE_HI_START + ((tmp >> 10) & ((1 << 10) - 1)); - const int lo = SURROGATE_LO_END + ((tmp >> 0) & ((1 << 10) - 1)); - ga_concat_len(gap, ((const char[]) { - '\\', 'u', - xdigits[(hi >> (4 * 3)) & 0xF], - xdigits[(hi >> (4 * 2)) & 0xF], - xdigits[(hi >> (4 * 1)) & 0xF], - xdigits[(hi >> (4 * 0)) & 0xF], - '\\', 'u', - xdigits[(lo >> (4 * 3)) & 0xF], - xdigits[(lo >> (4 * 2)) & 0xF], - xdigits[(lo >> (4 * 1)) & 0xF], - xdigits[(lo >> (4 * 0)) & 0xF], - }), (sizeof("\\u1234") - 1) * 2); - } - break; + case BS: + case TAB: + case NL: + case FF: + case CAR: + case '"': + case '\\': + ga_concat_len(gap, escapes[ch], 2); + break; + default: + if (ENCODE_RAW(ch)) { + ga_concat_len(gap, utf_buf + i, shift); + } else if (ch < SURROGATE_FIRST_CHAR) { + ga_concat_len(gap, ((const char[]) { + '\\', 'u', + xdigits[(ch >> (4 * 3)) & 0xF], + xdigits[(ch >> (4 * 2)) & 0xF], + xdigits[(ch >> (4 * 1)) & 0xF], + xdigits[(ch >> (4 * 0)) & 0xF], + }), sizeof("\\u1234") - 1); + } else { + const int tmp = ch - SURROGATE_FIRST_CHAR; + const int hi = SURROGATE_HI_START + ((tmp >> 10) & ((1 << 10) - 1)); + const int lo = SURROGATE_LO_END + ((tmp >> 0) & ((1 << 10) - 1)); + ga_concat_len(gap, ((const char[]) { + '\\', 'u', + xdigits[(hi >> (4 * 3)) & 0xF], + xdigits[(hi >> (4 * 2)) & 0xF], + xdigits[(hi >> (4 * 1)) & 0xF], + xdigits[(hi >> (4 * 0)) & 0xF], + '\\', 'u', + xdigits[(lo >> (4 * 3)) & 0xF], + xdigits[(lo >> (4 * 2)) & 0xF], + xdigits[(lo >> (4 * 1)) & 0xF], + xdigits[(lo >> (4 * 0)) & 0xF], + }), (sizeof("\\u1234") - 1) * 2); } + break; } i += shift; } @@ -723,47 +711,47 @@ static inline int convert_to_json_string(garray_T *const gap, #undef TYPVAL_ENCODE_CONV_STRING #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ - do { \ - if (convert_to_json_string(gap, (const char *) (buf), (len)) != OK) { \ - return FAIL; \ - } \ - } while (0) + do { \ + if (convert_to_json_string(gap, (const char *)(buf), (len)) != OK) { \ + return FAIL; \ + } \ + } while (0) #undef TYPVAL_ENCODE_CONV_EXT_STRING #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) \ - do { \ - xfree(buf); \ - EMSG(_("E474: Unable to convert EXT string to JSON")); \ - return FAIL; \ - } while (0) + do { \ + xfree(buf); \ + EMSG(_("E474: Unable to convert EXT string to JSON")); \ + return FAIL; \ + } while (0) #undef TYPVAL_ENCODE_CONV_BLOB #define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ - do { \ - const blob_T *const blob_ = (blob); \ - const int len_ = (len); \ - if (len_ == 0) { \ - ga_concat(gap, "[]"); \ - } else { \ - ga_append(gap, '['); \ - char numbuf[NUMBUFLEN]; \ - for (int i_ = 0; i_ < len_; i_++) { \ - if (i_ > 0) { \ - ga_concat(gap, ", "); \ - } \ - vim_snprintf((char *)numbuf, ARRAY_SIZE(numbuf), "%d", \ - (int)tv_blob_get(blob_, i_)); \ - ga_concat(gap, numbuf); \ + do { \ + const blob_T *const blob_ = (blob); \ + const int len_ = (len); \ + if (len_ == 0) { \ + ga_concat(gap, "[]"); \ + } else { \ + ga_append(gap, '['); \ + char numbuf[NUMBUFLEN]; \ + for (int i_ = 0; i_ < len_; i_++) { \ + if (i_ > 0) { \ + ga_concat(gap, ", "); \ } \ - ga_append(gap, ']'); \ + vim_snprintf((char *)numbuf, ARRAY_SIZE(numbuf), "%d", \ + (int)tv_blob_get(blob_, i_)); \ + ga_concat(gap, numbuf); \ } \ - } while (0) + ga_append(gap, ']'); \ + } \ + } while (0) #undef TYPVAL_ENCODE_CONV_FUNC_START #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ - return conv_error(_("E474: Error while dumping %s, %s: " \ - "attempt to dump function reference"), \ - mpstack, objname) + return conv_error(_("E474: Error while dumping %s, %s: " \ + "attempt to dump function reference"), \ + mpstack, objname) /// Check whether given key can be used in json_encode() /// @@ -804,12 +792,12 @@ bool encode_check_json_key(const typval_T *const tv) #undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK #define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key) \ - do { \ - if (!encode_check_json_key(&key)) { \ - EMSG(_("E474: Invalid key in special dictionary")); \ - goto label; \ - } \ - } while (0) + do { \ + if (!encode_check_json_key(&key)) { \ + EMSG(_("E474: Invalid key in special dictionary")); \ + goto label; \ + } \ + } while (0) #define TYPVAL_ENCODE_SCOPE static #define TYPVAL_ENCODE_NAME json @@ -867,10 +855,10 @@ char *encode_tv2string(typval_T *tv, size_t *len) assert(evs_ret == OK); did_echo_string_emsg = false; if (len != NULL) { - *len = (size_t) ga.ga_len; + *len = (size_t)ga.ga_len; } ga_append(&ga, '\0'); - return (char *) ga.ga_data; + return (char *)ga.ga_data; } /// Return a string with the string representation of a variable. @@ -895,10 +883,10 @@ char *encode_tv2echo(typval_T *tv, size_t *len) assert(eve_ret == OK); } if (len != NULL) { - *len = (size_t) ga.ga_len; + *len = (size_t)ga.ga_len; } ga_append(&ga, '\0'); - return (char *) ga.ga_data; + return (char *)ga.ga_data; } /// Return a string with the string representation of a variable. @@ -927,90 +915,90 @@ char *encode_tv2json(typval_T *tv, size_t *len) } #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ - do { \ - if (buf == NULL) { \ - msgpack_pack_bin(packer, 0); \ - } else { \ - const size_t len_ = (len); \ - msgpack_pack_bin(packer, len_); \ - msgpack_pack_bin_body(packer, buf, len_); \ - } \ - } while (0) + do { \ + if (buf == NULL) { \ + msgpack_pack_bin(packer, 0); \ + } else { \ + const size_t len_ = (len); \ + msgpack_pack_bin(packer, len_); \ + msgpack_pack_bin_body(packer, buf, len_); \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) \ - do { \ - if (buf == NULL) { \ - msgpack_pack_str(packer, 0); \ - } else { \ - const size_t len_ = (len); \ - msgpack_pack_str(packer, len_); \ - msgpack_pack_str_body(packer, buf, len_); \ - } \ - } while (0) + do { \ + if (buf == NULL) { \ + msgpack_pack_str(packer, 0); \ + } else { \ + const size_t len_ = (len); \ + msgpack_pack_str(packer, len_); \ + msgpack_pack_str_body(packer, buf, len_); \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) \ - do { \ - if (buf == NULL) { \ - msgpack_pack_ext(packer, 0, (int8_t) type); \ - } else { \ - const size_t len_ = (len); \ - msgpack_pack_ext(packer, len_, (int8_t) type); \ - msgpack_pack_ext_body(packer, buf, len_); \ - } \ - } while (0) + do { \ + if (buf == NULL) { \ + msgpack_pack_ext(packer, 0, (int8_t)type); \ + } else { \ + const size_t len_ = (len); \ + msgpack_pack_ext(packer, len_, (int8_t)type); \ + msgpack_pack_ext_body(packer, buf, len_); \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ - do { \ - const size_t len_ = (size_t)(len); \ - msgpack_pack_bin(packer, len_); \ - if (len_ > 0) { \ - msgpack_pack_bin_body(packer, (blob)->bv_ga.ga_data, len_); \ - } \ - } while (0) + do { \ + const size_t len_ = (size_t)(len); \ + msgpack_pack_bin(packer, len_); \ + if (len_ > 0) { \ + msgpack_pack_bin_body(packer, (blob)->bv_ga.ga_data, len_); \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ - msgpack_pack_int64(packer, (int64_t)(num)) + msgpack_pack_int64(packer, (int64_t)(num)) #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - msgpack_pack_double(packer, (double)(flt)) + msgpack_pack_double(packer, (double)(flt)) #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ - return conv_error(_("E5004: Error while dumping %s, %s: " \ - "attempt to dump function reference"), \ - mpstack, objname) + return conv_error(_("E5004: Error while dumping %s, %s: " \ + "attempt to dump function reference"), \ + mpstack, objname) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) #define TYPVAL_ENCODE_CONV_FUNC_END(tv) #define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ - msgpack_pack_array(packer, 0) + msgpack_pack_array(packer, 0) #define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ - msgpack_pack_array(packer, (size_t)(len)) + msgpack_pack_array(packer, (size_t)(len)) #define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ - msgpack_pack_map(packer, 0) + msgpack_pack_map(packer, 0) #define TYPVAL_ENCODE_CONV_NIL(tv) \ - msgpack_pack_nil(packer) + msgpack_pack_nil(packer) #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - do { \ - if (num) { \ - msgpack_pack_true(packer); \ - } else { \ - msgpack_pack_false(packer); \ - } \ - } while (0) + do { \ + if (num) { \ + msgpack_pack_true(packer); \ + } else { \ + msgpack_pack_false(packer); \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \ - msgpack_pack_uint64(packer, (num)) + msgpack_pack_uint64(packer, (num)) #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ - msgpack_pack_map(packer, (size_t)(len)) + msgpack_pack_map(packer, (size_t)(len)) #define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) @@ -1027,9 +1015,9 @@ char *encode_tv2json(typval_T *tv, size_t *len) #define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ - return conv_error(_("E5005: Unable to dump %s: " \ - "container references itself in %s"), \ - mpstack, objname) + return conv_error(_("E5005: Unable to dump %s: " \ + "container references itself in %s"), \ + mpstack, objname) #define TYPVAL_ENCODE_ALLOW_SPECIALS true diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 5ced2a0535..8eceda84cf 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -1,12 +1,12 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include "nvim/eval/typval.h" -#include "nvim/eval/executor.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/vim.h" -#include "nvim/globals.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # 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. /// /// @return OK or FAIL. -int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, - const char *const op) +int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *const op) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NO_SANITIZE_UNDEFINED { // 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 && tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL) { switch (tv1->v_type) { - case VAR_DICT: - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_BOOL: - case VAR_SPECIAL: { + case VAR_DICT: + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_BOOL: + case VAR_SPECIAL: + break; + case VAR_BLOB: + if (*op != '+' || tv2->v_type != VAR_BLOB) { break; } - case VAR_BLOB: { - if (*op != '+' || tv2->v_type != VAR_BLOB) { - break; - } - // Blob += Blob - if (tv1->vval.v_blob != NULL && tv2->vval.v_blob != NULL) { - 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: { - 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); + // Blob += Blob + if (tv1->vval.v_blob != NULL && tv2->vval.v_blob != NULL) { + 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_NUMBER: - case VAR_STRING: { - if (tv2->v_type == VAR_LIST) { - break; - } - 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; + return OK; + case VAR_LIST: + 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: + case VAR_STRING: + if (tv2->v_type == VAR_LIST) { + break; + } + 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 == '%') { - 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; + 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 { - // str .= str - if (tv2->v_type == VAR_FLOAT) { - break; + 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; } - 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; + tv1->v_type = VAR_NUMBER; + tv1->vval.v_number = n; } - return OK; - } - case VAR_FLOAT: { - if (*op == '%' || *op == '.' - || (tv2->v_type != VAR_FLOAT - && tv2->v_type != VAR_NUMBER - && tv2->v_type != VAR_STRING)) { + } else { + // str .= str + if (tv2->v_type == VAR_FLOAT) { 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 : (float_T)tv_get_number(tv2)); - switch (*op) { - case '+': tv1->vval.v_float += f; break; - case '-': tv1->vval.v_float -= f; break; - case '*': tv1->vval.v_float *= f; break; - case '/': tv1->vval.v_float /= f; break; - } - return OK; - } - case VAR_UNKNOWN: { - abort(); + switch (*op) { + case '+': + tv1->vval.v_float += f; break; + case '-': + tv1->vval.v_float -= f; break; + case '*': + tv1->vval.v_float *= f; break; + case '/': + tv1->vval.v_float /= f; break; } + return OK; + } + case VAR_UNKNOWN: + abort(); } } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 821a2c8e8e..35ebd0f3f8 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -115,8 +115,9 @@ char_u *get_function_name(expand_T *xp, int idx) static int intidx = -1; char_u *name; - if (idx == 0) + if (idx == 0) { intidx = -1; + } if (intidx < 0) { name = get_user_func_name(xp, idx); if (name != NULL) { @@ -155,12 +156,14 @@ char_u *get_expr_name(expand_T *xp, int idx) static int intidx = -1; char_u *name; - if (idx == 0) + if (idx == 0) { intidx = -1; + } if (intidx < 0) { name = get_function_name(xp, idx); - if (name != NULL) + if (name != NULL) { return name; + } } return get_user_var_name(xp, ++intidx); } @@ -177,8 +180,8 @@ const VimLFuncDef *find_internal_func(const char *const name) return find_internal_func_gperf(name, len); } -int call_internal_func(const char_u *const fname, const int argcount, - typval_T *const argvars, typval_T *const rettv) +int call_internal_func(const char_u *const fname, const int argcount, typval_T *const argvars, + typval_T *const rettv) FUNC_ATTR_NONNULL_ALL { const VimLFuncDef *const fdef = find_internal_func((const char *)fname); @@ -195,9 +198,8 @@ int call_internal_func(const char_u *const fname, const int argcount, } /// Invoke a method for base->method(). -int call_internal_method(const char_u *const fname, const int argcount, - typval_T *const argvars, typval_T *const rettv, - typval_T *const basetv) +int call_internal_method(const char_u *const fname, const int argcount, typval_T *const argvars, + typval_T *const rettv, typval_T *const basetv) FUNC_ATTR_NONNULL_ALL { const VimLFuncDef *const fdef = find_internal_func((const char *)fname); @@ -213,7 +215,7 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T argv[MAX_FUNC_ARGS + 1]; const ptrdiff_t base_index - = fdef->base_arg == BASE_LAST ? argcount : fdef->base_arg - 1; + = fdef->base_arg == BASE_LAST ? argcount : fdef->base_arg - 1; memcpy(argv, argvars, base_index * sizeof(typval_T)); argv[base_index] = *basetv; memcpy(argv + base_index + 1, argvars + base_index, @@ -444,8 +446,7 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string = NULL; int idx = tv_get_number_chk(&argvars[0], NULL); if (arglist != NULL && idx >= 0 && idx < argcount) { - rettv->vval.v_string = (char_u *)xstrdup( - (const char *)alist_name(&arglist[idx])); + rettv->vval.v_string = (char_u *)xstrdup((const char *)alist_name(&arglist[idx])); } else if (idx == -1) { get_arglist_as_rettv(arglist, argcount, rettv); } @@ -487,13 +488,13 @@ static void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "assert_report(msg) static void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - garray_T ga; + garray_T ga; - prepare_assert_error(&ga); - ga_concat(&ga, (const char_u *)tv_get_string(&argvars[0])); - assert_error(&ga); - ga_clear(&ga); - rettv->vval.v_number = 1; + prepare_assert_error(&ga); + ga_concat(&ga, (const char_u *)tv_get_string(&argvars[0])); + assert_error(&ga); + ga_clear(&ga); + rettv->vval.v_number = 1; } /// "assert_exception(string[, msg])" function @@ -577,11 +578,11 @@ static void f_browsedir(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static buf_T *find_buffer(typval_T *avar) { - buf_T *buf = NULL; + buf_T *buf = NULL; - if (avar->v_type == VAR_NUMBER) + if (avar->v_type == VAR_NUMBER) { buf = buflist_findnr((int)avar->vval.v_number); - else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL) { + } else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL) { buf = buflist_findname_exp(avar->vval.v_string); if (buf == NULL) { /* No full path name match, try a match with a URL or a "nofile" @@ -622,7 +623,7 @@ static void f_bufexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; + buf_T *buf; buf = find_buffer(&argvars[0]); rettv->vval.v_number = (buf != NULL && buf->b_p_bl); @@ -648,7 +649,7 @@ static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr) */ static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; + buf_T *buf; buf = find_buffer(&argvars[0]); rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL); @@ -750,19 +751,23 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ buf_T *tv_get_buf(typval_T *tv, int curtab_only) { - char_u *name = tv->vval.v_string; + char_u *name = tv->vval.v_string; int save_magic; - char_u *save_cpo; - buf_T *buf; + char_u *save_cpo; + buf_T *buf; - if (tv->v_type == VAR_NUMBER) + if (tv->v_type == VAR_NUMBER) { return buflist_findnr((int)tv->vval.v_number); - if (tv->v_type != VAR_STRING) + } + if (tv->v_type != VAR_STRING) { return NULL; - if (name == NULL || *name == NUL) + } + if (name == NULL || *name == NUL) { return curbuf; - if (name[0] == '$' && name[1] == NUL) + } + if (name[0] == '$' && name[1] == NUL) { return lastbuf; + } // Ignore 'magic' and 'cpoptions' here to make scripts portable save_magic = p_magic; @@ -876,9 +881,9 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) } bool owned = false; - char_u *func; - partial_T *partial = NULL; - dict_T *selfdict = NULL; + char_u *func; + partial_T *partial = NULL; + dict_T *selfdict = NULL; if (argvars[0].v_type == VAR_FUNC) { func = argvars[0].vval.v_string; } else if (argvars[0].v_type == VAR_PARTIAL) { @@ -928,7 +933,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_NUMBER || (argvars[1].v_type != VAR_STRING - && argvars[1].v_type != VAR_UNKNOWN)) { + && argvars[1].v_type != VAR_UNKNOWN)) { EMSG(_(e_invarg)); return; } @@ -1008,8 +1013,7 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - rettv->vval.v_number = utf_ptr2char( - (const char_u *)tv_get_string(&argvars[0])); + rettv->vval.v_number = utf_ptr2char((const char_u *)tv_get_string(&argvars[0])); } // "charidx()" function @@ -1072,8 +1076,9 @@ static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) curwin->w_cursor.lnum = lnum; rettv->vval.v_number = get_c_indent(); curwin->w_cursor = pos; - } else + } else { rettv->vval.v_number = -1; + } } static win_T * get_optional_window(typval_T *argvars, int idx) @@ -1108,7 +1113,7 @@ static void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) { colnr_T col = 0; - pos_T *fp; + pos_T *fp; int fnum = curbuf->b_fnum; fp = var2fpos(&argvars[0], FALSE, &fnum); @@ -1125,7 +1130,7 @@ static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) // col(".") when the cursor is on the NUL at the end of the line // because of "coladd" can be seen as an extra column. if (virtual_active() && fp == &curwin->w_cursor) { - char_u *p = get_cursor_pos_ptr(); + char_u *p = get_cursor_pos_ptr(); if (curwin->w_cursor.coladd >= (colnr_T)win_chartabsize(curwin, p, @@ -1133,8 +1138,9 @@ static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) - curwin->w_cursor.coladd))) { int l; - if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL) + if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL) { col += l; + } } } } @@ -1240,11 +1246,16 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) error = true; } else { switch (TOUPPER_ASC(*typestr)) { - case 'E': type = VIM_ERROR; break; - case 'Q': type = VIM_QUESTION; break; - case 'I': type = VIM_INFO; break; - case 'W': type = VIM_WARNING; break; - case 'G': type = VIM_GENERIC; break; + case 'E': + type = VIM_ERROR; break; + case 'Q': + type = VIM_QUESTION; break; + case 'I': + type = VIM_INFO; break; + case 'W': + type = VIM_WARNING; break; + case 'G': + type = VIM_GENERIC; break; } } } @@ -1256,8 +1267,8 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (!error) { - rettv->vval.v_number = do_dialog( - type, NULL, (char_u *)message, (char_u *)buttons, def, NULL, false); + rettv->vval.v_number = do_dialog(type, NULL, (char_u *)message, (char_u *)buttons, def, NULL, + false); } } @@ -1307,8 +1318,8 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } else if (argvars[0].v_type == VAR_LIST) { - listitem_T *li; - list_T *l; + listitem_T *li; + list_T *l; long idx; if ((l = argvars[0].vval.v_list) != NULL) { @@ -1323,8 +1334,9 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } - if (error) + if (error) { li = NULL; + } } for (; li != NULL; li = TV_LIST_ITEM_NEXT(l, li)) { @@ -1335,8 +1347,8 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } else if (argvars[0].v_type == VAR_DICT) { int todo; - dict_T *d; - hashitem_T *hi; + dict_T *d; + hashitem_T *hi; if ((d = argvars[0].vval.v_dict) != NULL) { if (argvars[2].v_type != VAR_UNKNOWN) { @@ -1855,57 +1867,45 @@ static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool n = true; switch (argvars[0].v_type) { - case VAR_STRING: - case VAR_FUNC: { - n = argvars[0].vval.v_string == NULL - || *argvars[0].vval.v_string == NUL; - break; - } - case VAR_PARTIAL: { + case VAR_STRING: + case VAR_FUNC: + n = argvars[0].vval.v_string == NULL + || *argvars[0].vval.v_string == NUL; + break; + case VAR_PARTIAL: + n = false; + break; + case VAR_NUMBER: + n = argvars[0].vval.v_number == 0; + break; + case VAR_FLOAT: + n = argvars[0].vval.v_float == 0.0; + break; + case VAR_LIST: + n = (tv_list_len(argvars[0].vval.v_list) == 0); + break; + case VAR_DICT: + n = (tv_dict_len(argvars[0].vval.v_dict) == 0); + break; + case VAR_BOOL: + switch (argvars[0].vval.v_bool) { + case kBoolVarTrue: n = false; break; - } - case VAR_NUMBER: { - n = argvars[0].vval.v_number == 0; - break; - } - case VAR_FLOAT: { - n = argvars[0].vval.v_float == 0.0; - break; - } - case VAR_LIST: { - n = (tv_list_len(argvars[0].vval.v_list) == 0); - break; - } - case VAR_DICT: { - n = (tv_dict_len(argvars[0].vval.v_dict) == 0); - break; - } - case VAR_BOOL: { - switch (argvars[0].vval.v_bool) { - case kBoolVarTrue: { - n = false; - break; - } - case kBoolVarFalse: { - n = true; - break; - } - } - break; - } - case VAR_SPECIAL: { - n = argvars[0].vval.v_special == kSpecialVarNull; - break; - } - case VAR_BLOB: { - n = (tv_blob_len(argvars[0].vval.v_blob) == 0); - break; - } - case VAR_UNKNOWN: { - internal_error("f_empty(UNKNOWN)"); + case kBoolVarFalse: + n = true; break; } + break; + case VAR_SPECIAL: + n = argvars[0].vval.v_special == kSpecialVarNull; + break; + case VAR_BLOB: + n = (tv_blob_len(argvars[0].vval.v_blob) == 0); + break; + case VAR_UNKNOWN: + internal_error("f_empty(UNKNOWN)"); + break; } rettv->vval.v_number = n; @@ -1965,9 +1965,8 @@ static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char buf[NUMBUFLEN]; - rettv->vval.v_string = vim_strsave_escaped( - (const char_u *)tv_get_string(&argvars[0]), - (const char_u *)tv_get_string_buf(&argvars[1], buf)); + rettv->vval.v_string = vim_strsave_escaped((const char_u *)tv_get_string(&argvars[0]), + (const char_u *)tv_get_string_buf(&argvars[1], buf)); rettv->v_type = VAR_STRING; } @@ -2048,8 +2047,7 @@ static char_u *get_list_line(int c, void *cookie, int indent, bool do_concat) return (char_u *)(s == NULL ? NULL : xstrdup(s)); } -static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, - int arg_off) +static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, int arg_off) { const int save_msg_silent = msg_silent; const int save_emsg_silent = emsg_silent; @@ -2155,7 +2153,7 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Update the status line if the cursor moved. if (win_valid(wp) && !equalpos(curpos, wp->w_cursor)) { - wp->w_redr_status = true; + wp->w_redr_status = true; } } } @@ -2223,7 +2221,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) { size_t len; - char_u *errormsg; + char_u *errormsg; int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; expand_T xpc; bool error = false; @@ -2522,8 +2520,9 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) if (*fname != NUL && !error) { do { - if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST) + if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST) { xfree(fresult); + } fresult = find_file_in_path_option(first ? (char_u *)fname : NULL, first ? strlen(fname) : 0, 0, first, path, @@ -2539,8 +2538,9 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL); } - if (rettv->v_type == VAR_STRING) + if (rettv->v_type == VAR_STRING) { rettv->vval.v_string = fresult; + } } @@ -2607,8 +2607,7 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_string = (char_u *)vim_strsave_fnameescape( - tv_get_string(&argvars[0]), false); + rettv->vval.v_string = (char_u *)vim_strsave_fnameescape(tv_get_string(&argvars[0]), false); rettv->v_type = VAR_STRING; } @@ -2698,12 +2697,12 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T foldstart; linenr_T foldend; - char_u *dashes; + char_u *dashes; linenr_T lnum; - char_u *s; - char_u *r; + char_u *s; + char_u *r; int len; - char *txt; + char *txt; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -2726,8 +2725,9 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) s = skipwhite(s + 2); if (*skipwhite(s) == NUL && lnum + 1 < foldend) { s = skipwhite(ml_get(lnum + 1)); - if (*s == '*') + if (*s == '*') { s = skipwhite(s + 1); + } } } unsigned long count = (unsigned long)(foldend - foldstart + 1); @@ -2750,7 +2750,7 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *text; + char_u *text; char_u buf[FOLD_TEXT_LEN]; static bool entered = false; @@ -2812,11 +2812,11 @@ static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - listitem_T *li; - list_T *l; - dictitem_T *di; - dict_T *d; - typval_T *tv = NULL; + listitem_T *li; + list_T *l; + dictitem_T *di; + dict_T *d; + typval_T *tv = NULL; bool what_is_dict = false; if (argvars[0].v_type == VAR_BLOB) { @@ -2975,11 +2975,7 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) * buffer. * If 'retlist' is TRUE, then the lines are returned as a Vim List. */ -static void get_buffer_lines(buf_T *buf, - linenr_T start, - linenr_T end, - int retlist, - typval_T *rettv) +static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv) { rettv->v_type = (retlist ? VAR_LIST : VAR_STRING); rettv->vval.v_string = NULL; @@ -3201,7 +3197,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) int col = mouse_col; int grid = mouse_grid; linenr_T lnum; - win_T *wp; + win_T *wp; int winnr = 1; if (row >= 0 && col >= 0) { @@ -3212,8 +3208,9 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) return; } (void)mouse_comp_pos(win, &row, &col, &lnum); - for (wp = firstwin; wp != win; wp = wp->w_next) + for (wp = firstwin; wp != win; wp = wp->w_next) { ++winnr; + } set_vim_var_nr(VV_MOUSE_WIN, winnr); set_vim_var_nr(VV_MOUSE_WINID, wp->handle); set_vim_var_nr(VV_MOUSE_LNUM, lnum); @@ -3312,11 +3309,11 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "getcompletion()" function static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *pat; + char_u *pat; expand_T xpc; bool filtered = false; int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH - | WILD_NO_BEEP; + | WILD_NO_BEEP; if (argvars[1].v_type != VAR_STRING) { EMSG2(_(e_invarg2), "type must be a string"); @@ -3410,7 +3407,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) char_u *from = NULL; // The original string to copy tabpage_T *tp = curtab; // The tabpage to look at. - win_T *win = curwin; // The window to look at. + win_T *win = curwin; // The window to look at. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -3473,29 +3470,29 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) cwd = xmalloc(MAXPATHL); switch (scope) { - case kCdScopeWindow: - assert(win); - from = win->w_localdir; - if (from) { - break; - } - FALLTHROUGH; - case kCdScopeTab: - assert(tp); - from = tp->tp_localdir; - if (from) { - break; - } - FALLTHROUGH; - case kCdScopeGlobal: - if (globaldir) { // `globaldir` is not always set. - from = globaldir; - } else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD. - from = (char_u *)""; // Return empty string on failure. - } + case kCdScopeWindow: + assert(win); + from = win->w_localdir; + if (from) { + break; + } + FALLTHROUGH; + case kCdScopeTab: + assert(tp); + from = tp->tp_localdir; + if (from) { break; - case kCdScopeInvalid: // We should never get here - abort(); + } + FALLTHROUGH; + case kCdScopeGlobal: + if (globaldir) { // `globaldir` is not always set. + from = globaldir; + } else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD. + from = (char_u *)""; // Return empty string on failure. + } + break; + case kCdScopeInvalid: // We should never get here + abort(); } if (from) { @@ -3588,8 +3585,8 @@ static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *type = NULL; - char *t; + char_u *type = NULL; + char *t; const char *fname = tv_get_string(&argvars[0]); @@ -3716,7 +3713,7 @@ static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (cur->match.regprog == NULL) { // match added with matchaddpos() for (i = 0; i < MAXPOSMATCH; i++) { - llpos_T *llpos; + llpos_T *llpos; char buf[30]; // use 30 to avoid compiler warning llpos = &cur->pos.pos[i]; @@ -3777,12 +3774,10 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos) tv_list_append_number(l, ((fp != NULL) ? (varnumber_T)fp->lnum : (varnumber_T)0)); - tv_list_append_number( - l, ((fp != NULL) + tv_list_append_number(l, ((fp != NULL) ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) - : (varnumber_T)0)); - tv_list_append_number( - l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); + : (varnumber_T)0)); + tv_list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); if (getcurpos) { const int save_set_curswant = curwin->w_set_curswant; const colnr_T save_curswant = curwin->w_curswant; @@ -3987,18 +3982,18 @@ static void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "gettagstack()" function static void f_gettagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - win_T *wp = curwin; // default is current window + win_T *wp = curwin; // default is current window - tv_dict_alloc_ret(rettv); + tv_dict_alloc_ret(rettv); - if (argvars[0].v_type != VAR_UNKNOWN) { - wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL) { - return; - } + if (argvars[0].v_type != VAR_UNKNOWN) { + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + return; } + } - get_tagstack(wp, rettv->vval.v_dict); + get_tagstack(wp, rettv->vval.v_dict); } /// "getwininfo()" function @@ -4116,12 +4111,11 @@ static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) // // Move the window wp into a new split of targetwin in a given direction // -static void win_move_into_split(win_T *wp, win_T *targetwin, - int size, int flags) +static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags) { int dir; int height = wp->w_height; - win_T *oldwin = curwin; + win_T *oldwin = curwin; if (wp == targetwin) { return; @@ -4157,8 +4151,8 @@ static void win_move_into_split(win_T *wp, win_T *targetwin, // "win_splitmove()" function static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - win_T *wp; - win_T *targetwin; + win_T *wp; + win_T *targetwin; int flags = 0, size = 0; wp = find_win_by_nr_or_id(&argvars[0]); @@ -4173,8 +4167,8 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[2].v_type != VAR_UNKNOWN) { - dict_T *d; - dictitem_T *di; + dict_T *d; + dictitem_T *di; if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL) { EMSG(_(e_invarg)); @@ -4253,11 +4247,12 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!error) { ExpandInit(&xpc); xpc.xp_context = EXPAND_FILES; - if (p_wic) + if (p_wic) { options += WILD_ICASE; + } if (rettv->v_type == VAR_STRING) { - rettv->vval.v_string = ExpandOne( - &xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options, WILD_ALL); + rettv->vval.v_string = ExpandOne(&xpc, (char_u *)tv_get_string( + &argvars[0]), NULL, options, WILD_ALL); } else { ExpandOne(&xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options, WILD_ALL_KEEP); @@ -4268,8 +4263,9 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) } ExpandCleanup(&xpc); } - } else + } else { rettv->vval.v_string = NULL; + } } /// "globpath()" function @@ -4529,8 +4525,9 @@ static void f_has_key(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG(_(e_dictreq)); return; } - if (argvars[0].vval.v_dict == NULL) + if (argvars[0].vval.v_dict == NULL) { return; + } rettv->vval.v_number = tv_dict_find(argvars[0].vval.v_dict, tv_get_string(&argvars[1]), @@ -4561,7 +4558,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) }; tabpage_T *tp = curtab; // The tabpage to look at. - win_T *win = curwin; // The window to look at. + win_T *win = curwin; // The window to look at. rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -4620,20 +4617,20 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) } switch (scope) { - case kCdScopeWindow: - assert(win); - rettv->vval.v_number = win->w_localdir ? 1 : 0; - break; - case kCdScopeTab: - assert(tp); - rettv->vval.v_number = tp->tp_localdir ? 1 : 0; - break; - case kCdScopeGlobal: - // The global scope never has a local directory - break; - case kCdScopeInvalid: - // We should never get here - abort(); + case kCdScopeWindow: + assert(win); + rettv->vval.v_number = win->w_localdir ? 1 : 0; + break; + case kCdScopeTab: + assert(tp); + rettv->vval.v_number = tp->tp_localdir ? 1 : 0; + break; + case kCdScopeGlobal: + // The global scope never has a local directory + break; + case kCdScopeInvalid: + // We should never get here + abort(); } } @@ -4756,8 +4753,7 @@ static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = syn_name2id( - (const char_u *)tv_get_string(&argvars[0])); + rettv->vval.v_number = syn_name2id((const char_u *)tv_get_string(&argvars[0])); } /* @@ -4765,8 +4761,7 @@ static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_hlexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = highlight_exists( - (const char_u *)tv_get_string(&argvars[0])); + rettv->vval.v_number = highlight_exists((const char_u *)tv_get_string(&argvars[0])); } /* @@ -4793,11 +4788,9 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *const str = tv_get_string(&argvars[0]); char buf1[NUMBUFLEN]; - char_u *const from = enc_canonize(enc_skip( - (char_u *)tv_get_string_buf(&argvars[1], buf1))); + char_u *const from = enc_canonize(enc_skip((char_u *)tv_get_string_buf(&argvars[1], buf1))); char buf2[NUMBUFLEN]; - char_u *const to = enc_canonize(enc_skip( - (char_u *)tv_get_string_buf(&argvars[2], buf2))); + char_u *const to = enc_canonize(enc_skip((char_u *)tv_get_string_buf(&argvars[2], buf2))); vimconv.vc_type = CONV_NONE; convert_setup(&vimconv, from, to); @@ -5062,8 +5055,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // "interrupt()" function -static void f_interrupt(typval_T *argvars FUNC_ATTR_UNUSED, - typval_T *rettv FUNC_ATTR_UNUSED, +static void f_interrupt(typval_T *argvars FUNC_ATTR_UNUSED, typval_T *rettv FUNC_ATTR_UNUSED, FunPtr fptr FUNC_ATTR_UNUSED) { got_int = true; @@ -5091,7 +5083,7 @@ static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) { lval_T lv; - dictitem_T *di; + dictitem_T *di; rettv->vval.v_number = -1; const char_u *const end = get_lval((char_u *)tv_get_string(&argvars[0]), @@ -5143,7 +5135,7 @@ static void f_isinf(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_isnan(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT - && xisnan(argvars[0].vval.v_float); + && xisnan(argvars[0].vval.v_float); } /// "id()" function @@ -5251,9 +5243,7 @@ static const char *required_env_vars[] = { NULL }; -static dict_T *create_environment(const dictitem_T *job_env, - const bool clear_env, - const bool pty, +static dict_T *create_environment(const dictitem_T *job_env, const bool clear_env, const bool pty, const char * const pty_term_name) { dict_T * env = tv_dict_alloc(); @@ -5502,7 +5492,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } if (argvars[0].v_type != VAR_LIST || (argvars[1].v_type != VAR_NUMBER - && argvars[1].v_type != VAR_UNKNOWN)) { + && argvars[1].v_type != VAR_UNKNOWN)) { EMSG(_(e_invarg)); return; } @@ -5688,33 +5678,27 @@ static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr) { switch (argvars[0].v_type) { - case VAR_STRING: - case VAR_NUMBER: { - rettv->vval.v_number = (varnumber_T)strlen( - tv_get_string(&argvars[0])); - break; - } - case VAR_BLOB: { - rettv->vval.v_number = tv_blob_len(argvars[0].vval.v_blob); - break; - } - case VAR_LIST: { - rettv->vval.v_number = tv_list_len(argvars[0].vval.v_list); - break; - } - case VAR_DICT: { - rettv->vval.v_number = tv_dict_len(argvars[0].vval.v_dict); - break; - } - case VAR_UNKNOWN: - case VAR_BOOL: - case VAR_SPECIAL: - case VAR_FLOAT: - case VAR_PARTIAL: - case VAR_FUNC: { - EMSG(_("E701: Invalid type for len()")); - break; - } + case VAR_STRING: + case VAR_NUMBER: + rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0])); + break; + case VAR_BLOB: + rettv->vval.v_number = tv_blob_len(argvars[0].vval.v_blob); + break; + case VAR_LIST: + rettv->vval.v_number = tv_list_len(argvars[0].vval.v_list); + break; + case VAR_DICT: + rettv->vval.v_number = tv_dict_len(argvars[0].vval.v_dict); + break; + case VAR_UNKNOWN: + case VAR_BOOL: + case VAR_SPECIAL: + case VAR_FLOAT: + case VAR_PARTIAL: + case VAR_FUNC: + EMSG(_("E701: Invalid type for len()")); + break; } } @@ -5759,7 +5743,7 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) } if (out_type == VAR_NUMBER) { - rettv->vval.v_number = (varnumber_T)int_out; + rettv->vval.v_number = (varnumber_T)int_out; } } @@ -5889,7 +5873,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) int mode; int abbr = FALSE; int get_dict = FALSE; - mapblock_T *mp; + mapblock_T *mp; int buffer_local; // Return empty string for failure. @@ -5931,11 +5915,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) if (*rhs == NUL) { rettv->vval.v_string = vim_strsave((char_u *)"<Nop>"); } else { - rettv->vval.v_string = (char_u *)str2special_save( - (char *)rhs, false, false); + rettv->vval.v_string = (char_u *)str2special_save((char *)rhs, false, false); } } - } else { tv_dict_alloc_ret(rettv); if (rhs != NULL) { @@ -5985,19 +5967,19 @@ static void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void find_some_match(typval_T *const argvars, typval_T *const rettv, const SomeMatchType type) { - char_u *str = NULL; + char_u *str = NULL; long len = 0; - char_u *expr = NULL; + char_u *expr = NULL; regmatch_T regmatch; - char_u *save_cpo; + char_u *save_cpo; long start = 0; long nth = 1; colnr_T startcol = 0; bool match = false; - list_T *l = NULL; - listitem_T *li = NULL; + list_T *l = NULL; + listitem_T *li = NULL; long idx = 0; - char_u *tofree = NULL; + char_u *tofree = NULL; // Make 'cpoptions' empty, the 'l' flag should not be used here. save_cpo = p_cpo; @@ -6005,30 +5987,26 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, rettv->vval.v_number = -1; switch (type) { - // matchlist(): return empty list when there are no matches. - case kSomeMatchList: { - tv_list_alloc_ret(rettv, kListLenMayKnow); - break; - } - // matchstrpos(): return ["", -1, -1, -1] - case kSomeMatchStrPos: { - tv_list_alloc_ret(rettv, 4); - tv_list_append_string(rettv->vval.v_list, "", 0); - tv_list_append_number(rettv->vval.v_list, -1); - tv_list_append_number(rettv->vval.v_list, -1); - tv_list_append_number(rettv->vval.v_list, -1); - break; - } - case kSomeMatchStr: { - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - break; - } - case kSomeMatch: - case kSomeMatchEnd: { - // Do nothing: zero is default. - break; - } + // matchlist(): return empty list when there are no matches. + case kSomeMatchList: + tv_list_alloc_ret(rettv, kListLenMayKnow); + break; + // matchstrpos(): return ["", -1, -1, -1] + case kSomeMatchStrPos: + tv_list_alloc_ret(rettv, 4); + tv_list_append_string(rettv->vval.v_list, "", 0); + tv_list_append_number(rettv->vval.v_list, -1); + tv_list_append_number(rettv->vval.v_list, -1); + tv_list_append_number(rettv->vval.v_list, -1); + break; + case kSomeMatchStr: + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + break; + case kSomeMatch: + case kSomeMatchEnd: + // Do nothing: zero is default. + break; } if (argvars[0].v_type == VAR_LIST) { @@ -6061,10 +6039,12 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, } li = tv_list_find(l, idx); } else { - if (start < 0) + if (start < 0) { start = 0; - if (start > len) + } + if (start > len) { goto theend; + } // When "count" argument is there ignore matches before "start", // otherwise skip part of the string. Differs when pattern is "^" // or "\<". @@ -6104,10 +6084,12 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, match = vim_regexec_nl(®match, str, (colnr_T)startcol); - if (match && --nth <= 0) + if (match && --nth <= 0) { break; - if (l == NULL && !match) + } + if (l == NULL && !match) { break; + } // Advance to just after the match. if (l != NULL) { @@ -6117,74 +6099,70 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, startcol = (colnr_T)(regmatch.startp[0] + (*mb_ptr2len)(regmatch.startp[0]) - str); if (startcol > (colnr_T)len || str + startcol <= regmatch.startp[0]) { - match = false; - break; + match = false; + break; } } } if (match) { switch (type) { - case kSomeMatchStrPos: { - list_T *const ret_l = rettv->vval.v_list; - listitem_T *li1 = tv_list_first(ret_l); - listitem_T *li2 = TV_LIST_ITEM_NEXT(ret_l, li1); - listitem_T *li3 = TV_LIST_ITEM_NEXT(ret_l, li2); - listitem_T *li4 = TV_LIST_ITEM_NEXT(ret_l, li3); - xfree(TV_LIST_ITEM_TV(li1)->vval.v_string); - - const size_t rd = (size_t)(regmatch.endp[0] - regmatch.startp[0]); - TV_LIST_ITEM_TV(li1)->vval.v_string = xmemdupz( - (const char *)regmatch.startp[0], rd); - TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)( - regmatch.startp[0] - expr); - TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)( - regmatch.endp[0] - expr); - if (l != NULL) { - TV_LIST_ITEM_TV(li2)->vval.v_number = (varnumber_T)idx; - } - break; - } - case kSomeMatchList: { - // Return list with matched string and submatches. - for (int i = 0; i < NSUBEXP; i++) { - if (regmatch.endp[i] == NULL) { - tv_list_append_string(rettv->vval.v_list, NULL, 0); - } else { - tv_list_append_string(rettv->vval.v_list, - (const char *)regmatch.startp[i], - (regmatch.endp[i] - regmatch.startp[i])); - } - } - break; + case kSomeMatchStrPos: { + list_T *const ret_l = rettv->vval.v_list; + listitem_T *li1 = tv_list_first(ret_l); + listitem_T *li2 = TV_LIST_ITEM_NEXT(ret_l, li1); + listitem_T *li3 = TV_LIST_ITEM_NEXT(ret_l, li2); + listitem_T *li4 = TV_LIST_ITEM_NEXT(ret_l, li3); + xfree(TV_LIST_ITEM_TV(li1)->vval.v_string); + + const size_t rd = (size_t)(regmatch.endp[0] - regmatch.startp[0]); + TV_LIST_ITEM_TV(li1)->vval.v_string = xmemdupz((const char *)regmatch.startp[0], rd); + TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)( + regmatch.startp[0] - expr); + TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)( + regmatch.endp[0] - expr); + if (l != NULL) { + TV_LIST_ITEM_TV(li2)->vval.v_number = (varnumber_T)idx; } - case kSomeMatchStr: { - // Return matched string. - if (l != NULL) { - tv_copy(TV_LIST_ITEM_TV(li), rettv); + break; + } + case kSomeMatchList: + // Return list with matched string and submatches. + for (int i = 0; i < NSUBEXP; i++) { + if (regmatch.endp[i] == NULL) { + tv_list_append_string(rettv->vval.v_list, NULL, 0); } else { - rettv->vval.v_string = (char_u *)xmemdupz( - (const char *)regmatch.startp[0], - (size_t)(regmatch.endp[0] - regmatch.startp[0])); + tv_list_append_string(rettv->vval.v_list, + (const char *)regmatch.startp[i], + (regmatch.endp[i] - regmatch.startp[i])); } - break; } - case kSomeMatch: - case kSomeMatchEnd: { - if (l != NULL) { - rettv->vval.v_number = idx; + break; + case kSomeMatchStr: + // Return matched string. + if (l != NULL) { + tv_copy(TV_LIST_ITEM_TV(li), rettv); + } else { + rettv->vval.v_string = (char_u *)xmemdupz((const char *)regmatch.startp[0], + (size_t)(regmatch.endp[0] - + regmatch.startp[0])); + } + break; + case kSomeMatch: + case kSomeMatchEnd: + if (l != NULL) { + rettv->vval.v_number = idx; + } else { + if (type == kSomeMatch) { + rettv->vval.v_number = + (varnumber_T)(regmatch.startp[0] - str); } else { - if (type == kSomeMatch) { - rettv->vval.v_number = - (varnumber_T)(regmatch.startp[0] - str); - } else { - rettv->vval.v_number = - (varnumber_T)(regmatch.endp[0] - str); - } - rettv->vval.v_number += (varnumber_T)(str - expr); + rettv->vval.v_number = + (varnumber_T)(regmatch.endp[0] - str); } - break; + rettv->vval.v_number += (varnumber_T)(str - expr); } + break; } } vim_regfree(regmatch.regprog); @@ -6333,7 +6311,7 @@ static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - win_T *win = get_optional_window(argvars, 1); + win_T *win = get_optional_window(argvars, 1); if (win == NULL) { rettv->vval.v_number = -1; } else { @@ -6381,8 +6359,7 @@ static void f_matchstrpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// vval.v_number, type is not touched. Returns zero for /// empty lists/dictionaries. /// @param[in] domax Determines whether maximal or minimal value is desired. -static void max_min(const typval_T *const tv, typval_T *const rettv, - const bool domax) +static void max_min(const typval_T *const tv, typval_T *const rettv, const bool domax) FUNC_ATTR_NONNULL_ALL { bool error = false; @@ -6532,41 +6509,38 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv, FunPtr fptr) msgpack_packer_free(packer); } -static int msgpackparse_convert_item(const msgpack_object data, - const msgpack_unpack_return result, - list_T *const ret_list, - const bool fail_if_incomplete) +static int msgpackparse_convert_item(const msgpack_object data, const msgpack_unpack_return result, + list_T *const ret_list, const bool fail_if_incomplete) FUNC_ATTR_NONNULL_ALL { switch (result) { - case MSGPACK_UNPACK_PARSE_ERROR: - EMSG2(_(e_invarg2), "Failed to parse msgpack string"); + case MSGPACK_UNPACK_PARSE_ERROR: + EMSG2(_(e_invarg2), "Failed to parse msgpack string"); + return FAIL; + case MSGPACK_UNPACK_NOMEM_ERROR: + EMSG(_(e_outofmem)); + return FAIL; + case MSGPACK_UNPACK_CONTINUE: + if (fail_if_incomplete) { + EMSG2(_(e_invarg2), "Incomplete msgpack string"); return FAIL; - case MSGPACK_UNPACK_NOMEM_ERROR: - EMSG(_(e_outofmem)); + } + return NOTDONE; + case MSGPACK_UNPACK_SUCCESS: { + typval_T tv = { .v_type = VAR_UNKNOWN }; + if (msgpack_to_vim(data, &tv) == FAIL) { + EMSG2(_(e_invarg2), "Failed to convert msgpack string"); return FAIL; - case MSGPACK_UNPACK_CONTINUE: - if (fail_if_incomplete) { - EMSG2(_(e_invarg2), "Incomplete msgpack string"); - return FAIL; - } - return NOTDONE; - case MSGPACK_UNPACK_SUCCESS: { - typval_T tv = { .v_type = VAR_UNKNOWN }; - if (msgpack_to_vim(data, &tv) == FAIL) { - EMSG2(_(e_invarg2), "Failed to convert msgpack string"); - return FAIL; - } - tv_list_append_owned_tv(ret_list, tv); - return OK; } - default: - abort(); + tv_list_append_owned_tv(ret_list, tv); + return OK; + } + default: + abort(); } } -static void msgpackparse_unpack_list(const list_T *const list, - list_T *const ret_list) +static void msgpackparse_unpack_list(const list_T *const list, list_T *const ret_list) FUNC_ATTR_NONNULL_ARG(2) { if (tv_list_len(list) == 0) { @@ -6590,8 +6564,8 @@ static void msgpackparse_unpack_list(const list_T *const list, goto end; } size_t read_bytes; - const int rlret = encode_read_from_list( - &lrstate, msgpack_unpacker_buffer(unpacker), IOSIZE, &read_bytes); + const int rlret = encode_read_from_list(&lrstate, msgpack_unpacker_buffer( + unpacker), IOSIZE, &read_bytes); if (rlret == FAIL) { EMSG2(_(e_invarg2), "List item is not a string"); goto end; @@ -6602,7 +6576,7 @@ static void msgpackparse_unpack_list(const list_T *const list, } while (unpacker->off < unpacker->used) { const msgpack_unpack_return result - = msgpack_unpacker_next(unpacker, &unpacked); + = msgpack_unpacker_next(unpacker, &unpacked); const int conv_result = msgpackparse_convert_item(unpacked.data, result, ret_list, rlret == OK); if (conv_result == NOTDONE) { @@ -6621,8 +6595,7 @@ end: msgpack_unpacked_destroy(&unpacked); } -static void msgpackparse_unpack_blob(const blob_T *const blob, - list_T *const ret_list) +static void msgpackparse_unpack_blob(const blob_T *const blob, list_T *const ret_list) FUNC_ATTR_NONNULL_ARG(2) { const int len = tv_blob_len(blob); @@ -6633,7 +6606,7 @@ static void msgpackparse_unpack_blob(const blob_T *const blob, msgpack_unpacked_init(&unpacked); for (size_t offset = 0; offset < (size_t)len;) { const msgpack_unpack_return result - = msgpack_unpack_next(&unpacked, blob->bv_ga.ga_data, len, &offset); + = msgpack_unpack_next(&unpacked, blob->bv_ga.ga_data, len, &offset); if (msgpackparse_convert_item(unpacked.data, result, ret_list, true) != OK) { break; @@ -6791,53 +6764,51 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // "prompt_setcallback({buffer}, {callback})" function -static void f_prompt_setcallback(typval_T *argvars, - typval_T *rettv, FunPtr fptr) +static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - Callback prompt_callback = { .type = kCallbackNone }; + buf_T *buf; + Callback prompt_callback = { .type = kCallbackNone }; - if (check_secure()) { - return; - } - buf = tv_get_buf(&argvars[0], false); - if (buf == NULL) { - return; - } + if (check_secure()) { + return; + } + buf = tv_get_buf(&argvars[0], false); + if (buf == NULL) { + return; + } - if (argvars[1].v_type != VAR_STRING || *argvars[1].vval.v_string != NUL) { - if (!callback_from_typval(&prompt_callback, &argvars[1])) { - return; - } + if (argvars[1].v_type != VAR_STRING || *argvars[1].vval.v_string != NUL) { + if (!callback_from_typval(&prompt_callback, &argvars[1])) { + return; } + } - callback_free(&buf->b_prompt_callback); - buf->b_prompt_callback = prompt_callback; + callback_free(&buf->b_prompt_callback); + buf->b_prompt_callback = prompt_callback; } // "prompt_setinterrupt({buffer}, {callback})" function -static void f_prompt_setinterrupt(typval_T *argvars, - typval_T *rettv, FunPtr fptr) +static void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - Callback interrupt_callback = { .type = kCallbackNone }; + buf_T *buf; + Callback interrupt_callback = { .type = kCallbackNone }; - if (check_secure()) { - return; - } - buf = tv_get_buf(&argvars[0], false); - if (buf == NULL) { - return; - } + if (check_secure()) { + return; + } + buf = tv_get_buf(&argvars[0], false); + if (buf == NULL) { + return; + } - if (argvars[1].v_type != VAR_STRING || *argvars[1].vval.v_string != NUL) { - if (!callback_from_typval(&interrupt_callback, &argvars[1])) { - return; - } + if (argvars[1].v_type != VAR_STRING || *argvars[1].vval.v_string != NUL) { + if (!callback_from_typval(&interrupt_callback, &argvars[1])) { + return; } + } - callback_free(&buf->b_prompt_interrupt); - buf->b_prompt_interrupt= interrupt_callback; + callback_free(&buf->b_prompt_interrupt); + buf->b_prompt_interrupt= interrupt_callback; } /// "prompt_getprompt({buffer})" function @@ -6861,23 +6832,22 @@ void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // "prompt_setprompt({buffer}, {text})" function -static void f_prompt_setprompt(typval_T *argvars, - typval_T *rettv, FunPtr fptr) +static void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - const char_u *text; + buf_T *buf; + const char_u *text; - if (check_secure()) { - return; - } - buf = tv_get_buf(&argvars[0], false); - if (buf == NULL) { - return; - } + if (check_secure()) { + return; + } + buf = tv_get_buf(&argvars[0], false); + if (buf == NULL) { + return; + } - text = (const char_u *)tv_get_string(&argvars[1]); - xfree(buf->b_prompt_text); - buf->b_prompt_text = vim_strsave(text); + text = (const char_u *)tv_get_string(&argvars[1]); + xfree(buf->b_prompt_text); + buf->b_prompt_text = vim_strsave(text); } // "pum_getpos()" function @@ -6892,8 +6862,9 @@ static void f_pum_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (pum_visible()) + if (pum_visible()) { rettv->vval.v_number = 1; + } } /* @@ -7068,11 +7039,11 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { bool binary = false; bool blob = false; - FILE *fd; + FILE *fd; char_u buf[(IOSIZE/256) * 256]; // rounded to avoid odd + 1 int io_size = sizeof(buf); int readlen; // size of last fread() - char_u *prev = NULL; // previously read bytes, if any + char_u *prev = NULL; // previously read bytes, if any long prevlen = 0; // length of data in prev long prevsize = 0; // size of prev buffer long maxline = MAXLNUM; @@ -7129,7 +7100,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary)); p++) { if (*p == '\n' || readlen <= 0) { - char_u *s = NULL; + char_u *s = NULL; size_t len = p - start; // Finished a line. Remove CRs before NL. @@ -7179,16 +7150,17 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } else if (*p == NUL) { *p = '\n'; - // Check for utf8 "bom"; U+FEFF is encoded as EF BB BF. Do this - // when finding the BF and check the previous two bytes. + // Check for utf8 "bom"; U+FEFF is encoded as EF BB BF. Do this + // when finding the BF and check the previous two bytes. } else if (*p == 0xbf && !binary) { // Find the two bytes before the 0xbf. If p is at buf, or buf + 1, // these may be in the "prev" string. char_u back1 = p >= buf + 1 ? p[-1] - : prevlen >= 1 ? prev[prevlen - 1] : NUL; + : prevlen >= 1 ? prev[prevlen - 1] : NUL; char_u back2 = p >= buf + 2 ? p[-2] - : p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1] - : prevlen >= 2 ? prev[prevlen - 2] : NUL; + : p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1] + : prevlen >= + 2 ? prev[prevlen - 2] : NUL; if (back2 == 0xef && back1 == 0xbb) { char_u *dest = p - 2; @@ -7206,8 +7178,9 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) // adjust_prevlen must be 1 or 2. dest = buf; } - if (readlen > p - buf + 1) + if (readlen > p - buf + 1) { memmove(dest, p + 1, readlen - (p - buf) - 1); + } readlen -= 3 - adjust_prevlen; prevlen -= adjust_prevlen; p = dest - 1; @@ -7226,9 +7199,9 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) * fragment of a line, so the first allocation is made * small, to avoid repeatedly 'allocing' large and * 'reallocing' small. */ - if (prevsize == 0) + if (prevsize == 0) { prevsize = (long)(p - start); - else { + } else { long grow50pc = (prevsize * 3) / 2; long growmin = (long)((p - start) * 2 + prevlen); prevsize = grow50pc > growmin ? grow50pc : growmin; @@ -7328,7 +7301,7 @@ static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr) // results, if varnumber_T or proftime_T change, the union cast will need // to be revised. STATIC_ASSERT(sizeof(u.prof) == sizeof(u) && sizeof(u.split) == sizeof(u), - "type punning will produce incorrect results on this platform"); + "type punning will produce incorrect results on this platform"); tv_list_alloc_ret(rettv, 2); tv_list_append_number(rettv->vval.v_list, u.split.high); @@ -7353,13 +7326,13 @@ static void f_reltimestr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - list_T *l; - listitem_T *item, *item2; - listitem_T *li; + list_T *l; + listitem_T *item, *item2; + listitem_T *li; long idx; long end; - dict_T *d; - dictitem_T *di; + dict_T *d; + dictitem_T *di; const char *const arg_errmsg = N_("remove() argument"); if (argvars[0].v_type == VAR_DICT) { @@ -7493,9 +7466,8 @@ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = -1; } else { char buf[NUMBUFLEN]; - rettv->vval.v_number = vim_rename( - (const char_u *)tv_get_string(&argvars[0]), - (const char_u *)tv_get_string_buf(&argvars[1], buf)); + rettv->vval.v_number = vim_rename((const char_u *)tv_get_string(&argvars[0]), + (const char_u *)tv_get_string_buf(&argvars[1], buf)); } } @@ -7763,30 +7735,40 @@ static int get_search_arg(typval_T *varp, int *flagsp) } while (*flags != NUL) { switch (*flags) { - case 'b': dir = BACKWARD; break; - case 'w': p_ws = true; break; - case 'W': p_ws = false; break; - default: { - mask = 0; - if (flagsp != NULL) { - switch (*flags) { - case 'c': mask = SP_START; break; - case 'e': mask = SP_END; break; - case 'm': mask = SP_RETCOUNT; break; - case 'n': mask = SP_NOMOVE; break; - case 'p': mask = SP_SUBPAT; break; - case 'r': mask = SP_REPEAT; break; - case 's': mask = SP_SETPCMARK; break; - case 'z': mask = SP_COLUMN; break; - } - } - if (mask == 0) { - emsgf(_(e_invarg2), flags); - dir = 0; - } else { - *flagsp |= mask; + case 'b': + dir = BACKWARD; break; + case 'w': + p_ws = true; break; + case 'W': + p_ws = false; break; + default: + mask = 0; + if (flagsp != NULL) { + switch (*flags) { + case 'c': + mask = SP_START; break; + case 'e': + mask = SP_END; break; + case 'm': + mask = SP_RETCOUNT; break; + case 'n': + mask = SP_NOMOVE; break; + case 'p': + mask = SP_SUBPAT; break; + case 'r': + mask = SP_REPEAT; break; + case 's': + mask = SP_SETPCMARK; break; + case 'z': + mask = SP_COLUMN; break; } } + if (mask == 0) { + emsgf(_(e_invarg2), flags); + dir = 0; + } else { + *flagsp |= mask; + } } if (dir == 0) { break; @@ -7865,12 +7847,14 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1, options, RE_SEARCH, &sia); if (subpatnum != FAIL) { - if (flags & SP_SUBPAT) + if (flags & SP_SUBPAT) { retval = subpatnum; - else + } else { retval = pos.lnum; - if (flags & SP_SETPCMARK) + } + if (flags & SP_SETPCMARK) { setpcmark(); + } curwin->w_cursor = pos; if (match_pos != NULL) { // Store the match cursor position @@ -8008,10 +7992,10 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) } msg_ext_set_kind("rpc_error"); if (name) { - emsgf_multiline("Error invoking '%s' on channel %"PRIu64" (%s):\n%s", + emsgf_multiline("Error invoking '%s' on channel %" PRIu64 " (%s):\n%s", method, chan_id, name, err.msg); } else { - emsgf_multiline("Error invoking '%s' on channel %"PRIu64":\n%s", + emsgf_multiline("Error invoking '%s' on channel %" PRIu64 ":\n%s", method, chan_id, err.msg); } @@ -8313,9 +8297,8 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) } } - retval = do_searchpair( - spat, mpat, epat, dir, skip, - flags, match_pos, lnum_stop, time_limit); + retval = do_searchpair(spat, mpat, epat, dir, skip, + flags, match_pos, lnum_stop, time_limit); theend: p_ws = save_p_ws; @@ -8356,22 +8339,19 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) * Used by searchpair(), see its documentation for the details. * Returns 0 or -1 for no match, */ -long -do_searchpair( - const char *spat, // start pattern - const char *mpat, // middle pattern - const char *epat, // end pattern - int dir, // BACKWARD or FORWARD - const typval_T *skip, // skip expression - int flags, // SP_SETPCMARK and other SP_ values - pos_T *match_pos, - linenr_T lnum_stop, // stop at this line if not zero - long time_limit // stop after this many msec -) +long do_searchpair(const char *spat, // start pattern + const char *mpat, // middle pattern + const char *epat, // end pattern + int dir, // BACKWARD or FORWARD + const typval_T *skip, // skip expression + int flags, // SP_SETPCMARK and other SP_ values + pos_T *match_pos, linenr_T lnum_stop, // stop at this line if not zero + long time_limit // stop after this many msec + ) FUNC_ATTR_NONNULL_ARG(1, 2, 3) { - char_u *save_cpo; - char_u *pat, *pat2 = NULL, *pat3 = NULL; + char_u *save_cpo; + char_u *pat, *pat2 = NULL, *pat3 = NULL; long retval = 0; pos_T pos; pos_T firstpos; @@ -8433,8 +8413,9 @@ do_searchpair( break; } - if (firstpos.lnum == 0) + if (firstpos.lnum == 0) { firstpos = pos; + } if (equalpos(pos, foundpos)) { // Found the same position again. Can happen with a pattern that // has "\zs" at the end and searching backwards. Advance one @@ -8463,8 +8444,9 @@ do_searchpair( retval = -1; break; } - if (r) + if (r) { continue; + } } if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2)) { @@ -8491,8 +8473,9 @@ do_searchpair( setpcmark(); } curwin->w_cursor = pos; - if (!(flags & SP_REPEAT)) + if (!(flags & SP_REPEAT)) { break; + } nest = 1; // search for next unmatched } } @@ -8624,16 +8607,16 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "setbufline()" function static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - buf_T *buf; + linenr_T lnum; + buf_T *buf; - buf = tv_get_buf(&argvars[0], false); - if (buf == NULL) { - rettv->vval.v_number = 1; // FAIL - } else { - lnum = tv_get_lnum_buf(&argvars[1], buf); - set_buffer_lines(buf, lnum, false, &argvars[2], rettv); - } + buf = tv_get_buf(&argvars[0], false); + if (buf == NULL) { + rettv->vval.v_number = 1; // FAIL + } else { + lnum = tv_get_lnum_buf(&argvars[1], buf); + set_buffer_lines(buf, lnum, false, &argvars[2], rettv); + } } /* @@ -8684,8 +8667,8 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - dict_T *d; - dictitem_T *di; + dict_T *d; + dictitem_T *di; if (argvars[0].v_type != VAR_DICT) { EMSG(_(e_dictreq)); @@ -8865,7 +8848,7 @@ skip_args: */ static void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - win_T *win; + win_T *win; rettv->vval.v_number = -1; @@ -9005,7 +8988,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) } check_cursor(); rettv->vval.v_number = 0; - } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { + } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { // set mark if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) { rettv->vval.v_number = 0; @@ -9057,31 +9040,31 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) } for (; *stropt != NUL; stropt++) { switch (*stropt) { - case 'a': case 'A': { // append - append = true; - break; - } - case 'v': case 'c': { // character-wise selection - yank_type = kMTCharWise; - break; - } - case 'V': case 'l': { // line-wise selection - yank_type = kMTLineWise; - break; - } - case 'b': case Ctrl_V: { // block-wise selection - yank_type = kMTBlockWise; - if (ascii_isdigit(stropt[1])) { - stropt++; - block_len = getdigits_long((char_u **)&stropt, true, 0) - 1; - stropt--; - } - break; - } - case 'u': case '"': { // unnamed register - set_unnamed = true; - break; + case 'a': + case 'A': // append + append = true; + break; + case 'v': + case 'c': // character-wise selection + yank_type = kMTCharWise; + break; + case 'V': + case 'l': // line-wise selection + yank_type = kMTLineWise; + break; + case 'b': + case Ctrl_V: // block-wise selection + yank_type = kMTBlockWise; + if (ascii_isdigit(stropt[1])) { + stropt++; + block_len = getdigits_long((char_u **)&stropt, true, 0) - 1; + stropt--; } + break; + case 'u': + case '"': // unnamed register + set_unnamed = true; + break; } } } @@ -9135,7 +9118,8 @@ free_lstval: if (set_unnamed) { // Discard the result. We already handle the error case. - if (op_reg_set_previous(regname)) { } + if (op_reg_set_previous(regname)) { + } } } @@ -9183,54 +9167,54 @@ static void f_settabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "settagstack()" function static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - static char *e_invact2 = N_("E962: Invalid action: '%s'"); - win_T *wp; - dict_T *d; - int action = 'r'; + static char *e_invact2 = N_("E962: Invalid action: '%s'"); + win_T *wp; + dict_T *d; + int action = 'r'; - rettv->vval.v_number = -1; + rettv->vval.v_number = -1; - // first argument: window number or id - wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL) { - return; - } + // first argument: window number or id + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + return; + } - // second argument: dict with items to set in the tag stack - if (argvars[1].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); - return; - } - d = argvars[1].vval.v_dict; - if (d == NULL) { + // second argument: dict with items to set in the tag stack + if (argvars[1].v_type != VAR_DICT) { + EMSG(_(e_dictreq)); + return; + } + d = argvars[1].vval.v_dict; + if (d == NULL) { + return; + } + + // third argument: action - 'a' for append and 'r' for replace. + // default is to replace the stack. + if (argvars[2].v_type == VAR_UNKNOWN) { + action = 'r'; + } else if (argvars[2].v_type == VAR_STRING) { + const char *actstr; + actstr = tv_get_string_chk(&argvars[2]); + if (actstr == NULL) { return; } - - // third argument: action - 'a' for append and 'r' for replace. - // default is to replace the stack. - if (argvars[2].v_type == VAR_UNKNOWN) { - action = 'r'; - } else if (argvars[2].v_type == VAR_STRING) { - const char *actstr; - actstr = tv_get_string_chk(&argvars[2]); - if (actstr == NULL) { - return; - } - if ((*actstr == 'r' || *actstr == 'a' || *actstr == 't') - && actstr[1] == NUL) { - action = *actstr; - } else { - EMSG2(_(e_invact2), actstr); - return; - } + if ((*actstr == 'r' || *actstr == 'a' || *actstr == 't') + && actstr[1] == NUL) { + action = *actstr; } else { - EMSG(_(e_stringreq)); - return; + EMSG2(_(e_invact2), actstr); + return; } + } else { + EMSG(_(e_stringreq)); + return; + } - if (set_tagstack(wp, d, action) == OK) { - rettv->vval.v_number = 0; - } + if (set_tagstack(wp, d, action) == OK) { + rettv->vval.v_number = 0; + } } /* @@ -9245,7 +9229,7 @@ static void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *p = tv_get_string(&argvars[0]); - const char *hash = sha256_bytes((const uint8_t *)p, strlen(p) , NULL, 0); + const char *hash = sha256_bytes((const uint8_t *)p, strlen(p), NULL, 0); // make a copy of the hash (sha256_bytes returns a static buffer) rettv->vval.v_string = (char_u *)xstrdup(hash); @@ -9259,8 +9243,8 @@ static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const bool do_special = non_zero_arg(&argvars[1]); - rettv->vval.v_string = vim_strsave_shellescape( - (const char_u *)tv_get_string(&argvars[0]), do_special, do_special); + rettv->vval.v_string = vim_strsave_shellescape((const char_u *)tv_get_string( + &argvars[0]), do_special, do_special); rettv->v_type = VAR_STRING; } @@ -9310,8 +9294,9 @@ static void f_sign_define(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - rettv->vval.v_number = sign_define_from_dict( - name, argvars[1].v_type == VAR_DICT ? argvars[1].vval.v_dict : NULL); + rettv->vval.v_number = sign_define_from_dict(name, + argvars[1].v_type == + VAR_DICT ? argvars[1].vval.v_dict : NULL); } /// "sign_getdefined()" function @@ -9443,8 +9428,8 @@ static void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - rettv->vval.v_number = sign_place_from_dict( - &argvars[0], &argvars[1], &argvars[2], &argvars[3], dict); + rettv->vval.v_number = sign_place_from_dict(&argvars[0], &argvars[1], &argvars[2], &argvars[3], + dict); } /// "sign_placelist()" function. Place multiple signs. @@ -9463,8 +9448,7 @@ static void f_sign_placelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) TV_LIST_ITER_CONST(argvars[0].vval.v_list, li, { sign_id = -1; if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) { - sign_id = sign_place_from_dict( - NULL, NULL, NULL, NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); + sign_id = sign_place_from_dict(NULL, NULL, NULL, NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); } else { EMSG(_(e_dictreq)); } @@ -9800,7 +9784,7 @@ static int item_compare2_not_keeping_zero(const void *s1, const void *s2) */ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) { - ListSortItem *ptrs; + ListSortItem *ptrs; long len; long i; @@ -9987,7 +9971,7 @@ static void f_uniq(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // "reltimefloat()" function -static void f_reltimefloat(typval_T *argvars , typval_T *rettv, FunPtr fptr) +static void f_reltimefloat(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { proftime_T tm; @@ -10062,10 +10046,12 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_append_string(rettv->vval.v_list, word, len); tv_list_append_string(rettv->vval.v_list, (attr == HLF_SPB ? "bad" - : attr == HLF_SPR ? "rare" - : attr == HLF_SPL ? "local" - : attr == HLF_SPC ? "caps" - : NULL), -1); + : attr == HLF_SPR ? "rare" + : attr == HLF_SPL ? "local" + : attr == + HLF_SPC ? "caps" + : + NULL), -1); } /* @@ -10122,7 +10108,7 @@ f_spellsuggest_return: static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *save_cpo; + char_u *save_cpo; int match; colnr_T col = 0; bool keepempty = false; @@ -10278,18 +10264,15 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) p = skipwhite(p + 1); } switch (base) { - case 2: { - what |= STR2NR_BIN | STR2NR_FORCE; - break; - } - case 8: { - what |= STR2NR_OCT | STR2NR_OOCT | STR2NR_FORCE; - break; - } - case 16: { - what |= STR2NR_HEX | STR2NR_FORCE; - break; - } + case 2: + what |= STR2NR_BIN | STR2NR_FORCE; + break; + case 8: + what |= STR2NR_OCT | STR2NR_OOCT | STR2NR_FORCE; + break; + case 16: + what |= STR2NR_HEX | STR2NR_FORCE; + break; } vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false); // Text after the number is silently ignored. @@ -10323,7 +10306,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)")); } else { vimconv_T conv; - char_u *enc; + char_u *enc; conv.vc_type = CONV_NONE; enc = enc_locale(); @@ -10799,53 +10782,46 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *p = NULL; switch (TOLOWER_ASC(what[0])) { - case 'b': { - if (TOLOWER_ASC(what[1]) == 'g') { // bg[#] - p = highlight_color(id, what, modec); - } else { // bold - p = highlight_has_attr(id, HL_BOLD, modec); - } - break; - } - case 'f': { // fg[#] or font + case 'b': + if (TOLOWER_ASC(what[1]) == 'g') { // bg[#] p = highlight_color(id, what, modec); - break; - } - case 'i': { - if (TOLOWER_ASC(what[1]) == 'n') { // inverse - p = highlight_has_attr(id, HL_INVERSE, modec); - } else { // italic - p = highlight_has_attr(id, HL_ITALIC, modec); - } - break; - } - case 'n': { // name - p = get_highlight_name_ext(NULL, id - 1, false); - break; + } else { // bold + p = highlight_has_attr(id, HL_BOLD, modec); } - case 'r': { // reverse + break; + case 'f': // fg[#] or font + p = highlight_color(id, what, modec); + break; + case 'i': + if (TOLOWER_ASC(what[1]) == 'n') { // inverse p = highlight_has_attr(id, HL_INVERSE, modec); - break; + } else { // italic + p = highlight_has_attr(id, HL_ITALIC, modec); } - case 's': { - if (TOLOWER_ASC(what[1]) == 'p') { // sp[#] - p = highlight_color(id, what, modec); - } else if (TOLOWER_ASC(what[1]) == 't' - && TOLOWER_ASC(what[2]) == 'r') { // strikethrough - p = highlight_has_attr(id, HL_STRIKETHROUGH, modec); - } else { // standout - p = highlight_has_attr(id, HL_STANDOUT, modec); - } - break; + break; + case 'n': // name + p = get_highlight_name_ext(NULL, id - 1, false); + break; + case 'r': // reverse + p = highlight_has_attr(id, HL_INVERSE, modec); + break; + case 's': + if (TOLOWER_ASC(what[1]) == 'p') { // sp[#] + p = highlight_color(id, what, modec); + } else if (TOLOWER_ASC(what[1]) == 't' + && TOLOWER_ASC(what[2]) == 'r') { // strikethrough + p = highlight_has_attr(id, HL_STRIKETHROUGH, modec); + } else { // standout + p = highlight_has_attr(id, HL_STANDOUT, modec); } - case 'u': { - if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c') { // underline - p = highlight_has_attr(id, HL_UNDERLINE, modec); - } else { // undercurl - p = highlight_has_attr(id, HL_UNDERCURL, modec); - } - break; + break; + case 'u': + if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c') { // underline + p = highlight_has_attr(id, HL_UNDERLINE, modec); + } else { // undercurl + p = highlight_has_attr(id, HL_UNDERCURL, modec); } + break; } rettv->v_type = VAR_STRING; @@ -10955,7 +10931,7 @@ static void f_systemlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - win_T *wp = NULL; + win_T *wp = NULL; if (argvars[0].v_type == VAR_UNKNOWN) { wp = firstwin; @@ -11008,9 +10984,9 @@ static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static int get_winnr(tabpage_T *tp, typval_T *argvar) { - win_T *twin; + win_T *twin; int nr = 1; - win_T *wp; + win_T *wp; twin = (tp == curtab) ? curwin : tp->tp_curwin; if (argvar->v_type != VAR_UNKNOWN) { @@ -11056,7 +11032,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) } } - if (nr > 0) + if (nr > 0) { for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin; wp != twin; wp = wp->w_next) { if (wp == NULL) { @@ -11066,6 +11042,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) } ++nr; } + } return nr; } @@ -11248,8 +11225,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // "test_garbagecollect_now()" function -static void f_test_garbagecollect_now(typval_T *argvars, - typval_T *rettv, FunPtr fptr) +static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr fptr) { // This is dangerous, any Lists and Dicts used internally may be freed // while still in use. @@ -11257,9 +11233,7 @@ static void f_test_garbagecollect_now(typval_T *argvars, } // "test_write_list_log()" function -static void f_test_write_list_log(typval_T *const argvars, - typval_T *const rettv, - FunPtr fptr) +static void f_test_write_list_log(typval_T *const argvars, typval_T *const rettv, FunPtr fptr) { const char *const fname = tv_get_string_chk(&argvars[0]); if (fname == NULL) { @@ -11334,24 +11308,24 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } rettv->vval.v_number = - timer_start(tv_get_number(&argvars[0]), repeat, &callback); + timer_start(tv_get_number(&argvars[0]), repeat, &callback); } // "timer_stop(timerid)" function static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (argvars[0].v_type != VAR_NUMBER) { - EMSG(_(e_number_exp)); - return; - } + if (argvars[0].v_type != VAR_NUMBER) { + EMSG(_(e_number_exp)); + return; + } - timer_T *timer = find_timer_by_nr(tv_get_number(&argvars[0])); - if (timer == NULL) { - return; - } + timer_T *timer = find_timer_by_nr(tv_get_number(&argvars[0])); + if (timer == NULL) { + return; + } - timer_stop(timer); + timer_stop(timer); } static void f_timer_stopall(typval_T *argvars, typval_T *unused, FunPtr fptr) @@ -11552,20 +11526,28 @@ static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr) int n = -1; switch (argvars[0].v_type) { - case VAR_NUMBER: n = VAR_TYPE_NUMBER; break; - case VAR_STRING: n = VAR_TYPE_STRING; break; - case VAR_PARTIAL: - case VAR_FUNC: n = VAR_TYPE_FUNC; break; - case VAR_LIST: n = VAR_TYPE_LIST; break; - case VAR_DICT: n = VAR_TYPE_DICT; break; - case VAR_FLOAT: n = VAR_TYPE_FLOAT; break; - case VAR_BOOL: n = VAR_TYPE_BOOL; break; - case VAR_SPECIAL: n = VAR_TYPE_SPECIAL; break; - case VAR_BLOB: n = VAR_TYPE_BLOB; break; - case VAR_UNKNOWN: { - internal_error("f_type(UNKNOWN)"); - break; - } + case VAR_NUMBER: + n = VAR_TYPE_NUMBER; break; + case VAR_STRING: + n = VAR_TYPE_STRING; break; + case VAR_PARTIAL: + case VAR_FUNC: + n = VAR_TYPE_FUNC; break; + case VAR_LIST: + n = VAR_TYPE_LIST; break; + case VAR_DICT: + n = VAR_TYPE_DICT; break; + case VAR_FLOAT: + n = VAR_TYPE_FLOAT; break; + case VAR_BOOL: + n = VAR_TYPE_BOOL; break; + case VAR_SPECIAL: + n = VAR_TYPE_SPECIAL; break; + case VAR_BLOB: + n = VAR_TYPE_BLOB; break; + case VAR_UNKNOWN: + internal_error("f_type(UNKNOWN)"); + break; } rettv->vval.v_number = n; } @@ -11625,7 +11607,7 @@ static void f_values(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr) { colnr_T vcol = 0; - pos_T *fp; + pos_T *fp; int fnum = curbuf->b_fnum; fp = var2fpos(&argvars[0], FALSE, &fnum); @@ -11876,10 +11858,12 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) win_new_width(curwin, curwin->w_width); changed_window_setting(); - if (curwin->w_topline <= 0) + if (curwin->w_topline <= 0) { curwin->w_topline = 1; - if (curwin->w_topline > curbuf->b_ml.ml_line_count) + } + if (curwin->w_topline > curbuf->b_ml.ml_line_count) { curwin->w_topline = curbuf->b_ml.ml_line_count; + } check_topfill(curwin, true); } } @@ -11889,7 +11873,7 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - dict_T *dict; + dict_T *dict; tv_dict_alloc_ret(rettv); dict = rettv->vval.v_dict; @@ -11962,15 +11946,18 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) } for (const char *p = flags; *p; p++) { switch (*p) { - case 'b': { binary = true; break; } - case 'a': { append = true; break; } - case 's': { do_fsync = true; break; } - case 'S': { do_fsync = false; break; } - default: { - // Using %s, p and not %c, *p to preserve multibyte characters - emsgf(_("E5060: Unknown flag: %s"), p); - return; - } + case 'b': + binary = true; break; + case 'a': + append = true; break; + case 's': + do_fsync = true; break; + case 'S': + do_fsync = false; break; + default: + // Using %s, p and not %c, *p to preserve multibyte characters + emsgf(_("E5060: Unknown flag: %s"), p); + return; } } } diff --git a/src/nvim/eval/gc.c b/src/nvim/eval/gc.c index 2bbf78d827..633e6abacf 100644 --- a/src/nvim/eval/gc.c +++ b/src/nvim/eval/gc.c @@ -1,8 +1,8 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include "nvim/eval/typval.h" #include "nvim/eval/gc.h" +#include "nvim/eval/typval.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/gc.c.generated.h" diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 381d70ea1b..3bc4ec9381 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1,36 +1,36 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include <stdio.h> +#include <assert.h> +#include <stdbool.h> #include <stddef.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <assert.h> -#include <stdbool.h> -#include "nvim/lib/queue.h" -#include "nvim/eval/typval.h" -#include "nvim/eval/gc.h" -#include "nvim/eval/executor.h" +#include "nvim/ascii.h" +#include "nvim/assert.h" +#include "nvim/charset.h" +#include "nvim/eval.h" #include "nvim/eval/encode.h" +#include "nvim/eval/executor.h" +#include "nvim/eval/gc.h" +#include "nvim/eval/typval.h" #include "nvim/eval/typval_encode.h" -#include "nvim/eval.h" #include "nvim/eval/userfunc.h" -#include "nvim/lua/executor.h" -#include "nvim/types.h" -#include "nvim/assert.h" -#include "nvim/memory.h" -#include "nvim/globals.h" -#include "nvim/hashtab.h" -#include "nvim/vim.h" -#include "nvim/ascii.h" -#include "nvim/pos.h" -#include "nvim/charset.h" #include "nvim/garray.h" #include "nvim/gettext.h" +#include "nvim/globals.h" +#include "nvim/hashtab.h" +#include "nvim/lib/queue.h" +#include "nvim/lua/executor.h" #include "nvim/macros.h" #include "nvim/mbyte.h" +#include "nvim/memory.h" #include "nvim/message.h" +#include "nvim/pos.h" +#include "nvim/types.h" +#include "nvim/vim.h" // TODO(ZyX-I): Move line_breakcheck out of misc1 #include "nvim/misc1.h" // For line_breakcheck #include "nvim/os/fileio.h" @@ -71,11 +71,11 @@ void list_write_log(const char *const fname) char buf[10 + 1 + ((16 + 3) * 3) + (8 + 2) + 2]; // act : hex " c:" len "[]" "\n\0" const ListLogEntry entry = chunk->entries[i]; - const size_t snp_len = (size_t)snprintf( - buf, sizeof(buf), - "%-10.10s: l:%016" PRIxPTR "[%08d] 1:%016" PRIxPTR " 2:%016" PRIxPTR - "\n", - entry.action, entry.l, entry.len, entry.li1, entry.li2); + const size_t snp_len = (size_t)snprintf(buf, sizeof(buf), + "%-10.10s: l:%016" PRIxPTR "[%08d] 1:%016" PRIxPTR " 2:%016" PRIxPTR + "\n", + entry.action, entry.l, entry.len, entry.li1, + entry.li2); assert(snp_len + 1 == sizeof(buf)); const ptrdiff_t fw_ret = file_write(&fp, buf, snp_len); if (fw_ret != (ptrdiff_t)snp_len) { @@ -343,8 +343,7 @@ void tv_list_unref(list_T *const l) /// @param[out] l List to remove from. /// @param[in] item First item to remove. /// @param[in] item2 Last item to remove. -void tv_list_drop_items(list_T *const l, listitem_T *const item, - listitem_T *const item2) +void tv_list_drop_items(list_T *const l, listitem_T *const item, listitem_T *const item2) FUNC_ATTR_NONNULL_ALL { list_log(l, item, item2, "drop"); @@ -369,8 +368,7 @@ void tv_list_drop_items(list_T *const l, listitem_T *const item, } /// Like tv_list_drop_items, but also frees all removed items -void tv_list_remove_items(list_T *const l, listitem_T *const item, - listitem_T *const item2) +void tv_list_remove_items(list_T *const l, listitem_T *const item, listitem_T *const item2) FUNC_ATTR_NONNULL_ALL { list_log(l, item, item2, "remove"); @@ -393,9 +391,8 @@ void tv_list_remove_items(list_T *const l, listitem_T *const item, /// @param[in] item2 Last item to move. /// @param[out] tgt_l List to move to. /// @param[in] cnt Number of items moved. -void tv_list_move_items(list_T *const l, listitem_T *const item, - listitem_T *const item2, list_T *const tgt_l, - const int cnt) +void tv_list_move_items(list_T *const l, listitem_T *const item, listitem_T *const item2, + list_T *const tgt_l, const int cnt) FUNC_ATTR_NONNULL_ALL { list_log(l, item, item2, "move"); @@ -418,8 +415,7 @@ void tv_list_move_items(list_T *const l, listitem_T *const item, /// @param[in,out] ni Item to insert. /// @param[in] item Item to insert before. If NULL, inserts at the end of the /// list. -void tv_list_insert(list_T *const l, listitem_T *const ni, - listitem_T *const item) +void tv_list_insert(list_T *const l, listitem_T *const ni, listitem_T *const item) FUNC_ATTR_NONNULL_ARG(1, 2) { if (item == NULL) { @@ -449,8 +445,7 @@ void tv_list_insert(list_T *const l, listitem_T *const ni, /// allocated listitem_T and inserted. /// @param[in] item Item to insert before. If NULL, inserts at the end of the /// list. -void tv_list_insert_tv(list_T *const l, typval_T *const tv, - listitem_T *const item) +void tv_list_insert_tv(list_T *const l, typval_T *const tv, listitem_T *const item) { listitem_T *const ni = tv_list_item_alloc(); @@ -544,8 +539,7 @@ void tv_list_append_dict(list_T *const l, dict_T *const dict) /// @param[in] len Length of the appended string. May be -1, in this /// case string is considered to be usual zero-terminated /// string or NULL “empty” string. -void tv_list_append_string(list_T *const l, const char *const str, - const ssize_t len) +void tv_list_append_string(list_T *const l, const char *const str, const ssize_t len) FUNC_ATTR_NONNULL_ARG(1) { tv_list_append_owned_tv(l, (typval_T) { @@ -601,8 +595,8 @@ void tv_list_append_number(list_T *const l, const varnumber_T n) /// /// @return Copied list. May be NULL in case original list is NULL or some /// failure happens. The refcount of the new list is set to 1. -list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig, - const bool deep, const int copyID) +list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig, const bool deep, + const int copyID) FUNC_ATTR_WARN_UNUSED_RESULT { if (orig == NULL) { @@ -697,8 +691,7 @@ int tv_list_flatten(list_T *list, long maxdepth) /// @param[out] l1 List to extend. /// @param[in] l2 List to extend with. /// @param[in] bef If not NULL, extends before this item. -void tv_list_extend(list_T *const l1, list_T *const l2, - listitem_T *const bef) +void tv_list_extend(list_T *const l1, list_T *const l2, listitem_T *const bef) FUNC_ATTR_NONNULL_ARG(1) { int todo = tv_list_len(l2); @@ -758,8 +751,8 @@ typedef struct { /// @param[in] join_gap Garray to keep each list item string. /// /// @return OK in case of success, FAIL otherwise. -static int list_join_inner(garray_T *const gap, list_T *const l, - const char *const sep, garray_T *const join_gap) +static int list_join_inner(garray_T *const gap, list_T *const l, const char *const sep, + garray_T *const join_gap) FUNC_ATTR_NONNULL_ALL { size_t sumlen = 0; @@ -844,8 +837,7 @@ int tv_list_join(garray_T *const gap, list_T *const l, const char *const sep) /// @param[in] recursive True when used recursively. /// /// @return True if lists are equal, false otherwise. -bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic, - const bool recursive) +bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic, const bool recursive) FUNC_ATTR_WARN_UNUSED_RESULT { if (l1 == l2) { @@ -915,8 +907,7 @@ void tv_list_reverse(list_T *const l) /// true list will not be modified. Must be initialized to false /// by the caller. void tv_list_item_sort(list_T *const l, ListSortItem *const ptrs, - const ListSorter item_compare_func, - bool *errp) + const ListSorter item_compare_func, bool *errp) FUNC_ATTR_NONNULL_ARG(3, 4) { const int len = tv_list_len(l); @@ -968,7 +959,7 @@ listitem_T *tv_list_find(list_T *const l, int n) } int idx; - listitem_T *item; + listitem_T *item; // When there is a cached index may start search from there. if (l->lv_idx_item != NULL) { @@ -1127,17 +1118,14 @@ bool tv_callback_equal(const Callback *cb1, const Callback *cb2) return false; } switch (cb1->type) { - case kCallbackFuncref: { - return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0; - } - case kCallbackPartial: { - // FIXME: this is inconsistent with tv_equal but is needed for precision - // maybe change dictwatcheradd to return a watcher id instead? - return cb1->data.partial == cb2->data.partial; - } - case kCallbackNone: { - return true; - } + case kCallbackFuncref: + return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0; + case kCallbackPartial: + // FIXME: this is inconsistent with tv_equal but is needed for precision + // maybe change dictwatcheradd to return a watcher id instead? + return cb1->data.partial == cb2->data.partial; + case kCallbackNone: + return true; } abort(); return false; @@ -1148,18 +1136,15 @@ void callback_free(Callback *callback) FUNC_ATTR_NONNULL_ALL { switch (callback->type) { - case kCallbackFuncref: { - func_unref(callback->data.funcref); - xfree(callback->data.funcref); - break; - } - case kCallbackPartial: { - partial_unref(callback->data.partial); - break; - } - case kCallbackNone: { - break; - } + case kCallbackFuncref: + func_unref(callback->data.funcref); + xfree(callback->data.funcref); + break; + case kCallbackPartial: + partial_unref(callback->data.partial); + break; + case kCallbackNone: + break; } callback->type = kCallbackNone; callback->data.funcref = NULL; @@ -1170,20 +1155,20 @@ void callback_put(Callback *cb, typval_T *tv) FUNC_ATTR_NONNULL_ALL { switch (cb->type) { - case kCallbackPartial: - tv->v_type = VAR_PARTIAL; - tv->vval.v_partial = cb->data.partial; - cb->data.partial->pt_refcount++; - break; - case kCallbackFuncref: - tv->v_type = VAR_FUNC; - tv->vval.v_string = vim_strsave(cb->data.funcref); - func_ref(cb->data.funcref); - break; - default: - tv->v_type = VAR_SPECIAL; - tv->vval.v_special = kSpecialVarNull; - break; + case kCallbackPartial: + tv->v_type = VAR_PARTIAL; + tv->vval.v_partial = cb->data.partial; + cb->data.partial->pt_refcount++; + break; + case kCallbackFuncref: + tv->v_type = VAR_FUNC; + tv->vval.v_string = vim_strsave(cb->data.funcref); + func_ref(cb->data.funcref); + break; + default: + tv->v_type = VAR_SPECIAL; + tv->vval.v_special = kSpecialVarNull; + break; } } @@ -1193,17 +1178,17 @@ void callback_copy(Callback *dest, Callback *src) { dest->type = src->type; switch (src->type) { - case kCallbackPartial: - dest->data.partial = src->data.partial; - dest->data.partial->pt_refcount++; - break; - case kCallbackFuncref: - dest->data.funcref = vim_strsave(src->data.funcref); - func_ref(src->data.funcref); - break; - default: - dest->data.funcref = NULL; - break; + case kCallbackPartial: + dest->data.partial = src->data.partial; + dest->data.partial->pt_refcount++; + break; + case kCallbackFuncref: + dest->data.funcref = vim_strsave(src->data.funcref); + func_ref(src->data.funcref); + break; + default: + dest->data.funcref = NULL; + break; } } @@ -1216,8 +1201,7 @@ void callback_copy(Callback *dest, Callback *src) /// /// @return True on success, false if relevant watcher was not found. bool tv_dict_watcher_remove(dict_T *const dict, const char *const key_pattern, - const size_t key_pattern_len, - Callback callback) + const size_t key_pattern_len, Callback callback) FUNC_ATTR_NONNULL_ARG(2) { if (dict == NULL) { @@ -1280,8 +1264,8 @@ static bool tv_dict_watcher_matches(DictWatcher *watcher, const char *const key) /// @param[in] key Key which was modified. /// @param[in] newtv New key value. /// @param[in] oldtv Old key value. -void tv_dict_watcher_notify(dict_T *const dict, const char *const key, - typval_T *const newtv, typval_T *const oldtv) +void tv_dict_watcher_notify(dict_T *const dict, const char *const key, typval_T *const newtv, + typval_T *const oldtv) FUNC_ATTR_NONNULL_ARG(1, 2) { typval_T argv[3]; @@ -1540,8 +1524,7 @@ void tv_dict_unref(dict_T *const d) /// @param[in] len Key length. If negative, then strlen(key) is used. /// /// @return found item or NULL if nothing was found. -dictitem_T *tv_dict_find(const dict_T *const d, const char *const key, - const ptrdiff_t len) +dictitem_T *tv_dict_find(const dict_T *const d, const char *const key, const ptrdiff_t len) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (d == NULL) { @@ -1628,8 +1611,7 @@ char **tv_dict_to_env(dict_T *denv) /// @return NULL if key does not exist, empty string in case of type error, /// string item value otherwise. If returned value is not NULL, it may /// be allocated depending on `save` argument. -char *tv_dict_get_string(const dict_T *const d, const char *const key, - const bool save) +char *tv_dict_get_string(const dict_T *const d, const char *const key, const bool save) FUNC_ATTR_WARN_UNUSED_RESULT { static char numbuf[NUMBUFLEN]; @@ -1649,8 +1631,7 @@ char *tv_dict_get_string(const dict_T *const d, const char *const key, /// /// @return NULL if key does not exist, empty string in case of type error, /// string item value otherwise. -const char *tv_dict_get_string_buf(const dict_T *const d, const char *const key, - char *const numbuf) +const char *tv_dict_get_string_buf(const dict_T *const d, const char *const key, char *const numbuf) FUNC_ATTR_WARN_UNUSED_RESULT { const dictitem_T *const di = tv_dict_find(d, key, -1); @@ -1672,10 +1653,8 @@ const char *tv_dict_get_string_buf(const dict_T *const d, const char *const key, /// @return `def` when key does not exist, /// NULL in case of type error, /// string item value in case of success. -const char *tv_dict_get_string_buf_chk(const dict_T *const d, - const char *const key, - const ptrdiff_t key_len, - char *const numbuf, +const char *tv_dict_get_string_buf_chk(const dict_T *const d, const char *const key, + const ptrdiff_t key_len, char *const numbuf, const char *const def) FUNC_ATTR_WARN_UNUSED_RESULT { @@ -1695,8 +1674,7 @@ const char *tv_dict_get_string_buf_chk(const dict_T *const d, /// will be left. /// /// @return true/false on success/failure. -bool tv_dict_get_callback(dict_T *const d, - const char *const key, const ptrdiff_t key_len, +bool tv_dict_get_callback(dict_T *const d, const char *const key, const ptrdiff_t key_len, Callback *const result) FUNC_ATTR_NONNULL_ARG(2, 4) FUNC_ATTR_WARN_UNUSED_RESULT { @@ -1743,8 +1721,8 @@ int tv_dict_add(dict_T *const d, dictitem_T *const item) /// @param list List to add. Will have reference count incremented. /// /// @return OK in case of success, FAIL when key already exists. -int tv_dict_add_list(dict_T *const d, const char *const key, - const size_t key_len, list_T *const list) +int tv_dict_add_list(dict_T *const d, const char *const key, const size_t key_len, + list_T *const list) FUNC_ATTR_NONNULL_ALL { dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); @@ -1766,15 +1744,14 @@ int tv_dict_add_list(dict_T *const d, const char *const key, /// @param[in] key_len Key length. /// /// @return FAIL if out of memory or key already exists. -int tv_dict_add_tv(dict_T *d, const char *key, const size_t key_len, - typval_T *tv) +int tv_dict_add_tv(dict_T *d, const char *key, const size_t key_len, typval_T *tv) { dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); tv_copy(tv, &item->di_tv); if (tv_dict_add(d, item) == FAIL) { - tv_dict_item_free(item); - return FAIL; + tv_dict_item_free(item); + return FAIL; } return OK; } @@ -1787,8 +1764,8 @@ int tv_dict_add_tv(dict_T *d, const char *key, const size_t key_len, /// @param dict Dictionary to add. Will have reference count incremented. /// /// @return OK in case of success, FAIL when key already exists. -int tv_dict_add_dict(dict_T *const d, const char *const key, - const size_t key_len, dict_T *const dict) +int tv_dict_add_dict(dict_T *const d, const char *const key, const size_t key_len, + dict_T *const dict) FUNC_ATTR_NONNULL_ALL { dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); @@ -1811,8 +1788,8 @@ int tv_dict_add_dict(dict_T *const d, const char *const key, /// @param[in] nr Number to add. /// /// @return OK in case of success, FAIL when key already exists. -int tv_dict_add_nr(dict_T *const d, const char *const key, - const size_t key_len, const varnumber_T nr) +int tv_dict_add_nr(dict_T *const d, const char *const key, const size_t key_len, + const varnumber_T nr) { dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); @@ -1833,8 +1810,8 @@ int tv_dict_add_nr(dict_T *const d, const char *const key, /// @param[in] nr Floating point number to add. /// /// @return OK in case of success, FAIL when key already exists. -int tv_dict_add_float(dict_T *const d, const char *const key, - const size_t key_len, const float_T nr) +int tv_dict_add_float(dict_T *const d, const char *const key, const size_t key_len, + const float_T nr) { dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); @@ -1855,8 +1832,7 @@ int tv_dict_add_float(dict_T *const d, const char *const key, /// @param[in] val BoolVarValue to add. /// /// @return OK in case of success, FAIL when key already exists. -int tv_dict_add_bool(dict_T *const d, const char *const key, - const size_t key_len, BoolVarValue val) +int tv_dict_add_bool(dict_T *const d, const char *const key, const size_t key_len, BoolVarValue val) { dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); @@ -1872,8 +1848,7 @@ int tv_dict_add_bool(dict_T *const d, const char *const key, /// Add a string entry to dictionary /// /// @see tv_dict_add_allocated_str -int tv_dict_add_str(dict_T *const d, - const char *const key, const size_t key_len, +int tv_dict_add_str(dict_T *const d, const char *const key, const size_t key_len, const char *const val) FUNC_ATTR_NONNULL_ARG(1, 2) { @@ -1889,8 +1864,7 @@ int tv_dict_add_str(dict_T *const d, /// @param[in] len Use this many bytes from `val`, or -1 for whole string. /// /// @return OK in case of success, FAIL when key already exists. -int tv_dict_add_str_len(dict_T *const d, - const char *const key, const size_t key_len, +int tv_dict_add_str_len(dict_T *const d, const char *const key, const size_t key_len, const char *const val, int len) FUNC_ATTR_NONNULL_ARG(1, 2) { @@ -1914,8 +1888,7 @@ int tv_dict_add_str_len(dict_T *const d, /// @param[in] val String to add. /// /// @return OK in case of success, FAIL when key already exists. -int tv_dict_add_allocated_str(dict_T *const d, - const char *const key, const size_t key_len, +int tv_dict_add_allocated_str(dict_T *const d, const char *const key, const size_t key_len, char *const val) FUNC_ATTR_NONNULL_ARG(1, 2) { @@ -1958,8 +1931,7 @@ void tv_dict_clear(dict_T *const d) /// e*, including "error": duplicate key gives an error. /// f*, including "force": duplicate d2 keys override d1. /// other, including "keep": duplicate d2 keys ignored. -void tv_dict_extend(dict_T *const d1, dict_T *const d2, - const char *const action) +void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action) FUNC_ATTR_NONNULL_ALL { const bool watched = tv_dict_is_watched(d1); @@ -2021,8 +1993,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, /// @param[in] d2 Second dictionary. /// @param[in] ic True if case is to be ignored. /// @param[in] recursive True when used recursively. -bool tv_dict_equal(dict_T *const d1, dict_T *const d2, - const bool ic, const bool recursive) +bool tv_dict_equal(dict_T *const d1, dict_T *const d2, const bool ic, const bool recursive) FUNC_ATTR_WARN_UNUSED_RESULT { if (d1 == d2) { @@ -2057,9 +2028,7 @@ bool tv_dict_equal(dict_T *const d1, dict_T *const d2, /// @return Copied dictionary. May be NULL in case original dictionary is NULL /// or some failure happens. The refcount of the new dictionary is set /// to 1. -dict_T *tv_dict_copy(const vimconv_T *const conv, - dict_T *const orig, - const bool deep, +dict_T *tv_dict_copy(const vimconv_T *const conv, dict_T *const orig, const bool deep, const int copyID) { if (orig == NULL) { @@ -2271,7 +2240,7 @@ void tv_blob_copy(typval_T *const from, typval_T *const to) if (len > 0) { to->vval.v_blob->bv_ga.ga_data - = xmemdup(from->vval.v_blob->bv_ga.ga_data, (size_t)len); + = xmemdup(from->vval.v_blob->bv_ga.ga_data, (size_t)len); } to->vval.v_blob->bv_ga.ga_len = len; to->vval.v_blob->bv_ga.ga_maxlen = len; @@ -2282,52 +2251,51 @@ void tv_blob_copy(typval_T *const from, typval_T *const to) #define TYPVAL_ENCODE_ALLOW_SPECIALS false #define TYPVAL_ENCODE_CONV_NIL(tv) \ - do { \ - tv->vval.v_special = kSpecialVarNull; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) + do { \ + tv->vval.v_special = kSpecialVarNull; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - do { \ - tv->vval.v_bool = kBoolVarFalse; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) + do { \ + tv->vval.v_bool = kBoolVarFalse; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) #define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ - do { \ - (void)num; \ - tv->vval.v_number = 0; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) + do { \ + (void)num; \ + tv->vval.v_number = 0; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - do { \ - tv->vval.v_float = 0; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) + do { \ + tv->vval.v_float = 0; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ - do { \ - xfree(buf); \ - tv->vval.v_string = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) + do { \ + xfree(buf); \ + tv->vval.v_string = NULL; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) #define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) #define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ - do { \ - tv_blob_unref(tv->vval.v_blob); \ - tv->vval.v_blob = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -static inline int _nothing_conv_func_start(typval_T *const tv, - char_u *const fun) + do { \ + tv_blob_unref(tv->vval.v_blob); \ + tv->vval.v_blob = NULL; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +static inline int _nothing_conv_func_start(typval_T *const tv, char_u *const fun) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1) { tv->v_lock = VAR_UNLOCKED; @@ -2348,11 +2316,11 @@ static inline int _nothing_conv_func_start(typval_T *const tv, return NOTDONE; } #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ - do { \ - if (_nothing_conv_func_start(tv, fun) != NOTDONE) { \ - return OK; \ - } \ - } while (0) + do { \ + if (_nothing_conv_func_start(tv, fun) != NOTDONE) { \ + return OK; \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) @@ -2380,14 +2348,13 @@ static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID) #define TYPVAL_ENCODE_CONV_FUNC_END(tv) _nothing_conv_func_end(tv, copyID) #define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ - do { \ - tv_list_unref(tv->vval.v_list); \ - tv->vval.v_list = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -static inline void _nothing_conv_empty_dict(typval_T *const tv, - dict_T **const dictp) + do { \ + tv_list_unref(tv->vval.v_list); \ + tv->vval.v_list = NULL; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +static inline void _nothing_conv_empty_dict(typval_T *const tv, dict_T **const dictp) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(2) { tv_dict_unref(*dictp); @@ -2397,13 +2364,13 @@ static inline void _nothing_conv_empty_dict(typval_T *const tv, } } #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ - do { \ - assert((void *)&dict != (void *)&TYPVAL_ENCODE_NODICT_VAR); \ - _nothing_conv_empty_dict(tv, ((dict_T **)&dict)); \ - } while (0) + do { \ + assert((void *)&dict != (void *)&TYPVAL_ENCODE_NODICT_VAR); \ + _nothing_conv_empty_dict(tv, ((dict_T **)&dict)); \ + } while (0) -static inline int _nothing_conv_real_list_after_start( - typval_T *const tv, MPConvStackVal *const mpsv) +static inline int _nothing_conv_real_list_after_start(typval_T *const tv, + MPConvStackVal *const mpsv) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT { assert(tv != NULL); @@ -2419,11 +2386,11 @@ static inline int _nothing_conv_real_list_after_start( #define TYPVAL_ENCODE_CONV_LIST_START(tv, len) #define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \ - do { \ - if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \ - goto typval_encode_stop_converting_one_item; \ - } \ - } while (0) + do { \ + if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \ + goto typval_encode_stop_converting_one_item; \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) @@ -2440,9 +2407,9 @@ static inline void _nothing_conv_list_end(typval_T *const tv) } #define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv) -static inline int _nothing_conv_real_dict_after_start( - typval_T *const tv, dict_T **const dictp, const void *const nodictvar, - MPConvStackVal *const mpsv) +static inline int _nothing_conv_real_dict_after_start(typval_T *const tv, dict_T **const dictp, + const void *const nodictvar, + MPConvStackVal *const mpsv) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT { if (tv != NULL) { @@ -2459,20 +2426,18 @@ static inline int _nothing_conv_real_dict_after_start( #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) #define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \ - do { \ - if (_nothing_conv_real_dict_after_start( \ - tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \ - &mpsv) != NOTDONE) { \ - goto typval_encode_stop_converting_one_item; \ - } \ - } while (0) + do { \ + if (_nothing_conv_real_dict_after_start(tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \ + &mpsv) != NOTDONE) { \ + goto typval_encode_stop_converting_one_item; \ + } \ + } while (0) #define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(tv, dict) #define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) #define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) -static inline void _nothing_conv_dict_end(typval_T *const tv, - dict_T **const dictp, +static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dictp, const void *const nodictvar) FUNC_ATTR_ALWAYS_INLINE { @@ -2482,8 +2447,8 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, } } #define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ - _nothing_conv_dict_end(tv, (dict_T **)&dict, \ - (void *)&TYPVAL_ENCODE_NODICT_VAR) + _nothing_conv_dict_end(tv, (dict_T **)&dict, \ + (void *)&TYPVAL_ENCODE_NODICT_VAR) #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) @@ -2554,37 +2519,30 @@ void tv_free(typval_T *tv) { if (tv != NULL) { switch (tv->v_type) { - case VAR_PARTIAL: { - partial_unref(tv->vval.v_partial); - break; - } - case VAR_FUNC: { - func_unref(tv->vval.v_string); - FALLTHROUGH; - } - case VAR_STRING: { - xfree(tv->vval.v_string); - break; - } - case VAR_BLOB: { - tv_blob_unref(tv->vval.v_blob); - break; - } - case VAR_LIST: { - tv_list_unref(tv->vval.v_list); - break; - } - case VAR_DICT: { - tv_dict_unref(tv->vval.v_dict); - break; - } - case VAR_BOOL: - case VAR_SPECIAL: - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_UNKNOWN: { - break; - } + case VAR_PARTIAL: + partial_unref(tv->vval.v_partial); + break; + case VAR_FUNC: + func_unref(tv->vval.v_string); + FALLTHROUGH; + case VAR_STRING: + xfree(tv->vval.v_string); + break; + case VAR_BLOB: + tv_blob_unref(tv->vval.v_blob); + break; + case VAR_LIST: + tv_list_unref(tv->vval.v_list); + break; + case VAR_DICT: + tv_dict_unref(tv->vval.v_dict); + break; + case VAR_BOOL: + case VAR_SPECIAL: + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_UNKNOWN: + break; } xfree(tv); } @@ -2608,48 +2566,41 @@ void tv_copy(const typval_T *const from, typval_T *const to) to->v_lock = VAR_UNLOCKED; memmove(&to->vval, &from->vval, sizeof(to->vval)); switch (from->v_type) { - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_BOOL: - case VAR_SPECIAL: { - break; - } - case VAR_STRING: - case VAR_FUNC: { - if (from->vval.v_string != NULL) { - to->vval.v_string = vim_strsave(from->vval.v_string); - if (from->v_type == VAR_FUNC) { - func_ref(to->vval.v_string); - } + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_BOOL: + case VAR_SPECIAL: + break; + case VAR_STRING: + case VAR_FUNC: + if (from->vval.v_string != NULL) { + to->vval.v_string = vim_strsave(from->vval.v_string); + if (from->v_type == VAR_FUNC) { + func_ref(to->vval.v_string); } - break; } - case VAR_PARTIAL: { - if (to->vval.v_partial != NULL) { - to->vval.v_partial->pt_refcount++; - } - break; + break; + case VAR_PARTIAL: + if (to->vval.v_partial != NULL) { + to->vval.v_partial->pt_refcount++; } - case VAR_BLOB: { - if (from->vval.v_blob != NULL) { - to->vval.v_blob->bv_refcount++; - } - break; + break; + case VAR_BLOB: + if (from->vval.v_blob != NULL) { + to->vval.v_blob->bv_refcount++; } - case VAR_LIST: { - tv_list_ref(to->vval.v_list); - break; - } - case VAR_DICT: { - if (from->vval.v_dict != NULL) { - to->vval.v_dict->dv_refcount++; - } - break; - } - case VAR_UNKNOWN: { - emsgf(_(e_intern2), "tv_copy(UNKNOWN)"); - break; + break; + case VAR_LIST: + tv_list_ref(to->vval.v_list); + break; + case VAR_DICT: + if (from->vval.v_dict != NULL) { + to->vval.v_dict->dv_refcount++; } + break; + case VAR_UNKNOWN: + emsgf(_(e_intern2), "tv_copy(UNKNOWN)"); + break; } } @@ -2662,8 +2613,7 @@ void tv_copy(const typval_T *const from, typval_T *const to) /// @param[in] lock True if it is needed to lock an item, false to unlock. /// @param[in] check_refcount If true, do not lock a list or dict with a /// reference count larger than 1. -void tv_item_lock(typval_T *const tv, const int deep, const bool lock, - const bool check_refcount) +void tv_item_lock(typval_T *const tv, const int deep, const bool lock, const bool check_refcount) FUNC_ATTR_NONNULL_ALL { // TODO(ZyX-I): Make this not recursive @@ -2690,51 +2640,49 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock, CHANGE_LOCK(lock, tv->v_lock); switch (tv->v_type) { - case VAR_BLOB: { - blob_T *const b = tv->vval.v_blob; - if (b != NULL && !(check_refcount && b->bv_refcount > 1)) { - CHANGE_LOCK(lock, b->bv_lock); - } - break; - } - case VAR_LIST: { - list_T *const l = tv->vval.v_list; - if (l != NULL && !(check_refcount && l->lv_refcount > 1)) { - CHANGE_LOCK(lock, l->lv_lock); - if (deep < 0 || deep > 1) { - // Recursive: lock/unlock the items the List contains. - TV_LIST_ITER(l, li, { + case VAR_BLOB: { + blob_T *const b = tv->vval.v_blob; + if (b != NULL && !(check_refcount && b->bv_refcount > 1)) { + CHANGE_LOCK(lock, b->bv_lock); + } + break; + } + case VAR_LIST: { + list_T *const l = tv->vval.v_list; + if (l != NULL && !(check_refcount && l->lv_refcount > 1)) { + CHANGE_LOCK(lock, l->lv_lock); + if (deep < 0 || deep > 1) { + // Recursive: lock/unlock the items the List contains. + TV_LIST_ITER(l, li, { tv_item_lock(TV_LIST_ITEM_TV(li), deep - 1, lock, check_refcount); }); - } } - break; } - case VAR_DICT: { - dict_T *const d = tv->vval.v_dict; - if (d != NULL && !(check_refcount && d->dv_refcount > 1)) { - CHANGE_LOCK(lock, d->dv_lock); - if (deep < 0 || deep > 1) { - // recursive: lock/unlock the items the List contains - TV_DICT_ITER(d, di, { + break; + } + case VAR_DICT: { + dict_T *const d = tv->vval.v_dict; + if (d != NULL && !(check_refcount && d->dv_refcount > 1)) { + CHANGE_LOCK(lock, d->dv_lock); + if (deep < 0 || deep > 1) { + // recursive: lock/unlock the items the List contains + TV_DICT_ITER(d, di, { tv_item_lock(&di->di_tv, deep - 1, lock, check_refcount); }); - } } - break; - } - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_STRING: - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_BOOL: - case VAR_SPECIAL: { - break; - } - case VAR_UNKNOWN: { - abort(); } + break; + } + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_STRING: + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_BOOL: + case VAR_SPECIAL: + break; + case VAR_UNKNOWN: + abort(); } #undef CHANGE_LOCK recurse--; @@ -2776,33 +2724,32 @@ bool tv_islocked(const typval_T *const tv) /// gettext. /// /// @return true if variable is locked, false otherwise. -bool tv_check_lock(const typval_T *tv, const char *name, - size_t name_len) +bool tv_check_lock(const typval_T *tv, const char *name, size_t name_len) FUNC_ATTR_WARN_UNUSED_RESULT { VarLockStatus lock = VAR_UNLOCKED; switch (tv->v_type) { - case VAR_BLOB: - if (tv->vval.v_blob != NULL) { - lock = tv->vval.v_blob->bv_lock; - } - break; - case VAR_LIST: - if (tv->vval.v_list != NULL) { - lock = tv->vval.v_list->lv_lock; - } - break; - case VAR_DICT: - if (tv->vval.v_dict != NULL) { - lock = tv->vval.v_dict->dv_lock; - } - break; - default: - break; + case VAR_BLOB: + if (tv->vval.v_blob != NULL) { + lock = tv->vval.v_blob->bv_lock; + } + break; + case VAR_LIST: + if (tv->vval.v_list != NULL) { + lock = tv->vval.v_list->lv_lock; + } + break; + case VAR_DICT: + if (tv->vval.v_dict != NULL) { + lock = tv->vval.v_dict->dv_lock; + } + break; + default: + break; } return var_check_lock(tv->v_lock, name, name_len) - || (lock != VAR_UNLOCKED && var_check_lock(lock, name, name_len)); + || (lock != VAR_UNLOCKED && var_check_lock(lock, name, name_len)); } /// @return true if variable "name" is locked (immutable) @@ -2810,17 +2757,14 @@ bool var_check_lock(VarLockStatus lock, const char *name, size_t name_len) { const char *error_message = NULL; switch (lock) { - case VAR_UNLOCKED: { - return false; - } - case VAR_LOCKED: { - error_message = N_("E741: Value is locked: %.*s"); - break; - } - case VAR_FIXED: { - error_message = N_("E742: Cannot change value of %.*s"); - break; - } + case VAR_UNLOCKED: + return false; + case VAR_LOCKED: + error_message = N_("E741: Value is locked: %.*s"); + break; + case VAR_FIXED: + error_message = N_("E742: Cannot change value of %.*s"); + break; } assert(error_message != NULL); @@ -2856,8 +2800,7 @@ static int tv_equal_recurse_limit; /// @param[in] recursive True when used recursively. /// /// @return true if values are equal. -bool tv_equal(typval_T *const tv1, typval_T *const tv2, const bool ic, - const bool recursive) +bool tv_equal(typval_T *const tv1, typval_T *const tv2, const bool ic, const bool recursive) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { // TODO(ZyX-I): Make this not recursive @@ -2882,58 +2825,52 @@ bool tv_equal(typval_T *const tv1, typval_T *const tv2, const bool ic, } switch (tv1->v_type) { - case VAR_LIST: { - recursive_cnt++; - const bool r = tv_list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, - true); - recursive_cnt--; - return r; - } - case VAR_DICT: { - recursive_cnt++; - const bool r = tv_dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, - true); - recursive_cnt--; - return r; - } - case VAR_PARTIAL: - case VAR_FUNC: { - if ((tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial == NULL) - || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial == NULL)) { - return false; - } - recursive_cnt++; - const bool r = func_equal(tv1, tv2, ic); - recursive_cnt--; - return r; - } - case VAR_BLOB: { - return tv_blob_equal(tv1->vval.v_blob, tv2->vval.v_blob); - } - case VAR_NUMBER: { - return tv1->vval.v_number == tv2->vval.v_number; - } - case VAR_FLOAT: { - return tv1->vval.v_float == tv2->vval.v_float; - } - case VAR_STRING: { - char buf1[NUMBUFLEN]; - char buf2[NUMBUFLEN]; - const char *s1 = tv_get_string_buf(tv1, buf1); - const char *s2 = tv_get_string_buf(tv2, buf2); - return mb_strcmp_ic((bool)ic, s1, s2) == 0; - } - case VAR_BOOL: { - return tv1->vval.v_bool == tv2->vval.v_bool; - } - case VAR_SPECIAL: { - return tv1->vval.v_special == tv2->vval.v_special; - } - case VAR_UNKNOWN: { - // VAR_UNKNOWN can be the result of an invalid expression, let’s say it - // does not equal anything, not even self. + case VAR_LIST: { + recursive_cnt++; + const bool r = tv_list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, + true); + recursive_cnt--; + return r; + } + case VAR_DICT: { + recursive_cnt++; + const bool r = tv_dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, + true); + recursive_cnt--; + return r; + } + case VAR_PARTIAL: + case VAR_FUNC: { + if ((tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial == NULL) + || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial == NULL)) { return false; } + recursive_cnt++; + const bool r = func_equal(tv1, tv2, ic); + recursive_cnt--; + return r; + } + case VAR_BLOB: + return tv_blob_equal(tv1->vval.v_blob, tv2->vval.v_blob); + case VAR_NUMBER: + return tv1->vval.v_number == tv2->vval.v_number; + case VAR_FLOAT: + return tv1->vval.v_float == tv2->vval.v_float; + case VAR_STRING: { + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *s1 = tv_get_string_buf(tv1, buf1); + const char *s2 = tv_get_string_buf(tv2, buf2); + return mb_strcmp_ic((bool)ic, s1, s2) == 0; + } + case VAR_BOOL: + return tv1->vval.v_bool == tv2->vval.v_bool; + case VAR_SPECIAL: + return tv1->vval.v_special == tv2->vval.v_special; + case VAR_UNKNOWN: + // VAR_UNKNOWN can be the result of an invalid expression, let’s say it + // does not equal anything, not even self. + return false; } abort(); @@ -2955,43 +2892,34 @@ bool tv_check_str_or_nr(const typval_T *const tv) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { switch (tv->v_type) { - case VAR_NUMBER: - case VAR_STRING: { - return true; - } - case VAR_FLOAT: { - EMSG(_("E805: Expected a Number or a String, Float found")); - return false; - } - case VAR_PARTIAL: - case VAR_FUNC: { - EMSG(_("E703: Expected a Number or a String, Funcref found")); - return false; - } - case VAR_LIST: { - EMSG(_("E745: Expected a Number or a String, List found")); - return false; - } - case VAR_DICT: { - EMSG(_("E728: Expected a Number or a String, Dictionary found")); - return false; - } - case VAR_BLOB: { - EMSG(_("E974: Expected a Number or a String, Blob found")); - return false; - } - case VAR_BOOL: { - EMSG(_("E5299: Expected a Number or a String, Boolean found")); - return false; - } - case VAR_SPECIAL: { - EMSG(_("E5300: Expected a Number or a String")); - return false; - } - case VAR_UNKNOWN: { - EMSG2(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)"); - return false; - } + case VAR_NUMBER: + case VAR_STRING: + return true; + case VAR_FLOAT: + EMSG(_("E805: Expected a Number or a String, Float found")); + return false; + case VAR_PARTIAL: + case VAR_FUNC: + EMSG(_("E703: Expected a Number or a String, Funcref found")); + return false; + case VAR_LIST: + EMSG(_("E745: Expected a Number or a String, List found")); + return false; + case VAR_DICT: + EMSG(_("E728: Expected a Number or a String, Dictionary found")); + return false; + case VAR_BLOB: + EMSG(_("E974: Expected a Number or a String, Blob found")); + return false; + case VAR_BOOL: + EMSG(_("E5299: Expected a Number or a String, Boolean found")); + return false; + case VAR_SPECIAL: + EMSG(_("E5300: Expected a Number or a String")); + return false; + case VAR_UNKNOWN: + EMSG2(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)"); + return false; } abort(); return false; @@ -3023,22 +2951,20 @@ bool tv_check_num(const typval_T *const tv) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { switch (tv->v_type) { - case VAR_NUMBER: - case VAR_BOOL: - case VAR_SPECIAL: - case VAR_STRING: { - return true; - } - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_LIST: - case VAR_DICT: - case VAR_FLOAT: - case VAR_BLOB: - case VAR_UNKNOWN: { - EMSG(_(num_errors[tv->v_type])); - return false; - } + case VAR_NUMBER: + case VAR_BOOL: + case VAR_SPECIAL: + case VAR_STRING: + return true; + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_BLOB: + case VAR_UNKNOWN: + EMSG(_(num_errors[tv->v_type])); + return false; } abort(); return false; @@ -3070,22 +2996,20 @@ bool tv_check_str(const typval_T *const tv) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { switch (tv->v_type) { - case VAR_NUMBER: - case VAR_BOOL: - case VAR_SPECIAL: - case VAR_STRING: { - return true; - } - case VAR_PARTIAL: - case VAR_FUNC: - case VAR_LIST: - case VAR_DICT: - case VAR_FLOAT: - case VAR_BLOB: - case VAR_UNKNOWN: { - EMSG(_(str_errors[tv->v_type])); - return false; - } + case VAR_NUMBER: + case VAR_BOOL: + case VAR_SPECIAL: + case VAR_STRING: + return true; + case VAR_PARTIAL: + case VAR_FUNC: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_BLOB: + case VAR_UNKNOWN: + EMSG(_(str_errors[tv->v_type])); + return false; } abort(); return false; @@ -3125,36 +3049,31 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1) { switch (tv->v_type) { - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_LIST: - case VAR_DICT: - case VAR_BLOB: - case VAR_FLOAT: { - EMSG(_(num_errors[tv->v_type])); - break; - } - case VAR_NUMBER: { - return tv->vval.v_number; - } - case VAR_STRING: { - varnumber_T n = 0; - if (tv->vval.v_string != NULL) { - vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, - false); - } - return n; - } - case VAR_BOOL: { - return tv->vval.v_bool == kBoolVarTrue ? 1 : 0; - } - case VAR_SPECIAL: { - return 0; - } - case VAR_UNKNOWN: { - emsgf(_(e_intern2), "tv_get_number(UNKNOWN)"); - break; - } + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_LIST: + case VAR_DICT: + case VAR_BLOB: + case VAR_FLOAT: + EMSG(_(num_errors[tv->v_type])); + break; + case VAR_NUMBER: + return tv->vval.v_number; + case VAR_STRING: { + varnumber_T n = 0; + if (tv->vval.v_string != NULL) { + vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, + false); + } + return n; + } + case VAR_BOOL: + return tv->vval.v_bool == kBoolVarTrue ? 1 : 0; + case VAR_SPECIAL: + return 0; + case VAR_UNKNOWN: + emsgf(_(e_intern2), "tv_get_number(UNKNOWN)"); + break; } if (ret_error != NULL) { *ret_error = true; @@ -3194,45 +3113,35 @@ float_T tv_get_float(const typval_T *const tv) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { switch (tv->v_type) { - case VAR_NUMBER: { - return (float_T)(tv->vval.v_number); - } - case VAR_FLOAT: { - return tv->vval.v_float; - } - case VAR_PARTIAL: - case VAR_FUNC: { - EMSG(_("E891: Using a Funcref as a Float")); - break; - } - case VAR_STRING: { - EMSG(_("E892: Using a String as a Float")); - break; - } - case VAR_LIST: { - EMSG(_("E893: Using a List as a Float")); - break; - } - case VAR_DICT: { - EMSG(_("E894: Using a Dictionary as a Float")); - break; - } - case VAR_BOOL: { - EMSG(_("E362: Using a boolean value as a Float")); - break; - } - case VAR_SPECIAL: { - EMSG(_("E907: Using a special value as a Float")); - break; - } - case VAR_BLOB: { - EMSG(_("E975: Using a Blob as a Float")); - break; - } - case VAR_UNKNOWN: { - emsgf(_(e_intern2), "tv_get_float(UNKNOWN)"); - break; - } + case VAR_NUMBER: + return (float_T)(tv->vval.v_number); + case VAR_FLOAT: + return tv->vval.v_float; + case VAR_PARTIAL: + case VAR_FUNC: + EMSG(_("E891: Using a Funcref as a Float")); + break; + case VAR_STRING: + EMSG(_("E892: Using a String as a Float")); + break; + case VAR_LIST: + EMSG(_("E893: Using a List as a Float")); + break; + case VAR_DICT: + EMSG(_("E894: Using a Dictionary as a Float")); + break; + case VAR_BOOL: + EMSG(_("E362: Using a boolean value as a Float")); + break; + case VAR_SPECIAL: + EMSG(_("E907: Using a special value as a Float")); + break; + case VAR_BLOB: + EMSG(_("E975: Using a Blob as a Float")); + break; + case VAR_UNKNOWN: + emsgf(_(e_intern2), "tv_get_float(UNKNOWN)"); + break; } return 0; } @@ -3265,34 +3174,29 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { switch (tv->v_type) { - case VAR_NUMBER: { - snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number); // -V576 - return buf; - } - case VAR_STRING: { - if (tv->vval.v_string != NULL) { - return (const char *)tv->vval.v_string; - } - return ""; - } - case VAR_BOOL: { - STRCPY(buf, encode_bool_var_names[tv->vval.v_bool]); - return buf; - } - case VAR_SPECIAL: { - STRCPY(buf, encode_special_var_names[tv->vval.v_special]); - return buf; - } - case VAR_PARTIAL: - case VAR_FUNC: - case VAR_LIST: - case VAR_DICT: - case VAR_FLOAT: - case VAR_BLOB: - case VAR_UNKNOWN: { - EMSG(_(str_errors[tv->v_type])); - return false; - } + case VAR_NUMBER: + snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number); // -V576 + return buf; + case VAR_STRING: + if (tv->vval.v_string != NULL) { + return (const char *)tv->vval.v_string; + } + return ""; + case VAR_BOOL: + STRCPY(buf, encode_bool_var_names[tv->vval.v_bool]); + return buf; + case VAR_SPECIAL: + STRCPY(buf, encode_special_var_names[tv->vval.v_special]); + return buf; + case VAR_PARTIAL: + case VAR_FUNC: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_BLOB: + case VAR_UNKNOWN: + EMSG(_(str_errors[tv->v_type])); + return false; } return NULL; } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 350c5ee1c2..2137804fdd 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -13,7 +13,6 @@ #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" -#include "nvim/ex_getln.h" #include "nvim/fileio.h" #include "nvim/getchar.h" #include "nvim/globals.h" @@ -55,24 +54,23 @@ static funccall_T *current_funccal = NULL; // item in it is still being used. static funccall_T *previous_funccal = NULL; -static char *e_funcexts = N_( - "E122: Function %s already exists, add ! to replace it"); +static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); static char *e_funcdict = N_("E717: Dictionary entry already exists"); static char *e_funcref = N_("E718: Funcref required"); static char *e_nofunc = N_("E130: Unknown function: %s"); void func_init(void) { - hash_init(&func_hashtab); + hash_init(&func_hashtab); } /// Get function arguments. -static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, - int *varargs, garray_T *default_args, bool skip) +static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, int *varargs, + garray_T *default_args, bool skip) { bool mustend = false; - char_u *arg = *argp; - char_u *p = arg; + char_u *arg = *argp; + char_u *p = arg; int c; int i; @@ -146,7 +144,7 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, *p = NUL; expr = vim_strsave(expr); ((char_u **)(default_args->ga_data)) - [default_args->ga_len] = expr; + [default_args->ga_len] = expr; default_args->ga_len++; *p = c; } else { @@ -200,18 +198,18 @@ static void register_closure(ufunc_T *fp) current_funccal->fc_refcount++; ga_grow(¤t_funccal->fc_funcs, 1); ((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. char_u * get_lambda_name(void) { - static char_u name[30]; - static int lambda_no = 0; + static char_u name[30]; + static int lambda_no = 0; - snprintf((char *)name, sizeof(name), "<lambda>%d", ++lambda_no); - return name; + snprintf((char *)name, sizeof(name), "<lambda>%d", ++lambda_no); + return name; } /// 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) { garray_T newargs = GA_EMPTY_INIT_VALUE; - garray_T *pnewargs; - ufunc_T *fp = NULL; + garray_T *pnewargs; + ufunc_T *fp = NULL; partial_T *pt = NULL; int varargs; int ret; - char_u *start = skipwhite(*arg + 1); - char_u *s, *e; - bool *old_eval_lavars = eval_lavars_used; + char_u *start = skipwhite(*arg + 1); + char_u *s, *e; + bool *old_eval_lavars = eval_lavars_used; bool eval_lavars = false; // First, check if this is a lambda expression. "->" must exists. @@ -348,8 +346,7 @@ errret: /// was not found. /// /// @return name of the function. -char_u *deref_func_name(const char *name, int *lenp, - partial_T **const partialp, bool no_autoload) +char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp, bool no_autoload) FUNC_ATTR_NONNULL_ARG(1, 2) { 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. * Return OK or FAIL. */ -int -get_func_tv( - const char_u *name, // name of the function - int len, // length of "name" or -1 to use strlen() - typval_T *rettv, - char_u **arg, // argument, pointing to the '(' - funcexe_T *funcexe // various values -) -{ - char_u *argp; +int get_func_tv(const char_u *name, // name of the function + int len, // length of "name" or -1 to use strlen() + typval_T *rettv, char_u **arg, // argument, pointing to the '(' + funcexe_T *funcexe // various values + ) +{ + char_u *argp; int ret = OK; - typval_T argvars[MAX_FUNC_ARGS + 1]; /* vars for arguments */ - int argcount = 0; /* number of arguments found */ + typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments + int argcount = 0; // number of arguments found /* * Get the arguments. @@ -438,13 +432,15 @@ get_func_tv( break; } ++argcount; - if (*argp != ',') + if (*argp != ',') { break; + } } - if (*argp == ')') + if (*argp == ')') { ++argp; - else + } else { ret = FAIL; + } if (ret == OK) { 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 /// memory. -static char_u *fname_trans_sid(const char_u *const name, - char_u *const fname_buf, +static char_u *fname_trans_sid(const char_u *const name, char_u *const fname_buf, char_u **const tofree, int *const error) 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. ufunc_T *find_func(const char_u *name) { - hashitem_T *hi; + hashitem_T *hi; hi = hash_find(&func_hashtab, name); - if (!HASHITEM_EMPTY(hi)) + if (!HASHITEM_EMPTY(hi)) { return HI2UF(hi); + } return NULL; } @@ -571,8 +567,9 @@ static void cat_func_name(char_u *buf, ufunc_T *fp) if (fp->uf_name[0] == K_SPECIAL) { STRCPY(buf, "<SNR>"); STRCAT(buf, fp->uf_name + 3); - } else + } else { 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) == DO_NOT_FREE_CNT) { fc->l_varlist.lv_first = NULL; // NOLINT(runtime/deprecated) - } else { 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] lastline Last line of range. /// @param selfdict Dictionary for "self" for dictionary functions. -void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, - typval_T *rettv, linenr_T firstline, linenr_T lastline, - dict_T *selfdict) +void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, + linenr_T firstline, linenr_T lastline, dict_T *selfdict) FUNC_ATTR_NONNULL_ARG(1, 3, 4) { - char_u *save_sourcing_name; + char_u *save_sourcing_name; linenr_T save_sourcing_lnum; bool using_sandbox = false; - funccall_T *fc; + funccall_T *fc; int save_did_emsg; static int depth = 0; - dictitem_T *v; + dictitem_T *v; int fixvar_idx = 0; // index in fixvar[] int ai; bool islambda = false; char_u numbuf[NUMBUFLEN]; - char_u *name; + char_u *name; typval_T *tv_to_free[MAX_FUNC_ARGS]; int tv_to_free_len = 0; 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; 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) { default_arg_err = true; 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 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_children); + fp->uf_tm_children); if (fc->caller != NULL && fc->caller->func->uf_profiling) { fc->caller->func->uf_tm_children = 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; verbose_enter_scroll(); - if (aborting()) + if (aborting()) { 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 ""), sourcing_name, (int64_t)fc->rettv->vval.v_number); - else { + } else { char_u buf[MSG_BUF_LEN]; // The value may be very long. Skip the middle part, so that we // have some idea how it starts and ends. smsg() would always // truncate it at the end. Don't want errors such as E724 here. 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; emsg_off--; if (s != NULL) { @@ -1269,8 +1264,8 @@ void set_current_funccal(funccall_T *fc) #if defined(EXITFREE) void free_all_functions(void) { - hashitem_T *hi; - ufunc_T *fp; + hashitem_T *hi; + ufunc_T *fp; uint64_t skipped = 0; uint64_t todo = 1; uint64_t used; @@ -1357,8 +1352,7 @@ static bool builtin_function(const char *name, int len) return p == NULL; } -int func_call(char_u *name, typval_T *args, partial_T *partial, - dict_T *selfdict, typval_T *rettv) +int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv) { typval_T argv[MAX_FUNC_ARGS + 1]; int argc = 0; @@ -1397,38 +1391,37 @@ static void user_func_error(int error, const char_u *name) FUNC_ATTR_NONNULL_ALL { switch (error) { - case ERROR_UNKNOWN: - emsg_funcname(N_("E117: Unknown function: %s"), name); - break; - case ERROR_NOTMETHOD: - emsg_funcname(N_("E276: Cannot use function as a method: %s"), name); - break; - case ERROR_DELETED: - emsg_funcname(N_("E933: Function was deleted: %s"), name); - break; - case ERROR_TOOMANY: - emsg_funcname(_(e_toomanyarg), name); - break; - case ERROR_TOOFEW: - emsg_funcname(N_("E119: Not enough arguments for function: %s"), - name); - break; - case ERROR_SCRIPT: - emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), - name); - break; - case ERROR_DICT: - emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), - name); - break; + case ERROR_UNKNOWN: + emsg_funcname(N_("E117: Unknown function: %s"), name); + break; + case ERROR_NOTMETHOD: + emsg_funcname(N_("E276: Cannot use function as a method: %s"), name); + break; + case ERROR_DELETED: + emsg_funcname(N_("E933: Function was deleted: %s"), name); + break; + case ERROR_TOOMANY: + emsg_funcname(_(e_toomanyarg), name); + break; + case ERROR_TOOFEW: + emsg_funcname(N_("E119: Not enough arguments for function: %s"), + name); + break; + case ERROR_SCRIPT: + emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), + name); + break; + case ERROR_DICT: + emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), + name); + break; } } /// Used by call_func to add a method base (if any) to a function argument list /// as the first argument. @see call_func -static void argv_add_base(typval_T *const basetv, typval_T **const argvars, - int *const argcount, typval_T *const new_argvars, - int *const argv_base) +static void argv_add_base(typval_T *const basetv, typval_T **const argvars, int *const argcount, + typval_T *const new_argvars, int *const argv_base) FUNC_ATTR_NONNULL_ARG(2, 3, 4, 5) { 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 /// occurred while executing the function! Set `msg_list` to capture /// the error, see do_cmdline()). -int -call_func( - const char_u *funcname, // name of the function - int len, // length of "name" or -1 to use strlen() - typval_T *rettv, // [out] value goes here - int argcount_in, // number of "argvars" - typval_T *argvars_in, // vars for arguments, must have "argcount" - // PLUS ONE elements! - funcexe_T *funcexe // more arguments -) +int call_func(const char_u *funcname, // name of the function + int len, // length of "name" or -1 to use strlen() + typval_T *rettv, // [out] value goes here + int argcount_in, // number of "argvars" + typval_T *argvars_in, // vars for arguments, must have "argcount" + // PLUS ONE elements! + funcexe_T *funcexe // more arguments + ) FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6) { int ret = FAIL; @@ -1612,8 +1603,9 @@ call_func( */ update_force_abort(); } - if (error == ERROR_NONE) + if (error == ERROR_NONE) { ret = OK; + } theend: // 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) { msg_start(); - if (indent) + if (indent) { MSG_PUTS(" "); + } MSG_PUTS(force ? "function! " : "function "); if (fp->uf_name[0] == K_SPECIAL) { 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). /// /// @return the function name in allocated memory, or NULL for failure. -char_u * -trans_function_name( - char_u **pp, - 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 -) +char_u *trans_function_name(char_u **pp, 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) { - char_u *name = NULL; + char_u *name = NULL; const char_u *start; const char_u *end; int lead; int len; lval_T lv; - if (fdp != NULL) + if (fdp != NULL) { memset(fdp, 0, sizeof(funcdict_T)); + } start = *pp; /* 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, lead > 2 ? 0 : FNE_CHECK_START); if (end == start) { - if (!skip) + if (!skip) { EMSG(_("E129: Function name required")); + } goto theend; } if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range))) { @@ -1806,7 +1797,7 @@ trans_function_name( 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) { len = (int)strlen(lv.ll_exp_name); name = deref_func_name(lv.ll_exp_name, &len, partial, @@ -1915,31 +1906,31 @@ theend: */ void ex_function(exarg_T *eap) { - char_u *theline; - char_u *line_to_free = NULL; + char_u *theline; + char_u *line_to_free = NULL; int c; int saved_did_emsg; bool saved_wait_return = need_wait_return; - char_u *name = NULL; - char_u *p; - char_u *arg; - char_u *line_arg = NULL; + char_u *name = NULL; + char_u *p; + char_u *arg; + char_u *line_arg = NULL; garray_T newargs; garray_T default_args; garray_T newlines; int varargs = false; int flags = 0; - ufunc_T *fp; + ufunc_T *fp; bool overwrite = false; int indent; int nesting; - dictitem_T *v; + dictitem_T *v; funcdict_T fudi; static int func_nr = 0; // number for nameless function int paren; - hashtab_T *ht; + hashtab_T *ht; int todo; - hashitem_T *hi; + hashitem_T *hi; linenr_T sourcing_lnum_off; linenr_T sourcing_lnum_top; bool is_heredoc = false; @@ -1992,15 +1983,17 @@ void ex_function(exarg_T *eap) --todo; fp = HI2UF(hi); if (!isdigit(*fp->uf_name) - && vim_regexec(®match, fp->uf_name, 0)) + && vim_regexec(®match, fp->uf_name, 0)) { list_func_head(fp, false, false); + } } } vim_regfree(regmatch.regprog); } } - if (*p == '/') + if (*p == '/') { ++p; + } eap->nextcmd = check_nextcmd(p); return; } @@ -2034,8 +2027,9 @@ void ex_function(exarg_T *eap) } xfree(fudi.fd_newkey); return; - } else + } else { eap->skip = TRUE; + } } /* 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; } eap->nextcmd = check_nextcmd(p); - if (eap->nextcmd != NULL) + if (eap->nextcmd != NULL) { *p = NUL; + } if (!eap->skip && !got_int) { fp = find_func(name); if (fp != NULL) { @@ -2083,8 +2078,9 @@ void ex_function(exarg_T *eap) msg_putchar('\n'); msg_puts(eap->forceit ? "endfunction" : " endfunction"); } - } else + } else { emsg_funcname(N_("E123: Undefined function: %s"), name); + } } goto ret_free; } @@ -2111,17 +2107,20 @@ void ex_function(exarg_T *eap) if (!eap->skip) { /* Check the name of the function. Unless it's a dictionary function * (that we are overwriting). */ - if (name != NULL) + if (name != NULL) { arg = name; - else + } else { arg = fudi.fd_newkey; + } if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) { int j = (*arg == K_SPECIAL) ? 3 : 0; while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j]) - : eval_isnamec(arg[j]))) + : eval_isnamec(arg[j]))) { ++j; - if (arg[j] != NUL) + } + if (arg[j] != NUL) { emsg_funcname((char *)e_invarg2, arg); + } } // Disallow using the g: dict. 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; if (current_funccal == NULL) { 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); 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 * need to skip the body to be able to find what follows. */ 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)); - else if (name != NULL && find_func(name) != NULL) + } else if (name != NULL && find_func(name) != NULL) { emsg_funcname(e_funcexts, name); + } } - if (!eap->skip && did_emsg) + if (!eap->skip && did_emsg) { goto erret; + } if (!ui_has(kUICmdline)) { 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. theline = line_arg; p = vim_strchr(theline, '\n'); - if (p == NULL) + if (p == NULL) { line_arg += STRLEN(line_arg); - else { + } else { *p = NUL; line_arg = p + 1; } @@ -2242,7 +2243,7 @@ void ex_function(exarg_T *eap) // Detect line continuation: sourcing_lnum increased more than one. sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie); if (sourcing_lnum < sourcing_lnum_off) { - sourcing_lnum_off -= sourcing_lnum; + sourcing_lnum_off -= sourcing_lnum; } else { sourcing_lnum_off = 0; } @@ -2306,13 +2307,14 @@ void ex_function(exarg_T *eap) /* Increase indent inside "if", "while", "for" and "try", decrease * at "end". */ - if (indent > 2 && STRNCMP(p, "end", 3) == 0) + if (indent > 2 && STRNCMP(p, "end", 3) == 0) { indent -= 2; - else if (STRNCMP(p, "if", 2) == 0 - || STRNCMP(p, "wh", 2) == 0 - || STRNCMP(p, "for", 3) == 0 - || STRNCMP(p, "try", 3) == 0) + } else if (STRNCMP(p, "if", 2) == 0 + || STRNCMP(p, "wh", 2) == 0 + || STRNCMP(p, "for", 3) == 0 + || STRNCMP(p, "try", 3) == 0) { indent += 2; + } // Check for defining a function inside this function. if (checkforcmd(&p, "function", 2)) { @@ -2362,10 +2364,11 @@ void ex_function(exarg_T *eap) && (!ASCII_ISALPHA(p[2]) || p[2] == 's')))) { // ":python <<" continues until a dot, like ":append" p = skipwhite(arg + 2); - if (*p == NUL) + if (*p == NUL) { skip_until = vim_strsave((char_u *)"."); - else + } else { skip_until = vim_strsave(p); + } } // 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 * 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; + } // Check for end of eap->arg. 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 * detected. */ - if (eap->skip || did_emsg) + if (eap->skip || did_emsg) { goto erret; + } /* * 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); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { emsg_funcname(N_("E707: Function name conflicts with variable: %s"), - name); + name); goto erret; } @@ -2445,7 +2450,7 @@ void ex_function(exarg_T *eap) } if (fp->uf_calls > 0) { emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"), - name); + name); goto erret; } if (fp->uf_refcount > 1) { @@ -2493,7 +2498,7 @@ void ex_function(exarg_T *eap) if (fp == NULL) { if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) { int slen, plen; - char_u *scriptname; + char_u *scriptname; // Check that the autoload name matches the script name. int j = FAIL; @@ -2503,14 +2508,14 @@ void ex_function(exarg_T *eap) plen = (int)STRLEN(p); slen = (int)STRLEN(sourcing_name); if (slen > plen && fnamecmp(p, - sourcing_name + slen - plen) == 0) + sourcing_name + slen - plen) == 0) { j = OK; + } xfree(scriptname); } if (j == FAIL) { - EMSG2(_( - "E746: Function name does not match script file name: %s"), - name); + EMSG2(_("E746: Function name does not match script file name: %s"), + name); 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) { static size_t done; - static hashitem_T *hi; - ufunc_T *fp; + static hashitem_T *hi; + ufunc_T *fp; if (idx == 0) { done = 0; @@ -2660,10 +2665,12 @@ char_u *get_user_func_name(expand_T *xp, int idx) } assert(hi); if (done < func_hashtab.ht_used) { - if (done++ > 0) + if (done++ > 0) { ++hi; - while (HASHITEM_EMPTY(hi)) + } + while (HASHITEM_EMPTY(hi)) { ++hi; + } fp = HI2UF(hi); 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); if (xp->xp_context != EXPAND_USER_FUNC) { STRCAT(IObuff, "("); - if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) + if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) { STRCAT(IObuff, ")"); + } } return IObuff; } @@ -2689,17 +2697,18 @@ char_u *get_user_func_name(expand_T *xp, int idx) /// ":delfunction {name}" void ex_delfunction(exarg_T *eap) { - ufunc_T *fp = NULL; - char_u *p; - char_u *name; + ufunc_T *fp = NULL; + char_u *p; + char_u *name; funcdict_T fudi; p = eap->arg; name = trans_function_name(&p, eap->skip, 0, &fudi, NULL); xfree(fudi.fd_newkey); if (name == NULL) { - if (fudi.fd_dict != NULL && !eap->skip) + if (fudi.fd_dict != NULL && !eap->skip) { EMSG(_(e_funcref)); + } return; } if (!ends_excmd(*skipwhite(p))) { @@ -2708,11 +2717,13 @@ void ex_delfunction(exarg_T *eap) return; } eap->nextcmd = check_nextcmd(p); - if (eap->nextcmd != NULL) + if (eap->nextcmd != NULL) { *p = NUL; + } - if (!eap->skip) + if (!eap->skip) { fp = find_func(name); + } xfree(name); if (!eap->skip) { @@ -2730,7 +2741,7 @@ void ex_delfunction(exarg_T *eap) // the reference count, and 1 is the initial refcount. if (fp->uf_refcount > 2) { EMSG2(_("Cannot delete function %s: It is being used internally"), - eap->arg); + eap->arg); return; } @@ -2778,8 +2789,8 @@ void func_unref(char_u *name) abort(); } #else - internal_error("func_unref()"); - abort(); + internal_error("func_unref()"); + abort(); #endif } func_ptr_unref(fp); @@ -2860,7 +2871,7 @@ static int can_free_funccal(funccall_T *fc, int copyID) */ void ex_return(exarg_T *eap) { - char_u *arg = eap->arg; + char_u *arg = eap->arg; typval_T rettv; int returning = FALSE; @@ -2869,8 +2880,9 @@ void ex_return(exarg_T *eap) return; } - if (eap->skip) + if (eap->skip) { ++emsg_skip; + } eap->nextcmd = NULL; if ((*arg != NUL && *arg != '|' && *arg != '\n') @@ -2900,21 +2912,22 @@ void ex_return(exarg_T *eap) eap->nextcmd = check_nextcmd(arg); } - if (eap->skip) + if (eap->skip) { --emsg_skip; + } } // 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) { - char_u *arg = eap->arg; - char_u *startarg; - char_u *name; - char_u *tofree; + char_u *arg = eap->arg; + char_u *startarg; + char_u *name; + char_u *tofree; int len; typval_T rettv; linenr_T lnum; @@ -3063,12 +3076,12 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) if (idx >= 0) { cstack->cs_pending[idx] = CSTP_RETURN; - if (!is_cmd && !reanimate) + if (!is_cmd && !reanimate) { /* A pending return again gets pending. "rettv" points to an * allocated variable with the rettv of the original ":return"'s * argument if present or is NULL else. */ cstack->cs_rettv[idx] = rettv; - else { + } else { /* When undoing a return in order to make it pending, get the stored * return rettv. */ 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. cstack->cs_rettv[idx] = xcalloc(1, sizeof(typval_T)); *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv; - } else + } else { cstack->cs_rettv[idx] = NULL; + } if (reanimate) { /* 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) { tv_clear(current_funccal->rettv); *current_funccal->rettv = *(typval_T *)rettv; - if (!is_cmd) + if (!is_cmd) { xfree(rettv); + } } } @@ -3119,7 +3134,7 @@ char_u *get_return_cmd(void *rettv) char_u *tofree = 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) { s = (char_u *)""; @@ -3127,8 +3142,9 @@ char_u *get_return_cmd(void *rettv) STRCPY(IObuff, ":return "); STRLCPY(IObuff + 8, s, IOSIZE - 8); - if (STRLEN(s) + 8 >= IOSIZE) + if (STRLEN(s) + 8 >= IOSIZE) { STRCPY(IObuff + IOSIZE - 4, "..."); + } xfree(tofree); 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) { - funccall_T *fcp = (funccall_T *)cookie; - ufunc_T *fp = fcp->func; - char_u *retval; - garray_T *gap; // growarray with function lines + funccall_T *fcp = (funccall_T *)cookie; + ufunc_T *fp = fcp->func; + char_u *retval; + garray_T *gap; // growarray with function lines // If breakpoints have been added/deleted need to check for it. if (fcp->dbg_tick != debug_tick) { fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, - sourcing_lnum); + sourcing_lnum); fcp->dbg_tick = debug_tick; } - if (do_profiling == PROF_YES) + if (do_profiling == PROF_YES) { func_line_end(cookie); + } gap = &fp->uf_lines; 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 { retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]); sourcing_lnum = fcp->linenr; - if (do_profiling == PROF_YES) + if (do_profiling == PROF_YES) { 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) { - 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 * 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. -dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, - int no_autoload) +dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, int no_autoload) { if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) { return NULL; @@ -3560,7 +3577,7 @@ bool set_ref_in_func_args(int copyID) for (int i = 0; i < funcargs.ga_len; i++) { if (set_ref_in_item(((typval_T **)funcargs.ga_data)[i], copyID, NULL, NULL)) { - return true; + return true; } } return false; diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c index 967d656dc5..c2aa923c49 100644 --- a/src/nvim/viml/parser/expressions.c +++ b/src/nvim/viml/parser/expressions.c @@ -50,20 +50,19 @@ // 7. 'isident' no longer applies to environment variables, they always include // ASCII alphanumeric characters and underscore and nothing except this. +#include <assert.h> #include <stdbool.h> #include <stddef.h> -#include <assert.h> #include <string.h> -#include "nvim/vim.h" -#include "nvim/memory.h" -#include "nvim/types.h" -#include "nvim/charset.h" #include "nvim/ascii.h" #include "nvim/assert.h" -#include "nvim/lib/kvec.h" +#include "nvim/charset.h" #include "nvim/eval/typval.h" - +#include "nvim/lib/kvec.h" +#include "nvim/memory.h" +#include "nvim/types.h" +#include "nvim/vim.h" #include "nvim/viml/parser/expressions.h" #include "nvim/viml/parser/parser.h" @@ -143,10 +142,8 @@ typedef enum { /// numbers are not supported. /// @param[in] exponent Exponent to scale by. /// @param[in] exponent_negative True if exponent is negative. -static inline float_T scale_number(const float_T num, - const uint8_t base, - const uvarnumber_T exponent, - const bool exponent_negative) +static inline float_T scale_number(const float_T num, const uint8_t base, + const uvarnumber_T exponent, const bool exponent_negative) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST { if (num == 0 || exponent == 0) { @@ -200,7 +197,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) if (ret.len < pline.size \ && strchr("?#", pline.data[ret.len]) != NULL) { \ ret.data.cmp.ccs = \ - (ExprCaseCompareStrategy)pline.data[ret.len]; \ + (ExprCaseCompareStrategy)pline.data[ret.len]; \ ret.len++; \ } else { \ ret.data.cmp.ccs = kCCStrategyUseOption; \ @@ -209,12 +206,12 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) switch (schar) { // Paired brackets. #define BRACKET(typ, opning, clsing) \ - case opning: \ - case clsing: { \ - ret.type = typ; \ - ret.data.brc.closing = (schar == clsing); \ - break; \ - } +case opning: \ +case clsing: { \ + ret.type = typ; \ + ret.data.brc.closing = (schar == clsing); \ + break; \ +} BRACKET(kExprLexParenthesis, '(', ')') BRACKET(kExprLexBracket, '[', ']') BRACKET(kExprLexFigureBrace, '{', '}') @@ -222,10 +219,10 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) // Single character tokens without data. #define CHAR(typ, ch) \ - case ch: { \ - ret.type = typ; \ - break; \ - } +case ch: { \ + ret.type = typ; \ + break; \ +} CHAR(kExprLexQuestion, '?') CHAR(kExprLexColon, ':') CHAR(kExprLexComma, ',') @@ -233,198 +230,265 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) // Multiplication/division/modulo. #define MUL(mul_type, ch) \ - case ch: { \ - ret.type = kExprLexMultiplication; \ - ret.data.mul.type = mul_type; \ - break; \ - } +case ch: { \ + ret.type = kExprLexMultiplication; \ + ret.data.mul.type = mul_type; \ + break; \ +} MUL(kExprLexMulMul, '*') MUL(kExprLexMulDiv, '/') MUL(kExprLexMulMod, '%') #undef MUL #define CHARREG(typ, cond) \ - do { \ - ret.type = typ; \ - for (; (ret.len < pline.size \ - && cond(pline.data[ret.len])) \ - ; ret.len++) { \ - } \ - } while (0) - - // Whitespace. - case ' ': - case TAB: { - CHARREG(kExprLexSpacing, ascii_iswhite); - break; - } - - // Control character, except for NUL, NL and TAB. - case Ctrl_A: case Ctrl_B: case Ctrl_C: case Ctrl_D: case Ctrl_E: - case Ctrl_F: case Ctrl_G: case Ctrl_H: + do { \ + ret.type = typ; \ + for (; (ret.len < pline.size \ + && cond(pline.data[ret.len])) \ + ; ret.len++) { \ + } \ + } while (0) - case Ctrl_K: case Ctrl_L: case Ctrl_M: case Ctrl_N: case Ctrl_O: - case Ctrl_P: case Ctrl_Q: case Ctrl_R: case Ctrl_S: case Ctrl_T: - case Ctrl_U: case Ctrl_V: case Ctrl_W: case Ctrl_X: case Ctrl_Y: - case Ctrl_Z: { + // Whitespace. + case ' ': + case TAB: + CHARREG(kExprLexSpacing, ascii_iswhite); + break; + + // Control character, except for NUL, NL and TAB. + case Ctrl_A: + case Ctrl_B: + case Ctrl_C: + case Ctrl_D: + case Ctrl_E: + case Ctrl_F: + case Ctrl_G: + case Ctrl_H: + + case Ctrl_K: + case Ctrl_L: + case Ctrl_M: + case Ctrl_N: + case Ctrl_O: + case Ctrl_P: + case Ctrl_Q: + case Ctrl_R: + case Ctrl_S: + case Ctrl_T: + case Ctrl_U: + case Ctrl_V: + case Ctrl_W: + case Ctrl_X: + case Ctrl_Y: + case Ctrl_Z: #define ISCTRL(schar) (schar < ' ') - CHARREG(kExprLexInvalid, ISCTRL); - ret.data.err.type = kExprLexSpacing; - ret.data.err.msg = - _("E15: Invalid control character present in input: %.*s"); - break; + CHARREG(kExprLexInvalid, ISCTRL); + ret.data.err.type = kExprLexSpacing; + ret.data.err.msg = + _("E15: Invalid control character present in input: %.*s"); + break; #undef ISCTRL - } - // Number. - case '0': case '1': case '2': case '3': case '4': case '5': case '6': - case '7': case '8': case '9': { - ret.data.num.is_float = false; - ret.data.num.base = 10; - size_t frac_start = 0; - size_t exp_start = 0; - size_t frac_end = 0; - bool exp_negative = false; - CHARREG(kExprLexNumber, ascii_isdigit); - if (flags & kELFlagAllowFloat) { - const LexExprToken non_float_ret = ret; + // Number. + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + ret.data.num.is_float = false; + ret.data.num.base = 10; + size_t frac_start = 0; + size_t exp_start = 0; + size_t frac_end = 0; + bool exp_negative = false; + CHARREG(kExprLexNumber, ascii_isdigit); + if (flags & kELFlagAllowFloat) { + const LexExprToken non_float_ret = ret; + if (pline.size > ret.len + 1 + && pline.data[ret.len] == '.' + && ascii_isdigit(pline.data[ret.len + 1])) { + ret.len++; + frac_start = ret.len; + frac_end = ret.len; + ret.data.num.is_float = true; + for (; ret.len < pline.size && ascii_isdigit(pline.data[ret.len]) + ; ret.len++) { + // A small optimization: trailing zeroes in fractional part do not + // add anything to significand, so it is useless to include them in + // frac_end. + if (pline.data[ret.len] != '0') { + frac_end = ret.len + 1; + } + } if (pline.size > ret.len + 1 - && pline.data[ret.len] == '.' - && ascii_isdigit(pline.data[ret.len + 1])) { + && (pline.data[ret.len] == 'e' + || pline.data[ret.len] == 'E') + && ((pline.size > ret.len + 2 + && (pline.data[ret.len + 1] == '+' + || pline.data[ret.len + 1] == '-') + && ascii_isdigit(pline.data[ret.len + 2])) + || ascii_isdigit(pline.data[ret.len + 1]))) { ret.len++; - frac_start = ret.len; - frac_end = ret.len; - ret.data.num.is_float = true; - for (; ret.len < pline.size && ascii_isdigit(pline.data[ret.len]) - ; ret.len++) { - // A small optimization: trailing zeroes in fractional part do not - // add anything to significand, so it is useless to include them in - // frac_end. - if (pline.data[ret.len] != '0') { - frac_end = ret.len + 1; - } - } - if (pline.size > ret.len + 1 - && (pline.data[ret.len] == 'e' - || pline.data[ret.len] == 'E') - && ((pline.size > ret.len + 2 - && (pline.data[ret.len + 1] == '+' - || pline.data[ret.len + 1] == '-') - && ascii_isdigit(pline.data[ret.len + 2])) - || ascii_isdigit(pline.data[ret.len + 1]))) { + if (pline.data[ret.len] == '+' + || (exp_negative = (pline.data[ret.len] == '-'))) { ret.len++; - if (pline.data[ret.len] == '+' - || (exp_negative = (pline.data[ret.len] == '-'))) { - ret.len++; - } - exp_start = ret.len; - CHARREG(kExprLexNumber, ascii_isdigit); } - } - if (pline.size > ret.len - && (pline.data[ret.len] == '.' - || ASCII_ISALPHA(pline.data[ret.len]))) { - ret = non_float_ret; + exp_start = ret.len; + CHARREG(kExprLexNumber, ascii_isdigit); } } - // TODO(ZyX-I): detect overflows - if (ret.data.num.is_float) { - // Vim used to use string2float here which in turn uses strtod(). There - // are two problems with this approach: - // 1. strtod() is locale-dependent. Not sure how it is worked around so - // that I do not see relevant bugs, but it still does not look like - // a good idea. - // 2. strtod() does not accept length argument. - // - // The below variant of parsing floats was recognized as acceptable - // because it is basically how uClibc does the thing: it generates - // a number ignoring decimal point (but recording its position), then - // uses recorded position to scale number down when processing exponent. - float_T significand_part = 0; - uvarnumber_T exp_part = 0; - const size_t frac_size = (size_t)(frac_end - frac_start); - for (size_t i = 0; i < frac_end; i++) { - if (i == frac_start - 1) { - continue; - } - significand_part = significand_part * 10 + (pline.data[i] - '0'); - } - if (exp_start) { - vim_str2nr(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part, - (int)(ret.len - exp_start), false); + if (pline.size > ret.len + && (pline.data[ret.len] == '.' + || ASCII_ISALPHA(pline.data[ret.len]))) { + ret = non_float_ret; + } + } + // TODO(ZyX-I): detect overflows + if (ret.data.num.is_float) { + // Vim used to use string2float here which in turn uses strtod(). There + // are two problems with this approach: + // 1. strtod() is locale-dependent. Not sure how it is worked around so + // that I do not see relevant bugs, but it still does not look like + // a good idea. + // 2. strtod() does not accept length argument. + // + // The below variant of parsing floats was recognized as acceptable + // because it is basically how uClibc does the thing: it generates + // a number ignoring decimal point (but recording its position), then + // uses recorded position to scale number down when processing exponent. + float_T significand_part = 0; + uvarnumber_T exp_part = 0; + const size_t frac_size = (size_t)(frac_end - frac_start); + for (size_t i = 0; i < frac_end; i++) { + if (i == frac_start - 1) { + continue; } - if (exp_negative) { - exp_part += frac_size; + significand_part = significand_part * 10 + (pline.data[i] - '0'); + } + if (exp_start) { + vim_str2nr(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part, + (int)(ret.len - exp_start), false); + } + if (exp_negative) { + exp_part += frac_size; + } else { + if (exp_part < frac_size) { + exp_negative = true; + exp_part = frac_size - exp_part; } else { - if (exp_part < frac_size) { - exp_negative = true; - exp_part = frac_size - exp_part; - } else { - exp_part -= frac_size; - } + exp_part -= frac_size; } - ret.data.num.val.floating = scale_number(significand_part, 10, exp_part, - exp_negative); - } else { - int len; - int prep; - vim_str2nr(pline.data, &prep, &len, STR2NR_ALL, NULL, - &ret.data.num.val.integer, (int)pline.size, false); - ret.len = (size_t)len; - const uint8_t bases[] = { - [0] = 10, - ['0'] = 8, - ['x'] = 16, ['X'] = 16, - ['b'] = 2, ['B'] = 2, - }; - ret.data.num.base = bases[prep]; } - break; + ret.data.num.val.floating = scale_number(significand_part, 10, exp_part, + exp_negative); + } else { + int len; + int prep; + vim_str2nr(pline.data, &prep, &len, STR2NR_ALL, NULL, + &ret.data.num.val.integer, (int)pline.size, false); + ret.len = (size_t)len; + const uint8_t bases[] = { + [0] = 10, + ['0'] = 8, + ['x'] = 16, ['X'] = 16, + ['b'] = 2, ['B'] = 2, + }; + ret.data.num.base = bases[prep]; } + break; + } #define ISWORD_OR_AUTOLOAD(x) \ - (ascii_isident(x) || (x) == AUTOLOAD_CHAR) - - // Environment variable. - case '$': { - CHARREG(kExprLexEnv, ascii_isident); - break; - } - - // Normal variable/function name. - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': - case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': - case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': - case 'v': case 'w': case 'x': case 'y': case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': - case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': - case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': - case 'V': case 'W': case 'X': case 'Y': case 'Z': - case '_': { - ret.data.var.scope = 0; - ret.data.var.autoload = false; - CHARREG(kExprLexPlainIdentifier, ascii_isident); - // "is" and "isnot" operators. - if (!(flags & kELFlagIsNotCmp) - && ((ret.len == 2 && memcmp(pline.data, "is", 2) == 0) - || (ret.len == 5 && memcmp(pline.data, "isnot", 5) == 0))) { - ret.type = kExprLexComparison; - ret.data.cmp.type = kExprCmpIdentical; - ret.data.cmp.inv = (ret.len == 5); - GET_CCS(ret, pline); + (ascii_isident(x) || (x) == AUTOLOAD_CHAR) + + // Environment variable. + case '$': + CHARREG(kExprLexEnv, ascii_isident); + break; + + // Normal variable/function name. + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + ret.data.var.scope = 0; + ret.data.var.autoload = false; + CHARREG(kExprLexPlainIdentifier, ascii_isident); + // "is" and "isnot" operators. + if (!(flags & kELFlagIsNotCmp) + && ((ret.len == 2 && memcmp(pline.data, "is", 2) == 0) + || (ret.len == 5 && memcmp(pline.data, "isnot", 5) == 0))) { + ret.type = kExprLexComparison; + ret.data.cmp.type = kExprCmpIdentical; + ret.data.cmp.inv = (ret.len == 5); + GET_CCS(ret, pline); // Scope: `s:`, etc. - } else if (ret.len == 1 - && pline.size > 1 - && memchr(EXPR_VAR_SCOPE_LIST, schar, - sizeof(EXPR_VAR_SCOPE_LIST)) != NULL - && pline.data[ret.len] == ':' - && !(flags & kELFlagForbidScope)) { - ret.len++; - ret.data.var.scope = (ExprVarScope)schar; - CHARREG(kExprLexPlainIdentifier, ISWORD_OR_AUTOLOAD); - ret.data.var.autoload = ( - memchr(pline.data + 2, AUTOLOAD_CHAR, ret.len - 2) - != NULL); + } else if (ret.len == 1 + && pline.size > 1 + && memchr(EXPR_VAR_SCOPE_LIST, schar, + sizeof(EXPR_VAR_SCOPE_LIST)) != NULL + && pline.data[ret.len] == ':' + && !(flags & kELFlagForbidScope)) { + ret.len++; + ret.data.var.scope = (ExprVarScope)schar; + CHARREG(kExprLexPlainIdentifier, ISWORD_OR_AUTOLOAD); + ret.data.var.autoload = ( + memchr(pline.data + 2, AUTOLOAD_CHAR, ret.len - 2) + != NULL); // Previous CHARREG stopped at autoload character in order to make it // possible to detect `is#`. Continue now with autoload characters // included. @@ -432,221 +496,213 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) // Warning: there is ambiguity for the lexer: `is#Foo(1)` is a call of // function `is#Foo()`, `1is#Foo(1)` is a comparison `1 is# Foo(1)`. This // needs to be resolved on the higher level where context is available. - } else if (pline.size > ret.len - && pline.data[ret.len] == AUTOLOAD_CHAR) { - ret.data.var.autoload = true; - CHARREG(kExprLexPlainIdentifier, ISWORD_OR_AUTOLOAD); - } - break; + } else if (pline.size > ret.len + && pline.data[ret.len] == AUTOLOAD_CHAR) { + ret.data.var.autoload = true; + CHARREG(kExprLexPlainIdentifier, ISWORD_OR_AUTOLOAD); } + break; #undef ISWORD_OR_AUTOLOAD #undef CHARREG - // Option. - case '&': { + // Option. + case '&': { #define OPTNAMEMISS(ret) \ - do { \ - ret.type = kExprLexInvalid; \ - ret.data.err.type = kExprLexOption; \ - ret.data.err.msg = _("E112: Option name missing: %.*s"); \ - } while (0) - if (pline.size > 1 && pline.data[1] == '&') { - ret.type = kExprLexAnd; - ret.len++; - break; + do { \ + ret.type = kExprLexInvalid; \ + ret.data.err.type = kExprLexOption; \ + ret.data.err.msg = _("E112: Option name missing: %.*s"); \ + } while (0) + if (pline.size > 1 && pline.data[1] == '&') { + ret.type = kExprLexAnd; + ret.len++; + break; + } + if (pline.size == 1 || !ASCII_ISALPHA(pline.data[1])) { + OPTNAMEMISS(ret); + break; + } + ret.type = kExprLexOption; + if (pline.size > 2 + && pline.data[2] == ':' + && memchr(EXPR_OPT_SCOPE_LIST, pline.data[1], + sizeof(EXPR_OPT_SCOPE_LIST)) != NULL) { + ret.len += 2; + ret.data.opt.scope = (ExprOptScope)pline.data[1]; + ret.data.opt.name = pline.data + 3; + } else { + ret.data.opt.scope = kExprOptScopeUnspecified; + ret.data.opt.name = pline.data + 1; + } + const char *p = ret.data.opt.name; + const char *const e = pline.data + pline.size; + if (e - p >= 4 && p[0] == 't' && p[1] == '_') { + ret.data.opt.len = 4; + ret.len += 4; + } else { + for (; p < e && ASCII_ISALPHA(*p); p++) { } - if (pline.size == 1 || !ASCII_ISALPHA(pline.data[1])) { + ret.data.opt.len = (size_t)(p - ret.data.opt.name); + if (ret.data.opt.len == 0) { OPTNAMEMISS(ret); - break; - } - ret.type = kExprLexOption; - if (pline.size > 2 - && pline.data[2] == ':' - && memchr(EXPR_OPT_SCOPE_LIST, pline.data[1], - sizeof(EXPR_OPT_SCOPE_LIST)) != NULL) { - ret.len += 2; - ret.data.opt.scope = (ExprOptScope)pline.data[1]; - ret.data.opt.name = pline.data + 3; } else { - ret.data.opt.scope = kExprOptScopeUnspecified; - ret.data.opt.name = pline.data + 1; - } - const char *p = ret.data.opt.name; - const char *const e = pline.data + pline.size; - if (e - p >= 4 && p[0] == 't' && p[1] == '_') { - ret.data.opt.len = 4; - ret.len += 4; - } else { - for (; p < e && ASCII_ISALPHA(*p); p++) { - } - ret.data.opt.len = (size_t)(p - ret.data.opt.name); - if (ret.data.opt.len == 0) { - OPTNAMEMISS(ret); - } else { - ret.len += ret.data.opt.len; - } + ret.len += ret.data.opt.len; } - break; -#undef OPTNAMEMISS } + break; +#undef OPTNAMEMISS + } - // Register. - case '@': { - ret.type = kExprLexRegister; - if (pline.size > 1) { - ret.len++; - ret.data.reg.name = (uint8_t)pline.data[1]; - } else { - ret.data.reg.name = -1; - } - break; + // Register. + case '@': + ret.type = kExprLexRegister; + if (pline.size > 1) { + ret.len++; + ret.data.reg.name = (uint8_t)pline.data[1]; + } else { + ret.data.reg.name = -1; } - - // Single quoted string. - case '\'': { - ret.type = kExprLexSingleQuotedString; - ret.data.str.closed = false; - for (; ret.len < pline.size && !ret.data.str.closed; ret.len++) { - if (pline.data[ret.len] == '\'') { - if (ret.len + 1 < pline.size && pline.data[ret.len + 1] == '\'') { - ret.len++; - } else { - ret.data.str.closed = true; - } + break; + + // Single quoted string. + case '\'': + ret.type = kExprLexSingleQuotedString; + ret.data.str.closed = false; + for (; ret.len < pline.size && !ret.data.str.closed; ret.len++) { + if (pline.data[ret.len] == '\'') { + if (ret.len + 1 < pline.size && pline.data[ret.len + 1] == '\'') { + ret.len++; + } else { + ret.data.str.closed = true; } } - break; } - - // Double quoted string. - case '"': { - ret.type = kExprLexDoubleQuotedString; - ret.data.str.closed = false; - for (; ret.len < pline.size && !ret.data.str.closed; ret.len++) { - if (pline.data[ret.len] == '\\') { - if (ret.len + 1 < pline.size) { - ret.len++; - } - } else if (pline.data[ret.len] == '"') { - ret.data.str.closed = true; + break; + + // Double quoted string. + case '"': + ret.type = kExprLexDoubleQuotedString; + ret.data.str.closed = false; + for (; ret.len < pline.size && !ret.data.str.closed; ret.len++) { + if (pline.data[ret.len] == '\\') { + if (ret.len + 1 < pline.size) { + ret.len++; } + } else if (pline.data[ret.len] == '"') { + ret.data.str.closed = true; } - break; } - - // Unary not, (un)equality and regex (not) match comparison operators. - case '!': - case '=': { - if (pline.size == 1) { - ret.type = (schar == '!' ? kExprLexNot : kExprLexAssignment); - ret.data.ass.type = kExprAsgnPlain; - break; - } - ret.type = kExprLexComparison; - ret.data.cmp.inv = (schar == '!'); - if (pline.data[1] == '=') { - ret.data.cmp.type = kExprCmpEqual; - ret.len++; - } else if (pline.data[1] == '~') { - ret.data.cmp.type = kExprCmpMatches; - ret.len++; - } else if (schar == '!') { - ret.type = kExprLexNot; - } else { - ret.type = kExprLexAssignment; - ret.data.ass.type = kExprAsgnPlain; - } - GET_CCS(ret, pline); + break; + + // Unary not, (un)equality and regex (not) match comparison operators. + case '!': + case '=': + if (pline.size == 1) { + ret.type = (schar == '!' ? kExprLexNot : kExprLexAssignment); + ret.data.ass.type = kExprAsgnPlain; break; } - - // Less/greater [or equal to] comparison operators. - case '>': - case '<': { - ret.type = kExprLexComparison; - const bool haseqsign = (pline.size > 1 && pline.data[1] == '='); - if (haseqsign) { - ret.len++; - } - GET_CCS(ret, pline); - ret.data.cmp.inv = (schar == '<'); - ret.data.cmp.type = ((ret.data.cmp.inv ^ haseqsign) + ret.type = kExprLexComparison; + ret.data.cmp.inv = (schar == '!'); + if (pline.data[1] == '=') { + ret.data.cmp.type = kExprCmpEqual; + ret.len++; + } else if (pline.data[1] == '~') { + ret.data.cmp.type = kExprCmpMatches; + ret.len++; + } else if (schar == '!') { + ret.type = kExprLexNot; + } else { + ret.type = kExprLexAssignment; + ret.data.ass.type = kExprAsgnPlain; + } + GET_CCS(ret, pline); + break; + + // Less/greater [or equal to] comparison operators. + case '>': + case '<': { + ret.type = kExprLexComparison; + const bool haseqsign = (pline.size > 1 && pline.data[1] == '='); + if (haseqsign) { + ret.len++; + } + GET_CCS(ret, pline); + ret.data.cmp.inv = (schar == '<'); + ret.data.cmp.type = ((ret.data.cmp.inv ^ haseqsign) ? kExprCmpGreaterOrEqual : kExprCmpGreater); - break; - } + break; + } - // Minus sign, arrow from lambdas or augmented assignment. - case '-': { - if (pline.size > 1 && pline.data[1] == '>') { - ret.len++; - ret.type = kExprLexArrow; - } else if (pline.size > 1 && pline.data[1] == '=') { - ret.len++; - ret.type = kExprLexAssignment; - ret.data.ass.type = kExprAsgnSubtract; - } else { - ret.type = kExprLexMinus; - } - break; + // Minus sign, arrow from lambdas or augmented assignment. + case '-': { + if (pline.size > 1 && pline.data[1] == '>') { + ret.len++; + ret.type = kExprLexArrow; + } else if (pline.size > 1 && pline.data[1] == '=') { + ret.len++; + ret.type = kExprLexAssignment; + ret.data.ass.type = kExprAsgnSubtract; + } else { + ret.type = kExprLexMinus; } + break; + } // Sign or augmented assignment. #define CHAR_OR_ASSIGN(ch, ch_type, ass_type) \ - case ch: { \ - if (pline.size > 1 && pline.data[1] == '=') { \ - ret.len++; \ - ret.type = kExprLexAssignment; \ - ret.data.ass.type = ass_type; \ - } else { \ - ret.type = ch_type; \ - } \ - break; \ - } +case ch: { \ + if (pline.size > 1 && pline.data[1] == '=') { \ + ret.len++; \ + ret.type = kExprLexAssignment; \ + ret.data.ass.type = ass_type; \ + } else { \ + ret.type = ch_type; \ + } \ + break; \ +} CHAR_OR_ASSIGN('+', kExprLexPlus, kExprAsgnAdd) CHAR_OR_ASSIGN('.', kExprLexDot, kExprAsgnConcat) #undef CHAR_OR_ASSIGN - // Expression end because Ex command ended. - case NUL: - case NL: { - if (flags & kELFlagForbidEOC) { - ret.type = kExprLexInvalid; - ret.data.err.msg = _("E15: Unexpected EOC character: %.*s"); - ret.data.err.type = kExprLexSpacing; - } else { - ret.type = kExprLexEOC; - } - break; - } - - case '|': { - if (pline.size >= 2 && pline.data[ret.len] == '|') { - // "||" is or. - ret.len++; - ret.type = kExprLexOr; - } else if (flags & kELFlagForbidEOC) { - // Note: `<C-r>=1 | 2<CR>` actually yields 1 in Vim without any - // errors. This will be changed here. - ret.type = kExprLexInvalid; - ret.data.err.msg = _("E15: Unexpected EOC character: %.*s"); - ret.data.err.type = kExprLexOr; - } else { - ret.type = kExprLexEOC; - } - break; + // Expression end because Ex command ended. + case NUL: + case NL: + if (flags & kELFlagForbidEOC) { + ret.type = kExprLexInvalid; + ret.data.err.msg = _("E15: Unexpected EOC character: %.*s"); + ret.data.err.type = kExprLexSpacing; + } else { + ret.type = kExprLexEOC; } - - // Everything else is not valid. - default: { - ret.len = (size_t)utfc_ptr2len_len((const char_u *)pline.data, - (int)pline.size); + break; + + case '|': + if (pline.size >= 2 && pline.data[ret.len] == '|') { + // "||" is or. + ret.len++; + ret.type = kExprLexOr; + } else if (flags & kELFlagForbidEOC) { + // Note: `<C-r>=1 | 2<CR>` actually yields 1 in Vim without any + // errors. This will be changed here. ret.type = kExprLexInvalid; - ret.data.err.type = kExprLexPlainIdentifier; - ret.data.err.msg = _("E15: Unidentified character: %.*s"); - break; + ret.data.err.msg = _("E15: Unexpected EOC character: %.*s"); + ret.data.err.type = kExprLexOr; + } else { + ret.type = kExprLexEOC; } + break; + + // Everything else is not valid. + default: + ret.len = (size_t)utfc_ptr2len_len((const char_u *)pline.data, + (int)pline.size); + ret.type = kExprLexInvalid; + ret.data.err.type = kExprLexPlainIdentifier; + ret.data.err.msg = _("E15: Unidentified character: %.*s"); + break; } #undef GET_CCS viml_pexpr_next_token_adv_return: @@ -737,8 +793,7 @@ static const char *const eltkn_opt_scope_tab[] = { /// /// @return Token represented in a string form, in a static buffer (overwritten /// on each call). -const char *viml_pexpr_repr_token(const ParserState *const pstate, - const LexExprToken token, +const char *viml_pexpr_repr_token(const ParserState *const pstate, const LexExprToken token, size_t *const ret_size) FUNC_ATTR_WARN_UNUSED_RESULT { @@ -756,10 +811,10 @@ const char *viml_pexpr_repr_token(const ParserState *const pstate, eltkn_type_tab[token.type]); switch (token.type) { #define TKNARGS(tkn_type, ...) \ - case tkn_type: { \ - ADDSTR(__VA_ARGS__); \ - break; \ - } +case tkn_type: { \ + ADDSTR(__VA_ARGS__); \ + break; \ +} TKNARGS(kExprLexComparison, "(type=%s,ccs=%s,inv=%i)", eltkn_cmp_type_tab[token.data.cmp.type], ccs_tab[token.data.cmp.ccs], @@ -769,7 +824,7 @@ const char *viml_pexpr_repr_token(const ParserState *const pstate, TKNARGS(kExprLexAssignment, "(type=%s)", expr_asgn_type_tab[token.data.ass.type]) TKNARGS(kExprLexRegister, "(name=%s)", intchar2str(token.data.reg.name)) - case kExprLexDoubleQuotedString: + case kExprLexDoubleQuotedString: TKNARGS(kExprLexSingleQuotedString, "(closed=%i)", (int)token.data.str.closed) TKNARGS(kExprLexOption, "(scope=%s,name=%.*s)", @@ -785,19 +840,17 @@ const char *viml_pexpr_repr_token(const ParserState *const pstate, ? (double)token.data.num.val.floating : (double)token.data.num.val.integer)) TKNARGS(kExprLexInvalid, "(msg=%s)", token.data.err.msg) - default: { - // No additional arguments. - break; - } + default: + // No additional arguments. + break; #undef TKNARGS } if (pstate == NULL) { ADDSTR("::%zu", token.len); } else { *p++ = ':'; - memmove( - p, &pstate->reader.lines.items[token.start.line].data[token.start.col], - token.len); + memmove(p, &pstate->reader.lines.items[token.start.line].data[token.start.col], + token.len); p += token.len; *p = NUL; } @@ -886,9 +939,8 @@ static const char *intchar2str(const int ch) #include <stdio.h> REAL_FATTR_UNUSED -static inline void viml_pexpr_debug_print_ast_node( - const ExprASTNode *const *const eastnode_p, - const char *const prefix) +static inline void viml_pexpr_debug_print_ast_node(const ExprASTNode *const *const eastnode_p, + const char *const prefix) { if (*eastnode_p == NULL) { fprintf(stderr, "%s %p : NULL\n", prefix, (void *)eastnode_p); @@ -901,35 +953,33 @@ static inline void viml_pexpr_debug_print_ast_node( } REAL_FATTR_UNUSED -static inline void viml_pexpr_debug_print_ast_stack( - const ExprASTStack *const ast_stack, - const char *const msg) +static inline void viml_pexpr_debug_print_ast_stack(const ExprASTStack *const ast_stack, + const char *const msg) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { fprintf(stderr, "\n%sstack: %zu:\n", msg, kv_size(*ast_stack)); for (size_t i = 0; i < kv_size(*ast_stack); i++) { - viml_pexpr_debug_print_ast_node( - (const ExprASTNode *const *)kv_A(*ast_stack, i), - "-"); + viml_pexpr_debug_print_ast_node((const ExprASTNode *const *)kv_A(*ast_stack, i), + "-"); } } REAL_FATTR_UNUSED -static inline void viml_pexpr_debug_print_token( - const ParserState *const pstate, const LexExprToken token) +static inline void viml_pexpr_debug_print_token(const ParserState *const pstate, + const LexExprToken token) FUNC_ATTR_ALWAYS_INLINE { fprintf(stderr, "\ntkn: %s\n", viml_pexpr_repr_token(pstate, token, NULL)); } #define PSTACK(msg) \ - viml_pexpr_debug_print_ast_stack(&ast_stack, #msg) + viml_pexpr_debug_print_ast_stack(&ast_stack, #msg) #define PSTACK_P(msg) \ - viml_pexpr_debug_print_ast_stack(ast_stack, #msg) + viml_pexpr_debug_print_ast_stack(ast_stack, #msg) #define PNODE_P(eastnode_p, msg) \ - viml_pexpr_debug_print_ast_node((const ExprASTNode *const *)eastnode_p, \ - (#msg)) + viml_pexpr_debug_print_ast_node((const ExprASTNode *const *)eastnode_p, \ + (#msg)) #define PTOKEN(tkn) \ - viml_pexpr_debug_print_token(pstate, tkn) + viml_pexpr_debug_print_token(pstate, tkn) #endif const uint8_t node_maxchildren[] = { @@ -1009,50 +1059,48 @@ void viml_pexpr_free_ast(ExprAST ast) } else if (*cur_node != NULL) { kv_drop(ast_stack, 1); switch ((*cur_node)->type) { - case kExprNodeDoubleQuotedString: - case kExprNodeSingleQuotedString: { - xfree((*cur_node)->data.str.value); - break; - } - case kExprNodeMissing: - case kExprNodeOpMissing: - case kExprNodeTernary: - case kExprNodeTernaryValue: - case kExprNodeRegister: - case kExprNodeSubscript: - case kExprNodeListLiteral: - case kExprNodeUnaryPlus: - case kExprNodeBinaryPlus: - case kExprNodeNested: - case kExprNodeCall: - case kExprNodePlainIdentifier: - case kExprNodePlainKey: - case kExprNodeComplexIdentifier: - case kExprNodeUnknownFigure: - case kExprNodeLambda: - case kExprNodeDictLiteral: - case kExprNodeCurlyBracesIdentifier: - case kExprNodeAssignment: - case kExprNodeComma: - case kExprNodeColon: - case kExprNodeArrow: - case kExprNodeComparison: - case kExprNodeConcat: - case kExprNodeConcatOrSubscript: - case kExprNodeInteger: - case kExprNodeFloat: - case kExprNodeOr: - case kExprNodeAnd: - case kExprNodeUnaryMinus: - case kExprNodeBinaryMinus: - case kExprNodeNot: - case kExprNodeMultiplication: - case kExprNodeDivision: - case kExprNodeMod: - case kExprNodeOption: - case kExprNodeEnvironment: { - break; - } + case kExprNodeDoubleQuotedString: + case kExprNodeSingleQuotedString: + xfree((*cur_node)->data.str.value); + break; + case kExprNodeMissing: + case kExprNodeOpMissing: + case kExprNodeTernary: + case kExprNodeTernaryValue: + case kExprNodeRegister: + case kExprNodeSubscript: + case kExprNodeListLiteral: + case kExprNodeUnaryPlus: + case kExprNodeBinaryPlus: + case kExprNodeNested: + case kExprNodeCall: + case kExprNodePlainIdentifier: + case kExprNodePlainKey: + case kExprNodeComplexIdentifier: + case kExprNodeUnknownFigure: + case kExprNodeLambda: + case kExprNodeDictLiteral: + case kExprNodeCurlyBracesIdentifier: + case kExprNodeAssignment: + case kExprNodeComma: + case kExprNodeColon: + case kExprNodeArrow: + case kExprNodeComparison: + case kExprNodeConcat: + case kExprNodeConcatOrSubscript: + case kExprNodeInteger: + case kExprNodeFloat: + case kExprNodeOr: + case kExprNodeAnd: + case kExprNodeUnaryMinus: + case kExprNodeBinaryMinus: + case kExprNodeNot: + case kExprNodeMultiplication: + case kExprNodeDivision: + case kExprNodeMod: + case kExprNodeOption: + case kExprNodeEnvironment: + break; } xfree(*cur_node); *cur_node = NULL; @@ -1204,10 +1252,8 @@ static inline ExprOpAssociativity node_ass(const ExprASTNode node) /// @param[out] ast_err Location where error is saved, if any. /// /// @return True if no errors occurred, false otherwise. -static bool viml_pexpr_handle_bop(const ParserState *const pstate, - ExprASTStack *const ast_stack, - ExprASTNode *const bop_node, - ExprASTWantedNode *const want_node_p, +static bool viml_pexpr_handle_bop(const ParserState *const pstate, ExprASTStack *const ast_stack, + ExprASTNode *const bop_node, ExprASTWantedNode *const want_node_p, ExprASTError *const ast_err) FUNC_ATTR_NONNULL_ALL { @@ -1223,8 +1269,8 @@ static bool viml_pexpr_handle_bop(const ParserState *const pstate, : node_lvl(*bop_node)); #ifndef NDEBUG const ExprOpAssociativity bop_node_ass = ( - (bop_node->type == kExprNodeCall - || bop_node->type == kExprNodeSubscript) + (bop_node->type == kExprNodeCall + || bop_node->type == kExprNodeSubscript) ? kEOpAssLeft : node_ass(*bop_node)); #endif @@ -1301,8 +1347,7 @@ static bool viml_pexpr_handle_bop(const ParserState *const pstate, /// @param[in] shift Number of bytes to shift. /// /// @return Shifted position. -static inline ParserPosition shifted_pos(const ParserPosition pos, - const size_t shift) +static inline ParserPosition shifted_pos(const ParserPosition pos, const size_t shift) FUNC_ATTR_CONST FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT { return (ParserPosition) { .line = pos.line, .col = pos.col + shift }; @@ -1316,8 +1361,7 @@ static inline ParserPosition shifted_pos(const ParserPosition pos, /// @param[in] new_col New column. /// /// @return Shifted position. -static inline ParserPosition recol_pos(const ParserPosition pos, - const size_t new_col) +static inline ParserPosition recol_pos(const ParserPosition pos, const size_t new_col) FUNC_ATTR_CONST FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT { return (ParserPosition) { .line = pos.line, .col = new_col }; @@ -1328,22 +1372,22 @@ static inline ParserPosition recol_pos(const ParserPosition pos, /// Highlight current token with the given group #define HL_CUR_TOKEN(g) \ - viml_parser_highlight(pstate, cur_token.start, cur_token.len, \ - HL(g)) + viml_parser_highlight(pstate, cur_token.start, cur_token.len, \ + HL(g)) /// Allocate new node, saving some values #define NEW_NODE(type) \ - viml_pexpr_new_node(type) + viml_pexpr_new_node(type) /// Set position of the given node to position from the given token /// /// @param cur_node Node to modify. /// @param cur_token Token to set position from. #define POS_FROM_TOKEN(cur_node, cur_token) \ - do { \ - (cur_node)->start = cur_token.start; \ - (cur_node)->len = cur_token.len; \ - } while (0) + do { \ + (cur_node)->start = cur_token.start; \ + (cur_node)->len = cur_token.len; \ + } while (0) /// Allocate new node and set its position from the current token /// @@ -1352,27 +1396,27 @@ static inline ParserPosition recol_pos(const ParserPosition pos, /// @param cur_node Variable to save allocated node to. /// @param typ Node type. #define NEW_NODE_WITH_CUR_POS(cur_node, typ) \ - do { \ - (cur_node) = NEW_NODE(typ); \ - POS_FROM_TOKEN((cur_node), cur_token); \ - if (prev_token.type == kExprLexSpacing) { \ - (cur_node)->start = prev_token.start; \ - (cur_node)->len += prev_token.len; \ - } \ - } while (0) + do { \ + (cur_node) = NEW_NODE(typ); \ + POS_FROM_TOKEN((cur_node), cur_token); \ + if (prev_token.type == kExprLexSpacing) { \ + (cur_node)->start = prev_token.start; \ + (cur_node)->len += prev_token.len; \ + } \ + } while (0) /// Check whether it is possible to have next expression after current /// /// For :echo: `:echo @a @a` is a valid expression. `:echo (@a @a)` is not. #define MAY_HAVE_NEXT_EXPR \ - (kv_size(ast_stack) == 1) + (kv_size(ast_stack) == 1) /// Add operator node /// /// @param[in] cur_node Node to add. #define ADD_OP_NODE(cur_node) \ - is_invalid |= !viml_pexpr_handle_bop(pstate, &ast_stack, cur_node, \ - &want_node, &ast.err) + is_invalid |= !viml_pexpr_handle_bop(pstate, &ast_stack, cur_node, \ + &want_node, &ast.err) /// Record missing operator: for things like /// @@ -1384,33 +1428,33 @@ static inline ParserPosition recol_pos(const ParserPosition pos, /// /// (parsed as OpMissing(@a, @a)). #define OP_MISSING \ - do { \ - if (flags & kExprFlagsMulti && MAY_HAVE_NEXT_EXPR) { \ - /* Multiple expressions allowed, return without calling */ \ - /* viml_parser_advance(). */ \ - goto viml_pexpr_parse_end; \ - } else { \ - assert(*top_node_p != NULL); \ - ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Missing operator: %.*s")); \ - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeOpMissing); \ - cur_node->len = 0; \ - ADD_OP_NODE(cur_node); \ - goto viml_pexpr_parse_process_token; \ - } \ - } while (0) + do { \ + if (flags & kExprFlagsMulti && MAY_HAVE_NEXT_EXPR) { \ + /* Multiple expressions allowed, return without calling */ \ + /* viml_parser_advance(). */ \ + goto viml_pexpr_parse_end; \ + } else { \ + assert(*top_node_p != NULL); \ + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Missing operator: %.*s")); \ + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeOpMissing); \ + cur_node->len = 0; \ + ADD_OP_NODE(cur_node); \ + goto viml_pexpr_parse_process_token; \ + } \ + } while (0) /// Record missing value: for things like "* 5" /// /// @param[in] msg Error message. #define ADD_VALUE_IF_MISSING(msg) \ - do { \ - if (want_node == kENodeValue) { \ - ERROR_FROM_TOKEN_AND_MSG(cur_token, (msg)); \ - NEW_NODE_WITH_CUR_POS((*top_node_p), kExprNodeMissing); \ - (*top_node_p)->len = 0; \ - want_node = kENodeOperator; \ - } \ - } while (0) + do { \ + if (want_node == kENodeValue) { \ + ERROR_FROM_TOKEN_AND_MSG(cur_token, (msg)); \ + NEW_NODE_WITH_CUR_POS((*top_node_p), kExprNodeMissing); \ + (*top_node_p)->len = 0; \ + want_node = kENodeOperator; \ + } \ + } while (0) /// Set AST error, unless AST already is not correct /// @@ -1419,10 +1463,8 @@ static inline ParserPosition recol_pos(const ParserPosition pos, /// @param[in] msg Error message, assumed to be already translated and /// containing a single %token "%.*s". /// @param[in] start Position at which error occurred. -static inline void east_set_error(const ParserState *const pstate, - ExprASTError *const ret_ast_err, - const char *const msg, - const ParserPosition start) +static inline void east_set_error(const ParserState *const pstate, ExprASTError *const ret_ast_err, + const char *const msg, const ParserPosition start) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { if (ret_ast_err->msg != NULL) { @@ -1436,21 +1478,21 @@ static inline void east_set_error(const ParserState *const pstate, /// Set error from the given token and given message #define ERROR_FROM_TOKEN_AND_MSG(cur_token, msg) \ - do { \ - is_invalid = true; \ - east_set_error(pstate, &ast.err, msg, cur_token.start); \ - } while (0) + do { \ + is_invalid = true; \ + east_set_error(pstate, &ast.err, msg, cur_token.start); \ + } while (0) /// Like #ERROR_FROM_TOKEN_AND_MSG, but gets position from a node #define ERROR_FROM_NODE_AND_MSG(node, msg) \ - do { \ - is_invalid = true; \ - east_set_error(pstate, &ast.err, msg, node->start); \ - } while (0) + do { \ + is_invalid = true; \ + east_set_error(pstate, &ast.err, msg, node->start); \ + } while (0) /// Set error from the given kExprLexInvalid token #define ERROR_FROM_TOKEN(cur_token) \ - ERROR_FROM_TOKEN_AND_MSG(cur_token, cur_token.data.err.msg) + ERROR_FROM_TOKEN_AND_MSG(cur_token, cur_token.data.err.msg) /// Select figure brace type, altering highlighting as well if needed /// @@ -1459,16 +1501,16 @@ static inline void east_set_error(const ParserState *const pstate, /// kExprNode prefix. /// @param[in] hl Corresponding highlighting, passed as an argument to #HL. #define SELECT_FIGURE_BRACE_TYPE(node, new_type, hl) \ - do { \ - ExprASTNode *const node_ = (node); \ - assert(node_->type == kExprNodeUnknownFigure \ - || node_->type == kExprNode##new_type); \ - node_->type = kExprNode##new_type; \ - if (pstate->colors) { \ - kv_A(*pstate->colors, node_->data.fig.opening_hl_idx).group = \ - HL(hl); \ - } \ - } while (0) + do { \ + ExprASTNode *const node_ = (node); \ + assert(node_->type == kExprNodeUnknownFigure \ + || node_->type == kExprNode##new_type); \ + node_->type = kExprNode##new_type; \ + if (pstate->colors) { \ + kv_A(*pstate->colors, node_->data.fig.opening_hl_idx).group = \ + HL(hl); \ + } \ + } while (0) /// Add identifier which should constitute complex identifier node /// @@ -1479,45 +1521,45 @@ static inline void east_set_error(const ParserState *const pstate, /// a trailing semicolon. /// @param hl Highlighting name to use, passed as an argument to #HL. #define ADD_IDENT(new_ident_node_code, hl) \ - do { \ - assert(want_node == kENodeOperator); \ - /* Operator: may only be curly braces name, but only under certain */ \ - /* conditions. */ \ + do { \ + assert(want_node == kENodeOperator); \ + /* Operator: may only be curly braces name, but only under certain */ \ + /* conditions. */ \ \ - /* First condition is that there is no space before a part of complex */ \ - /* identifier. */ \ - if (prev_token.type == kExprLexSpacing) { \ - OP_MISSING; \ - } \ - switch ((*top_node_p)->type) { \ - /* Second is that previous node is one of the identifiers: */ \ - /* complex, plain, curly braces. */ \ + /* First condition is that there is no space before a part of complex */ \ + /* identifier. */ \ + if (prev_token.type == kExprLexSpacing) { \ + OP_MISSING; \ + } \ + switch ((*top_node_p)->type) { \ + /* Second is that previous node is one of the identifiers: */ \ + /* complex, plain, curly braces. */ \ \ - /* TODO(ZyX-I): Extend syntax to allow ${expr}. This is needed to */ \ - /* handle environment variables like those bash uses for */ \ - /* `export -f`: their names consist not only of alphanumeric */ \ - /* characetrs. */ \ - case kExprNodeComplexIdentifier: \ - case kExprNodePlainIdentifier: \ - case kExprNodeCurlyBracesIdentifier: { \ - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeComplexIdentifier); \ - cur_node->len = 0; \ - cur_node->children = *top_node_p; \ - *top_node_p = cur_node; \ - kvi_push(ast_stack, &cur_node->children->next); \ - ExprASTNode **const new_top_node_p = kv_last(ast_stack); \ - assert(*new_top_node_p == NULL); \ - new_ident_node_code; \ - *new_top_node_p = cur_node; \ - HL_CUR_TOKEN(hl); \ - break; \ - } \ - default: { \ - OP_MISSING; \ - break; \ - } \ - } \ - } while (0) + /* TODO(ZyX-I): Extend syntax to allow ${expr}. This is needed to */ \ + /* handle environment variables like those bash uses for */ \ + /* `export -f`: their names consist not only of alphanumeric */ \ + /* characetrs. */ \ + case kExprNodeComplexIdentifier: \ + case kExprNodePlainIdentifier: \ + case kExprNodeCurlyBracesIdentifier: { \ + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeComplexIdentifier); \ + cur_node->len = 0; \ + cur_node->children = *top_node_p; \ + *top_node_p = cur_node; \ + kvi_push(ast_stack, &cur_node->children->next); \ + ExprASTNode **const new_top_node_p = kv_last(ast_stack); \ + assert(*new_top_node_p == NULL); \ + new_ident_node_code; \ + *new_top_node_p = cur_node; \ + HL_CUR_TOKEN(hl); \ + break; \ + } \ + default: { \ + OP_MISSING; \ + break; \ + } \ + } \ + } while (0) /// Determine whether given parse type is an assignment /// @@ -1551,10 +1593,8 @@ typedef struct { /// @param[in] ast_stack Parser AST stack, used to detect whether current /// string is a regex. /// @param[in] is_invalid Whether currently processed token is not valid. -static void parse_quoted_string(ParserState *const pstate, - ExprASTNode *const node, - const LexExprToken token, - const ExprASTStack ast_stack, +static void parse_quoted_string(ParserState *const pstate, ExprASTNode *const node, + const LexExprToken token, const ExprASTStack ast_stack, const bool is_invalid) FUNC_ATTR_NONNULL_ALL { @@ -1577,10 +1617,10 @@ static void parse_quoted_string(ParserState *const pstate, p = chunk_e + 2; if (pstate->colors) { kvi_push(shifts, ((StringShift) { - .start = token.start.col + (size_t)(chunk_e - s), - .orig_len = 2, - .act_len = 1, - .escape_not_known = false, + .start = token.start.col + (size_t)(chunk_e - s), + .orig_len = 2, + .act_len = 1, + .escape_not_known = false, })); } } @@ -1613,70 +1653,74 @@ static void parse_quoted_string(ParserState *const pstate, break; } switch (*p) { - // A "\<x>" form occupies at least 4 characters, and produces up to - // 6 characters: reserve space for 2 extra, but do not compute actual - // length just now, it would be costy. - case '<': { - size += 2; - break; - } - // Hexadecimal, always single byte, but at least three bytes each. - case 'x': case 'X': { + // A "\<x>" form occupies at least 4 characters, and produces up to + // 6 characters: reserve space for 2 extra, but do not compute actual + // length just now, it would be costy. + case '<': + size += 2; + break; + // Hexadecimal, always single byte, but at least three bytes each. + case 'x': + case 'X': + size--; + if (ascii_isxdigit(p[1])) { size--; - if (ascii_isxdigit(p[1])) { + if (p + 2 < e && ascii_isxdigit(p[2])) { size--; - if (p + 2 < e && ascii_isxdigit(p[2])) { - size--; - } } - break; } - // Unicode - // - // \uF takes 1 byte which is 2 bytes less then escape sequence. - // \uFF: 2 bytes, 2 bytes less. - // \uFFF: 3 bytes, 2 bytes less. - // \uFFFF: 3 bytes, 3 bytes less. - // \UFFFFF: 4 bytes, 3 bytes less. - // \UFFFFFF: 5 bytes, 3 bytes less. - // \UFFFFFFF: 6 bytes, 3 bytes less. - // \U7FFFFFFF: 6 bytes, 4 bytes less. - case 'u': case 'U': { - const char *const esc_start = p; - size_t n = (*p == 'u' ? 4 : 8); - int nr = 0; + break; + // Unicode + // + // \uF takes 1 byte which is 2 bytes less then escape sequence. + // \uFF: 2 bytes, 2 bytes less. + // \uFFF: 3 bytes, 2 bytes less. + // \uFFFF: 3 bytes, 3 bytes less. + // \UFFFFF: 4 bytes, 3 bytes less. + // \UFFFFFF: 5 bytes, 3 bytes less. + // \UFFFFFFF: 6 bytes, 3 bytes less. + // \U7FFFFFFF: 6 bytes, 4 bytes less. + case 'u': + case 'U': { + const char *const esc_start = p; + size_t n = (*p == 'u' ? 4 : 8); + int nr = 0; + p++; + while (p + 1 < e && n-- && ascii_isxdigit(p[1])) { p++; - while (p + 1 < e && n-- && ascii_isxdigit(p[1])) { - p++; - nr = (nr << 4) + hex2nr(*p); - } - // Escape length: (esc_start - 1) points to "\\", esc_start to "u" - // or "U", p to the byte after last byte. So escape sequence - // occupies p - (esc_start - 1), but it stands for a utf_char2len - // bytes. - size -= (size_t)((p - (esc_start - 1)) - utf_char2len(nr)); - p--; - break; + nr = (nr << 4) + hex2nr(*p); } - // Octal, always single byte, but at least two bytes each. - case '0': case '1': case '2': case '3': case '4': case '5': case '6': - case '7': { + // Escape length: (esc_start - 1) points to "\\", esc_start to "u" + // or "U", p to the byte after last byte. So escape sequence + // occupies p - (esc_start - 1), but it stands for a utf_char2len + // bytes. + size -= (size_t)((p - (esc_start - 1)) - utf_char2len(nr)); + p--; + break; + } + // Octal, always single byte, but at least two bytes each. + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + size--; + p++; + if (*p >= '0' && *p <= '7') { size--; p++; - if (*p >= '0' && *p <= '7') { + if (p < e && *p >= '0' && *p <= '7') { size--; p++; - if (p < e && *p >= '0' && *p <= '7') { - size--; - p++; - } } - break; - } - default: { - size--; - break; } + break; + default: + size--; + break; } } } @@ -1705,11 +1749,11 @@ static void parse_quoted_string(ParserState *const pstate, const char *const v_p_start = v_p; switch (*p) { #define SINGLE_CHAR_ESC(ch, real_ch) \ - case ch: { \ - *v_p++ = real_ch; \ - p++; \ - break; \ - } +case ch: { \ + *v_p++ = real_ch; \ + p++; \ + break; \ +} SINGLE_CHAR_ESC('b', BS) SINGLE_CHAR_ESC('e', ESC) SINGLE_CHAR_ESC('f', FF) @@ -1720,76 +1764,83 @@ static void parse_quoted_string(ParserState *const pstate, SINGLE_CHAR_ESC('\\', '\\') #undef SINGLE_CHAR_ESC - // Hexadecimal or unicode. - case 'X': case 'x': case 'u': case 'U': { - if (p + 1 < e && ascii_isxdigit(p[1])) { - size_t n; - int nr; - bool is_hex = (*p == 'x' || *p == 'X'); - - if (is_hex) { - n = 2; - } else if (*p == 'u') { - n = 4; - } else { - n = 8; - } - nr = 0; - while (p + 1 < e && n-- && ascii_isxdigit(p[1])) { - p++; - nr = (nr << 4) + hex2nr(*p); - } - p++; - if (is_hex) { - *v_p++ = (char)nr; - } else { - v_p += utf_char2bytes(nr, (char_u *)v_p); - } + // Hexadecimal or unicode. + case 'X': + case 'x': + case 'u': + case 'U': + if (p + 1 < e && ascii_isxdigit(p[1])) { + size_t n; + int nr; + bool is_hex = (*p == 'x' || *p == 'X'); + + if (is_hex) { + n = 2; + } else if (*p == 'u') { + n = 4; } else { - is_unknown = true; - *v_p++ = *p; + n = 8; + } + nr = 0; + while (p + 1 < e && n-- && ascii_isxdigit(p[1])) { p++; + nr = (nr << 4) + hex2nr(*p); + } + p++; + if (is_hex) { + *v_p++ = (char)nr; + } else { + v_p += utf_char2bytes(nr, (char_u *)v_p); } - break; + } else { + is_unknown = true; + *v_p++ = *p; + p++; } - // Octal: "\1", "\12", "\123". - case '0': case '1': case '2': case '3': case '4': case '5': case '6': - case '7': { - uint8_t ch = (uint8_t)(*p++ - '0'); + break; + // Octal: "\1", "\12", "\123". + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { + uint8_t ch = (uint8_t)(*p++ - '0'); + if (p < e && *p >= '0' && *p <= '7') { + ch = (uint8_t)((ch << 3) + *p++ - '0'); if (p < e && *p >= '0' && *p <= '7') { ch = (uint8_t)((ch << 3) + *p++ - '0'); - if (p < e && *p >= '0' && *p <= '7') { - ch = (uint8_t)((ch << 3) + *p++ - '0'); - } } - *v_p++ = (char)ch; - break; } - // Special key, e.g.: "\<C-W>" - case '<': { - const size_t special_len = ( - trans_special((const char_u **)&p, (size_t)(e - p), - (char_u *)v_p, true, true)); - if (special_len != 0) { - v_p += special_len; - } else { - is_unknown = true; - mb_copy_char((const char_u **)&p, (char_u **)&v_p); - } - break; - } - default: { + *v_p++ = (char)ch; + break; + } + // Special key, e.g.: "\<C-W>" + case '<': { + const size_t special_len = ( + trans_special((const char_u **)&p, (size_t)(e - p), + (char_u *)v_p, true, true)); + if (special_len != 0) { + v_p += special_len; + } else { is_unknown = true; mb_copy_char((const char_u **)&p, (char_u **)&v_p); - break; } + break; + } + default: + is_unknown = true; + mb_copy_char((const char_u **)&p, (char_u **)&v_p); + break; } if (pstate->colors) { kvi_push(shifts, ((StringShift) { - .start = token.start.col + (size_t)(chunk_e - s), - .orig_len = (size_t)(p - chunk_e), - .act_len = (size_t)(v_p - (char *)v_p_start), - .escape_not_known = is_unknown, + .start = token.start.col + (size_t)(chunk_e - s), + .orig_len = (size_t)(p - chunk_e), + .act_len = (size_t)(v_p - (char *)v_p_start), + .escape_not_known = is_unknown, })); } } @@ -1901,21 +1952,23 @@ ExprAST viml_pexpr_parse(ParserState *const pstate, const int flags) size_t asgn_level = 0; do { const bool is_concat_or_subscript = ( - want_node == kENodeValue - && kv_size(ast_stack) > 1 - && (*kv_Z(ast_stack, 1))->type == kExprNodeConcatOrSubscript); + want_node == kENodeValue + && kv_size(ast_stack) > 1 + && (*kv_Z(ast_stack, + 1))->type == kExprNodeConcatOrSubscript); const int lexer_additional_flags = ( - kELFlagPeek - | ((flags & kExprFlagsDisallowEOC) ? kELFlagForbidEOC : 0) - | ((want_node == kENodeValue - && (kv_size(ast_stack) == 1 - || ((*kv_Z(ast_stack, 1))->type != kExprNodeConcat - && ((*kv_Z(ast_stack, 1))->type - != kExprNodeConcatOrSubscript)))) + kELFlagPeek + | ((flags & kExprFlagsDisallowEOC) ? kELFlagForbidEOC : 0) + | ((want_node == kENodeValue + && (kv_size(ast_stack) == 1 + || ((*kv_Z(ast_stack, 1))->type != kExprNodeConcat + && ((*kv_Z(ast_stack, 1))->type + != kExprNodeConcatOrSubscript)))) ? kELFlagAllowFloat : 0)); - LexExprToken cur_token = viml_pexpr_next_token( - pstate, want_node_to_lexer_flags[want_node] | lexer_additional_flags); + LexExprToken cur_token = viml_pexpr_next_token(pstate, + want_node_to_lexer_flags[want_node] | + lexer_additional_flags); if (cur_token.type == kExprLexEOC) { break; } @@ -1924,8 +1977,8 @@ ExprAST viml_pexpr_parse(ParserState *const pstate, const int flags) bool is_invalid = token_invalid; viml_pexpr_parse_process_token: // May use different flags this time. - cur_token = viml_pexpr_next_token( - pstate, want_node_to_lexer_flags[want_node] | lexer_additional_flags); + cur_token = viml_pexpr_next_token(pstate, + want_node_to_lexer_flags[want_node] | lexer_additional_flags); if (tok_type == kExprLexSpacing) { if (is_invalid) { HL_CUR_TOKEN(Spacing); @@ -1977,12 +2030,12 @@ viml_pexpr_parse_process_token: // for ternary and because concatenating dictionary with anything is not // valid. There are more cases when this will make a difference though. const bool node_is_key = ( - is_concat_or_subscript - && (cur_token.type == kExprLexPlainIdentifier + is_concat_or_subscript + && (cur_token.type == kExprLexPlainIdentifier ? (!cur_token.data.var.autoload && cur_token.data.var.scope == kExprVarScopeMissing) : (cur_token.type == kExprLexNumber)) - && prev_token.type != kExprLexSpacing); + && prev_token.type != kExprLexSpacing); if (is_concat_or_subscript && !node_is_key) { // Note: in Vim "d. a" (this is the reason behind `prev_token.type != // kExprLexSpacing` part of the condition) as well as any other "d.{expr}" @@ -1997,951 +2050,896 @@ viml_pexpr_parse_process_token: // Pop some stack pt_stack items in case of misplaced nodes. const bool is_single_assignment = kv_last(pt_stack) == kEPTSingleAssignment; switch (kv_last(pt_stack)) { - case kEPTExpr: { - break; - } - case kEPTLambdaArguments: { - if ((want_node == kENodeOperator - && tok_type != kExprLexComma - && tok_type != kExprLexArrow) - || (want_node == kENodeValue - && !(cur_token.type == kExprLexPlainIdentifier - && cur_token.data.var.scope == kExprVarScopeMissing - && !cur_token.data.var.autoload) - && tok_type != kExprLexArrow)) { - lambda_node->data.fig.type_guesses.allow_lambda = false; - if (lambda_node->children != NULL - && lambda_node->children->type == kExprNodeComma) { - // If lambda has comma child this means that parser has already seen - // at least "{arg1,", so node cannot possibly be anything, but - // lambda. - - // Vim may give E121 or E720 in this case, but it does not look - // right to have either because both are results of reevaluation - // possibly-lambda node as a dictionary and here this is not going - // to happen. - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E15: Expected lambda arguments list or arrow: %.*s")); - } else { - // Else it may appear that possibly-lambda node is actually - // a dictionary or curly-braces-name identifier. - lambda_node = NULL; - kv_drop(pt_stack, 1); - } + case kEPTExpr: + break; + case kEPTLambdaArguments: + if ((want_node == kENodeOperator + && tok_type != kExprLexComma + && tok_type != kExprLexArrow) + || (want_node == kENodeValue + && !(cur_token.type == kExprLexPlainIdentifier + && cur_token.data.var.scope == kExprVarScopeMissing + && !cur_token.data.var.autoload) + && tok_type != kExprLexArrow)) { + lambda_node->data.fig.type_guesses.allow_lambda = false; + if (lambda_node->children != NULL + && lambda_node->children->type == kExprNodeComma) { + // If lambda has comma child this means that parser has already seen + // at least "{arg1,", so node cannot possibly be anything, but + // lambda. + + // Vim may give E121 or E720 in this case, but it does not look + // right to have either because both are results of reevaluation + // possibly-lambda node as a dictionary and here this is not going + // to happen. + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E15: Expected lambda arguments list or arrow: %.*s")); + } else { + // Else it may appear that possibly-lambda node is actually + // a dictionary or curly-braces-name identifier. + lambda_node = NULL; + kv_drop(pt_stack, 1); } - break; } - case kEPTSingleAssignment: - case kEPTAssignment: { - if (want_node == kENodeValue - && tok_type != kExprLexBracket - && tok_type != kExprLexPlainIdentifier - && (tok_type != kExprLexFigureBrace || cur_token.data.brc.closing) - && !(node_is_key && tok_type == kExprLexNumber) - && tok_type != kExprLexEnv - && tok_type != kExprLexOption - && tok_type != kExprLexRegister) { - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E15: Expected value part of assignment lvalue: %.*s")); - kv_drop(pt_stack, 1); - } else if (want_node == kENodeOperator - && tok_type != kExprLexBracket - && (tok_type != kExprLexFigureBrace - || cur_token.data.brc.closing) - && tok_type != kExprLexDot - && (tok_type != kExprLexComma || !is_single_assignment) - && tok_type != kExprLexAssignment - // Curly brace identifiers: will contain plain identifier or - // another curly brace in position where operator is wanted. - && !((tok_type == kExprLexPlainIdentifier - || (tok_type == kExprLexFigureBrace - && !cur_token.data.brc.closing)) - && prev_token.type != kExprLexSpacing)) { - if (flags & kExprFlagsMulti && MAY_HAVE_NEXT_EXPR) { - goto viml_pexpr_parse_end; - } - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E15: Expected assignment operator or subscript: %.*s")); - kv_drop(pt_stack, 1); + break; + case kEPTSingleAssignment: + case kEPTAssignment: + if (want_node == kENodeValue + && tok_type != kExprLexBracket + && tok_type != kExprLexPlainIdentifier + && (tok_type != kExprLexFigureBrace || cur_token.data.brc.closing) + && !(node_is_key && tok_type == kExprLexNumber) + && tok_type != kExprLexEnv + && tok_type != kExprLexOption + && tok_type != kExprLexRegister) { + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E15: Expected value part of assignment lvalue: %.*s")); + kv_drop(pt_stack, 1); + } else if (want_node == kENodeOperator + && tok_type != kExprLexBracket + && (tok_type != kExprLexFigureBrace + || cur_token.data.brc.closing) + && tok_type != kExprLexDot + && (tok_type != kExprLexComma || !is_single_assignment) + && tok_type != kExprLexAssignment + // Curly brace identifiers: will contain plain identifier or + // another curly brace in position where operator is wanted. + && !((tok_type == kExprLexPlainIdentifier + || (tok_type == kExprLexFigureBrace + && !cur_token.data.brc.closing)) + && prev_token.type != kExprLexSpacing)) { + if (flags & kExprFlagsMulti && MAY_HAVE_NEXT_EXPR) { + goto viml_pexpr_parse_end; } - assert(kv_size(pt_stack)); - break; + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E15: Expected assignment operator or subscript: %.*s")); + kv_drop(pt_stack, 1); } + assert(kv_size(pt_stack)); + break; } assert(kv_size(pt_stack)); const ExprASTParseType cur_pt = kv_last(pt_stack); assert(lambda_node == NULL || cur_pt == kEPTLambdaArguments); switch (tok_type) { - case kExprLexMissing: - case kExprLexSpacing: - case kExprLexEOC: { - abort(); - } - case kExprLexInvalid: { - ERROR_FROM_TOKEN(cur_token); - tok_type = cur_token.data.err.type; - goto viml_pexpr_parse_process_token; - } - case kExprLexRegister: { - if (want_node == kENodeOperator) { - // Register in operator position: e.g. @a @a - OP_MISSING; - } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeRegister); - cur_node->data.reg.name = cur_token.data.reg.name; - *top_node_p = cur_node; - want_node = kENodeOperator; - HL_CUR_TOKEN(Register); - break; + case kExprLexMissing: + case kExprLexSpacing: + case kExprLexEOC: + abort(); + case kExprLexInvalid: + ERROR_FROM_TOKEN(cur_token); + tok_type = cur_token.data.err.type; + goto viml_pexpr_parse_process_token; + case kExprLexRegister: { + if (want_node == kENodeOperator) { + // Register in operator position: e.g. @a @a + OP_MISSING; } + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeRegister); + cur_node->data.reg.name = cur_token.data.reg.name; + *top_node_p = cur_node; + want_node = kENodeOperator; + HL_CUR_TOKEN(Register); + break; + } #define SIMPLE_UB_OP(op) \ - case kExprLex##op: { \ - if (want_node == kENodeValue) { \ - /* Value level: assume unary operator. */ \ - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeUnary##op); \ - *top_node_p = cur_node; \ - kvi_push(ast_stack, &cur_node->children); \ - HL_CUR_TOKEN(Unary##op); \ - } else { \ - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeBinary##op); \ - ADD_OP_NODE(cur_node); \ - HL_CUR_TOKEN(Binary##op); \ - } \ - want_node = kENodeValue; \ - break; \ - } +case kExprLex##op: { \ + if (want_node == kENodeValue) { \ + /* Value level: assume unary operator. */ \ + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeUnary##op); \ + *top_node_p = cur_node; \ + kvi_push(ast_stack, &cur_node->children); \ + HL_CUR_TOKEN(Unary##op); \ + } else { \ + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeBinary##op); \ + ADD_OP_NODE(cur_node); \ + HL_CUR_TOKEN(Binary##op); \ + } \ + want_node = kENodeValue; \ + break; \ +} SIMPLE_UB_OP(Plus) SIMPLE_UB_OP(Minus) #undef SIMPLE_UB_OP #define SIMPLE_B_OP(op, msg) \ - case kExprLex##op: { \ - ADD_VALUE_IF_MISSING(_("E15: Unexpected " msg ": %.*s")); \ - NEW_NODE_WITH_CUR_POS(cur_node, kExprNode##op); \ - HL_CUR_TOKEN(op); \ - ADD_OP_NODE(cur_node); \ - break; \ - } +case kExprLex##op: { \ + ADD_VALUE_IF_MISSING(_("E15: Unexpected " msg ": %.*s")); \ + NEW_NODE_WITH_CUR_POS(cur_node, kExprNode##op); \ + HL_CUR_TOKEN(op); \ + ADD_OP_NODE(cur_node); \ + break; \ +} SIMPLE_B_OP(Or, "or operator") SIMPLE_B_OP(And, "and operator") #undef SIMPLE_B_OP - case kExprLexMultiplication: { - ADD_VALUE_IF_MISSING( - _("E15: Unexpected multiplication-like operator: %.*s")); - switch (cur_token.data.mul.type) { + case kExprLexMultiplication: + ADD_VALUE_IF_MISSING(_("E15: Unexpected multiplication-like operator: %.*s")); + switch (cur_token.data.mul.type) { #define MUL_OP(lex_op_tail, node_op_tail) \ - case kExprLexMul##lex_op_tail: { \ - NEW_NODE_WITH_CUR_POS(cur_node, kExprNode##node_op_tail); \ - HL_CUR_TOKEN(node_op_tail); \ - break; \ - } - MUL_OP(Mul, Multiplication) - MUL_OP(Div, Division) - MUL_OP(Mod, Mod) +case kExprLexMul##lex_op_tail: { \ + NEW_NODE_WITH_CUR_POS(cur_node, kExprNode##node_op_tail); \ + HL_CUR_TOKEN(node_op_tail); \ + break; \ +} + MUL_OP(Mul, Multiplication) + MUL_OP(Div, Division) + MUL_OP(Mod, Mod) #undef MUL_OP - } - ADD_OP_NODE(cur_node); - break; } - case kExprLexOption: { - if (want_node == kENodeOperator) { - OP_MISSING; - } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeOption); - if (cur_token.type == kExprLexInvalid) { - assert(cur_token.len == 1 - || (cur_token.len == 3 - && pline.data[cur_token.start.col + 2] == ':')); - cur_node->data.opt.ident = ( - pline.data + cur_token.start.col + cur_token.len); - cur_node->data.opt.ident_len = 0; - cur_node->data.opt.scope = ( - cur_token.len == 3 + ADD_OP_NODE(cur_node); + break; + case kExprLexOption: { + if (want_node == kENodeOperator) { + OP_MISSING; + } + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeOption); + if (cur_token.type == kExprLexInvalid) { + assert(cur_token.len == 1 + || (cur_token.len == 3 + && pline.data[cur_token.start.col + 2] == ':')); + cur_node->data.opt.ident = ( + pline.data + cur_token.start.col + cur_token.len); + cur_node->data.opt.ident_len = 0; + cur_node->data.opt.scope = ( + cur_token.len == 3 ? (ExprOptScope)pline.data[cur_token.start.col + 1] : kExprOptScopeUnspecified); - } else { - cur_node->data.opt.ident = cur_token.data.opt.name; - cur_node->data.opt.ident_len = cur_token.data.opt.len; - cur_node->data.opt.scope = cur_token.data.opt.scope; - } + } else { + cur_node->data.opt.ident = cur_token.data.opt.name; + cur_node->data.opt.ident_len = cur_token.data.opt.len; + cur_node->data.opt.scope = cur_token.data.opt.scope; + } + *top_node_p = cur_node; + want_node = kENodeOperator; + viml_parser_highlight(pstate, cur_token.start, 1, HL(OptionSigil)); + const size_t scope_shift = ( + cur_token.data.opt.scope == kExprOptScopeUnspecified ? 0 : 2); + if (scope_shift) { + viml_parser_highlight(pstate, shifted_pos(cur_token.start, 1), 1, + HL(OptionScope)); + viml_parser_highlight(pstate, shifted_pos(cur_token.start, 2), 1, + HL(OptionScopeDelimiter)); + } + viml_parser_highlight(pstate, shifted_pos(cur_token.start, scope_shift + 1), + cur_token.len - (scope_shift + 1), HL(OptionName)); + break; + } + case kExprLexEnv: + if (want_node == kENodeOperator) { + OP_MISSING; + } + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeEnvironment); + cur_node->data.env.ident = pline.data + cur_token.start.col + 1; + cur_node->data.env.ident_len = cur_token.len - 1; + if (cur_node->data.env.ident_len == 0) { + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E15: Environment variable name missing")); + } + *top_node_p = cur_node; + want_node = kENodeOperator; + viml_parser_highlight(pstate, cur_token.start, 1, HL(EnvironmentSigil)); + viml_parser_highlight(pstate, shifted_pos(cur_token.start, 1), + cur_token.len - 1, HL(EnvironmentName)); + break; + case kExprLexNot: + if (want_node == kENodeOperator) { + OP_MISSING; + } + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeNot); + *top_node_p = cur_node; + kvi_push(ast_stack, &cur_node->children); + HL_CUR_TOKEN(Not); + break; + case kExprLexComparison: + ADD_VALUE_IF_MISSING(_("E15: Expected value, got comparison operator: %.*s")); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeComparison); + if (cur_token.type == kExprLexInvalid) { + cur_node->data.cmp.ccs = kCCStrategyUseOption; + cur_node->data.cmp.type = kExprCmpEqual; + cur_node->data.cmp.inv = false; + } else { + cur_node->data.cmp.ccs = cur_token.data.cmp.ccs; + cur_node->data.cmp.type = cur_token.data.cmp.type; + cur_node->data.cmp.inv = cur_token.data.cmp.inv; + } + ADD_OP_NODE(cur_node); + if (cur_token.data.cmp.ccs != kCCStrategyUseOption) { + viml_parser_highlight(pstate, cur_token.start, cur_token.len - 1, + HL(Comparison)); + viml_parser_highlight(pstate, shifted_pos(cur_token.start, cur_token.len - 1), 1, + HL(ComparisonModifier)); + } else { + HL_CUR_TOKEN(Comparison); + } + want_node = kENodeValue; + break; + case kExprLexComma: + assert(!(want_node == kENodeValue && cur_pt == kEPTLambdaArguments)); + if (want_node == kENodeValue) { + // Value level: comma appearing here is not valid. + // Note: in Vim string(,x) will give E116, this is not the case here. + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Expected value, got comma: %.*s")); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeMissing); + cur_node->len = 0; *top_node_p = cur_node; want_node = kENodeOperator; - viml_parser_highlight(pstate, cur_token.start, 1, HL(OptionSigil)); - const size_t scope_shift = ( - cur_token.data.opt.scope == kExprOptScopeUnspecified ? 0 : 2); - if (scope_shift) { - viml_parser_highlight(pstate, shifted_pos(cur_token.start, 1), 1, - HL(OptionScope)); - viml_parser_highlight(pstate, shifted_pos(cur_token.start, 2), 1, - HL(OptionScopeDelimiter)); - } - viml_parser_highlight( - pstate, shifted_pos(cur_token.start, scope_shift + 1), - cur_token.len - (scope_shift + 1), HL(OptionName)); - break; } - case kExprLexEnv: { - if (want_node == kENodeOperator) { - OP_MISSING; - } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeEnvironment); - cur_node->data.env.ident = pline.data + cur_token.start.col + 1; - cur_node->data.env.ident_len = cur_token.len - 1; - if (cur_node->data.env.ident_len == 0) { + if (cur_pt == kEPTLambdaArguments) { + assert(lambda_node != NULL); + assert(lambda_node->data.fig.type_guesses.allow_lambda); + SELECT_FIGURE_BRACE_TYPE(lambda_node, Lambda, Lambda); + } + if (kv_size(ast_stack) < 2) { + goto viml_pexpr_parse_invalid_comma; + } + for (size_t i = 1; i < kv_size(ast_stack); i++) { + ExprASTNode *const *const eastnode_p = + (ExprASTNode *const *)kv_Z(ast_stack, i); + const ExprASTNodeType eastnode_type = (*eastnode_p)->type; + const ExprOpLvl eastnode_lvl = node_lvl(**eastnode_p); + if (eastnode_type == kExprNodeLambda) { + assert(cur_pt == kEPTLambdaArguments + && want_node == kENodeOperator); + break; + } else if (eastnode_type == kExprNodeDictLiteral + || eastnode_type == kExprNodeListLiteral + || eastnode_type == kExprNodeCall) { + break; + } else if (eastnode_type == kExprNodeComma + || eastnode_type == kExprNodeColon + || eastnode_lvl > kEOpLvlComma) { + // Do nothing + } else { +viml_pexpr_parse_invalid_comma: ERROR_FROM_TOKEN_AND_MSG(cur_token, - _("E15: Environment variable name missing")); + _("E15: Comma outside of call, lambda or literal: %.*s")); + break; + } + if (i == kv_size(ast_stack) - 1) { + goto viml_pexpr_parse_invalid_comma; } - *top_node_p = cur_node; - want_node = kENodeOperator; - viml_parser_highlight(pstate, cur_token.start, 1, HL(EnvironmentSigil)); - viml_parser_highlight(pstate, shifted_pos(cur_token.start, 1), - cur_token.len - 1, HL(EnvironmentName)); - break; } - case kExprLexNot: { - if (want_node == kENodeOperator) { - OP_MISSING; + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeComma); + ADD_OP_NODE(cur_node); + HL_CUR_TOKEN(Comma); + break; +#define EXP_VAL_COLON "E15: Expected value, got colon: %.*s" + case kExprLexColon: { + bool is_ternary = false; + if (kv_size(ast_stack) < 2) { + goto viml_pexpr_parse_invalid_colon; + } + bool can_be_ternary = true; + bool is_subscript = false; + for (size_t i = 1; i < kv_size(ast_stack); i++) { + ExprASTNode *const *const eastnode_p = + (ExprASTNode *const *)kv_Z(ast_stack, i); + const ExprASTNodeType eastnode_type = (*eastnode_p)->type; + const ExprOpLvl eastnode_lvl = node_lvl(**eastnode_p); + STATIC_ASSERT(kEOpLvlTernary > kEOpLvlComma, + "Unexpected operator priorities"); + if (can_be_ternary && eastnode_type == kExprNodeTernaryValue + && !(*eastnode_p)->data.ter.got_colon) { + kv_drop(ast_stack, i); + (*eastnode_p)->start = cur_token.start; + (*eastnode_p)->len = cur_token.len; + if (prev_token.type == kExprLexSpacing) { + (*eastnode_p)->start = prev_token.start; + (*eastnode_p)->len += prev_token.len; + } + is_ternary = true; + (*eastnode_p)->data.ter.got_colon = true; + ADD_VALUE_IF_MISSING(_(EXP_VAL_COLON)); + assert((*eastnode_p)->children != NULL); + assert((*eastnode_p)->children->next == NULL); + kvi_push(ast_stack, &(*eastnode_p)->children->next); + break; + } else if (eastnode_type == kExprNodeUnknownFigure) { + SELECT_FIGURE_BRACE_TYPE(*eastnode_p, DictLiteral, Dict); + break; + } else if (eastnode_type == kExprNodeDictLiteral) { + break; + } else if (eastnode_type == kExprNodeSubscript) { + is_subscript = true; + // can_be_ternary = false; + assert(!is_ternary); + break; + } else if (eastnode_type == kExprNodeColon) { + goto viml_pexpr_parse_invalid_colon; + } else if (eastnode_lvl >= kEOpLvlTernaryValue) { + // Do nothing + } else if (eastnode_lvl >= kEOpLvlComma) { + can_be_ternary = false; + } else { + goto viml_pexpr_parse_invalid_colon; + } + if (i == kv_size(ast_stack) - 1) { + goto viml_pexpr_parse_invalid_colon; } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeNot); - *top_node_p = cur_node; - kvi_push(ast_stack, &cur_node->children); - HL_CUR_TOKEN(Not); - break; } - case kExprLexComparison: { - ADD_VALUE_IF_MISSING( - _("E15: Expected value, got comparison operator: %.*s")); - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeComparison); - if (cur_token.type == kExprLexInvalid) { - cur_node->data.cmp.ccs = kCCStrategyUseOption; - cur_node->data.cmp.type = kExprCmpEqual; - cur_node->data.cmp.inv = false; + if (is_subscript) { + assert(kv_size(ast_stack) > 1); + // Colon immediately following subscript start: it is empty subscript + // part like a[:2]. + if (want_node == kENodeValue + && (*kv_Z(ast_stack, 1))->type == kExprNodeSubscript) { + NEW_NODE_WITH_CUR_POS(*top_node_p, kExprNodeMissing); + (*top_node_p)->len = 0; + want_node = kENodeOperator; } else { - cur_node->data.cmp.ccs = cur_token.data.cmp.ccs; - cur_node->data.cmp.type = cur_token.data.cmp.type; - cur_node->data.cmp.inv = cur_token.data.cmp.inv; + ADD_VALUE_IF_MISSING(_(EXP_VAL_COLON)); } + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeColon); ADD_OP_NODE(cur_node); - if (cur_token.data.cmp.ccs != kCCStrategyUseOption) { - viml_parser_highlight(pstate, cur_token.start, cur_token.len - 1, - HL(Comparison)); - viml_parser_highlight( - pstate, shifted_pos(cur_token.start, cur_token.len - 1), 1, - HL(ComparisonModifier)); + HL_CUR_TOKEN(SubscriptColon); + } else { + goto viml_pexpr_parse_valid_colon; +viml_pexpr_parse_invalid_colon: + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E15: Colon outside of dictionary or ternary operator: %.*s")); +viml_pexpr_parse_valid_colon: + ADD_VALUE_IF_MISSING(_(EXP_VAL_COLON)); + if (is_ternary) { + HL_CUR_TOKEN(TernaryColon); } else { - HL_CUR_TOKEN(Comparison); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeColon); + ADD_OP_NODE(cur_node); + HL_CUR_TOKEN(Colon); } - want_node = kENodeValue; - break; } - case kExprLexComma: { - assert(!(want_node == kENodeValue && cur_pt == kEPTLambdaArguments)); - if (want_node == kENodeValue) { - // Value level: comma appearing here is not valid. - // Note: in Vim string(,x) will give E116, this is not the case here. - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E15: Expected value, got comma: %.*s")); - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeMissing); + want_node = kENodeValue; + break; + } +#undef EXP_VAL_COLON + case kExprLexBracket: + if (cur_token.data.brc.closing) { + ExprASTNode **new_top_node_p = NULL; + // Always drop the topmost value: + // + // 1. When want_node != kENodeValue topmost item on stack is + // a *finished* left operand, which may as well be "{@a}" which + // needs not be finished again. + // 2. Otherwise it is pointing to NULL what nobody wants. + kv_drop(ast_stack, 1); + if (!kv_size(ast_stack)) { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeListLiteral); cur_node->len = 0; + if (want_node != kENodeValue) { + cur_node->children = *top_node_p; + } *top_node_p = cur_node; - want_node = kENodeOperator; - } - if (cur_pt == kEPTLambdaArguments) { - assert(lambda_node != NULL); - assert(lambda_node->data.fig.type_guesses.allow_lambda); - SELECT_FIGURE_BRACE_TYPE(lambda_node, Lambda, Lambda); + goto viml_pexpr_parse_bracket_closing_error; } - if (kv_size(ast_stack) < 2) { - goto viml_pexpr_parse_invalid_comma; + if (want_node == kENodeValue) { + // It is OK to want value if + // + // 1. It is empty list literal, in which case top node will be + // ListLiteral. + // 2. It is list literal with trailing comma, in which case top node + // will be that comma. + // 3. It is subscript with colon, but without one of the values: + // e.g. "a[:]", "a[1:]", top node will be colon in this case. + if ((*kv_last(ast_stack))->type != kExprNodeListLiteral + && (*kv_last(ast_stack))->type != kExprNodeComma + && (*kv_last(ast_stack))->type != kExprNodeColon) { + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E15: Expected value, got closing bracket: %.*s")); + } } - for (size_t i = 1; i < kv_size(ast_stack); i++) { - ExprASTNode *const *const eastnode_p = - (ExprASTNode *const *)kv_Z(ast_stack, i); - const ExprASTNodeType eastnode_type = (*eastnode_p)->type; - const ExprOpLvl eastnode_lvl = node_lvl(**eastnode_p); - if (eastnode_type == kExprNodeLambda) { - assert(cur_pt == kEPTLambdaArguments - && want_node == kENodeOperator); - break; - } else if (eastnode_type == kExprNodeDictLiteral - || eastnode_type == kExprNodeListLiteral - || eastnode_type == kExprNodeCall) { - break; - } else if (eastnode_type == kExprNodeComma - || eastnode_type == kExprNodeColon - || eastnode_lvl > kEOpLvlComma) { - // Do nothing - } else { -viml_pexpr_parse_invalid_comma: - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E15: Comma outside of call, lambda or literal: %.*s")); - break; + do { + new_top_node_p = kv_pop(ast_stack); + } while (kv_size(ast_stack) + && (new_top_node_p == NULL + || ((*new_top_node_p)->type != kExprNodeListLiteral + && (*new_top_node_p)->type != kExprNodeSubscript))); + ExprASTNode *new_top_node = *new_top_node_p; + switch (new_top_node->type) { + case kExprNodeListLiteral: + if (pt_is_assignment(cur_pt) && new_top_node->children == NULL) { + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E475: Unable to assign to empty list: %.*s")); } - if (i == kv_size(ast_stack) - 1) { - goto viml_pexpr_parse_invalid_comma; + HL_CUR_TOKEN(List); + break; + case kExprNodeSubscript: + HL_CUR_TOKEN(SubscriptBracket); + break; + default: +viml_pexpr_parse_bracket_closing_error: + assert(!kv_size(ast_stack)); + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Unexpected closing figure brace: %.*s")); + HL_CUR_TOKEN(List); + break; + } + kvi_push(ast_stack, new_top_node_p); + want_node = kENodeOperator; + if (kv_size(ast_stack) <= asgn_level) { + assert(kv_size(ast_stack) == asgn_level); + asgn_level = 0; + if (cur_pt == kEPTAssignment) { + assert(ast.err.msg); + } else if (cur_pt == kEPTExpr + && kv_size(pt_stack) > 1 + && pt_is_assignment(kv_Z(pt_stack, 1))) { + kv_drop(pt_stack, 1); } } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeComma); - ADD_OP_NODE(cur_node); - HL_CUR_TOKEN(Comma); - break; - } -#define EXP_VAL_COLON "E15: Expected value, got colon: %.*s" - case kExprLexColon: { - bool is_ternary = false; - if (kv_size(ast_stack) < 2) { - goto viml_pexpr_parse_invalid_colon; + if (cur_pt == kEPTSingleAssignment && kv_size(ast_stack) == 1) { + kv_drop(pt_stack, 1); } - bool can_be_ternary = true; - bool is_subscript = false; - for (size_t i = 1; i < kv_size(ast_stack); i++) { - ExprASTNode *const *const eastnode_p = - (ExprASTNode *const *)kv_Z(ast_stack, i); - const ExprASTNodeType eastnode_type = (*eastnode_p)->type; - const ExprOpLvl eastnode_lvl = node_lvl(**eastnode_p); - STATIC_ASSERT(kEOpLvlTernary > kEOpLvlComma, - "Unexpected operator priorities"); - if (can_be_ternary && eastnode_type == kExprNodeTernaryValue - && !(*eastnode_p)->data.ter.got_colon) { - kv_drop(ast_stack, i); - (*eastnode_p)->start = cur_token.start; - (*eastnode_p)->len = cur_token.len; - if (prev_token.type == kExprLexSpacing) { - (*eastnode_p)->start = prev_token.start; - (*eastnode_p)->len += prev_token.len; - } - is_ternary = true; - (*eastnode_p)->data.ter.got_colon = true; - ADD_VALUE_IF_MISSING(_(EXP_VAL_COLON)); - assert((*eastnode_p)->children != NULL); - assert((*eastnode_p)->children->next == NULL); - kvi_push(ast_stack, &(*eastnode_p)->children->next); - break; - } else if (eastnode_type == kExprNodeUnknownFigure) { - SELECT_FIGURE_BRACE_TYPE(*eastnode_p, DictLiteral, Dict); - break; - } else if (eastnode_type == kExprNodeDictLiteral) { - break; - } else if (eastnode_type == kExprNodeSubscript) { - is_subscript = true; - // can_be_ternary = false; - assert(!is_ternary); - break; - } else if (eastnode_type == kExprNodeColon) { - goto viml_pexpr_parse_invalid_colon; - } else if (eastnode_lvl >= kEOpLvlTernaryValue) { - // Do nothing - } else if (eastnode_lvl >= kEOpLvlComma) { - can_be_ternary = false; - } else { - goto viml_pexpr_parse_invalid_colon; - } - if (i == kv_size(ast_stack) - 1) { - goto viml_pexpr_parse_invalid_colon; + } else { + if (want_node == kENodeValue) { + // Value means list literal or list assignment. + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeListLiteral); + *top_node_p = cur_node; + kvi_push(ast_stack, &cur_node->children); + want_node = kENodeValue; + if (cur_pt == kEPTAssignment) { + // Additional assignment parse type allows to easily forbid nested + // lists. + kvi_push(pt_stack, kEPTSingleAssignment); + } else if (cur_pt == kEPTSingleAssignment) { + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E475: Nested lists not allowed when assigning: %.*s")); } - } - if (is_subscript) { - assert(kv_size(ast_stack) > 1); - // Colon immediately following subscript start: it is empty subscript - // part like a[:2]. - if (want_node == kENodeValue - && (*kv_Z(ast_stack, 1))->type == kExprNodeSubscript) { - NEW_NODE_WITH_CUR_POS(*top_node_p, kExprNodeMissing); - (*top_node_p)->len = 0; - want_node = kENodeOperator; - } else { - ADD_VALUE_IF_MISSING(_(EXP_VAL_COLON)); + HL_CUR_TOKEN(List); + } else { + // Operator means subscript, also in assignment. But in assignment + // subscript may be pretty much any expression, so need to push + // kEPTExpr. + if (prev_token.type == kExprLexSpacing) { + OP_MISSING; } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeColon); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeSubscript); ADD_OP_NODE(cur_node); - HL_CUR_TOKEN(SubscriptColon); - } else { - goto viml_pexpr_parse_valid_colon; -viml_pexpr_parse_invalid_colon: - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E15: Colon outside of dictionary or ternary operator: %.*s")); -viml_pexpr_parse_valid_colon: - ADD_VALUE_IF_MISSING(_(EXP_VAL_COLON)); - if (is_ternary) { - HL_CUR_TOKEN(TernaryColon); - } else { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeColon); - ADD_OP_NODE(cur_node); - HL_CUR_TOKEN(Colon); + HL_CUR_TOKEN(SubscriptBracket); + if (pt_is_assignment(cur_pt)) { + assert(want_node == kENodeValue); // Subtract 1 for NULL at top. + asgn_level = kv_size(ast_stack) - 1; + kvi_push(pt_stack, kEPTExpr); } } - want_node = kENodeValue; - break; } -#undef EXP_VAL_COLON - case kExprLexBracket: { - if (cur_token.data.brc.closing) { - ExprASTNode **new_top_node_p = NULL; - // Always drop the topmost value: - // - // 1. When want_node != kENodeValue topmost item on stack is - // a *finished* left operand, which may as well be "{@a}" which - // needs not be finished again. - // 2. Otherwise it is pointing to NULL what nobody wants. - kv_drop(ast_stack, 1); - if (!kv_size(ast_stack)) { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeListLiteral); - cur_node->len = 0; - if (want_node != kENodeValue) { - cur_node->children = *top_node_p; - } - *top_node_p = cur_node; - goto viml_pexpr_parse_bracket_closing_error; - } - if (want_node == kENodeValue) { - // It is OK to want value if - // - // 1. It is empty list literal, in which case top node will be - // ListLiteral. - // 2. It is list literal with trailing comma, in which case top node - // will be that comma. - // 3. It is subscript with colon, but without one of the values: - // e.g. "a[:]", "a[1:]", top node will be colon in this case. - if ((*kv_last(ast_stack))->type != kExprNodeListLiteral - && (*kv_last(ast_stack))->type != kExprNodeComma - && (*kv_last(ast_stack))->type != kExprNodeColon) { - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E15: Expected value, got closing bracket: %.*s")); - } + break; + case kExprLexFigureBrace: + if (cur_token.data.brc.closing) { + ExprASTNode **new_top_node_p = NULL; + // Always drop the topmost value: + // + // 1. When want_node != kENodeValue topmost item on stack is + // a *finished* left operand, which may as well be "{@a}" which + // needs not be finished again. + // 2. Otherwise it is pointing to NULL what nobody wants. + kv_drop(ast_stack, 1); + if (!kv_size(ast_stack)) { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeUnknownFigure); + cur_node->data.fig.type_guesses.allow_lambda = false; + cur_node->data.fig.type_guesses.allow_dict = false; + cur_node->data.fig.type_guesses.allow_ident = false; + cur_node->len = 0; + if (want_node != kENodeValue) { + cur_node->children = *top_node_p; } - do { - new_top_node_p = kv_pop(ast_stack); - } while (kv_size(ast_stack) - && (new_top_node_p == NULL - || ((*new_top_node_p)->type != kExprNodeListLiteral - && (*new_top_node_p)->type != kExprNodeSubscript))); - ExprASTNode *new_top_node = *new_top_node_p; - switch (new_top_node->type) { - case kExprNodeListLiteral: { - if (pt_is_assignment(cur_pt) && new_top_node->children == NULL) { - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E475: Unable to assign to empty list: %.*s")); - } - HL_CUR_TOKEN(List); - break; - } - case kExprNodeSubscript: { - HL_CUR_TOKEN(SubscriptBracket); - break; - } - default: { -viml_pexpr_parse_bracket_closing_error: - assert(!kv_size(ast_stack)); - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E15: Unexpected closing figure brace: %.*s")); - HL_CUR_TOKEN(List); - break; - } + *top_node_p = cur_node; + new_top_node_p = top_node_p; + goto viml_pexpr_parse_figure_brace_closing_error; + } + if (want_node == kENodeValue) { + if ((*kv_last(ast_stack))->type != kExprNodeUnknownFigure + && (*kv_last(ast_stack))->type != kExprNodeComma) { + // kv_last being UnknownFigure may occur for empty dictionary + // literal, while Comma is expected in case of non-empty one. + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E15: Expected value, got closing figure brace: %.*s")); } - kvi_push(ast_stack, new_top_node_p); - want_node = kENodeOperator; - if (kv_size(ast_stack) <= asgn_level) { - assert(kv_size(ast_stack) == asgn_level); - asgn_level = 0; - if (cur_pt == kEPTAssignment) { - assert(ast.err.msg); - } else if (cur_pt == kEPTExpr - && kv_size(pt_stack) > 1 - && pt_is_assignment(kv_Z(pt_stack, 1))) { - kv_drop(pt_stack, 1); + } + do { + new_top_node_p = kv_pop(ast_stack); + } while (kv_size(ast_stack) + && (new_top_node_p == NULL + || ((*new_top_node_p)->type != kExprNodeUnknownFigure + && (*new_top_node_p)->type != kExprNodeDictLiteral + && ((*new_top_node_p)->type + != kExprNodeCurlyBracesIdentifier) + && (*new_top_node_p)->type != kExprNodeLambda))); + ExprASTNode *new_top_node = *new_top_node_p; + switch (new_top_node->type) { + case kExprNodeUnknownFigure: + if (new_top_node->children == NULL) { + // No children of curly braces node indicates empty dictionary. + assert(want_node == kENodeValue); + assert(new_top_node->data.fig.type_guesses.allow_dict); + SELECT_FIGURE_BRACE_TYPE(new_top_node, DictLiteral, Dict); + HL_CUR_TOKEN(Dict); + } else if (new_top_node->data.fig.type_guesses.allow_ident) { + SELECT_FIGURE_BRACE_TYPE(new_top_node, CurlyBracesIdentifier, + Curly); + HL_CUR_TOKEN(Curly); + } else { + // If by this time type of the node has not already been + // guessed, but it definitely is not a curly braces name then + // it is invalid for sure. + ERROR_FROM_NODE_AND_MSG(new_top_node, + _("E15: Don't know what figure brace means: %.*s")); + if (pstate->colors) { + // Will reset to NvimInvalidFigureBrace. + kv_A(*pstate->colors, + new_top_node->data.fig.opening_hl_idx).group = ( + HL(FigureBrace)); } + HL_CUR_TOKEN(FigureBrace); } - if (cur_pt == kEPTSingleAssignment && kv_size(ast_stack) == 1) { + break; + case kExprNodeDictLiteral: + HL_CUR_TOKEN(Dict); + break; + case kExprNodeCurlyBracesIdentifier: + HL_CUR_TOKEN(Curly); + break; + case kExprNodeLambda: + HL_CUR_TOKEN(Lambda); + break; + default: +viml_pexpr_parse_figure_brace_closing_error: + assert(!kv_size(ast_stack)); + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Unexpected closing figure brace: %.*s")); + HL_CUR_TOKEN(FigureBrace); + break; + } + kvi_push(ast_stack, new_top_node_p); + want_node = kENodeOperator; + if (kv_size(ast_stack) <= asgn_level) { + assert(kv_size(ast_stack) == asgn_level); + if (cur_pt == kEPTExpr + && kv_size(pt_stack) > 1 + && pt_is_assignment(kv_Z(pt_stack, 1))) { kv_drop(pt_stack, 1); - } - } else { - if (want_node == kENodeValue) { - // Value means list literal or list assignment. - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeListLiteral); - *top_node_p = cur_node; - kvi_push(ast_stack, &cur_node->children); - want_node = kENodeValue; - if (cur_pt == kEPTAssignment) { - // Additional assignment parse type allows to easily forbid nested - // lists. - kvi_push(pt_stack, kEPTSingleAssignment); - } else if (cur_pt == kEPTSingleAssignment) { - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E475: Nested lists not allowed when assigning: %.*s")); - } - HL_CUR_TOKEN(List); - } else { - // Operator means subscript, also in assignment. But in assignment - // subscript may be pretty much any expression, so need to push - // kEPTExpr. - if (prev_token.type == kExprLexSpacing) { - OP_MISSING; - } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeSubscript); - ADD_OP_NODE(cur_node); - HL_CUR_TOKEN(SubscriptBracket); - if (pt_is_assignment(cur_pt)) { - assert(want_node == kENodeValue); // Subtract 1 for NULL at top. - asgn_level = kv_size(ast_stack) - 1; - kvi_push(pt_stack, kEPTExpr); - } + asgn_level = 0; } } - break; - } - case kExprLexFigureBrace: { - if (cur_token.data.brc.closing) { - ExprASTNode **new_top_node_p = NULL; - // Always drop the topmost value: - // - // 1. When want_node != kENodeValue topmost item on stack is - // a *finished* left operand, which may as well be "{@a}" which - // needs not be finished again. - // 2. Otherwise it is pointing to NULL what nobody wants. - kv_drop(ast_stack, 1); - if (!kv_size(ast_stack)) { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeUnknownFigure); + } else { + if (want_node == kENodeValue) { + HL_CUR_TOKEN(FigureBrace); + // Value: may be any of lambda, dictionary literal and curly braces + // name. + + // Though if we are in an assignment this may only be a curly braces + // name. + if (pt_is_assignment(cur_pt)) { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeCurlyBracesIdentifier); cur_node->data.fig.type_guesses.allow_lambda = false; cur_node->data.fig.type_guesses.allow_dict = false; - cur_node->data.fig.type_guesses.allow_ident = false; - cur_node->len = 0; - if (want_node != kENodeValue) { - cur_node->children = *top_node_p; - } - *top_node_p = cur_node; - new_top_node_p = top_node_p; - goto viml_pexpr_parse_figure_brace_closing_error; - } - if (want_node == kENodeValue) { - if ((*kv_last(ast_stack))->type != kExprNodeUnknownFigure - && (*kv_last(ast_stack))->type != kExprNodeComma) { - // kv_last being UnknownFigure may occur for empty dictionary - // literal, while Comma is expected in case of non-empty one. - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E15: Expected value, got closing figure brace: %.*s")); - } - } - do { - new_top_node_p = kv_pop(ast_stack); - } while (kv_size(ast_stack) - && (new_top_node_p == NULL - || ((*new_top_node_p)->type != kExprNodeUnknownFigure - && (*new_top_node_p)->type != kExprNodeDictLiteral - && ((*new_top_node_p)->type - != kExprNodeCurlyBracesIdentifier) - && (*new_top_node_p)->type != kExprNodeLambda))); - ExprASTNode *new_top_node = *new_top_node_p; - switch (new_top_node->type) { - case kExprNodeUnknownFigure: { - if (new_top_node->children == NULL) { - // No children of curly braces node indicates empty dictionary. - assert(want_node == kENodeValue); - assert(new_top_node->data.fig.type_guesses.allow_dict); - SELECT_FIGURE_BRACE_TYPE(new_top_node, DictLiteral, Dict); - HL_CUR_TOKEN(Dict); - } else if (new_top_node->data.fig.type_guesses.allow_ident) { - SELECT_FIGURE_BRACE_TYPE(new_top_node, CurlyBracesIdentifier, - Curly); - HL_CUR_TOKEN(Curly); - } else { - // If by this time type of the node has not already been - // guessed, but it definitely is not a curly braces name then - // it is invalid for sure. - ERROR_FROM_NODE_AND_MSG( - new_top_node, - _("E15: Don't know what figure brace means: %.*s")); - if (pstate->colors) { - // Will reset to NvimInvalidFigureBrace. - kv_A(*pstate->colors, - new_top_node->data.fig.opening_hl_idx).group = ( - HL(FigureBrace)); - } - HL_CUR_TOKEN(FigureBrace); - } - break; - } - case kExprNodeDictLiteral: { - HL_CUR_TOKEN(Dict); - break; - } - case kExprNodeCurlyBracesIdentifier: { - HL_CUR_TOKEN(Curly); - break; - } - case kExprNodeLambda: { - HL_CUR_TOKEN(Lambda); - break; - } - default: { -viml_pexpr_parse_figure_brace_closing_error: - assert(!kv_size(ast_stack)); - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E15: Unexpected closing figure brace: %.*s")); - HL_CUR_TOKEN(FigureBrace); - break; - } + cur_node->data.fig.type_guesses.allow_ident = true; + kvi_push(pt_stack, kEPTExpr); + } else { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeUnknownFigure); + cur_node->data.fig.type_guesses.allow_lambda = true; + cur_node->data.fig.type_guesses.allow_dict = true; + cur_node->data.fig.type_guesses.allow_ident = true; } - kvi_push(ast_stack, new_top_node_p); - want_node = kENodeOperator; - if (kv_size(ast_stack) <= asgn_level) { - assert(kv_size(ast_stack) == asgn_level); - if (cur_pt == kEPTExpr - && kv_size(pt_stack) > 1 - && pt_is_assignment(kv_Z(pt_stack, 1))) { - kv_drop(pt_stack, 1); - asgn_level = 0; - } + if (pstate->colors) { + cur_node->data.fig.opening_hl_idx = kv_size(*pstate->colors) - 1; } + *top_node_p = cur_node; + kvi_push(ast_stack, &cur_node->children); + kvi_push(pt_stack, kEPTLambdaArguments); + lambda_node = cur_node; } else { - if (want_node == kENodeValue) { - HL_CUR_TOKEN(FigureBrace); - // Value: may be any of lambda, dictionary literal and curly braces - // name. - - // Though if we are in an assignment this may only be a curly braces - // name. + ADD_IDENT(do { + NEW_NODE_WITH_CUR_POS(cur_node, + kExprNodeCurlyBracesIdentifier); + cur_node->data.fig.opening_hl_idx = kv_size(*pstate->colors); + cur_node->data.fig.type_guesses.allow_lambda = false; + cur_node->data.fig.type_guesses.allow_dict = false; + cur_node->data.fig.type_guesses.allow_ident = true; + kvi_push(ast_stack, &cur_node->children); if (pt_is_assignment(cur_pt)) { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeCurlyBracesIdentifier); - cur_node->data.fig.type_guesses.allow_lambda = false; - cur_node->data.fig.type_guesses.allow_dict = false; - cur_node->data.fig.type_guesses.allow_ident = true; kvi_push(pt_stack, kEPTExpr); - } else { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeUnknownFigure); - cur_node->data.fig.type_guesses.allow_lambda = true; - cur_node->data.fig.type_guesses.allow_dict = true; - cur_node->data.fig.type_guesses.allow_ident = true; - } - if (pstate->colors) { - cur_node->data.fig.opening_hl_idx = kv_size(*pstate->colors) - 1; } - *top_node_p = cur_node; - kvi_push(ast_stack, &cur_node->children); - kvi_push(pt_stack, kEPTLambdaArguments); - lambda_node = cur_node; - } else { - ADD_IDENT( - do { - NEW_NODE_WITH_CUR_POS(cur_node, - kExprNodeCurlyBracesIdentifier); - cur_node->data.fig.opening_hl_idx = kv_size(*pstate->colors); - cur_node->data.fig.type_guesses.allow_lambda = false; - cur_node->data.fig.type_guesses.allow_dict = false; - cur_node->data.fig.type_guesses.allow_ident = true; - kvi_push(ast_stack, &cur_node->children); - if (pt_is_assignment(cur_pt)) { - kvi_push(pt_stack, kEPTExpr); - } - want_node = kENodeValue; - } while (0), - Curly); - } - if (pt_is_assignment(cur_pt) - && !pt_is_assignment(kv_last(pt_stack))) { - assert(want_node == kENodeValue); // Subtract 1 for NULL at top. - asgn_level = kv_size(ast_stack) - 1; - } + want_node = kENodeValue; + } while (0), + Curly); + } + if (pt_is_assignment(cur_pt) + && !pt_is_assignment(kv_last(pt_stack))) { + assert(want_node == kENodeValue); // Subtract 1 for NULL at top. + asgn_level = kv_size(ast_stack) - 1; } - break; } - case kExprLexArrow: { - if (cur_pt == kEPTLambdaArguments) { - kv_drop(pt_stack, 1); - assert(kv_size(pt_stack)); - if (want_node == kENodeValue) { - // Wanting value means trailing comma and NULL at the top of the - // stack. - kv_drop(ast_stack, 1); - } - assert(kv_size(ast_stack) >= 1); - while ((*kv_last(ast_stack))->type != kExprNodeLambda - && (*kv_last(ast_stack))->type != kExprNodeUnknownFigure) { - kv_drop(ast_stack, 1); - } - assert((*kv_last(ast_stack)) == lambda_node); - SELECT_FIGURE_BRACE_TYPE(lambda_node, Lambda, Lambda); - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeArrow); - if (lambda_node->children == NULL) { - assert(want_node == kENodeValue); - lambda_node->children = cur_node; - kvi_push(ast_stack, &lambda_node->children); - } else { - assert(lambda_node->children->next == NULL); - lambda_node->children->next = cur_node; - kvi_push(ast_stack, &lambda_node->children->next); - } - kvi_push(ast_stack, &cur_node->children); - lambda_node = NULL; + break; + case kExprLexArrow: + if (cur_pt == kEPTLambdaArguments) { + kv_drop(pt_stack, 1); + assert(kv_size(pt_stack)); + if (want_node == kENodeValue) { + // Wanting value means trailing comma and NULL at the top of the + // stack. + kv_drop(ast_stack, 1); + } + assert(kv_size(ast_stack) >= 1); + while ((*kv_last(ast_stack))->type != kExprNodeLambda + && (*kv_last(ast_stack))->type != kExprNodeUnknownFigure) { + kv_drop(ast_stack, 1); + } + assert((*kv_last(ast_stack)) == lambda_node); + SELECT_FIGURE_BRACE_TYPE(lambda_node, Lambda, Lambda); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeArrow); + if (lambda_node->children == NULL) { + assert(want_node == kENodeValue); + lambda_node->children = cur_node; + kvi_push(ast_stack, &lambda_node->children); } else { - // Only first branch is valid. - ADD_VALUE_IF_MISSING(_("E15: Unexpected arrow: %.*s")); - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E15: Arrow outside of lambda: %.*s")); - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeArrow); - ADD_OP_NODE(cur_node); + assert(lambda_node->children->next == NULL); + lambda_node->children->next = cur_node; + kvi_push(ast_stack, &lambda_node->children->next); } - want_node = kENodeValue; - HL_CUR_TOKEN(Arrow); - break; + kvi_push(ast_stack, &cur_node->children); + lambda_node = NULL; + } else { + // Only first branch is valid. + ADD_VALUE_IF_MISSING(_("E15: Unexpected arrow: %.*s")); + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Arrow outside of lambda: %.*s")); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeArrow); + ADD_OP_NODE(cur_node); } - case kExprLexPlainIdentifier: { - const ExprVarScope scope = (cur_token.type == kExprLexInvalid + want_node = kENodeValue; + HL_CUR_TOKEN(Arrow); + break; + case kExprLexPlainIdentifier: { + const ExprVarScope scope = (cur_token.type == kExprLexInvalid ? kExprVarScopeMissing : cur_token.data.var.scope); - if (want_node == kENodeValue) { - want_node = kENodeOperator; - NEW_NODE_WITH_CUR_POS(cur_node, - (node_is_key + if (want_node == kENodeValue) { + want_node = kENodeOperator; + NEW_NODE_WITH_CUR_POS(cur_node, + (node_is_key ? kExprNodePlainKey : kExprNodePlainIdentifier)); - cur_node->data.var.scope = scope; - const size_t scope_shift = (scope == kExprVarScopeMissing ? 0 : 2); - cur_node->data.var.ident = (pline.data + cur_token.start.col - + scope_shift); - cur_node->data.var.ident_len = cur_token.len - scope_shift; - *top_node_p = cur_node; - if (scope_shift) { - assert(!node_is_key); - viml_parser_highlight(pstate, cur_token.start, 1, - HL(IdentifierScope)); - viml_parser_highlight(pstate, shifted_pos(cur_token.start, 1), 1, - HL(IdentifierScopeDelimiter)); - } - viml_parser_highlight(pstate, shifted_pos(cur_token.start, - scope_shift), - cur_token.len - scope_shift, - (node_is_key + cur_node->data.var.scope = scope; + const size_t scope_shift = (scope == kExprVarScopeMissing ? 0 : 2); + cur_node->data.var.ident = (pline.data + cur_token.start.col + + scope_shift); + cur_node->data.var.ident_len = cur_token.len - scope_shift; + *top_node_p = cur_node; + if (scope_shift) { + assert(!node_is_key); + viml_parser_highlight(pstate, cur_token.start, 1, + HL(IdentifierScope)); + viml_parser_highlight(pstate, shifted_pos(cur_token.start, 1), 1, + HL(IdentifierScopeDelimiter)); + } + viml_parser_highlight(pstate, shifted_pos(cur_token.start, + scope_shift), + cur_token.len - scope_shift, + (node_is_key ? HL(IdentifierKey) : HL(IdentifierName))); + } else { + if (scope == kExprVarScopeMissing) { + ADD_IDENT(do { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodePlainIdentifier); + cur_node->data.var.scope = scope; + cur_node->data.var.ident = pline.data + cur_token.start.col; + cur_node->data.var.ident_len = cur_token.len; + want_node = kENodeOperator; + } while (0), + IdentifierName); } else { - if (scope == kExprVarScopeMissing) { - ADD_IDENT( - do { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodePlainIdentifier); - cur_node->data.var.scope = scope; - cur_node->data.var.ident = pline.data + cur_token.start.col; - cur_node->data.var.ident_len = cur_token.len; - want_node = kENodeOperator; - } while (0), - IdentifierName); - } else { - OP_MISSING; - } - } - break; - } - case kExprLexNumber: { - if (want_node != kENodeValue) { OP_MISSING; } - if (node_is_key) { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodePlainKey); - cur_node->data.var.ident = pline.data + cur_token.start.col; - cur_node->data.var.ident_len = cur_token.len; - HL_CUR_TOKEN(IdentifierKey); - } else if (cur_token.data.num.is_float) { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeFloat); - cur_node->data.flt.value = cur_token.data.num.val.floating; - HL_CUR_TOKEN(Float); - } else { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeInteger); - cur_node->data.num.value = cur_token.data.num.val.integer; - const uint8_t prefix_length = base_to_prefix_length[ - cur_token.data.num.base]; - viml_parser_highlight(pstate, cur_token.start, prefix_length, - HL(NumberPrefix)); - viml_parser_highlight( - pstate, shifted_pos(cur_token.start, prefix_length), - cur_token.len - prefix_length, HL(Number)); - } - want_node = kENodeOperator; - *top_node_p = cur_node; - break; } - case kExprLexDot: { - ADD_VALUE_IF_MISSING(_("E15: Unexpected dot: %.*s")); - if (prev_token.type == kExprLexSpacing) { - if (cur_pt == kEPTAssignment) { - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E15: Cannot concatenate in assignments: %.*s")); - } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeConcat); - HL_CUR_TOKEN(Concat); - } else { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeConcatOrSubscript); - HL_CUR_TOKEN(ConcatOrSubscript); + break; + } + case kExprLexNumber: + if (want_node != kENodeValue) { + OP_MISSING; + } + if (node_is_key) { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodePlainKey); + cur_node->data.var.ident = pline.data + cur_token.start.col; + cur_node->data.var.ident_len = cur_token.len; + HL_CUR_TOKEN(IdentifierKey); + } else if (cur_token.data.num.is_float) { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeFloat); + cur_node->data.flt.value = cur_token.data.num.val.floating; + HL_CUR_TOKEN(Float); + } else { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeInteger); + cur_node->data.num.value = cur_token.data.num.val.integer; + const uint8_t prefix_length = base_to_prefix_length[ + cur_token.data.num.base]; + viml_parser_highlight(pstate, cur_token.start, prefix_length, + HL(NumberPrefix)); + viml_parser_highlight(pstate, shifted_pos(cur_token.start, prefix_length), + cur_token.len - prefix_length, HL(Number)); + } + want_node = kENodeOperator; + *top_node_p = cur_node; + break; + case kExprLexDot: + ADD_VALUE_IF_MISSING(_("E15: Unexpected dot: %.*s")); + if (prev_token.type == kExprLexSpacing) { + if (cur_pt == kEPTAssignment) { + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Cannot concatenate in assignments: %.*s")); } - ADD_OP_NODE(cur_node); - break; + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeConcat); + HL_CUR_TOKEN(Concat); + } else { + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeConcatOrSubscript); + HL_CUR_TOKEN(ConcatOrSubscript); } - case kExprLexParenthesis: { - if (cur_token.data.brc.closing) { - if (want_node == kENodeValue) { - if (kv_size(ast_stack) > 1) { - const ExprASTNode *const prev_top_node = *kv_Z(ast_stack, 1); - if (prev_top_node->type == kExprNodeCall) { - // Function call without arguments, this is not an error. - // But further code does not expect NULL nodes. - kv_drop(ast_stack, 1); - goto viml_pexpr_parse_no_paren_closing_error; - } + ADD_OP_NODE(cur_node); + break; + case kExprLexParenthesis: + if (cur_token.data.brc.closing) { + if (want_node == kENodeValue) { + if (kv_size(ast_stack) > 1) { + const ExprASTNode *const prev_top_node = *kv_Z(ast_stack, 1); + if (prev_top_node->type == kExprNodeCall) { + // Function call without arguments, this is not an error. + // But further code does not expect NULL nodes. + kv_drop(ast_stack, 1); + goto viml_pexpr_parse_no_paren_closing_error; } - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E15: Expected value, got parenthesis: %.*s")); - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeMissing); - cur_node->len = 0; - *top_node_p = cur_node; - } else { - // Always drop the topmost value: when want_node != kENodeValue - // topmost item on stack is a *finished* left operand, which may as - // well be "(@a)" which needs not be finished again. - kv_drop(ast_stack, 1); } + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Expected value, got parenthesis: %.*s")); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeMissing); + cur_node->len = 0; + *top_node_p = cur_node; + } else { + // Always drop the topmost value: when want_node != kENodeValue + // topmost item on stack is a *finished* left operand, which may as + // well be "(@a)" which needs not be finished again. + kv_drop(ast_stack, 1); + } viml_pexpr_parse_no_paren_closing_error: {} - ExprASTNode **new_top_node_p = NULL; - while (kv_size(ast_stack) - && (new_top_node_p == NULL - || ((*new_top_node_p)->type != kExprNodeNested - && (*new_top_node_p)->type != kExprNodeCall))) { - new_top_node_p = kv_pop(ast_stack); - } - if (new_top_node_p != NULL - && ((*new_top_node_p)->type == kExprNodeNested - || (*new_top_node_p)->type == kExprNodeCall)) { - if ((*new_top_node_p)->type == kExprNodeNested) { - HL_CUR_TOKEN(NestingParenthesis); - } else { - HL_CUR_TOKEN(CallingParenthesis); - } - } else { - // “Always drop the topmost value” branch has got rid of the single - // value stack had, so there is nothing known to enclose. Correct - // this. - if (new_top_node_p == NULL) { - new_top_node_p = top_node_p; - } - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E15: Unexpected closing parenthesis: %.*s")); + ExprASTNode **new_top_node_p = NULL; + while (kv_size(ast_stack) + && (new_top_node_p == NULL + || ((*new_top_node_p)->type != kExprNodeNested + && (*new_top_node_p)->type != kExprNodeCall))) { + new_top_node_p = kv_pop(ast_stack); + } + if (new_top_node_p != NULL + && ((*new_top_node_p)->type == kExprNodeNested + || (*new_top_node_p)->type == kExprNodeCall)) { + if ((*new_top_node_p)->type == kExprNodeNested) { HL_CUR_TOKEN(NestingParenthesis); - cur_node = NEW_NODE(kExprNodeNested); - cur_node->start = cur_token.start; - cur_node->len = 0; - // Unexpected closing parenthesis, assume that it was wanted to - // enclose everything in (). - cur_node->children = *new_top_node_p; - *new_top_node_p = cur_node; - assert(cur_node->next == NULL); + } else { + HL_CUR_TOKEN(CallingParenthesis); } - kvi_push(ast_stack, new_top_node_p); - want_node = kENodeOperator; } else { - switch (want_node) { - case kENodeValue: { - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeNested); - *top_node_p = cur_node; - kvi_push(ast_stack, &cur_node->children); - HL_CUR_TOKEN(NestingParenthesis); - break; - } - case kENodeOperator: { - if (prev_token.type == kExprLexSpacing) { - // For some reason "function (args)" is a function call, but - // "(funcref) (args)" is not. AFAIR this somehow involves - // compatibility and Bram was commenting that this is - // intentionally inconsistent and he is not very happy with the - // situation himself. - if ((*top_node_p)->type != kExprNodePlainIdentifier - && (*top_node_p)->type != kExprNodeComplexIdentifier - && (*top_node_p)->type != kExprNodeCurlyBracesIdentifier) { - OP_MISSING; - } - } - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeCall); - ADD_OP_NODE(cur_node); - HL_CUR_TOKEN(CallingParenthesis); - break; + // “Always drop the topmost value” branch has got rid of the single + // value stack had, so there is nothing known to enclose. Correct + // this. + if (new_top_node_p == NULL) { + new_top_node_p = top_node_p; + } + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Unexpected closing parenthesis: %.*s")); + HL_CUR_TOKEN(NestingParenthesis); + cur_node = NEW_NODE(kExprNodeNested); + cur_node->start = cur_token.start; + cur_node->len = 0; + // Unexpected closing parenthesis, assume that it was wanted to + // enclose everything in (). + cur_node->children = *new_top_node_p; + *new_top_node_p = cur_node; + assert(cur_node->next == NULL); + } + kvi_push(ast_stack, new_top_node_p); + want_node = kENodeOperator; + } else { + switch (want_node) { + case kENodeValue: + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeNested); + *top_node_p = cur_node; + kvi_push(ast_stack, &cur_node->children); + HL_CUR_TOKEN(NestingParenthesis); + break; + case kENodeOperator: + if (prev_token.type == kExprLexSpacing) { + // For some reason "function (args)" is a function call, but + // "(funcref) (args)" is not. AFAIR this somehow involves + // compatibility and Bram was commenting that this is + // intentionally inconsistent and he is not very happy with the + // situation himself. + if ((*top_node_p)->type != kExprNodePlainIdentifier + && (*top_node_p)->type != kExprNodeComplexIdentifier + && (*top_node_p)->type != kExprNodeCurlyBracesIdentifier) { + OP_MISSING; } } - want_node = kENodeValue; + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeCall); + ADD_OP_NODE(cur_node); + HL_CUR_TOKEN(CallingParenthesis); + break; } - break; - } - case kExprLexQuestion: { - ADD_VALUE_IF_MISSING(_("E15: Expected value, got question mark: %.*s")); - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeTernary); - ADD_OP_NODE(cur_node); - HL_CUR_TOKEN(Ternary); - ExprASTNode *ter_val_node; - NEW_NODE_WITH_CUR_POS(ter_val_node, kExprNodeTernaryValue); - ter_val_node->data.ter.got_colon = false; - assert(cur_node->children != NULL); - assert(cur_node->children->next == NULL); - assert(kv_last(ast_stack) == &cur_node->children->next); - *kv_last(ast_stack) = ter_val_node; - kvi_push(ast_stack, &ter_val_node->children); - break; + want_node = kENodeValue; } - case kExprLexDoubleQuotedString: - case kExprLexSingleQuotedString: { - const bool is_double = (tok_type == kExprLexDoubleQuotedString); - if (!cur_token.data.str.closed) { - // It is weird, but Vim has two identical errors messages with - // different error numbers: "E114: Missing quote" and - // "E115: Missing quote". - ERROR_FROM_TOKEN_AND_MSG( - cur_token, (is_double + break; + case kExprLexQuestion: { + ADD_VALUE_IF_MISSING(_("E15: Expected value, got question mark: %.*s")); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeTernary); + ADD_OP_NODE(cur_node); + HL_CUR_TOKEN(Ternary); + ExprASTNode *ter_val_node; + NEW_NODE_WITH_CUR_POS(ter_val_node, kExprNodeTernaryValue); + ter_val_node->data.ter.got_colon = false; + assert(cur_node->children != NULL); + assert(cur_node->children->next == NULL); + assert(kv_last(ast_stack) == &cur_node->children->next); + *kv_last(ast_stack) = ter_val_node; + kvi_push(ast_stack, &ter_val_node->children); + break; + } + case kExprLexDoubleQuotedString: + case kExprLexSingleQuotedString: { + const bool is_double = (tok_type == kExprLexDoubleQuotedString); + if (!cur_token.data.str.closed) { + // It is weird, but Vim has two identical errors messages with + // different error numbers: "E114: Missing quote" and + // "E115: Missing quote". + ERROR_FROM_TOKEN_AND_MSG(cur_token, (is_double ? _("E114: Missing double quote: %.*s") : _("E115: Missing single quote: %.*s"))); - } - if (want_node == kENodeOperator) { - OP_MISSING; - } - NEW_NODE_WITH_CUR_POS( - cur_node, (is_double + } + if (want_node == kENodeOperator) { + OP_MISSING; + } + NEW_NODE_WITH_CUR_POS(cur_node, (is_double ? kExprNodeDoubleQuotedString : kExprNodeSingleQuotedString)); - *top_node_p = cur_node; - parse_quoted_string(pstate, cur_node, cur_token, ast_stack, is_invalid); - want_node = kENodeOperator; - break; + *top_node_p = cur_node; + parse_quoted_string(pstate, cur_node, cur_token, ast_stack, is_invalid); + want_node = kENodeOperator; + break; + } + case kExprLexAssignment: + if (cur_pt == kEPTAssignment) { + kv_drop(pt_stack, 1); + } else if (cur_pt == kEPTSingleAssignment) { + kv_drop(pt_stack, 2); + ERROR_FROM_TOKEN_AND_MSG(cur_token, + _("E475: Expected closing bracket to end list assignment " + "lvalue: %.*s")); + } else { + ERROR_FROM_TOKEN_AND_MSG(cur_token, _("E15: Misplaced assignment: %.*s")); } - case kExprLexAssignment: { - if (cur_pt == kEPTAssignment) { - kv_drop(pt_stack, 1); - } else if (cur_pt == kEPTSingleAssignment) { - kv_drop(pt_stack, 2); - ERROR_FROM_TOKEN_AND_MSG( - cur_token, - _("E475: Expected closing bracket to end list assignment " - "lvalue: %.*s")); - } else { - ERROR_FROM_TOKEN_AND_MSG( - cur_token, _("E15: Misplaced assignment: %.*s")); - } - assert(kv_size(pt_stack)); - assert(kv_last(pt_stack) == kEPTExpr); - ADD_VALUE_IF_MISSING(_("E15: Unexpected assignment: %.*s")); - NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeAssignment); - cur_node->data.ass.type = cur_token.data.ass.type; - switch (cur_token.data.ass.type) { + assert(kv_size(pt_stack)); + assert(kv_last(pt_stack) == kEPTExpr); + ADD_VALUE_IF_MISSING(_("E15: Unexpected assignment: %.*s")); + NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeAssignment); + cur_node->data.ass.type = cur_token.data.ass.type; + switch (cur_token.data.ass.type) { #define HL_ASGN(asgn, hl) \ - case kExprAsgn##asgn: { HL_CUR_TOKEN(hl); break; } - HL_ASGN(Plain, PlainAssignment) - HL_ASGN(Add, AssignmentWithAddition) - HL_ASGN(Subtract, AssignmentWithSubtraction) - HL_ASGN(Concat, AssignmentWithConcatenation) +case kExprAsgn##asgn: { HL_CUR_TOKEN(hl); break; } + HL_ASGN(Plain, PlainAssignment) + HL_ASGN(Add, AssignmentWithAddition) + HL_ASGN(Subtract, AssignmentWithSubtraction) + HL_ASGN(Concat, AssignmentWithConcatenation) #undef HL_ASGN - } - ADD_OP_NODE(cur_node); - break; } + ADD_OP_NODE(cur_node); + break; } viml_pexpr_parse_cycle_end: prev_token = cur_token; @@ -2972,115 +2970,96 @@ viml_pexpr_parse_end: assert(cur_node != NULL); // TODO(ZyX-I): Rehighlight as invalid? switch (cur_node->type) { - case kExprNodeOpMissing: - case kExprNodeMissing: { - // Error should’ve been already reported. - break; - } - case kExprNodeCall: { - east_set_error( - pstate, &ast.err, - _("E116: Missing closing parenthesis for function call: %.*s"), - cur_node->start); - break; - } - case kExprNodeNested: { - east_set_error( - pstate, &ast.err, - _("E110: Missing closing parenthesis for nested expression" - ": %.*s"), - cur_node->start); - break; - } - case kExprNodeListLiteral: { - // For whatever reason "[1" yields "E696: Missing comma in list" error - // in Vim while "[1," yields E697. - east_set_error( - pstate, &ast.err, - _("E697: Missing end of List ']': %.*s"), - cur_node->start); - break; - } - case kExprNodeDictLiteral: { - // Same problem like with list literal with E722 (missing comma) vs - // E723, but additionally just "{" yields only E15. - east_set_error( - pstate, &ast.err, - _("E723: Missing end of Dictionary '}': %.*s"), - cur_node->start); - break; - } - case kExprNodeUnknownFigure: { - east_set_error( - pstate, &ast.err, - _("E15: Missing closing figure brace: %.*s"), - cur_node->start); - break; - } - case kExprNodeLambda: { - east_set_error( - pstate, &ast.err, - _("E15: Missing closing figure brace for lambda: %.*s"), - cur_node->start); - break; - } - case kExprNodeCurlyBracesIdentifier: { - // Until trailing "}" it is impossible to distinguish curly braces - // identifier and dictionary, so it must not appear in the stack like - // this. - abort(); - } - case kExprNodeInteger: - case kExprNodeFloat: - case kExprNodeSingleQuotedString: - case kExprNodeDoubleQuotedString: - case kExprNodeOption: - case kExprNodeEnvironment: - case kExprNodeRegister: - case kExprNodePlainIdentifier: - case kExprNodePlainKey: { - // These are plain values and not containers, for them it should only - // be possible to show up in the topmost stack element, but it was - // unconditionally popped at the start. - abort(); - } - case kExprNodeComma: - case kExprNodeColon: - case kExprNodeArrow: { - // It is actually only valid inside something else, but everything - // where one of the above is valid requires to be closed and thus is - // to be caught later. - break; - } - case kExprNodeSubscript: - case kExprNodeConcatOrSubscript: - case kExprNodeComplexIdentifier: - case kExprNodeAssignment: - case kExprNodeMod: - case kExprNodeDivision: - case kExprNodeMultiplication: - case kExprNodeNot: - case kExprNodeAnd: - case kExprNodeOr: - case kExprNodeConcat: - case kExprNodeComparison: - case kExprNodeUnaryMinus: - case kExprNodeUnaryPlus: - case kExprNodeBinaryMinus: - case kExprNodeTernary: - case kExprNodeBinaryPlus: { - // It is OK to see these in the stack. - break; - } - case kExprNodeTernaryValue: { - if (!cur_node->data.ter.got_colon) { - // Actually Vim throws E109 in more cases. - east_set_error( - pstate, &ast.err, _("E109: Missing ':' after '?': %.*s"), - cur_node->start); - } - break; + case kExprNodeOpMissing: + case kExprNodeMissing: + // Error should’ve been already reported. + break; + case kExprNodeCall: + east_set_error(pstate, &ast.err, + _("E116: Missing closing parenthesis for function call: %.*s"), + cur_node->start); + break; + case kExprNodeNested: + east_set_error(pstate, &ast.err, + _("E110: Missing closing parenthesis for nested expression" + ": %.*s"), + cur_node->start); + break; + case kExprNodeListLiteral: + // For whatever reason "[1" yields "E696: Missing comma in list" error + // in Vim while "[1," yields E697. + east_set_error(pstate, &ast.err, + _("E697: Missing end of List ']': %.*s"), + cur_node->start); + break; + case kExprNodeDictLiteral: + // Same problem like with list literal with E722 (missing comma) vs + // E723, but additionally just "{" yields only E15. + east_set_error(pstate, &ast.err, + _("E723: Missing end of Dictionary '}': %.*s"), + cur_node->start); + break; + case kExprNodeUnknownFigure: + east_set_error(pstate, &ast.err, + _("E15: Missing closing figure brace: %.*s"), + cur_node->start); + break; + case kExprNodeLambda: + east_set_error(pstate, &ast.err, + _("E15: Missing closing figure brace for lambda: %.*s"), + cur_node->start); + break; + case kExprNodeCurlyBracesIdentifier: + // Until trailing "}" it is impossible to distinguish curly braces + // identifier and dictionary, so it must not appear in the stack like + // this. + abort(); + case kExprNodeInteger: + case kExprNodeFloat: + case kExprNodeSingleQuotedString: + case kExprNodeDoubleQuotedString: + case kExprNodeOption: + case kExprNodeEnvironment: + case kExprNodeRegister: + case kExprNodePlainIdentifier: + case kExprNodePlainKey: + // These are plain values and not containers, for them it should only + // be possible to show up in the topmost stack element, but it was + // unconditionally popped at the start. + abort(); + case kExprNodeComma: + case kExprNodeColon: + case kExprNodeArrow: + // It is actually only valid inside something else, but everything + // where one of the above is valid requires to be closed and thus is + // to be caught later. + break; + case kExprNodeSubscript: + case kExprNodeConcatOrSubscript: + case kExprNodeComplexIdentifier: + case kExprNodeAssignment: + case kExprNodeMod: + case kExprNodeDivision: + case kExprNodeMultiplication: + case kExprNodeNot: + case kExprNodeAnd: + case kExprNodeOr: + case kExprNodeConcat: + case kExprNodeComparison: + case kExprNodeUnaryMinus: + case kExprNodeUnaryPlus: + case kExprNodeBinaryMinus: + case kExprNodeTernary: + case kExprNodeBinaryPlus: + // It is OK to see these in the stack. + break; + case kExprNodeTernaryValue: + if (!cur_node->data.ter.got_colon) { + // Actually Vim throws E109 in more cases. + east_set_error(pstate, &ast.err, _("E109: Missing ':' after '?': %.*s"), + cur_node->start); } + break; } } } |