From 20dc04470e00a369d2ba917a22b06ef2d173953f Mon Sep 17 00:00:00 2001 From: James McCoy Date: Fri, 7 Apr 2017 16:08:58 -0400 Subject: vim-patch:8.0.0499 Problem: taglist() does not prioritize tags for a buffer. Solution: Add an optional buffer argument. (Duncan McDougall, closes vim/vim#1194) https://github.com/vim/vim/commit/c6aafbaf3ea755e3ab4ee2e3045911126a08b038 --- src/nvim/eval.c | 10 +++++++--- src/nvim/eval.lua | 2 +- src/nvim/tag.c | 10 ++++------ src/nvim/testdir/test_alot.vim | 1 + src/nvim/testdir/test_taglist.vim | 21 +++++++++++++++++++++ 5 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 src/nvim/testdir/test_taglist.vim (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 1636b490d5..e15d6c0240 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8728,8 +8728,7 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) } fold_count = foldedCount(curwin, lnum, &foldinfo); if (fold_count > 0) { - text = get_foldtext(curwin, lnum, lnum + fold_count - 1, - &foldinfo, buf); + text = get_foldtext(curwin, lnum, lnum + fold_count - 1, &foldinfo, buf); if (text == buf) text = vim_strsave(text); rettv->vval.v_string = text; @@ -16436,7 +16435,12 @@ static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - (void)get_tags(tv_list_alloc_ret(rettv), (char_u *)tag_pattern); + const char *fname = NULL; + if (argvars[1].v_type != VAR_UNKNOWN) { + fname = tv_get_string(&argvars[1]); + } + (void)get_tags(tv_list_alloc_ret(rettv), (char_u *)tag_pattern, + (char_u *)fname); } /* diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index e3c5981b32..6f876e2a96 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -300,7 +300,7 @@ return { tabpagenr={args={0, 1}}, tabpagewinnr={args={1, 2}}, tagfiles={}, - taglist={args=1}, + taglist={args={1, 2}}, tan={args=1, func="float_op_wrapper", data="&tan"}, tanh={args=1, func="float_op_wrapper", data="&tanh"}, tempname={}, diff --git a/src/nvim/tag.c b/src/nvim/tag.c index b812dd2ffd..e4ff829807 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -2797,11 +2797,9 @@ add_tag_field ( return retval; } -/* - * Add the tags matching the specified pattern to the list "list" - * as a dictionary - */ -int get_tags(list_T *list, char_u *pat) +/// Add the tags matching the specified pattern "pat" to the list "list" +/// as a dictionary. Use "buf_fname" for priority, unless NULL. +int get_tags(list_T *list, char_u *pat, char_u *buf_fname) { int num_matches, i, ret; char_u **matches, *p; @@ -2811,7 +2809,7 @@ int get_tags(list_T *list, char_u *pat) bool is_static; ret = find_tags(pat, &num_matches, &matches, - TAG_REGEXP | TAG_NOIC, (int)MAXCOL, NULL); + TAG_REGEXP | TAG_NOIC, (int)MAXCOL, buf_fname); if (ret == OK && num_matches > 0) { for (i = 0; i < num_matches; ++i) { int parse_result = parse_match(matches[i], &tp); diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index baf49b7ff7..99d9835996 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -26,6 +26,7 @@ source test_tabline.vim " source test_tabpage.vim source test_tagcase.vim source test_tagjump.vim +source test_taglist.vim source test_true_false.vim source test_unlet.vim source test_utf8.vim diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim new file mode 100644 index 0000000000..b89b25eae2 --- /dev/null +++ b/src/nvim/testdir/test_taglist.vim @@ -0,0 +1,21 @@ +" test 'taglist' function + +func Test_taglist() + call writefile([ + \ "FFoo\tXfoo\t1", + \ "FBar\tXfoo\t2", + \ "BFoo\tXbar\t1", + \ "BBar\tXbar\t2" + \ ], 'Xtags') + set tags=Xtags + split Xtext + + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo"), {i, v -> v.name})) + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xtext"), {i, v -> v.name})) + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xfoo"), {i, v -> v.name})) + call assert_equal(['BFoo', 'FFoo'], map(taglist("Foo", "Xbar"), {i, v -> v.name})) + + call delete('Xtags') + bwipe +endfunc + -- cgit From 98dd9b801281bb6eb82817ba92c4f635bb5f45e0 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Fri, 7 Apr 2017 16:18:25 -0400 Subject: vim-patch:8.0.0550 Problem: Some etags format tags file use 0x01, breaking the parsing. Solution: Use 0x02 for TAG_SEP. (James McCoy, closes vim/vim#1614) https://github.com/vim/vim/commit/9585a1655ba0d34ea88574617112093a9bd4f2e9 --- src/nvim/tag.c | 10 +++++----- src/nvim/testdir/test_taglist.vim | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/tag.c b/src/nvim/tag.c index e4ff829807..f01b8b8ab1 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -1847,14 +1847,14 @@ parse_line: } } } else { -#define TAG_SEP 0x01 +#define TAG_SEP 0x02 size_t tag_fname_len = STRLEN(tag_fname); // Save the tag in a buffer. - // Use 0x01 to separate fields (Can't use NUL, because the + // Use 0x02 to separate fields (Can't use NUL, because the // hash key is terminated by NUL). - // Emacs tag: - // other tag: - // without Emacs tags: + // Emacs tag: <0x02><0x02> + // other tag: <0x02><0x02> + // without Emacs tags: <0x02> // Here is the "mtt" value plus 1 to avoid NUL. len = (int)tag_fname_len + (int)STRLEN(lbuf) + 3; mfp = xmalloc(sizeof(char_u) + len + 1); diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim index b89b25eae2..2d1557ebd9 100644 --- a/src/nvim/testdir/test_taglist.vim +++ b/src/nvim/testdir/test_taglist.vim @@ -19,3 +19,40 @@ func Test_taglist() bwipe endfunc +func Test_taglist_native_etags() + if !has('emacs_tags') + return + endif + call writefile([ + \ "\x0c", + \ "src/os_unix.c,13491", + \ "set_signals(\x7f1335,32699", + \ "reset_signals(\x7f1407,34136", + \ ], 'Xtags') + + set tags=Xtags + + call assert_equal([['set_signals', '1335,32699'], ['reset_signals', '1407,34136']], + \ map(taglist('set_signals'), {i, v -> [v.name, v.cmd]})) + + call delete('Xtags') +endfunc + +func Test_taglist_ctags_etags() + if !has('emacs_tags') + return + endif + call writefile([ + \ "\x0c", + \ "src/os_unix.c,13491", + \ "set_signals(void)\x7fset_signals\x011335,32699", + \ "reset_signals(void)\x7freset_signals\x011407,34136", + \ ], 'Xtags') + + set tags=Xtags + + call assert_equal([['set_signals', '1335,32699'], ['reset_signals', '1407,34136']], + \ map(taglist('set_signals'), {i, v -> [v.name, v.cmd]})) + + call delete('Xtags') +endfunc -- cgit From 123931e65e8f6ca3ac13fff8279720c8328a018e Mon Sep 17 00:00:00 2001 From: James McCoy Date: Fri, 7 Apr 2017 16:38:06 -0400 Subject: lint --- src/nvim/eval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index e15d6c0240..124d6acfe9 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8729,8 +8729,9 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) fold_count = foldedCount(curwin, lnum, &foldinfo); if (fold_count > 0) { text = get_foldtext(curwin, lnum, lnum + fold_count - 1, &foldinfo, buf); - if (text == buf) + if (text == buf) { text = vim_strsave(text); + } rettv->vval.v_string = text; } } -- cgit From fd8f18bce25e6dcc66dec1fa4870a7ca5c106dec Mon Sep 17 00:00:00 2001 From: dedmass Date: Tue, 4 Apr 2017 20:30:32 -0400 Subject: refactor/single-include: cursor_shape.h #6442 --- src/nvim/CMakeLists.txt | 1 - src/nvim/cursor_shape.h | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index d0f75a2b5b..db3b406b4a 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -424,7 +424,6 @@ function(get_test_target prefix sfile relative_path_var target_var) endfunction() set(NO_SINGLE_CHECK_HEADERS - cursor_shape.h digraph.h ex_cmds.h ex_getln.h diff --git a/src/nvim/cursor_shape.h b/src/nvim/cursor_shape.h index 0006ede31d..7cf65cba3c 100644 --- a/src/nvim/cursor_shape.h +++ b/src/nvim/cursor_shape.h @@ -1,6 +1,9 @@ #ifndef NVIM_CURSOR_SHAPE_H #define NVIM_CURSOR_SHAPE_H +#include "nvim/types.h" +#include "nvim/api/private/defs.h" + /// struct to store values from 'guicursor' and 'mouseshape' /// Indexes in shape_table[] typedef enum { -- cgit From f4e97fe49988b834fea8d8b7a62de0938325395a Mon Sep 17 00:00:00 2001 From: dedmass Date: Tue, 4 Apr 2017 20:53:26 -0400 Subject: refactor/single-include: digraph.h #6444 --- src/nvim/CMakeLists.txt | 1 - src/nvim/digraph.h | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index db3b406b4a..5524c4d87d 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -424,7 +424,6 @@ function(get_test_target prefix sfile relative_path_var target_var) endfunction() set(NO_SINGLE_CHECK_HEADERS - digraph.h ex_cmds.h ex_getln.h file_search.h diff --git a/src/nvim/digraph.h b/src/nvim/digraph.h index b623969e08..d0f10eaf78 100644 --- a/src/nvim/digraph.h +++ b/src/nvim/digraph.h @@ -1,6 +1,9 @@ #ifndef NVIM_DIGRAPH_H #define NVIM_DIGRAPH_H +#include "nvim/types.h" // for char_u +#include "nvim/ex_cmds_defs.h" // for exarg_T + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "digraph.h.generated.h" #endif -- cgit From 3d4a2ee9c72e772113e69c9928fbc58e9dc4b09b Mon Sep 17 00:00:00 2001 From: dedmass Date: Thu, 6 Apr 2017 09:12:59 -0400 Subject: refactor/single-include: ex_cmds.h #6453 --- src/nvim/CMakeLists.txt | 1 - src/nvim/ex_cmds.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 5524c4d87d..843bff3655 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -424,7 +424,6 @@ function(get_test_target prefix sfile relative_path_var target_var) endfunction() set(NO_SINGLE_CHECK_HEADERS - ex_cmds.h ex_getln.h file_search.h fold.h diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h index 65bbd8a99e..792e2f772f 100644 --- a/src/nvim/ex_cmds.h +++ b/src/nvim/ex_cmds.h @@ -6,6 +6,8 @@ #include "nvim/os/time.h" #include "nvim/pos.h" #include "nvim/eval/typval.h" +#include "nvim/buffer_defs.h" // for buf_T and win_T +#include "nvim/ex_cmds_defs.h" // for exarg_T // flags for do_ecmd() #define ECMD_HIDE 0x01 // don't free the current buffer -- cgit From b47e1029a549d6563eeec17e099b82d781925f71 Mon Sep 17 00:00:00 2001 From: dedmass Date: Thu, 6 Apr 2017 21:56:27 -0400 Subject: refactor/single-include: move.h #6469 --- src/nvim/CMakeLists.txt | 1 - src/nvim/move.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 843bff3655..cdfc6367e5 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -438,7 +438,6 @@ set(NO_SINGLE_CHECK_HEADERS memline_defs.h menu.h misc2.h - move.h msgpack_rpc/server.h ops.h option.h diff --git a/src/nvim/move.h b/src/nvim/move.h index 3f3bf70929..1cdf1f6f52 100644 --- a/src/nvim/move.h +++ b/src/nvim/move.h @@ -2,6 +2,8 @@ #define NVIM_MOVE_H #include +#include "nvim/buffer_defs.h" // for win_T +#include "nvim/pos.h" // for linenr_T #ifdef INCLUDE_GENERATED_DECLARATIONS # include "move.h.generated.h" -- cgit From 89deb6ff223ffef5c1e93e629b4df2cf666d9cd1 Mon Sep 17 00:00:00 2001 From: dedmass Date: Thu, 6 Apr 2017 17:16:56 -0400 Subject: refactor/single-include: memline_defs.h #6465 --- src/nvim/CMakeLists.txt | 1 - src/nvim/memfile_defs.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index cdfc6367e5..4d83e9b1ea 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -435,7 +435,6 @@ set(NO_SINGLE_CHECK_HEADERS mbyte.h memfile_defs.h memline.h - memline_defs.h menu.h misc2.h msgpack_rpc/server.h diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h index cc71e1a7ff..57d8abbe30 100644 --- a/src/nvim/memfile_defs.h +++ b/src/nvim/memfile_defs.h @@ -3,8 +3,10 @@ #include #include +#include // for size_t #include "nvim/types.h" +#include "nvim/pos.h" // for linenr_T /// A block number. /// -- cgit From fd69c3f561ea8862ce4b1ff67a5650acaf5f932d Mon Sep 17 00:00:00 2001 From: dedmass Date: Thu, 6 Apr 2017 09:22:44 -0400 Subject: refactor/single-include: ex_getln.h #6454 --- src/nvim/CMakeLists.txt | 1 - src/nvim/ex_getln.h | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 4d83e9b1ea..3d3d30081a 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -424,7 +424,6 @@ function(get_test_target prefix sfile relative_path_var target_var) endfunction() set(NO_SINGLE_CHECK_HEADERS - ex_getln.h file_search.h fold.h getchar.h diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h index 5a1ca5213a..a29c8297d5 100644 --- a/src/nvim/ex_getln.h +++ b/src/nvim/ex_getln.h @@ -3,6 +3,9 @@ #include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" +#include "nvim/ex_cmds_defs.h" // for exarg_T +#include "nvim/os/time.h" // for Timestamp +#include "nvim/regexp_defs.h" // for regmatch_T /* Values for nextwild() and ExpandOne(). See ExpandOne() for meaning. */ #define WILD_FREE 1 -- cgit From 3fd9b70c485c55adb95848aa0e2c67bfb3db786a Mon Sep 17 00:00:00 2001 From: dedmass Date: Thu, 6 Apr 2017 09:40:17 -0400 Subject: refactor/single-include: fold.h #6456 --- src/nvim/CMakeLists.txt | 1 - src/nvim/fold.h | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 3d3d30081a..24a6ec8b5e 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -425,7 +425,6 @@ endfunction() set(NO_SINGLE_CHECK_HEADERS file_search.h - fold.h getchar.h hardcopy.h if_cscope.h diff --git a/src/nvim/fold.h b/src/nvim/fold.h index 2ff10c0e91..2393f4ef47 100644 --- a/src/nvim/fold.h +++ b/src/nvim/fold.h @@ -1,7 +1,12 @@ #ifndef NVIM_FOLD_H #define NVIM_FOLD_H +#include // for FILE + #include "nvim/pos.h" +#include "nvim/garray.h" // for garray_T +#include "nvim/types.h" // for char_u +#include "nvim/buffer_defs.h" // for win_T /* * Info used to pass info about a fold from the fold-detection code to the -- cgit From e586047a53d4145db9c797af7f42c71c35143896 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Apr 2017 17:15:56 +0300 Subject: eval/decode,shada: Do not forget to clean up converters --- src/nvim/eval/decode.c | 1 + src/nvim/shada.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'src') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index fb31a65971..a4fc6c8eb1 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -892,6 +892,7 @@ json_decode_string_fail: tv_clear(&(kv_pop(stack).val)); } json_decode_string_ret: + convert_setup(&conv, NULL, NULL); kv_destroy(stack); kv_destroy(container_stack); return ret; diff --git a/src/nvim/shada.c b/src/nvim/shada.c index c7b95958e0..9ee364d962 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -709,6 +709,7 @@ static ptrdiff_t write_file(ShaDaWriteDef *const sd_writer, static void close_sd_reader(ShaDaReadDef *const sd_reader) FUNC_ATTR_NONNULL_ALL { + convert_setup(&sd_reader->sd_conv, NULL, NULL); close_file(sd_reader->cookie); } @@ -716,6 +717,7 @@ static void close_sd_reader(ShaDaReadDef *const sd_reader) static void close_sd_writer(ShaDaWriteDef *const sd_writer) FUNC_ATTR_NONNULL_ALL { + convert_setup(&sd_writer->sd_conv, NULL, NULL); close_file(sd_writer->cookie); } -- cgit From b3587a456b4c235822006aae928667433ab85e66 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Apr 2017 17:18:40 +0300 Subject: shada: Initialize vimconv_T --- src/nvim/shada.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 9ee364d962..3c4fd8b992 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -800,6 +800,7 @@ static int open_shada_file_for_reading(const char *const fname, .eof = false, .fpos = 0, .cookie = file_open_new(&error, fname, kFileReadOnly, 0), + .sd_conv.vc_type = CONV_NONE, }; if (sd_reader->cookie == NULL) { return error; @@ -2939,6 +2940,7 @@ int shada_write_file(const char *const file, bool nomerge) .write = &write_file, .close = &close_sd_writer, .error = NULL, + .sd_conv.vc_type = CONV_NONE, }; ShaDaReadDef sd_reader = { .close = NULL }; -- cgit From 6006cb74ef7c43b58e8c06e5ecaa5823247b970a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Apr 2017 17:36:02 +0300 Subject: eval/decode: Omit calling convert_setup for each string Uses the same trick eval/encode does. --- src/nvim/eval/decode.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index a4fc6c8eb1..e8c06b2927 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -606,6 +606,17 @@ parse_json_number_ret: } \ } while (0) +/// Last used p_enc value +/// +/// Generic pointer: it is not used as a string, only pointer comparisons are +/// performed. Must not be freed. +static const void *last_p_enc = NULL; + +/// Conversion setup for converting from UTF-8 to last_p_enc +static vimconv_T p_enc_conv = { + .vc_type = CONV_NONE, +}; + /// Convert JSON string into VimL object /// /// @param[in] buf String to convert. UTF-8 encoding is assumed. @@ -626,9 +637,12 @@ int json_decode_string(const char *const buf, const size_t buf_len, EMSG(_("E474: Attempt to decode a blank string")); return FAIL; } - vimconv_T conv = { .vc_type = CONV_NONE }; - convert_setup(&conv, (char_u *) "utf-8", p_enc); - conv.vc_fail = true; + if (last_p_enc != (const void *)p_enc) { + p_enc_conv.vc_type = CONV_NONE; + convert_setup(&p_enc_conv, (char_u *)"utf-8", p_enc); + p_enc_conv.vc_fail = true; + last_p_enc = p_enc; + } int ret = OK; ValuesStack stack = KV_INITIAL_VALUE; ContainerStack container_stack = KV_INITIAL_VALUE; @@ -774,9 +788,9 @@ json_decode_string_cycle_start: break; } case '"': { - if (parse_json_string(&conv, buf, buf_len, &p, &stack, &container_stack, - &next_map_special, &didcomma, &didcolon) - == FAIL) { + if (parse_json_string( + &p_enc_conv, buf, buf_len, &p, &stack, &container_stack, + &next_map_special, &didcomma, &didcolon) == FAIL) { // Error message was already given goto json_decode_string_fail; } @@ -892,7 +906,6 @@ json_decode_string_fail: tv_clear(&(kv_pop(stack).val)); } json_decode_string_ret: - convert_setup(&conv, NULL, NULL); kv_destroy(stack); kv_destroy(container_stack); return ret; -- cgit From e81469522371837615d2e2ffbd578ef44f883d2a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Apr 2017 18:03:56 +0300 Subject: eval/*code,shada: Drop support for converting UTF-8 from/to p_enc Not needed any longer since p_enc is always utf-8. --- src/nvim/eval/decode.c | 39 +-------- src/nvim/eval/encode.c | 56 +++--------- src/nvim/shada.c | 234 +++++++------------------------------------------ 3 files changed, 45 insertions(+), 284 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index e8c06b2927..c7ca3a8ce5 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -222,8 +222,6 @@ static inline int json_decoder_pop(ValuesStackItem obj, /// Parse JSON double-quoted string /// -/// @param[in] conv Defines conversion necessary to convert UTF-8 string to -/// &encoding. /// @param[in] buf Buffer being converted. /// @param[in] buf_len Length of the buffer. /// @param[in,out] pp Pointer to the start of the string. Must point to '"'. @@ -240,8 +238,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, /// value when decoder is restarted, otherwise unused. /// /// @return OK in case of success, FAIL in case of error. -static inline int parse_json_string(vimconv_T *const conv, - const char *const buf, const size_t buf_len, +static inline int parse_json_string(const char *const buf, const size_t buf_len, const char **const pp, ValuesStack *const stack, ContainerStack *const container_stack, @@ -416,20 +413,6 @@ static inline int parse_json_string(vimconv_T *const conv, } PUT_FST_IN_PAIR(fst_in_pair, str_end); #undef PUT_FST_IN_PAIR - if (conv->vc_type != CONV_NONE) { - size_t str_len = (size_t) (str_end - str); - char *const new_str = (char *) string_convert(conv, (char_u *) str, - &str_len); - if (new_str == NULL) { - emsgf(_("E474: Failed to convert string \"%.*s\" from UTF-8"), - (int) str_len, str); - xfree(str); - goto parse_json_string_fail; - } - xfree(str); - str = new_str; - str_end = new_str + str_len; - } if (hasnul) { typval_T obj; list_T *const list = tv_list_alloc(); @@ -606,17 +589,6 @@ parse_json_number_ret: } \ } while (0) -/// Last used p_enc value -/// -/// Generic pointer: it is not used as a string, only pointer comparisons are -/// performed. Must not be freed. -static const void *last_p_enc = NULL; - -/// Conversion setup for converting from UTF-8 to last_p_enc -static vimconv_T p_enc_conv = { - .vc_type = CONV_NONE, -}; - /// Convert JSON string into VimL object /// /// @param[in] buf String to convert. UTF-8 encoding is assumed. @@ -637,12 +609,7 @@ int json_decode_string(const char *const buf, const size_t buf_len, EMSG(_("E474: Attempt to decode a blank string")); return FAIL; } - if (last_p_enc != (const void *)p_enc) { - p_enc_conv.vc_type = CONV_NONE; - convert_setup(&p_enc_conv, (char_u *)"utf-8", p_enc); - p_enc_conv.vc_fail = true; - last_p_enc = p_enc; - } + assert(STRCMP(p_enc, "utf-8") == 0); int ret = OK; ValuesStack stack = KV_INITIAL_VALUE; ContainerStack container_stack = KV_INITIAL_VALUE; @@ -789,7 +756,7 @@ json_decode_string_cycle_start: } case '"': { if (parse_json_string( - &p_enc_conv, buf, buf_len, &p, &stack, &container_stack, + buf, buf_len, &p, &stack, &container_stack, &next_map_special, &didcomma, &didcolon) == FAIL) { // Error message was already given goto json_decode_string_fail; diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 26f9aaa27d..b64217f969 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -11,7 +11,7 @@ #include #include "nvim/eval/encode.h" -#include "nvim/buffer_defs.h" // vimconv_T +#include "nvim/buffer_defs.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/garray.h" @@ -29,10 +29,6 @@ #define utf_ptr2char(b) utf_ptr2char((char_u *)b) #define utf_ptr2len(b) ((size_t)utf_ptr2len((char_u *)b)) #define utf_char2len(b) ((size_t)utf_char2len(b)) -#define string_convert(a, b, c) \ - ((char *)string_convert((vimconv_T *)a, (char_u *)b, c)) -#define convert_setup(vcp, from, to) \ - (convert_setup(vcp, (char_u *)from, (char_u *)to)) const char *const encode_special_var_names[] = { [kSpecialVarNull] = "null", @@ -537,17 +533,6 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, } \ } while (0) -/// Last used p_enc value -/// -/// Generic pointer: it is not used as a string, only pointer comparisons are -/// performed. Must not be freed. -static const void *last_p_enc = NULL; - -/// Conversion setup for converting from last_p_enc to UTF-8 -static vimconv_T p_enc_conv = { - .vc_type = CONV_NONE, -}; - /// Escape sequences used in JSON static const char escapes[][3] = { [BS] = "\\b", @@ -579,33 +564,16 @@ static inline int convert_to_json_string(garray_T *const gap, } else { size_t utf_len = len; char *tofree = NULL; - if (last_p_enc != (const void *) p_enc) { - p_enc_conv.vc_type = CONV_NONE; - convert_setup(&p_enc_conv, p_enc, "utf-8"); - p_enc_conv.vc_fail = true; - last_p_enc = p_enc; - } - if (p_enc_conv.vc_type != CONV_NONE) { - tofree = string_convert(&p_enc_conv, buf, &utf_len); - if (tofree == NULL) { - emsgf(_("E474: Failed to convert string \"%.*s\" to UTF-8"), - utf_len, utf_buf); - return FAIL; - } - utf_buf = tofree; - } + assert(STRCMP(p_enc, "utf-8") == 0); size_t str_len = 0; - // Encode character as \u0000 if - // 1. It is an ASCII control character (0x0 .. 0x1F, 0x7F). - // 2. &encoding is not UTF-8 and code point is above 0x7F. - // 3. &encoding is UTF-8 and code point is not printable according to - // utf_printable(). - // This is done to make it possible to :echo values when &encoding is not - // UTF-8. -#define ENCODE_RAW(p_enc_conv, ch) \ - (ch >= 0x20 && (p_enc_conv.vc_type == CONV_NONE \ - ? utf_printable(ch) \ - : ch < 0x7F)) + // Encode character as \uNNNN if + // 1. It is an ASCII control character (0x0 .. 0x1F; 0x7F not + // utf_printable and thus not checked specially). + // 2. Code point is not printable according to utf_printable(). + // This is done to make resulting values displayable on screen also not from + // Neovim. +#define ENCODE_RAW(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)); @@ -636,7 +604,7 @@ static inline int convert_to_json_string(garray_T *const gap, utf_len - (i - shift), utf_buf + i - shift); xfree(tofree); return FAIL; - } else if (ENCODE_RAW(p_enc_conv, ch)) { + } else if (ENCODE_RAW(ch)) { str_len += shift; } else { str_len += ((sizeof("\\u1234") - 1) @@ -666,7 +634,7 @@ static inline int convert_to_json_string(garray_T *const gap, break; } default: { - if (ENCODE_RAW(p_enc_conv, ch)) { + if (ENCODE_RAW(ch)) { ga_concat_len(gap, utf_buf + i, shift); } else if (ch < SURROGATE_FIRST_CHAR) { ga_concat_len(gap, ((const char[]) { diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 3c4fd8b992..cfe0bd8774 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -73,15 +73,10 @@ KHASH_SET_INIT_STR(strset) (vim_rename((char_u *)a, (char_u *)b)) #define mb_strnicmp(a, b, c) \ (mb_strnicmp((char_u *)a, (char_u *)b, c)) -#define has_non_ascii(a) (has_non_ascii((char_u *)a)) -#define string_convert(a, b, c) \ - ((char *)string_convert((vimconv_T *)a, (char_u *)b, c)) #define path_shorten_fname_if_possible(b) \ ((char *)path_shorten_fname_if_possible((char_u *)b)) #define buflist_new(ffname, sfname, ...) \ (buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__)) -#define convert_setup(vcp, from, to) \ - (convert_setup(vcp, (char_u *)from, (char_u *)to)) #define os_isdir(f) (os_isdir((char_u *) f)) #define regtilde(s, m) ((char *) regtilde((char_u *) s, m)) #define path_tail_with_sep(f) ((char *) path_tail_with_sep((char_u *)f)) @@ -413,8 +408,6 @@ typedef struct sd_read_def { const char *error; ///< Error message in case of error. uintmax_t fpos; ///< Current position (amount of bytes read since ///< reader structure initialization). May overflow. - vimconv_T sd_conv; ///< Structure used for converting encodings of some - ///< items. } ShaDaReadDef; struct sd_write_def; @@ -435,8 +428,6 @@ typedef struct sd_write_def { ShaDaWriteCloser close; ///< Close function. void *cookie; ///< Data describing object written to. const char *error; ///< Error message in case of error. - vimconv_T sd_conv; ///< Structure used for converting encodings of some - ///< items. } ShaDaWriteDef; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -709,7 +700,6 @@ static ptrdiff_t write_file(ShaDaWriteDef *const sd_writer, static void close_sd_reader(ShaDaReadDef *const sd_reader) FUNC_ATTR_NONNULL_ALL { - convert_setup(&sd_reader->sd_conv, NULL, NULL); close_file(sd_reader->cookie); } @@ -717,7 +707,6 @@ static void close_sd_reader(ShaDaReadDef *const sd_reader) static void close_sd_writer(ShaDaWriteDef *const sd_writer) FUNC_ATTR_NONNULL_ALL { - convert_setup(&sd_writer->sd_conv, NULL, NULL); close_file(sd_writer->cookie); } @@ -800,13 +789,12 @@ static int open_shada_file_for_reading(const char *const fname, .eof = false, .fpos = 0, .cookie = file_open_new(&error, fname, kFileReadOnly, 0), - .sd_conv.vc_type = CONV_NONE, }; if (sd_reader->cookie == NULL) { return error; } - convert_setup(&sd_reader->sd_conv, "utf-8", p_enc); + assert(STRCMP(p_enc, "utf-8") == 0); return 0; } @@ -1902,127 +1890,24 @@ shada_pack_entry_error: } #undef PACK_STRING -/// Write single ShaDa entry, converting it if needed +/// Write single ShaDa entry and free it afterwards /// -/// @warning Frees entry after packing. +/// Will not free if entry could not be freed. /// /// @param[in] packer Packer used to write entry. -/// @param[in] sd_conv Conversion definitions. -/// @param[in] entry Entry written. If entry.can_free_entry is false then -/// it assumes that entry was not converted, otherwise it -/// is assumed that entry was already converted. +/// @param[in] entry Entry written. /// @param[in] max_kbyte Maximum size of an item in KiB. Zero means no /// restrictions. -static ShaDaWriteResult shada_pack_encoded_entry(msgpack_packer *const packer, - const vimconv_T *const sd_conv, - PossiblyFreedShadaEntry entry, - const size_t max_kbyte) - FUNC_ATTR_NONNULL_ALL +static inline ShaDaWriteResult shada_pack_pfreed_entry( + msgpack_packer *const packer, PossiblyFreedShadaEntry entry, + const size_t max_kbyte) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { ShaDaWriteResult ret = kSDWriteSuccessfull; + ret = shada_pack_entry(packer, entry.data, max_kbyte); if (entry.can_free_entry) { - ret = shada_pack_entry(packer, entry.data, max_kbyte); shada_free_shada_entry(&entry.data); - return ret; } -#define RUN_WITH_CONVERTED_STRING(cstr, code) \ - do { \ - bool did_convert = false; \ - if (sd_conv->vc_type != CONV_NONE && has_non_ascii((cstr))) { \ - char *const converted_string = string_convert(sd_conv, (cstr), NULL); \ - if (converted_string != NULL) { \ - (cstr) = converted_string; \ - did_convert = true; \ - } \ - } \ - code \ - if (did_convert) { \ - xfree((cstr)); \ - } \ - } while (0) - switch (entry.data.type) { - case kSDItemUnknown: - case kSDItemMissing: { - assert(false); - } - case kSDItemSearchPattern: { - RUN_WITH_CONVERTED_STRING(entry.data.data.search_pattern.pat, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemHistoryEntry: { - RUN_WITH_CONVERTED_STRING(entry.data.data.history_item.string, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemSubString: { - RUN_WITH_CONVERTED_STRING(entry.data.data.sub_string.sub, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemVariable: { - if (sd_conv->vc_type != CONV_NONE) { - typval_T tgttv; - var_item_copy(sd_conv, &entry.data.data.global_var.value, &tgttv, - true, 0); - tv_clear(&entry.data.data.global_var.value); - entry.data.data.global_var.value = tgttv; - } - ret = shada_pack_entry(packer, entry.data, max_kbyte); - break; - } - case kSDItemRegister: { - bool did_convert = false; - if (sd_conv->vc_type != CONV_NONE) { - size_t first_non_ascii = 0; - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - if (has_non_ascii(entry.data.data.reg.contents[i])) { - first_non_ascii = i; - did_convert = true; - break; - } - } - if (did_convert) { - entry.data.data.reg.contents = - xmemdup(entry.data.data.reg.contents, - (entry.data.data.reg.contents_size - * sizeof(entry.data.data.reg.contents[0]))); - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - if (i >= first_non_ascii) { - entry.data.data.reg.contents[i] = get_converted_string( - sd_conv, - entry.data.data.reg.contents[i], - strlen(entry.data.data.reg.contents[i])); - } else { - entry.data.data.reg.contents[i] = - xstrdup(entry.data.data.reg.contents[i]); - } - } - } - } - ret = shada_pack_entry(packer, entry.data, max_kbyte); - if (did_convert) { - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - xfree(entry.data.data.reg.contents[i]); - } - xfree(entry.data.data.reg.contents); - } - break; - } - case kSDItemHeader: - case kSDItemGlobalMark: - case kSDItemJump: - case kSDItemBufferList: - case kSDItemLocalMark: - case kSDItemChange: { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - break; - } - } -#undef RUN_WITH_CONVERTED_STRING return ret; } @@ -2559,11 +2444,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, break; } typval_T tgttv; - if (sd_writer->sd_conv.vc_type != CONV_NONE) { - var_item_copy(&sd_writer->sd_conv, &vartv, &tgttv, true, 0); - } else { - tv_copy(&vartv, &tgttv); - } + tv_copy(&vartv, &tgttv); ShaDaWriteResult spe_ret; if ((spe_ret = shada_pack_entry(packer, (ShadaEntry) { .type = kSDItemVariable, @@ -2814,9 +2695,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, do { \ for (size_t i_ = 0; i_ < ARRAY_SIZE(wms_array); i_++) { \ if (wms_array[i_].data.type != kSDItemMissing) { \ - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, \ - wms_array[i_], \ - max_kbyte) == kSDWriteFailed) { \ + if (shada_pack_pfreed_entry(packer, wms_array[i_], max_kbyte) \ + == kSDWriteFailed) { \ ret = kSDWriteFailed; \ goto shada_write_exit; \ } \ @@ -2826,8 +2706,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, PACK_WMS_ARRAY(wms->global_marks); PACK_WMS_ARRAY(wms->registers); for (size_t i = 0; i < wms->jumps_size; i++) { - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms->jumps[i], - max_kbyte) == kSDWriteFailed) { + if (shada_pack_pfreed_entry(packer, wms->jumps[i], max_kbyte) + == kSDWriteFailed) { ret = kSDWriteFailed; goto shada_write_exit; } @@ -2835,8 +2715,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, #define PACK_WMS_ENTRY(wms_entry) \ do { \ if (wms_entry.data.type != kSDItemMissing) { \ - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms_entry, \ - max_kbyte) == kSDWriteFailed) { \ + if (shada_pack_pfreed_entry(packer, wms_entry, max_kbyte) \ + == kSDWriteFailed) { \ ret = kSDWriteFailed; \ goto shada_write_exit; \ } \ @@ -2863,9 +2743,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, for (size_t i = 0; i < file_markss_to_dump; i++) { PACK_WMS_ARRAY(all_file_markss[i]->marks); for (size_t j = 0; j < all_file_markss[i]->changes_size; j++) { - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, - all_file_markss[i]->changes[j], - max_kbyte) == kSDWriteFailed) { + if (shada_pack_pfreed_entry(packer, all_file_markss[i]->changes[j], + max_kbyte) == kSDWriteFailed) { ret = kSDWriteFailed; goto shada_write_exit; } @@ -2889,8 +2768,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, if (dump_one_history[i]) { hms_insert_whole_neovim_history(&wms->hms[i]); HMS_ITER(&wms->hms[i], cur_entry, { - if (shada_pack_encoded_entry( - packer, &sd_writer->sd_conv, (PossiblyFreedShadaEntry) { + if (shada_pack_pfreed_entry( + packer, (PossiblyFreedShadaEntry) { .data = cur_entry->data, .can_free_entry = cur_entry->can_free_entry, }, max_kbyte) == kSDWriteFailed) { @@ -2940,7 +2819,6 @@ int shada_write_file(const char *const file, bool nomerge) .write = &write_file, .close = &close_sd_writer, .error = NULL, - .sd_conv.vc_type = CONV_NONE, }; ShaDaReadDef sd_reader = { .close = NULL }; @@ -3042,7 +2920,7 @@ shada_write_file_nomerge: {} verbose_leave(); } - convert_setup(&sd_writer.sd_conv, p_enc, "utf-8"); + assert(STRCMP(p_enc, "utf-8") == 0); const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge ? NULL @@ -3331,29 +3209,6 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, return kSDReadStatusSuccess; } -/// Convert or copy and return a string -/// -/// @param[in] sd_conv Conversion definition. -/// @param[in] str String to convert. -/// @param[in] len String length. -/// -/// @return [allocated] converted string or copy of the original string. -static inline char *get_converted_string(const vimconv_T *const sd_conv, - const char *const str, - const size_t len) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (!has_non_ascii_len(str, len)) { - return xmemdupz(str, len); - } - size_t new_len = len; - char *const new_str = string_convert(sd_conv, str, &new_len); - if (new_str == NULL) { - return xmemdupz(str, len); - } - return new_str; -} - #define READERR(entry_name, error_desc) \ RERR "Error while reading ShaDa file: " \ entry_name " entry at position %" PRIu64 " " \ @@ -3431,10 +3286,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, sizeof(*unpacked.data.via.map.ptr)); \ ad_ga.ga_len++; \ } -#define CONVERTED(str, len) ( \ - sd_reader->sd_conv.vc_type != CONV_NONE \ - ? get_converted_string(&sd_reader->sd_conv, (str), (len)) \ - : xmemdupz((str), (len))) +#define CONVERTED(str, len) (xmemdupz((str), (len))) #define BIN_CONVERTED(b) CONVERTED(b.ptr, b.size) #define SET_ADDITIONAL_DATA(tgt, name) \ do { \ @@ -3807,30 +3659,14 @@ shada_read_next_item_start: (char) unpacked.data.via.array.ptr[2].via.u64; } size_t strsize; - if (sd_reader->sd_conv.vc_type == CONV_NONE - || !has_non_ascii_len(unpacked.data.via.array.ptr[1].via.bin.ptr, - unpacked.data.via.array.ptr[1].via.bin.size)) { -shada_read_next_item_hist_no_conv: - strsize = ( - unpacked.data.via.array.ptr[1].via.bin.size - + 1 // Zero byte - + 1); // Separator character - entry->data.history_item.string = xmalloc(strsize); - memcpy(entry->data.history_item.string, - unpacked.data.via.array.ptr[1].via.bin.ptr, - unpacked.data.via.array.ptr[1].via.bin.size); - } else { - size_t len = unpacked.data.via.array.ptr[1].via.bin.size; - char *const converted = string_convert( - &sd_reader->sd_conv, unpacked.data.via.array.ptr[1].via.bin.ptr, - &len); - if (converted != NULL) { - strsize = len + 2; - entry->data.history_item.string = xrealloc(converted, strsize); - } else { - goto shada_read_next_item_hist_no_conv; - } - } + strsize = ( + unpacked.data.via.array.ptr[1].via.bin.size + + 1 // Zero byte + + 1); // Separator character + entry->data.history_item.string = xmalloc(strsize); + memcpy(entry->data.history_item.string, + unpacked.data.via.array.ptr[1].via.bin.ptr, + unpacked.data.via.array.ptr[1].via.bin.size); entry->data.history_item.string[strsize - 2] = 0; entry->data.history_item.string[strsize - 1] = entry->data.history_item.sep; @@ -3863,16 +3699,6 @@ shada_read_next_item_hist_no_conv: "be converted to the VimL value")), initial_fpos); goto shada_read_next_item_error; } - if (sd_reader->sd_conv.vc_type != CONV_NONE) { - typval_T tgttv; - var_item_copy(&sd_reader->sd_conv, - &entry->data.global_var.value, - &tgttv, - true, - 0); - tv_clear(&entry->data.global_var.value); - entry->data.global_var.value = tgttv; - } SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 2, entry->data.global_var.additional_elements, "variable"); -- cgit From ab19fa155203a4071cb8e780db7d3480b562aee0 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Apr 2017 19:11:42 +0300 Subject: *: Fix linter errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drops comments `// for …` that do not pass linter for them being unmaintainable and fast to becoming incomplete or even incorrect. Mention @dedmass --- src/nvim/digraph.h | 4 ++-- src/nvim/eval/decode.c | 6 +++--- src/nvim/ex_cmds.h | 4 ++-- src/nvim/ex_getln.h | 6 +++--- src/nvim/fold.h | 8 ++++---- src/nvim/memfile_defs.h | 4 ++-- src/nvim/move.h | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nvim/digraph.h b/src/nvim/digraph.h index d0f10eaf78..1b73ccaf3f 100644 --- a/src/nvim/digraph.h +++ b/src/nvim/digraph.h @@ -1,8 +1,8 @@ #ifndef NVIM_DIGRAPH_H #define NVIM_DIGRAPH_H -#include "nvim/types.h" // for char_u -#include "nvim/ex_cmds_defs.h" // for exarg_T +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "digraph.h.generated.h" diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index c7ca3a8ce5..f9889ca547 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -755,9 +755,9 @@ json_decode_string_cycle_start: break; } case '"': { - if (parse_json_string( - buf, buf_len, &p, &stack, &container_stack, - &next_map_special, &didcomma, &didcolon) == FAIL) { + 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; } diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h index 792e2f772f..b564cde56c 100644 --- a/src/nvim/ex_cmds.h +++ b/src/nvim/ex_cmds.h @@ -6,8 +6,8 @@ #include "nvim/os/time.h" #include "nvim/pos.h" #include "nvim/eval/typval.h" -#include "nvim/buffer_defs.h" // for buf_T and win_T -#include "nvim/ex_cmds_defs.h" // for exarg_T +#include "nvim/buffer_defs.h" +#include "nvim/ex_cmds_defs.h" // flags for do_ecmd() #define ECMD_HIDE 0x01 // don't free the current buffer diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h index a29c8297d5..051564fbe1 100644 --- a/src/nvim/ex_getln.h +++ b/src/nvim/ex_getln.h @@ -3,9 +3,9 @@ #include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" -#include "nvim/ex_cmds_defs.h" // for exarg_T -#include "nvim/os/time.h" // for Timestamp -#include "nvim/regexp_defs.h" // for regmatch_T +#include "nvim/ex_cmds_defs.h" +#include "nvim/os/time.h" +#include "nvim/regexp_defs.h" /* Values for nextwild() and ExpandOne(). See ExpandOne() for meaning. */ #define WILD_FREE 1 diff --git a/src/nvim/fold.h b/src/nvim/fold.h index 2393f4ef47..f35b328fb1 100644 --- a/src/nvim/fold.h +++ b/src/nvim/fold.h @@ -1,12 +1,12 @@ #ifndef NVIM_FOLD_H #define NVIM_FOLD_H -#include // for FILE +#include #include "nvim/pos.h" -#include "nvim/garray.h" // for garray_T -#include "nvim/types.h" // for char_u -#include "nvim/buffer_defs.h" // for win_T +#include "nvim/garray.h" +#include "nvim/types.h" +#include "nvim/buffer_defs.h" /* * Info used to pass info about a fold from the fold-detection code to the diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h index 57d8abbe30..b3c2f3564c 100644 --- a/src/nvim/memfile_defs.h +++ b/src/nvim/memfile_defs.h @@ -3,10 +3,10 @@ #include #include -#include // for size_t +#include #include "nvim/types.h" -#include "nvim/pos.h" // for linenr_T +#include "nvim/pos.h" /// A block number. /// diff --git a/src/nvim/move.h b/src/nvim/move.h index 1cdf1f6f52..00fbcc580f 100644 --- a/src/nvim/move.h +++ b/src/nvim/move.h @@ -2,8 +2,8 @@ #define NVIM_MOVE_H #include -#include "nvim/buffer_defs.h" // for win_T -#include "nvim/pos.h" // for linenr_T +#include "nvim/buffer_defs.h" +#include "nvim/pos.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "move.h.generated.h" -- cgit From cd0a436622d0eeafcbc79e0a6e53088b881ab5b1 Mon Sep 17 00:00:00 2001 From: dedmass Date: Thu, 6 Apr 2017 17:06:35 -0400 Subject: refactor/single-include Closes #6463 refactor/single-include: file_search.h Closes #6455 refactor/single-include: hardcopy.h Closes #6457 refactor/single-include: if_cscope.h Closes #6458 refactor/single-include: mark.h Closes #6461 refactor/single-include: mbyte.h Closes #6462 refactor/single-include: memline.h Closes #6464 refactor/single-include: menu.h Closes #6468 refactor/single-include: ops.h Closes #6470 --- src/nvim/CMakeLists.txt | 9 --------- src/nvim/file_search.h | 5 +++++ src/nvim/hardcopy.h | 4 ++++ src/nvim/if_cscope.h | 3 +++ src/nvim/mark.h | 1 + src/nvim/mbyte.h | 1 + src/nvim/memline.h | 2 ++ src/nvim/menu.h | 5 +++++ src/nvim/ops.h | 2 ++ 9 files changed, 23 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 24a6ec8b5e..e0f4944762 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -424,19 +424,10 @@ function(get_test_target prefix sfile relative_path_var target_var) endfunction() set(NO_SINGLE_CHECK_HEADERS - file_search.h getchar.h - hardcopy.h - if_cscope.h if_cscope_defs.h - mark.h - mbyte.h - memfile_defs.h - memline.h - menu.h misc2.h msgpack_rpc/server.h - ops.h option.h os/shell.h os_unix.h diff --git a/src/nvim/file_search.h b/src/nvim/file_search.h index 833a1a05ff..b128029123 100644 --- a/src/nvim/file_search.h +++ b/src/nvim/file_search.h @@ -1,6 +1,11 @@ #ifndef NVIM_FILE_SEARCH_H #define NVIM_FILE_SEARCH_H +#include // for size_t + +#include "nvim/types.h" // for char_u +#include "nvim/globals.h" // for CdScope + /* Flags for find_file_*() functions. */ #define FINDFILE_FILE 0 /* only files */ #define FINDFILE_DIR 1 /* only directories */ diff --git a/src/nvim/hardcopy.h b/src/nvim/hardcopy.h index 4ead8dd5d4..a70b20e6f5 100644 --- a/src/nvim/hardcopy.h +++ b/src/nvim/hardcopy.h @@ -2,6 +2,10 @@ #define NVIM_HARDCOPY_H #include +#include // for size_t + +#include "nvim/types.h" // for char_u +#include "nvim/ex_cmds_defs.h" // for exarg_T /* * Structure to hold printing color and font attributes. diff --git a/src/nvim/if_cscope.h b/src/nvim/if_cscope.h index 351d9caef6..e20462576a 100644 --- a/src/nvim/if_cscope.h +++ b/src/nvim/if_cscope.h @@ -1,6 +1,9 @@ #ifndef NVIM_IF_CSCOPE_H #define NVIM_IF_CSCOPE_H +#include "nvim/types.h" // for char_u and expand_T +#include "nvim/ex_cmds_defs.h" // for exarg_T + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "if_cscope.h.generated.h" #endif diff --git a/src/nvim/mark.h b/src/nvim/mark.h index efba9708db..c22a102926 100644 --- a/src/nvim/mark.h +++ b/src/nvim/mark.h @@ -8,6 +8,7 @@ #include "nvim/memory.h" #include "nvim/pos.h" #include "nvim/os/time.h" +#include "nvim/ex_cmds_defs.h" // for exarg_T /// Set fmark using given value #define SET_FMARK(fmarkp_, mark_, fnum_) \ diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h index 3565202466..ad9e38004c 100644 --- a/src/nvim/mbyte.h +++ b/src/nvim/mbyte.h @@ -7,6 +7,7 @@ #include "nvim/iconv.h" #include "nvim/func_attr.h" #include "nvim/os/os_defs.h" // For WCHAR, indirect +#include "nvim/types.h" // for char_u /* * Return byte length of character that starts with byte "b". diff --git a/src/nvim/memline.h b/src/nvim/memline.h index f84e86fea0..a239c6a031 100644 --- a/src/nvim/memline.h +++ b/src/nvim/memline.h @@ -2,6 +2,8 @@ #define NVIM_MEMLINE_H #include "nvim/types.h" +#include "nvim/pos.h" // for pos_T, linenr_T, colnr_T +#include "nvim/buffer_defs.h" // for buf_T #ifdef INCLUDE_GENERATED_DECLARATIONS # include "memline.h.generated.h" diff --git a/src/nvim/menu.h b/src/nvim/menu.h index 3266c511b4..a84b7d812e 100644 --- a/src/nvim/menu.h +++ b/src/nvim/menu.h @@ -1,6 +1,11 @@ #ifndef NVIM_MENU_H #define NVIM_MENU_H +#include // for bool + +#include "nvim/types.h" // for char_u and expand_T +#include "nvim/ex_cmds_defs.h" // for exarg_T + /* Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode */ #define MENU_INDEX_INVALID -1 #define MENU_INDEX_NORMAL 0 diff --git a/src/nvim/ops.h b/src/nvim/ops.h index 13d0142343..a8867e02ea 100644 --- a/src/nvim/ops.h +++ b/src/nvim/ops.h @@ -8,6 +8,8 @@ #include "nvim/types.h" #include "nvim/eval/typval.h" #include "nvim/os/time.h" +#include "nvim/normal.h" // for MotionType and oparg_T +#include "nvim/ex_cmds_defs.h" // for exarg_T typedef int (*Indenter)(void); -- cgit From 7701014b659d3505c6d4f0de95c06042155c98d1 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Apr 2017 20:22:46 +0300 Subject: *: Remove useless asserts --- src/nvim/eval/decode.c | 1 - src/nvim/eval/encode.c | 1 - src/nvim/shada.c | 2 -- 3 files changed, 4 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index f9889ca547..a7dc6b205d 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -609,7 +609,6 @@ int json_decode_string(const char *const buf, const size_t buf_len, EMSG(_("E474: Attempt to decode a blank string")); return FAIL; } - assert(STRCMP(p_enc, "utf-8") == 0); int ret = OK; ValuesStack stack = KV_INITIAL_VALUE; ContainerStack container_stack = KV_INITIAL_VALUE; diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index b64217f969..d74913a481 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -564,7 +564,6 @@ static inline int convert_to_json_string(garray_T *const gap, } else { size_t utf_len = len; char *tofree = NULL; - assert(STRCMP(p_enc, "utf-8") == 0); size_t str_len = 0; // Encode character as \uNNNN if // 1. It is an ASCII control character (0x0 .. 0x1F; 0x7F not diff --git a/src/nvim/shada.c b/src/nvim/shada.c index cfe0bd8774..8c5d6dff65 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -2920,8 +2920,6 @@ shada_write_file_nomerge: {} verbose_leave(); } - assert(STRCMP(p_enc, "utf-8") == 0); - const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge ? NULL : &sd_reader)); -- cgit From 0f4b4c7529d6699bcae5c943a4bc27827c9aa8d6 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Apr 2017 18:23:02 +0300 Subject: headers: Remove useless HAVE_CONFIG_H macros We do not have non-cmake build options, cmake always does configure_file. --- src/nvim/iconv.h | 4 +--- src/nvim/vim.h | 10 ++++------ 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/iconv.h b/src/nvim/iconv.h index bf29b15247..d7234090c4 100644 --- a/src/nvim/iconv.h +++ b/src/nvim/iconv.h @@ -10,9 +10,7 @@ // USE_ICONV, or to put the USE_ICONV definition in config.h.in directly. As // it stands, globals.h needs to be included alongside iconv.h. -#ifdef HAVE_CONFIG_H -# include "auto/config.h" -#endif +#include "auto/config.h" // Use iconv() when it's available, either by linking to the library at // compile time or by loading it at runtime. diff --git a/src/nvim/vim.h b/src/nvim/vim.h index cc0587fb88..d92115ecdf 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -13,18 +13,16 @@ /* ============ the header file puzzle (ca. 50-100 pieces) ========= */ -#ifdef HAVE_CONFIG_H /* GNU autoconf (or something else) was here */ -# include "auto/config.h" -# define HAVE_PATHDEF +#include "auto/config.h" +#define HAVE_PATHDEF /* * Check if configure correctly managed to find sizeof(int). If this failed, * it becomes zero. This is likely a problem of not being able to run the * test program. Other items from configure may also be wrong then! */ -# if (SIZEOF_INT == 0) -Error: configure did not run properly.Check auto/config.log. -# endif +#if (SIZEOF_INT == 0) +# error Configure did not run properly. #endif #include "nvim/os/os_defs.h" /* bring lots of system header files */ -- cgit From 8e519a22ddcad6a38d966a7c340c9fd77d72f392 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Apr 2017 18:51:29 +0300 Subject: vim.h: Remove strange comments --- src/nvim/vim.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/nvim/vim.h b/src/nvim/vim.h index d92115ecdf..172e62b039 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -11,8 +11,6 @@ #define RUNTIME_DIRNAME "runtime" /* end */ -/* ============ the header file puzzle (ca. 50-100 pieces) ========= */ - #include "auto/config.h" #define HAVE_PATHDEF @@ -44,11 +42,6 @@ enum { NUMBUFLEN = 65 }; #include "nvim/keymap.h" #include "nvim/macros.h" - - - -/* ================ end of the header file puzzle =============== */ - #include "nvim/gettext.h" /* special attribute addition: Put message in history */ -- cgit From 3a6b8c28c813f8e65851c8e89c7cf56b4d6cf03f Mon Sep 17 00:00:00 2001 From: Nikolai Aleksandrovich Pavlov Date: Sun, 9 Apr 2017 04:28:48 +0300 Subject: cmake: Use archive instead of downloading *.json files (#6482) --- src/nvim/CMakeLists.txt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index e0f4944762..1daa5dc3c4 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -41,7 +41,7 @@ set(LINT_SUPPRESS_URL "${LINT_SUPPRESS_URL_BASE}/errors.json") set(LINT_PRG ${PROJECT_SOURCE_DIR}/src/clint.py) set(DOWNLOAD_SCRIPT ${PROJECT_SOURCE_DIR}/cmake/Download.cmake) set(LINT_SUPPRESSES_ROOT ${PROJECT_BINARY_DIR}/errors) -set(LINT_SUPPRESSES_URL "https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint/errors.tar.gz") +set(LINT_SUPPRESSES_URL "${LINT_SUPPRESS_URL_BASE}/errors.tar.gz") include_directories(${GENERATED_DIR}) include_directories(${CACHED_GENERATED_DIR}) @@ -486,6 +486,20 @@ function(add_download output url allow_failure) ) endfunction() +include(ExternalProject) +ExternalProject_Add( + clint-error-files + PREFIX "${LINT_SUPPRESSES_ROOT}" + URL "${LINT_SUPPRESSES_URL}" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + BUILD_IN_SOURCE 1 + INSTALL_COMMAND + "${CMAKE_COMMAND}" + -DTARGET=${LINT_SUPPRESSES_ROOT} + -P "${PROJECT_SOURCE_DIR}/cmake/InstallClintErrors.cmake" +) + add_download(${LINT_SUPPRESS_FILE} ${LINT_SUPPRESS_URL} off) set(LINT_NVIM_REL_SOURCES) @@ -494,14 +508,13 @@ foreach(sfile ${LINT_NVIM_SOURCES}) set(suppress_file ${LINT_SUPPRESSES_ROOT}/${suffix}.json) set(suppress_url "${LINT_SUPPRESS_URL_BASE}/${suffix}.json") set(rsfile src/nvim/${r}) - add_download(${suppress_file} ${suppress_url} on) set(touch_file "${TOUCHES_DIR}/ran-clint-${suffix}") add_custom_command( OUTPUT ${touch_file} COMMAND ${LINT_PRG} --suppress-errors=${suppress_file} ${rsfile} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${CMAKE_COMMAND} -E touch ${touch_file} - DEPENDS ${LINT_PRG} ${sfile} ${suppress_file} + DEPENDS ${LINT_PRG} ${sfile} clint-error-files ) list(APPEND LINT_TARGETS ${touch_file}) list(APPEND LINT_NVIM_REL_SOURCES ${rsfile}) -- cgit From c8243ad071f6cfcb9650ee00c53feadaaf7d90d5 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 05:18:09 +0300 Subject: cmake: Do not build clint-error-files by default --- src/nvim/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 1daa5dc3c4..6a4fa7eadb 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -491,6 +491,7 @@ ExternalProject_Add( clint-error-files PREFIX "${LINT_SUPPRESSES_ROOT}" URL "${LINT_SUPPRESSES_URL}" + EXCLUDE_FROM_ALL 1 CONFIGURE_COMMAND "" BUILD_COMMAND "" BUILD_IN_SOURCE 1 -- cgit From b99cac277812d337e8a5f1bc6a182e62f1e8c448 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 06:17:02 +0300 Subject: cmake: Do not use ExternalProject Necessary argument (EXCLUDE_FROM_ALL) only appears in 3.1.0. --- src/nvim/CMakeLists.txt | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 6a4fa7eadb..cb003c2026 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -42,6 +42,9 @@ set(LINT_PRG ${PROJECT_SOURCE_DIR}/src/clint.py) set(DOWNLOAD_SCRIPT ${PROJECT_SOURCE_DIR}/cmake/Download.cmake) set(LINT_SUPPRESSES_ROOT ${PROJECT_BINARY_DIR}/errors) set(LINT_SUPPRESSES_URL "${LINT_SUPPRESS_URL_BASE}/errors.tar.gz") +set(LINT_SUPPRESSES_ARCHIVE ${LINT_SUPPRESSES_ROOT}/errors.tar.gz) +set(LINT_SUPPRESSES_TOUCH_FILE "${TOUCHES_DIR}/unpacked-clint-errors-archive") +set(LINT_SUPPRESSES_INSTALL_SCRIPT "${PROJECT_SOURCE_DIR}/cmake/InstallClintErrors.cmake") include_directories(${GENERATED_DIR}) include_directories(${CACHED_GENERATED_DIR}) @@ -50,6 +53,8 @@ include_directories(${GENERATED_INCLUDES_DIR}) file(MAKE_DIRECTORY ${TOUCHES_DIR}) file(MAKE_DIRECTORY ${GENERATED_DIR}) file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}) +file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}) +file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src) file(GLOB NVIM_SOURCES *.c) file(GLOB NVIM_HEADERS *.h) @@ -486,19 +491,18 @@ function(add_download output url allow_failure) ) endfunction() -include(ExternalProject) -ExternalProject_Add( - clint-error-files - PREFIX "${LINT_SUPPRESSES_ROOT}" - URL "${LINT_SUPPRESSES_URL}" - EXCLUDE_FROM_ALL 1 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - BUILD_IN_SOURCE 1 - INSTALL_COMMAND - "${CMAKE_COMMAND}" +add_download(${LINT_SUPPRESSES_ARCHIVE} ${LINT_SUPPRESSES_URL} off) + +add_custom_command( + OUTPUT ${LINT_SUPPRESSES_TOUCH_FILE} + WORKING_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src + COMMAND ${CMAKE_COMMAND} -E tar xfz ${LINT_SUPPRESSES_ARCHIVE} + COMMAND + ${CMAKE_COMMAND} -DTARGET=${LINT_SUPPRESSES_ROOT} - -P "${PROJECT_SOURCE_DIR}/cmake/InstallClintErrors.cmake" + -P ${LINT_SUPPRESSES_INSTALL_SCRIPT} + DEPENDS + ${LINT_SUPPRESSES_ARCHIVE} ${LINT_SUPPRESSES_INSTALL_SCRIPT} ) add_download(${LINT_SUPPRESS_FILE} ${LINT_SUPPRESS_URL} off) @@ -515,7 +519,7 @@ foreach(sfile ${LINT_NVIM_SOURCES}) COMMAND ${LINT_PRG} --suppress-errors=${suppress_file} ${rsfile} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${CMAKE_COMMAND} -E touch ${touch_file} - DEPENDS ${LINT_PRG} ${sfile} clint-error-files + DEPENDS ${LINT_PRG} ${sfile} ${LINT_SUPPRESSES_TOUCH_FILE} ) list(APPEND LINT_TARGETS ${touch_file}) list(APPEND LINT_NVIM_REL_SOURCES ${rsfile}) -- cgit From fb66a7c69ef061fd2da12df8bca47592df25438f Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 8 Apr 2017 21:22:11 -0400 Subject: vim-patch:8.0.0377 Problem: Possible overflow when reading corrupted undo file. Solution: Check if allocated size is not too big. (King) https://github.com/vim/vim/commit/3eb1637b1bba19519885dd6d377bd5596e91d22c CVE-2017-6349 --- src/nvim/undo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 4d4e8d9bb9..83c171d66a 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include @@ -1400,7 +1401,9 @@ void u_read_undo(char *name, char_u *hash, char_u *orig_name) // sequence numbers of the headers. // When there are no headers uhp_table is NULL. if (num_head > 0) { - uhp_table = xmalloc((size_t)num_head * sizeof(u_header_T *)); + if ((size_t)num_head < SIZE_MAX / sizeof(*uhp_table)) { + uhp_table = xmalloc((size_t)num_head * sizeof(*uhp_table)); + } } long num_read_uhps = 0; -- cgit From ad66826abee14009abddfbef3e6088afc773ab9d Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 8 Apr 2017 21:56:02 -0400 Subject: vim-patch:8.0.0378 Problem: Another possible overflow when reading corrupted undo file. Solution: Check if allocated size is not too big. (King) https://github.com/vim/vim/commit/0c8485f0e4931463c0f7986e1ea84a7d79f10c75 CVE-2017-6350 --- src/nvim/undo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 83c171d66a..571ad7204f 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -967,12 +967,12 @@ static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error, uep->ue_lcount = undo_read_4c(bi); uep->ue_size = undo_read_4c(bi); - char_u **array; + char_u **array = NULL; if (uep->ue_size > 0) { - array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size); - memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size); - } else { - array = NULL; + if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char_u *)) { + array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size); + memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size); + } } uep->ue_array = array; -- cgit From b338bb9d6c331fa4a45fbbeb7da3210f30f31702 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 9 Apr 2017 00:45:19 -0400 Subject: vim-patch:8.0.0322 Problem: Possible overflow with spell file where the tree length is corrupted. Solution: Check for an invalid length (suggested by shqking) https://github.com/vim/vim/commit/399c297aa93afe2c0a39e2a1b3f972aebba44c9d CVE-2017-5953 --- src/nvim/spellfile.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 4d7ff558ad..81000b95f5 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1572,6 +1572,10 @@ spell_read_tree ( int len = get4c(fd); if (len < 0) return SP_TRUNCERROR; + if (len >= 0x3ffffff) { + // Invalid length, multiply with sizeof(int) would overflow. + return SP_FORMERROR; + } if (len > 0) { // Allocate the byte array. bp = xmalloc(len); -- cgit From 4af6c60826b4cb939fd9b7fe67a0b03e86d72bfc Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 9 Apr 2017 00:46:52 -0400 Subject: vim-patch:8.0.0376 Problem: Size computations in spell file reading are not exactly right. Solution: Make "len" a "long" and check with LONG_MAX. https://github.com/vim/vim/commit/6d3c8586fc81b022e9f06c611b9926108fb878c7 --- src/nvim/spellfile.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 81000b95f5..a6cee59795 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -223,6 +223,7 @@ // few bytes as possible, see offset2bytes()) #include +#include #include #include "nvim/vim.h" @@ -1569,10 +1570,10 @@ spell_read_tree ( // The tree size was computed when writing the file, so that we can // allocate it as one long block. - int len = get4c(fd); + long len = get4c(fd); if (len < 0) return SP_TRUNCERROR; - if (len >= 0x3ffffff) { + if ((size_t)len >= SIZE_MAX / sizeof(int)) { // Invalid length, multiply with sizeof(int) would overflow. return SP_FORMERROR; } -- cgit From 06a96df510e1fa8d77d21a8120e97342d04be15f Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 9 Apr 2017 01:17:15 -0400 Subject: lint --- src/nvim/spellfile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index a6cee59795..bbef1f5032 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1571,8 +1571,9 @@ spell_read_tree ( // The tree size was computed when writing the file, so that we can // allocate it as one long block. long len = get4c(fd); - if (len < 0) + if (len < 0) { return SP_TRUNCERROR; + } if ((size_t)len >= SIZE_MAX / sizeof(int)) { // Invalid length, multiply with sizeof(int) would overflow. return SP_FORMERROR; -- cgit From 8d982ab52269e8adccbc21cc0d6f8ab3b817bf6e Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 20:55:48 +0300 Subject: coverity/13686: Do not allow NUL byte in precondition regex Before this commit it emitted e_spell_trunc in the first case and treated file as completely valid on the second. While first is fine (both errors are actually valid, though old error is probably better), second results in incorrect regex used. --- src/nvim/spellfile.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index bbef1f5032..2c0db0694a 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -267,7 +267,7 @@ #define SAL_REM_ACCENTS 4 #define VIMSPELLMAGIC "VIMspell" // string at start of Vim spell file -#define VIMSPELLMAGICL 8 +#define VIMSPELLMAGICL (sizeof(VIMSPELLMAGIC) - 1) #define VIMSPELLVERSION 50 // Section IDs. Only renumber them when VIMSPELLVERSION changes! @@ -516,7 +516,6 @@ spell_load_file ( FILE *fd; char_u buf[VIMSPELLMAGICL]; char_u *p; - int i; int n; int len; char_u *save_sourcing_name = sourcing_name; @@ -558,8 +557,9 @@ spell_load_file ( sourcing_lnum = 0; //
: - for (i = 0; i < VIMSPELLMAGICL; ++i) + for (size_t i = 0; i < VIMSPELLMAGICL; i++) { buf[i] = getc(fd); // + } if (STRNCMP(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { EMSG(_("E757: This does not look like a spell file")); goto endFAIL; @@ -983,35 +983,36 @@ static int read_charflags_section(FILE *fd) // Return SP_*ERROR flags. static int read_prefcond_section(FILE *fd, slang_T *lp) { - int cnt; - int i; - int n; - char_u *p; - char_u buf[MAXWLEN + 1]; - // ... - cnt = get2c(fd); // - if (cnt <= 0) + const int cnt = get2c(fd); // + if (cnt <= 0) { return SP_FORMERROR; + } lp->sl_prefprog = xcalloc(cnt, sizeof(regprog_T *)); lp->sl_prefixcnt = cnt; - for (i = 0; i < cnt; ++i) { + for (int i = 0; i < cnt; ++i) { // : - n = getc(fd); // - if (n < 0 || n >= MAXWLEN) + const int n = getc(fd); // + if (n < 0 || n >= MAXWLEN) { return SP_FORMERROR; + } // When is zero we have an empty condition. Otherwise // compile the regexp program used to check for the condition. if (n > 0) { - buf[0] = '^'; // always match at one position only - p = buf + 1; - while (n-- > 0) - *p++ = getc(fd); // - *p = NUL; - lp->sl_prefprog[i] = vim_regcomp(buf, RE_MAGIC + RE_STRING); + char buf[MAXWLEN + 1]; + buf[0] = '^'; // always match at one position only + const size_t read_byte = fread(buf + 1, 1, (size_t)n, fd); + if (read_byte != (size_t)n) { + return feof(fd) ? SP_FORMERROR : SP_OTHERERROR; + } + if (memchr(buf + 1, NUL, (size_t)n)) { + return SP_FORMERROR; + } + buf[n + 1] = NUL; + lp->sl_prefprog[i] = vim_regcomp((char_u *)buf, RE_MAGIC | RE_STRING); } } return 0; -- cgit From 5b4f07ee86194a7c6032991102c96387581029c9 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 21:47:45 +0300 Subject: spellfile: Use old error This makes first test not actually show any change in behaviour. --- src/nvim/spellfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 2c0db0694a..4909b7b14e 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1006,7 +1006,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) buf[0] = '^'; // always match at one position only const size_t read_byte = fread(buf + 1, 1, (size_t)n, fd); if (read_byte != (size_t)n) { - return feof(fd) ? SP_FORMERROR : SP_OTHERERROR; + return feof(fd) ? SP_TRUNCERROR : SP_OTHERERROR; } if (memchr(buf + 1, NUL, (size_t)n)) { return SP_FORMERROR; -- cgit From ecce981dba367d61be170b535083691dd9c40cd2 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 22:02:26 +0300 Subject: coverity/13687: Do not allow NUL byte in region names --- src/nvim/spellfile.c | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 4909b7b14e..97a82582c0 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -494,6 +494,41 @@ typedef struct spellinfo_S { # include "spellfile.c.generated.h" #endif +/// Read n bytes from fd to buf, returning on errors +/// +/// @param[out] buf Buffer to read to, must be at least n bytes long. +/// @param[in] n Amount of bytes to read. +/// @param fd FILE* to read from. +/// +/// @return Allows to proceed if everything is OK, returns SP_TRUNCERROR if +/// there are not enough bytes, returns SP_OTHERERROR if reading failed. +#define SPELL_READ_BYTES(buf, n, fd) \ + do { \ + const size_t n__SPRB = (n); \ + FILE *const fd__SPRB = (fd); \ + char *const buf__SPRB = (buf); \ + const size_t read_bytes__SPRB = fread(buf__SPRB, 1, n__SPRB, fd__SPRB); \ + if (read_bytes__SPRB != n__SPRB) { \ + return feof(fd__SPRB) ? SP_TRUNCERROR : SP_OTHERERROR; \ + } \ + } while (0) + +/// Like #SPELL_READ_BYTES, but also error out if NUL byte was read +/// +/// @return Allows to proceed if everything is OK, returns SP_TRUNCERROR if +/// there are not enough bytes, returns SP_OTHERERROR if reading failed, +/// returns SP_FORMERROR if read out a NUL byte. +#define SPELL_READ_NONNUL_BYTES(buf, n, fd) \ + do { \ + const size_t n__SPRNB = (n); \ + FILE *const fd__SPRNB = (fd); \ + char *const buf__SPRNB = (buf); \ + SPELL_READ_BYTES(buf__SPRNB, n__SPRNB, fd__SPRNB); \ + if (memchr(buf__SPRNB, NUL, (size_t)n__SPRNB)) { \ + return SP_FORMERROR; \ + } \ + } while (0) + // Load one spell file and store the info into a slang_T. // // This is invoked in three ways: @@ -935,12 +970,10 @@ static char_u *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) // Return SP_*ERROR flags. static int read_region_section(FILE *fd, slang_T *lp, int len) { - int i; - - if (len > 16) + if (len > 16) { return SP_FORMERROR; - for (i = 0; i < len; ++i) - lp->sl_regions[i] = getc(fd); // + } + SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd); lp->sl_regions[len] = NUL; return 0; } @@ -1004,13 +1037,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) if (n > 0) { char buf[MAXWLEN + 1]; buf[0] = '^'; // always match at one position only - const size_t read_byte = fread(buf + 1, 1, (size_t)n, fd); - if (read_byte != (size_t)n) { - return feof(fd) ? SP_TRUNCERROR : SP_OTHERERROR; - } - if (memchr(buf + 1, NUL, (size_t)n)) { - return SP_FORMERROR; - } + SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd); buf[n + 1] = NUL; lp->sl_prefprog[i] = vim_regcomp((char_u *)buf, RE_MAGIC | RE_STRING); } -- cgit From 8f75b67c0733f09b8bc1d99235eb3231abc6500c Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 22:16:26 +0300 Subject: coverity/13688: Check for NUL bytes in salfrom --- src/nvim/spellfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 97a82582c0..8756bee21c 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1157,8 +1157,8 @@ static int read_sal_section(FILE *fd, slang_T *slang) if (i < ccnt) // store the char we got while checking for end of sm_lead *p++ = c; - for (++i; i < ccnt; ++i) - *p++ = getc(fd); // + SPELL_READ_NONNUL_BYTES((char *)p, (size_t)ccnt, fd); // + p += ccnt; *p++ = NUL; // -- cgit From 35584594f5cfd46e9a56d9bc3473244c437a944a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 22:30:48 +0300 Subject: coverity/13689: Check file header with memcmp Not that it is actually useful (would fail in any case), but should fix coverity report. --- src/nvim/spellfile.c | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 8756bee21c..9943a71a7c 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -225,6 +225,7 @@ #include #include #include +#include #include "nvim/vim.h" #include "nvim/spell_defs.h" @@ -529,6 +530,26 @@ typedef struct spellinfo_S { } \ } while (0) +/// Check that spell file starts with a magic string +/// +/// Does not check for version of the file. +/// +/// @param fd File to check. +/// +/// @return 0 in case of success, SP_TRUNCERROR if file contains not enough +/// bytes, SP_FORMERROR if it does not match magic string and +/// SP_OTHERERROR if reading file failed. +static inline int spell_check_magic_string(FILE *const fd) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE +{ + char buf[VIMSPELLMAGICL]; + SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd); + if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { + return SP_FORMERROR; + } + return 0; +} + // Load one spell file and store the info into a slang_T. // // This is invoked in three ways: @@ -549,7 +570,6 @@ spell_load_file ( ) { FILE *fd; - char_u buf[VIMSPELLMAGICL]; char_u *p; int n; int len; @@ -592,12 +612,20 @@ spell_load_file ( sourcing_lnum = 0; //
: - for (size_t i = 0; i < VIMSPELLMAGICL; i++) { - buf[i] = getc(fd); // - } - if (STRNCMP(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { - EMSG(_("E757: This does not look like a spell file")); - goto endFAIL; + const int scms_ret = spell_check_magic_string(fd); + switch (scms_ret) { + case SP_FORMERROR: + case SP_TRUNCERROR: { + emsgf(_("E757: This does not look like a spell file")); + goto endFAIL; + } + case SP_OTHERERROR: { + emsgf(_("E5042: Failed to read spell file %s: %s"), + fname, strerror(ferror(fd))); + } + case 0: { + break; + } } c = getc(fd); // if (c < VIMSPELLVERSION) { -- cgit From aa857f9e481770059642b9286b66c75b1d9bd758 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 22:33:45 +0300 Subject: spellfile: Fix memory leak --- src/nvim/spellfile.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 9943a71a7c..d34c3a8ba1 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -500,16 +500,18 @@ typedef struct spellinfo_S { /// @param[out] buf Buffer to read to, must be at least n bytes long. /// @param[in] n Amount of bytes to read. /// @param fd FILE* to read from. +/// @param exit_code Code to run before returning. /// /// @return Allows to proceed if everything is OK, returns SP_TRUNCERROR if /// there are not enough bytes, returns SP_OTHERERROR if reading failed. -#define SPELL_READ_BYTES(buf, n, fd) \ +#define SPELL_READ_BYTES(buf, n, fd, exit_code) \ do { \ const size_t n__SPRB = (n); \ FILE *const fd__SPRB = (fd); \ char *const buf__SPRB = (buf); \ const size_t read_bytes__SPRB = fread(buf__SPRB, 1, n__SPRB, fd__SPRB); \ if (read_bytes__SPRB != n__SPRB) { \ + exit_code; \ return feof(fd__SPRB) ? SP_TRUNCERROR : SP_OTHERERROR; \ } \ } while (0) @@ -519,13 +521,14 @@ typedef struct spellinfo_S { /// @return Allows to proceed if everything is OK, returns SP_TRUNCERROR if /// there are not enough bytes, returns SP_OTHERERROR if reading failed, /// returns SP_FORMERROR if read out a NUL byte. -#define SPELL_READ_NONNUL_BYTES(buf, n, fd) \ +#define SPELL_READ_NONNUL_BYTES(buf, n, fd, exit_code) \ do { \ const size_t n__SPRNB = (n); \ FILE *const fd__SPRNB = (fd); \ char *const buf__SPRNB = (buf); \ - SPELL_READ_BYTES(buf__SPRNB, n__SPRNB, fd__SPRNB); \ + SPELL_READ_BYTES(buf__SPRNB, n__SPRNB, fd__SPRNB, exit_code); \ if (memchr(buf__SPRNB, NUL, (size_t)n__SPRNB)) { \ + exit_code; \ return SP_FORMERROR; \ } \ } while (0) @@ -543,7 +546,7 @@ static inline int spell_check_magic_string(FILE *const fd) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { char buf[VIMSPELLMAGICL]; - SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd); + SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd, ); if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { return SP_FORMERROR; } @@ -1001,7 +1004,7 @@ static int read_region_section(FILE *fd, slang_T *lp, int len) if (len > 16) { return SP_FORMERROR; } - SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd); + SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ); lp->sl_regions[len] = NUL; return 0; } @@ -1065,7 +1068,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) if (n > 0) { char buf[MAXWLEN + 1]; buf[0] = '^'; // always match at one position only - SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd); + SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd, ); buf[n + 1] = NUL; lp->sl_prefprog[i] = vim_regcomp((char_u *)buf, RE_MAGIC | RE_STRING); } @@ -1185,7 +1188,8 @@ static int read_sal_section(FILE *fd, slang_T *slang) if (i < ccnt) // store the char we got while checking for end of sm_lead *p++ = c; - SPELL_READ_NONNUL_BYTES((char *)p, (size_t)ccnt, fd); // + SPELL_READ_NONNUL_BYTES( // + (char *)p, (size_t)ccnt, fd, xfree(smp->sm_lead)); p += ccnt; *p++ = NUL; -- cgit From eb3663eb1000bdf9b5c754614921001b21a2cf03 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 22:39:23 +0300 Subject: spellfile: Fix clint errors --- src/nvim/spellfile.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index d34c3a8ba1..f4acb37a7a 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -546,7 +546,7 @@ static inline int spell_check_magic_string(FILE *const fd) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { char buf[VIMSPELLMAGICL]; - SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd, ); + SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd, ;); if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { return SP_FORMERROR; } @@ -1004,7 +1004,7 @@ static int read_region_section(FILE *fd, slang_T *lp, int len) if (len > 16) { return SP_FORMERROR; } - SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ); + SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ;); lp->sl_regions[len] = NUL; return 0; } @@ -1056,7 +1056,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) lp->sl_prefprog = xcalloc(cnt, sizeof(regprog_T *)); lp->sl_prefixcnt = cnt; - for (int i = 0; i < cnt; ++i) { + for (int i = 0; i < cnt; i++) { // : const int n = getc(fd); // if (n < 0 || n >= MAXWLEN) { @@ -1068,7 +1068,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) if (n > 0) { char buf[MAXWLEN + 1]; buf[0] = '^'; // always match at one position only - SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd, ); + SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd, ;); buf[n + 1] = NUL; lp->sl_prefprog[i] = vim_regcomp((char_u *)buf, RE_MAGIC | RE_STRING); } -- cgit From fa7ace446e724f888c815fe177c7b6e7b8057b7d Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 23:38:05 +0300 Subject: coverity/56795: Fix NULL dereference in :syn keyword non-printable Bug was introduced 3 years earlier, in 13848aa: NULL keyword_copy was incorrectly treated as an indicator of OOM. --- src/nvim/syntax.c | 124 +++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index e36b00d770..1ed65ec52a 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -4246,83 +4246,81 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) if (rest != NULL) { syn_id = syn_check_group(arg, (int)(group_name_end - arg)); - if (syn_id != 0) - /* allocate a buffer, for removing backslashes in the keyword */ + if (syn_id != 0) { + // Allocate a buffer, for removing backslashes in the keyword. keyword_copy = xmalloc(STRLEN(rest) + 1); - syn_opt_arg.flags = 0; - syn_opt_arg.keyword = TRUE; - syn_opt_arg.sync_idx = NULL; - syn_opt_arg.has_cont_list = FALSE; - syn_opt_arg.cont_in_list = NULL; - syn_opt_arg.next_list = NULL; - - /* - * The options given apply to ALL keywords, so all options must be - * found before keywords can be created. - * 1: collect the options and copy the keywords to keyword_copy. - */ - cnt = 0; - p = keyword_copy; - for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { - rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); - if (rest == NULL || ends_excmd(*rest)) - break; - /* Copy the keyword, removing backslashes, and add a NUL. */ - while (*rest != NUL && !ascii_iswhite(*rest)) { - if (*rest == '\\' && rest[1] != NUL) - ++rest; - *p++ = *rest++; - } - *p++ = NUL; - ++cnt; } + if (keyword_copy != NULL) { + syn_opt_arg.flags = 0; + syn_opt_arg.keyword = true; + syn_opt_arg.sync_idx = NULL; + syn_opt_arg.has_cont_list = false; + syn_opt_arg.cont_in_list = NULL; + syn_opt_arg.next_list = NULL; + + // The options given apply to ALL keywords, so all options must be + // found before keywords can be created. + // 1: collect the options and copy the keywords to keyword_copy. + cnt = 0; + p = keyword_copy; + for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); + if (rest == NULL || ends_excmd(*rest)) { + break; + } + // Copy the keyword, removing backslashes, and add a NUL. + while (*rest != NUL && !ascii_iswhite(*rest)) { + if (*rest == '\\' && rest[1] != NUL) { + rest++; + } + *p++ = *rest++; + } + *p++ = NUL; + cnt++; + } - if (!eap->skip) { - /* Adjust flags for use of ":syn include". */ - syn_incl_toplevel(syn_id, &syn_opt_arg.flags); + if (!eap->skip) { + // Adjust flags for use of ":syn include". + syn_incl_toplevel(syn_id, &syn_opt_arg.flags); - /* - * 2: Add an entry for each keyword. - */ - for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { - for (p = vim_strchr(kw, '[');; ) { - if (p != NULL) - *p = NUL; - add_keyword(kw, syn_id, syn_opt_arg.flags, - syn_opt_arg.cont_in_list, - syn_opt_arg.next_list, conceal_char); - if (p == NULL) - break; - if (p[1] == NUL) { - EMSG2(_("E789: Missing ']': %s"), kw); - goto error; - } - if (p[1] == ']') { - if (p[2] != NUL) { - EMSG3(_("E890: trailing char after ']': %s]%s"), - kw, &p[2]); + // 2: Add an entry for each keyword. + for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { + for (p = vim_strchr(kw, '[');; ) { + if (p != NULL) { + *p = NUL; + } + add_keyword(kw, syn_id, syn_opt_arg.flags, + syn_opt_arg.cont_in_list, + syn_opt_arg.next_list, conceal_char); + if (p == NULL) { + break; + } + if (p[1] == NUL) { + emsgf(_("E789: Missing ']': %s"), kw); goto error; } - kw = p + 1; - break; // skip over the "]" - } - if (has_mbyte) { - int l = (*mb_ptr2len)(p + 1); + if (p[1] == ']') { + if (p[2] != NUL) { + emsgf(_("E890: trailing char after ']': %s]%s"), + kw, &p[2]); + goto error; + } + kw = p + 1; + break; // skip over the "]" + } + const int l = (*mb_ptr2len)(p + 1); memmove(p, p + 1, l); p += l; - } else { - p[0] = p[1]; - ++p; } } } - } error: - xfree(keyword_copy); - xfree(syn_opt_arg.cont_in_list); - xfree(syn_opt_arg.next_list); + xfree(keyword_copy); + xfree(syn_opt_arg.cont_in_list); + xfree(syn_opt_arg.next_list); + } } if (rest != NULL) -- cgit From ebe50519775081565b66e18a471473e46f713442 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 23:46:38 +0300 Subject: spellfile: Fix SAL sections reading --- src/nvim/spellfile.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index f4acb37a7a..1da71dc4f9 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1123,7 +1123,6 @@ static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first) // Return SP_*ERROR flags. static int read_sal_section(FILE *fd, slang_T *slang) { - int i; int cnt; garray_T *gap; salitem_T *smp; @@ -1133,13 +1132,16 @@ static int read_sal_section(FILE *fd, slang_T *slang) slang->sl_sofo = false; - i = getc(fd); // - if (i & SAL_F0LLOWUP) + const int flags = getc(fd); // + if (flags & SAL_F0LLOWUP) { slang->sl_followup = true; - if (i & SAL_COLLAPSE) + } + if (flags & SAL_COLLAPSE) { slang->sl_collapse = true; - if (i & SAL_REM_ACCENTS) + } + if (flags & SAL_REM_ACCENTS) { slang->sl_rem_accents = true; + } cnt = get2c(fd); // if (cnt < 0) @@ -1159,7 +1161,8 @@ static int read_sal_section(FILE *fd, slang_T *slang) smp->sm_lead = p; // Read up to the first special char into sm_lead. - for (i = 0; i < ccnt; ++i) { + int i = 0; + for (; i < ccnt; ++i) { c = getc(fd); // if (vim_strchr((char_u *)"0123456789(-<^$", c) != NULL) break; @@ -1185,12 +1188,17 @@ static int read_sal_section(FILE *fd, slang_T *slang) // Any following chars go in sm_rules. smp->sm_rules = p; - if (i < ccnt) + if (i < ccnt) { // store the char we got while checking for end of sm_lead *p++ = c; - SPELL_READ_NONNUL_BYTES( // - (char *)p, (size_t)ccnt, fd, xfree(smp->sm_lead)); - p += ccnt; + } + i++; + if (i < ccnt) { + SPELL_READ_NONNUL_BYTES( // + (char *)p, (size_t)(ccnt - i), fd, xfree(smp->sm_lead)); + p += (ccnt - i); + i = ccnt; + } *p++ = NUL; // -- cgit From 1b66ed890b6e1444b6be113bc5572f1baf82db6c Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 10 Apr 2017 02:53:00 +0300 Subject: cmake: Do not forget to actually create a touch file for errors.tar.gz --- src/nvim/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index cb003c2026..a91657f1bd 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -501,6 +501,7 @@ add_custom_command( ${CMAKE_COMMAND} -DTARGET=${LINT_SUPPRESSES_ROOT} -P ${LINT_SUPPRESSES_INSTALL_SCRIPT} + COMMAND ${CMAKE_COMMAND} -E touch ${LINT_SUPPRESSES_TOUCH_FILE} DEPENDS ${LINT_SUPPRESSES_ARCHIVE} ${LINT_SUPPRESSES_INSTALL_SCRIPT} ) -- cgit From db9ef6263ec5b7885782ccf0a93e06b0c71f6944 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 8 Apr 2017 16:45:38 +0200 Subject: mbyte: replace vim_tolower with mb_tolower handling locale correctly --- src/nvim/charset.c | 69 +++----------------------------------------------- src/nvim/edit.c | 22 ++++++++-------- src/nvim/eval.c | 2 +- src/nvim/ex_getln.c | 4 +-- src/nvim/file_search.c | 2 +- src/nvim/macros.h | 2 +- src/nvim/mbyte.c | 17 ++++++++----- src/nvim/message.c | 4 +-- src/nvim/ops.c | 10 ++++---- src/nvim/path.c | 4 +-- src/nvim/regexp.c | 34 ++++++++++++------------- src/nvim/regexp_nfa.c | 20 +++++++-------- src/nvim/search.c | 4 +-- src/nvim/spell.c | 14 +++++----- src/nvim/spell_defs.h | 4 +-- src/nvim/strings.c | 2 +- 16 files changed, 79 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 99d3e2dd88..645139f696 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -212,8 +212,8 @@ int buf_init_chartab(buf_T *buf, int global) // work properly when 'encoding' is "latin1" and the locale is // "C". if (!do_isalpha - || vim_islower(c) - || vim_isupper(c) + || mb_islower(c) + || mb_isupper(c) || (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))) { if (i == 0) { // (re)set ID flag @@ -417,11 +417,11 @@ char_u* str_foldcase(char_u *str, int orglen, char_u *buf, int buflen) while (STR_CHAR(i) != NUL) { int c = utf_ptr2char(STR_PTR(i)); int olen = utf_ptr2len(STR_PTR(i)); - int lc = utf_tolower(c); + int lc = mb_tolower(c); // Only replace the character when it is not an invalid // sequence (ASCII character or more than one byte) and - // utf_tolower() doesn't return the original character. + // mb_tolower() doesn't return the original character. if (((c < 0x80) || (olen > 1)) && (c != lc)) { int nlen = utf_char2len(lc); @@ -1506,67 +1506,6 @@ char_u* skiptohex(char_u *q) return p; } -// Vim's own character class functions. These exist because many library -// islower()/toupper() etc. do not work properly: they crash when used with -// invalid values or can't handle latin1 when the locale is C. -// Speed is most important here. - -/// Check that the character is lower-case -/// -/// @param c character to check -bool vim_islower(int c) - FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (c <= '@') { - return false; - } - - if (c >= 0x80) { - return utf_islower(c); - } - return islower(c); -} - -/// Check that the character is upper-case -/// -/// @param c character to check -bool vim_isupper(int c) - FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (c <= '@') { - return false; - } - - if (c >= 0x80) { - return utf_isupper(c); - } - return isupper(c); -} - -int vim_toupper(int c) -{ - if (c <= '@') { - return c; - } - - if (c >= 0x80) { - return utf_toupper(c); - } - return TOUPPER_LOC(c); -} - -int vim_tolower(int c) -{ - if (c <= '@') { - return c; - } - - if (c >= 0x80) { - return utf_tolower(c); - } - return TOLOWER_LOC(c); -} - /// Skip over text until ' ' or '\t' or NUL /// /// @param[in] p Text to skip over. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index b35504908e..aa254b0577 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -2037,12 +2037,12 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int } else { c = *(p++); } - if (vim_islower(c)) { + if (mb_islower(c)) { has_lower = true; - if (vim_isupper(wca[i])) { + if (mb_isupper(wca[i])) { // Rule 1 is satisfied. for (i = actual_compl_length; i < actual_len; i++) { - wca[i] = vim_tolower(wca[i]); + wca[i] = mb_tolower(wca[i]); } break; } @@ -2062,14 +2062,14 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int } else { c = *(p++); } - if (was_letter && vim_isupper(c) && vim_islower(wca[i])) { + if (was_letter && mb_isupper(c) && mb_islower(wca[i])) { // Rule 2 is satisfied. for (i = actual_compl_length; i < actual_len; i++) { - wca[i] = vim_toupper(wca[i]); + wca[i] = mb_toupper(wca[i]); } break; } - was_letter = vim_islower(c) || vim_isupper(c); + was_letter = mb_islower(c) || mb_isupper(c); } } @@ -2082,10 +2082,10 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int } else { c = *(p++); } - if (vim_islower(c)) { - wca[i] = vim_tolower(wca[i]); - } else if (vim_isupper(c)) { - wca[i] = vim_toupper(wca[i]); + if (mb_islower(c)) { + wca[i] = mb_tolower(wca[i]); + } else if (mb_isupper(c)) { + wca[i] = mb_toupper(wca[i]); } } } @@ -2302,7 +2302,7 @@ static void ins_compl_longest_match(compl_T *match) c1 = *p; c2 = *s; } - if (match->cp_icase ? (vim_tolower(c1) != vim_tolower(c2)) + if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) : (c1 != c2)) break; if (has_mbyte) { diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 124d6acfe9..c1ee33b06a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -16802,7 +16802,7 @@ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) int c, lc; c = utf_ptr2char(p); - lc = utf_tolower(c); + lc = mb_tolower(c); l = utf_ptr2len(p); /* TODO: reallocate string when byte count changes. */ if (utf_char2len(lc) == l) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 8810204c03..9d74f554ba 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1231,7 +1231,7 @@ static int command_line_handle_key(CommandLineState *s) // command line has no uppercase characters, convert // the character to lowercase if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff)) { - s->c = vim_tolower(s->c); + s->c = mb_tolower(s->c); } if (s->c != NUL) { @@ -3018,7 +3018,7 @@ ExpandOne ( || xp->xp_context == EXPAND_FILES || xp->xp_context == EXPAND_SHELLCMD || xp->xp_context == EXPAND_BUFFERS)) { - if (vim_tolower(c0) != vim_tolower(ci)) { + if (mb_tolower(c0) != mb_tolower(ci)) { break; } } else if (c0 != ci) { diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 9592235905..db745bdd15 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1057,7 +1057,7 @@ static bool ff_wc_equal(char_u *s1, char_u *s2) c1 = PTR2CHAR(s1 + i); c2 = PTR2CHAR(s2 + j); - if ((p_fic ? vim_tolower(c1) != vim_tolower(c2) : c1 != c2) + if ((p_fic ? mb_tolower(c1) != mb_tolower(c2) : c1 != c2) && (prev1 != '*' || prev2 != '*')) { return false; } diff --git a/src/nvim/macros.h b/src/nvim/macros.h index a8df6322cf..22fd48de9d 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -62,7 +62,7 @@ * toupper() and tolower() that use the current locale. * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the * range 0 - 255. toupper()/tolower() on some systems can't handle others. - * Note: It is often better to use vim_tolower() and vim_toupper(), because many + * Note: It is often better to use mb_tolower() and mb_toupper(), because many * toupper() and tolower() implementations only work for ASCII. */ #define TOUPPER_LOC toupper diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 460528b85f..5f5abbeac5 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1174,11 +1174,16 @@ int utf_fold(int a) return utf_convert(a, foldCase, ARRAY_SIZE(foldCase)); } +// Vim's own character class functions. These exist because many library +// islower()/toupper() etc. do not work properly: they crash when used with +// invalid values or can't handle latin1 when the locale is C. +// Speed is most important here. + /* * Return the upper-case equivalent of "a", which is a UCS-4 character. Use * simple case folding. */ -int utf_toupper(int a) +int mb_toupper(int a) { /* If 'casemap' contains "keepascii" use ASCII style toupper(). */ if (a < 128 && (cmp_flags & CMP_KEEPASCII)) @@ -1198,17 +1203,17 @@ int utf_toupper(int a) return utf_convert(a, toUpper, ARRAY_SIZE(toUpper)); } -bool utf_islower(int a) +bool mb_islower(int a) { /* German sharp s is lower case but has no upper case equivalent. */ - return (utf_toupper(a) != a) || a == 0xdf; + return (mb_toupper(a) != a) || a == 0xdf; } /* * Return the lower-case equivalent of "a", which is a UCS-4 character. Use * simple case folding. */ -int utf_tolower(int a) +int mb_tolower(int a) { /* If 'casemap' contains "keepascii" use ASCII style tolower(). */ if (a < 128 && (cmp_flags & CMP_KEEPASCII)) @@ -1228,9 +1233,9 @@ int utf_tolower(int a) return utf_convert(a, toLower, ARRAY_SIZE(toLower)); } -bool utf_isupper(int a) +bool mb_isupper(int a) { - return utf_tolower(a) != a; + return mb_tolower(a) != a; } static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, diff --git a/src/nvim/message.c b/src/nvim/message.c index 1d3609291a..2cc426cf42 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2731,7 +2731,7 @@ do_dialog ( } /* Make the character lowercase, as chars in "hotkeys" are. */ - c = vim_tolower(c); + c = mb_tolower(c); retval = 1; for (i = 0; hotkeys[i]; ++i) { if (has_mbyte) { @@ -2777,7 +2777,7 @@ copy_char ( if (has_mbyte) { if (lowercase) { - c = vim_tolower((*mb_ptr2char)(from)); + c = mb_tolower((*mb_ptr2char)(from)); return (*mb_char2bytes)(c, to); } else { len = (*mb_ptr2len)(from); diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 68ef27222c..c5b7e65983 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1956,16 +1956,16 @@ int swapchar(int op_type, pos_T *pos) if (enc_dbcs != 0 && c >= 0x100) /* No lower/uppercase letter */ return FALSE; nc = c; - if (vim_islower(c)) { + if (mb_islower(c)) { if (op_type == OP_ROT13) nc = ROT13(c, 'a'); else if (op_type != OP_LOWER) - nc = vim_toupper(c); - } else if (vim_isupper(c)) { + nc = mb_toupper(c); + } else if (mb_isupper(c)) { if (op_type == OP_ROT13) nc = ROT13(c, 'A'); else if (op_type != OP_UPPER) - nc = vim_tolower(c); + nc = mb_tolower(c); } if (nc != c) { if (enc_utf8 && (c >= 0x80 || nc >= 0x80)) { @@ -3327,7 +3327,7 @@ void ex_display(exarg_T *eap) get_clipboard(name, &yb, true); - if (name == vim_tolower(redir_reg) + if (name == mb_tolower(redir_reg) || (redir_reg == '"' && yb == y_previous)) continue; /* do not list register being written to, the * pointer can be freed */ diff --git a/src/nvim/path.c b/src/nvim/path.c index 6bf42ed2fa..781522f63f 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1853,7 +1853,7 @@ int pathcmp(const char *p, const char *q, int maxlen) break; } - if ((p_fic ? vim_toupper(c1) != vim_toupper(c2) : c1 != c2) + if ((p_fic ? mb_toupper(c1) != mb_toupper(c2) : c1 != c2) #ifdef BACKSLASH_IN_FILENAME /* consider '/' and '\\' to be equal */ && !((c1 == '/' && c2 == '\\') @@ -1864,7 +1864,7 @@ int pathcmp(const char *p, const char *q, int maxlen) return -1; if (vim_ispathsep(c2)) return 1; - return p_fic ? vim_toupper(c1) - vim_toupper(c2) + return p_fic ? mb_toupper(c1) - mb_toupper(c2) : c1 - c2; /* no match */ } diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 9baa53d2a2..7e2fc261f2 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -2350,7 +2350,7 @@ collection: break; case CLASS_LOWER: for (cu = 1; cu <= 255; cu++) { - if (vim_islower(cu) && cu != 170 && cu != 186) { + if (mb_islower(cu) && cu != 170 && cu != 186) { regmbc(cu); } } @@ -2376,7 +2376,7 @@ collection: break; case CLASS_UPPER: for (cu = 1; cu <= 255; cu++) { - if (vim_isupper(cu)) { + if (mb_isupper(cu)) { regmbc(cu); } } @@ -3474,7 +3474,7 @@ static long bt_regexec_both(char_u *line, || (ireg_ic && (((enc_utf8 && utf_fold(prog->regstart) == utf_fold(c))) || (c < 255 && prog->regstart < 255 - && vim_tolower(prog->regstart) == vim_tolower(c))))) { + && mb_tolower(prog->regstart) == mb_tolower(c))))) { retval = regtry(prog, col); } else { retval = 0; @@ -4155,7 +4155,7 @@ regmatch ( if (*opnd != *reginput && (!ireg_ic || (!enc_utf8 - && vim_tolower(*opnd) != vim_tolower(*reginput)))) { + && mb_tolower(*opnd) != mb_tolower(*reginput)))) { status = RA_NOMATCH; } else if (*opnd == NUL) { // match empty string always works; happens when "~" is @@ -4573,10 +4573,10 @@ regmatch ( if (OP(next) == EXACTLY) { rst.nextb = *OPERAND(next); if (ireg_ic) { - if (vim_isupper(rst.nextb)) - rst.nextb_ic = vim_tolower(rst.nextb); + if (mb_isupper(rst.nextb)) + rst.nextb_ic = mb_tolower(rst.nextb); else - rst.nextb_ic = vim_toupper(rst.nextb); + rst.nextb_ic = mb_toupper(rst.nextb); } else rst.nextb_ic = rst.nextb; } else { @@ -5339,8 +5339,8 @@ do_class: * would have been used for it. It does handle single-byte * characters, such as latin1. */ if (ireg_ic) { - cu = vim_toupper(*opnd); - cl = vim_tolower(*opnd); + cu = mb_toupper(*opnd); + cl = mb_tolower(*opnd); while (count < maxcount && (*scan == cu || *scan == cl)) { count++; scan++; @@ -6314,10 +6314,10 @@ static char_u *cstrchr(char_u *s, int c) * For UTF-8 need to use folded case. */ if (enc_utf8 && c > 0x80) cc = utf_fold(c); - else if (vim_isupper(c)) - cc = vim_tolower(c); - else if (vim_islower(c)) - cc = vim_toupper(c); + else if (mb_isupper(c)) + cc = mb_tolower(c); + else if (mb_islower(c)) + cc = mb_toupper(c); else return vim_strchr(s, c); @@ -6348,28 +6348,28 @@ static char_u *cstrchr(char_u *s, int c) static fptr_T do_upper(int *d, int c) { - *d = vim_toupper(c); + *d = mb_toupper(c); return (fptr_T)NULL; } static fptr_T do_Upper(int *d, int c) { - *d = vim_toupper(c); + *d = mb_toupper(c); return (fptr_T)do_Upper; } static fptr_T do_lower(int *d, int c) { - *d = vim_tolower(c); + *d = mb_tolower(c); return (fptr_T)NULL; } static fptr_T do_Lower(int *d, int c) { - *d = vim_tolower(c); + *d = mb_tolower(c); return (fptr_T)do_Lower; } diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 5b49ab38f0..1d57595cbe 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -4373,7 +4373,7 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_LOWER: - if (vim_islower(c) && c != 170 && c != 186) { + if (mb_islower(c) && c != 170 && c != 186) { return OK; } break; @@ -4391,7 +4391,7 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_UPPER: - if (vim_isupper(c)) + if (mb_isupper(c)) return OK; break; case NFA_CLASS_XDIGIT: @@ -4892,7 +4892,7 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) int c2_len = PTR2LEN(s2); int c2 = PTR2CHAR(s2); - if ((c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2))) + if ((c1 != c2 && (!ireg_ic || mb_tolower(c1) != mb_tolower(c2))) || c1_len != c2_len) { match = false; break; @@ -5585,11 +5585,11 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, break; } if (ireg_ic) { - int curc_low = vim_tolower(curc); + int curc_low = mb_tolower(curc); int done = FALSE; for (; c1 <= c2; ++c1) - if (vim_tolower(c1) == curc_low) { + if (mb_tolower(c1) == curc_low) { result = result_if_matched; done = TRUE; break; @@ -5599,8 +5599,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } } else if (state->c < 0 ? check_char_class(state->c, curc) : (curc == state->c - || (ireg_ic && vim_tolower(curc) - == vim_tolower(state->c)))) { + || (ireg_ic && mb_tolower(curc) + == mb_tolower(state->c)))) { result = result_if_matched; break; } @@ -6004,7 +6004,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, result = (c == curc); if (!result && ireg_ic) - result = vim_tolower(c) == vim_tolower(curc); + result = mb_tolower(c) == mb_tolower(curc); // If ireg_icombine is not set only skip over the character // itself. When it is set skip over composing characters. @@ -6152,8 +6152,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // Checking if the required start character matches is // cheaper than adding a state that won't match. c = PTR2CHAR(reginput + clen); - if (c != prog->regstart && (!ireg_ic || vim_tolower(c) - != vim_tolower(prog->regstart))) { + if (c != prog->regstart && (!ireg_ic || mb_tolower(c) + != mb_tolower(prog->regstart))) { #ifdef REGEXP_DEBUG fprintf(log_fd, " Skipping start state, regstart does not match\n"); diff --git a/src/nvim/search.c b/src/nvim/search.c index c5c92b41c5..4f060b2b8b 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -336,7 +336,7 @@ int pat_has_uppercase(char_u *pat) int l; if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) { - if (enc_utf8 && utf_isupper(utf_ptr2char(p))) + if (enc_utf8 && mb_isupper(utf_ptr2char(p))) return TRUE; p += l; } else if (*p == '\\') { @@ -348,7 +348,7 @@ int pat_has_uppercase(char_u *pat) p += 2; else p += 1; - } else if (vim_isupper(*p)) + } else if (mb_isupper(*p)) return TRUE; else ++p; diff --git a/src/nvim/spell.c b/src/nvim/spell.c index d4f49bffb2..99661d0ef5 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -2545,10 +2545,10 @@ void init_spell_chartab(void) } else if (enc_utf8) { for (i = 128; i < 256; ++i) { int f = utf_fold(i); - int u = utf_toupper(i); + int u = mb_toupper(i); - spelltab.st_isu[i] = utf_isupper(i); - spelltab.st_isw[i] = spelltab.st_isu[i] || utf_islower(i); + spelltab.st_isu[i] = mb_isupper(i); + spelltab.st_isw[i] = spelltab.st_isu[i] || mb_islower(i); // The folded/upper-cased value is different between latin1 and // utf8 for 0xb5, causing E763 for no good reason. Use the latin1 // value for utf-8 to avoid this. @@ -2558,13 +2558,13 @@ void init_spell_chartab(void) } else { // Rough guess: use locale-dependent library functions. for (i = 128; i < 256; ++i) { - if (vim_isupper(i)) { + if (mb_isupper(i)) { spelltab.st_isw[i] = true; spelltab.st_isu[i] = true; - spelltab.st_fold[i] = vim_tolower(i); - } else if (vim_islower(i)) { + spelltab.st_fold[i] = mb_tolower(i); + } else if (mb_islower(i)) { spelltab.st_isw[i] = true; - spelltab.st_upper[i] = vim_toupper(i); + spelltab.st_upper[i] = mb_toupper(i); } } } diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h index c54a7f5390..ddd54c724e 100644 --- a/src/nvim/spell_defs.h +++ b/src/nvim/spell_defs.h @@ -265,11 +265,11 @@ typedef struct trystate_S { : (c) < \ 256 ? (int)spelltab.st_fold[c] : (int)towlower(c)) -#define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \ +#define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? mb_toupper(c) \ : (c) < \ 256 ? (int)spelltab.st_upper[c] : (int)towupper(c)) -#define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \ +#define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? mb_isupper(c) \ : (c) < 256 ? spelltab.st_isu[c] : iswupper(c)) // First language that is loaded, start of the linked list of loaded diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 5dcffe00e0..e7c0fb8a7d 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -309,7 +309,7 @@ char *strup_save(const char *const orig) if (enc_utf8) { int c = utf_ptr2char((const char_u *)p); - int uc = utf_toupper(c); + int uc = mb_toupper(c); // Reallocate string when byte count changes. This is rare, // thus it's OK to do another malloc()/free(). -- cgit From 4c857dae1169f3b8c7b6a9740f50acfd3c16858d Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 9 Apr 2017 09:29:00 +0200 Subject: vim-patch:8.0.0243 Problem: When making a character lower case with tolower() changes the byte cound, it is not made lower case. Solution: Add strlow_save(). (Dominique Pelle, closes vim/vim#1406) https://github.com/vim/vim/commit/cc5b22b3bfdc0e9e835cf7871166badda31447bd Join almost identical strup_save and strlow_save functions to one Function. --- src/nvim/eval.c | 26 +------ src/nvim/strings.c | 51 ++++++------- src/nvim/testdir/test_functions.vim | 144 ++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c1ee33b06a..ed07de51c8 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -16791,30 +16791,8 @@ void timer_teardown(void) */ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = (char_u *)xstrdup(tv_get_string(&argvars[0])); rettv->v_type = VAR_STRING; - rettv->vval.v_string = p; - - while (*p != NUL) { - int l; - - if (enc_utf8) { - int c, lc; - - c = utf_ptr2char(p); - lc = mb_tolower(c); - l = utf_ptr2len(p); - /* TODO: reallocate string when byte count changes. */ - if (utf_char2len(lc) == l) - utf_char2bytes(lc, p); - p += l; - } else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) - p += l; /* skip multi-byte character */ - else { - *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ - ++p; - } - } + rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), false); } /* @@ -16823,7 +16801,7 @@ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)strup_save(tv_get_string(&argvars[0])); + rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), true); } /* diff --git a/src/nvim/strings.c b/src/nvim/strings.c index e7c0fb8a7d..87e066d80a 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -291,14 +291,15 @@ void vim_strup(char_u *p) } } -/// Make given string all upper-case +/// Make given string all upper-case or all lower-case /// -/// Handels multi-byte characters as good as possible. +/// Handles multi-byte characters as good as possible. /// /// @param[in] orig Input string. +/// @param[in] upper If true make uppercase, otherwise lowercase /// /// @return [allocated] upper-cased string. -char *strup_save(const char *const orig) +char *strcase_save(const char *const orig, bool upper) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { char *res = xstrdup(orig); @@ -307,33 +308,25 @@ char *strup_save(const char *const orig) while (*p != NUL) { int l; - if (enc_utf8) { - int c = utf_ptr2char((const char_u *)p); - int uc = mb_toupper(c); - - // Reallocate string when byte count changes. This is rare, - // thus it's OK to do another malloc()/free(). - l = utf_ptr2len((const char_u *)p); - int newl = utf_char2len(uc); - if (newl != l) { - // TODO(philix): use xrealloc() in strup_save() - char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); - memcpy(s, res, (size_t)(p - res)); - STRCPY(s + (p - res) + newl, p + l); - p = s + (p - res); - xfree(res); - res = s; - } - - utf_char2bytes(uc, (char_u *)p); - p += newl; - } else if (has_mbyte && (l = (*mb_ptr2len)((const char_u *)p)) > 1) { - p += l; // Skip multi-byte character. - } else { - // note that toupper() can be a macro - *p = (char)(uint8_t)TOUPPER_LOC(*p); - p++; + int c = utf_ptr2char((const char_u *)p); + int uc = upper ? mb_toupper(c) : mb_tolower(c); + + // Reallocate string when byte count changes. This is rare, + // thus it's OK to do another malloc()/free(). + l = utf_ptr2len((const char_u *)p); + int newl = utf_char2len(uc); + if (newl != l) { + // TODO(philix): use xrealloc() in strup_save() + char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); + memcpy(s, res, (size_t)(p - res)); + STRCPY(s + (p - res) + newl, p + l); + p = s + (p - res); + xfree(res); + res = s; } + + utf_char2bytes(uc, (char_u *)p); + p += newl; } return res; diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 81cb6314ce..3c258299c1 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -29,3 +29,147 @@ func Test_setbufvar_options() bwipe! endfunc +func Test_tolower() + call assert_equal("", tolower("")) + + " Test with all printable ASCII characters. + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~', + \ tolower(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')) + + if !has('multi_byte') + return + endif + + " Test with a few uppercase diacritics. + call assert_equal("aàáâãäåāăąǎǟǡả", tolower("AÀÁÂÃÄÅĀĂĄǍǞǠẢ")) + call assert_equal("bḃḇ", tolower("BḂḆ")) + call assert_equal("cçćĉċč", tolower("CÇĆĈĊČ")) + call assert_equal("dďđḋḏḑ", tolower("DĎĐḊḎḐ")) + call assert_equal("eèéêëēĕėęěẻẽ", tolower("EÈÉÊËĒĔĖĘĚẺẼ")) + call assert_equal("fḟ ", tolower("FḞ ")) + call assert_equal("gĝğġģǥǧǵḡ", tolower("GĜĞĠĢǤǦǴḠ")) + call assert_equal("hĥħḣḧḩ", tolower("HĤĦḢḦḨ")) + call assert_equal("iìíîïĩīĭįiǐỉ", tolower("IÌÍÎÏĨĪĬĮİǏỈ")) + call assert_equal("jĵ", tolower("JĴ")) + call assert_equal("kķǩḱḵ", tolower("KĶǨḰḴ")) + call assert_equal("lĺļľŀłḻ", tolower("LĹĻĽĿŁḺ")) + call assert_equal("mḿṁ", tolower("MḾṀ")) + call assert_equal("nñńņňṅṉ", tolower("NÑŃŅŇṄṈ")) + call assert_equal("oòóôõöøōŏőơǒǫǭỏ", tolower("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ")) + call assert_equal("pṕṗ", tolower("PṔṖ")) + call assert_equal("q", tolower("Q")) + call assert_equal("rŕŗřṙṟ", tolower("RŔŖŘṘṞ")) + call assert_equal("sśŝşšṡ", tolower("SŚŜŞŠṠ")) + call assert_equal("tţťŧṫṯ", tolower("TŢŤŦṪṮ")) + call assert_equal("uùúûüũūŭůűųưǔủ", tolower("UÙÚÛÜŨŪŬŮŰŲƯǓỦ")) + call assert_equal("vṽ", tolower("VṼ")) + call assert_equal("wŵẁẃẅẇ", tolower("WŴẀẂẄẆ")) + call assert_equal("xẋẍ", tolower("XẊẌ")) + call assert_equal("yýŷÿẏỳỷỹ", tolower("YÝŶŸẎỲỶỸ")) + call assert_equal("zźżžƶẑẕ", tolower("ZŹŻŽƵẐẔ")) + + " Test with a few lowercase diacritics, which should remain unchanged. + call assert_equal("aàáâãäåāăąǎǟǡả", tolower("aàáâãäåāăąǎǟǡả")) + call assert_equal("bḃḇ", tolower("bḃḇ")) + call assert_equal("cçćĉċč", tolower("cçćĉċč")) + call assert_equal("dďđḋḏḑ", tolower("dďđḋḏḑ")) + call assert_equal("eèéêëēĕėęěẻẽ", tolower("eèéêëēĕėęěẻẽ")) + call assert_equal("fḟ", tolower("fḟ")) + call assert_equal("gĝğġģǥǧǵḡ", tolower("gĝğġģǥǧǵḡ")) + call assert_equal("hĥħḣḧḩẖ", tolower("hĥħḣḧḩẖ")) + call assert_equal("iìíîïĩīĭįǐỉ", tolower("iìíîïĩīĭįǐỉ")) + call assert_equal("jĵǰ", tolower("jĵǰ")) + call assert_equal("kķǩḱḵ", tolower("kķǩḱḵ")) + call assert_equal("lĺļľŀłḻ", tolower("lĺļľŀłḻ")) + call assert_equal("mḿṁ ", tolower("mḿṁ ")) + call assert_equal("nñńņňʼnṅṉ", tolower("nñńņňʼnṅṉ")) + call assert_equal("oòóôõöøōŏőơǒǫǭỏ", tolower("oòóôõöøōŏőơǒǫǭỏ")) + call assert_equal("pṕṗ", tolower("pṕṗ")) + call assert_equal("q", tolower("q")) + call assert_equal("rŕŗřṙṟ", tolower("rŕŗřṙṟ")) + call assert_equal("sśŝşšṡ", tolower("sśŝşšṡ")) + call assert_equal("tţťŧṫṯẗ", tolower("tţťŧṫṯẗ")) + call assert_equal("uùúûüũūŭůűųưǔủ", tolower("uùúûüũūŭůűųưǔủ")) + call assert_equal("vṽ", tolower("vṽ")) + call assert_equal("wŵẁẃẅẇẘ", tolower("wŵẁẃẅẇẘ")) + call assert_equal("ẋẍ", tolower("ẋẍ")) + call assert_equal("yýÿŷẏẙỳỷỹ", tolower("yýÿŷẏẙỳỷỹ")) + call assert_equal("zźżžƶẑẕ", tolower("zźżžƶẑẕ")) + + " According to https://twitter.com/jifa/status/625776454479970304 + " Ⱥ (U+023A) and Ⱦ (U+023E) are the *only* code points to increase + " in length (2 to 3 bytes) when lowercased. So let's test them. + call assert_equal("ⱥ ⱦ", tolower("Ⱥ Ⱦ")) +endfunc + +func Test_toupper() + call assert_equal("", toupper("")) + + " Test with all printable ASCII characters. + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~', + \ toupper(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')) + + if !has('multi_byte') + return + endif + + " Test with a few lowercase diacritics. + call assert_equal("AÀÁÂÃÄÅĀĂĄǍǞǠẢ", toupper("aàáâãäåāăąǎǟǡả")) + call assert_equal("BḂḆ", toupper("bḃḇ")) + call assert_equal("CÇĆĈĊČ", toupper("cçćĉċč")) + call assert_equal("DĎĐḊḎḐ", toupper("dďđḋḏḑ")) + call assert_equal("EÈÉÊËĒĔĖĘĚẺẼ", toupper("eèéêëēĕėęěẻẽ")) + call assert_equal("FḞ", toupper("fḟ")) + call assert_equal("GĜĞĠĢǤǦǴḠ", toupper("gĝğġģǥǧǵḡ")) + call assert_equal("HĤĦḢḦḨẖ", toupper("hĥħḣḧḩẖ")) + call assert_equal("IÌÍÎÏĨĪĬĮǏỈ", toupper("iìíîïĩīĭįǐỉ")) + call assert_equal("JĴǰ", toupper("jĵǰ")) + call assert_equal("KĶǨḰḴ", toupper("kķǩḱḵ")) + call assert_equal("LĹĻĽĿŁḺ", toupper("lĺļľŀłḻ")) + call assert_equal("MḾṀ ", toupper("mḿṁ ")) + call assert_equal("NÑŃŅŇʼnṄṈ", toupper("nñńņňʼnṅṉ")) + call assert_equal("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ", toupper("oòóôõöøōŏőơǒǫǭỏ")) + call assert_equal("PṔṖ", toupper("pṕṗ")) + call assert_equal("Q", toupper("q")) + call assert_equal("RŔŖŘṘṞ", toupper("rŕŗřṙṟ")) + call assert_equal("SŚŜŞŠṠ", toupper("sśŝşšṡ")) + call assert_equal("TŢŤŦṪṮẗ", toupper("tţťŧṫṯẗ")) + call assert_equal("UÙÚÛÜŨŪŬŮŰŲƯǓỦ", toupper("uùúûüũūŭůűųưǔủ")) + call assert_equal("VṼ", toupper("vṽ")) + call assert_equal("WŴẀẂẄẆẘ", toupper("wŵẁẃẅẇẘ")) + call assert_equal("ẊẌ", toupper("ẋẍ")) + call assert_equal("YÝŸŶẎẙỲỶỸ", toupper("yýÿŷẏẙỳỷỹ")) + call assert_equal("ZŹŻŽƵẐẔ", toupper("zźżžƶẑẕ")) + + " Test that uppercase diacritics, which should remain unchanged. + call assert_equal("AÀÁÂÃÄÅĀĂĄǍǞǠẢ", toupper("AÀÁÂÃÄÅĀĂĄǍǞǠẢ")) + call assert_equal("BḂḆ", toupper("BḂḆ")) + call assert_equal("CÇĆĈĊČ", toupper("CÇĆĈĊČ")) + call assert_equal("DĎĐḊḎḐ", toupper("DĎĐḊḎḐ")) + call assert_equal("EÈÉÊËĒĔĖĘĚẺẼ", toupper("EÈÉÊËĒĔĖĘĚẺẼ")) + call assert_equal("FḞ ", toupper("FḞ ")) + call assert_equal("GĜĞĠĢǤǦǴḠ", toupper("GĜĞĠĢǤǦǴḠ")) + call assert_equal("HĤĦḢḦḨ", toupper("HĤĦḢḦḨ")) + call assert_equal("IÌÍÎÏĨĪĬĮİǏỈ", toupper("IÌÍÎÏĨĪĬĮİǏỈ")) + call assert_equal("JĴ", toupper("JĴ")) + call assert_equal("KĶǨḰḴ", toupper("KĶǨḰḴ")) + call assert_equal("LĹĻĽĿŁḺ", toupper("LĹĻĽĿŁḺ")) + call assert_equal("MḾṀ", toupper("MḾṀ")) + call assert_equal("NÑŃŅŇṄṈ", toupper("NÑŃŅŇṄṈ")) + call assert_equal("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ", toupper("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ")) + call assert_equal("PṔṖ", toupper("PṔṖ")) + call assert_equal("Q", toupper("Q")) + call assert_equal("RŔŖŘṘṞ", toupper("RŔŖŘṘṞ")) + call assert_equal("SŚŜŞŠṠ", toupper("SŚŜŞŠṠ")) + call assert_equal("TŢŤŦṪṮ", toupper("TŢŤŦṪṮ")) + call assert_equal("UÙÚÛÜŨŪŬŮŰŲƯǓỦ", toupper("UÙÚÛÜŨŪŬŮŰŲƯǓỦ")) + call assert_equal("VṼ", toupper("VṼ")) + call assert_equal("WŴẀẂẄẆ", toupper("WŴẀẂẄẆ")) + call assert_equal("XẊẌ", toupper("XẊẌ")) + call assert_equal("YÝŶŸẎỲỶỸ", toupper("YÝŶŸẎỲỶỸ")) + call assert_equal("ZŹŻŽƵẐẔ", toupper("ZŹŻŽƵẐẔ")) + + call assert_equal("ⱥ ⱦ", tolower("Ⱥ Ⱦ")) +endfunc + + -- cgit From acc06b0b7b99925d7567d2e79c2f5e88434edae8 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 9 Apr 2017 09:40:12 +0200 Subject: vim-patch:8.0.0552 Problem: Toupper and tolower don't work properly for Turkish when 'casemap' is empty. (Bjorn Linse) Solution: Check the 'casemap' options when deciding how to upper/lower case. https://github.com/vim/vim/commit/3317d5ebbe8304da82b8088446060afcae0012af vim-patch:8.0.0553 Problem: Toupper/tolower test with Turkish locale fails on Mac. Solution: Skip the test on Mac. https://github.com/vim/vim/commit/9f4de1f5435b900e43e19766da1a5bed4686cf44 vim-patch:8.0.0554 Problem: Toupper and tolower don't work properly for Turkish when 'casemap' contains "keepascii". (Bjorn Linse) Solution: When 'casemap' contains "keepascii" use ASCII toupper/tolower. https://github.com/vim/vim/commit/1cc482069a3407132aeb43a55d6dc284153e79c7 vim-patch:8.0.0555 Problem: Toupper/tolower test fails on OSX without Darwin. Solution: Skip that part of the test also for OSX. (Kazunobu Kuriyama) https://github.com/vim/vim/commit/d2381a2cadb9ef359ad5efb916734c635b29bd13 --- src/nvim/testdir/test_normal.vim | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src') diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index a22dca35cc..c529971528 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -1606,6 +1606,40 @@ fun! Test_normal30_changecase() norm! V~ call assert_equal('THIS IS A simple test: äüöss', getline('.')) + " Turkish ASCII turns to multi-byte. On Mac the Turkish locale is available + " but toupper()/tolower() don't do the right thing. + if !has('mac') && !has('osx') + try + lang tr_TR.UTF-8 + set casemap= + call setline(1, 'iI') + 1normal gUU + call assert_equal("\u0130I", getline(1)) + call assert_equal("\u0130I", toupper("iI")) + + call setline(1, 'iI') + 1normal guu + call assert_equal("i\u0131", getline(1)) + call assert_equal("i\u0131", tolower("iI")) + + set casemap& + call setline(1, 'iI') + 1normal gUU + call assert_equal("II", getline(1)) + call assert_equal("II", toupper("iI")) + + call setline(1, 'iI') + 1normal guu + call assert_equal("ii", getline(1)) + call assert_equal("ii", tolower("iI")) + + lang en_US.UTF-8 + catch /E197:/ + " can't use Turkish locale + throw 'Skipped: Turkish locale not available' + endtry + endif + " clean up bw! endfunc -- cgit From c1cf03398143f4dc0ac9155988edad349d24deca Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 9 Apr 2017 10:08:26 +0200 Subject: lint: fix clint errors around mb_tolower calls --- src/nvim/edit.c | 3 ++- src/nvim/eval.c | 6 ++++-- src/nvim/mbyte.c | 14 +++++--------- src/nvim/message.c | 2 +- src/nvim/ops.c | 17 ++++++++++------- src/nvim/path.c | 2 +- src/nvim/regexp.c | 17 ++++++++++------- src/nvim/regexp_nfa.c | 14 +++++++++----- src/nvim/search.c | 25 ++++++++++++++----------- src/nvim/spell.c | 44 ++++++++++++-------------------------------- 10 files changed, 68 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index aa254b0577..fe00027dec 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -2303,8 +2303,9 @@ static void ins_compl_longest_match(compl_T *match) c2 = *s; } if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) - : (c1 != c2)) + : (c1 != c2)) { break; + } if (has_mbyte) { mb_ptr_adv(p); mb_ptr_adv(s); diff --git a/src/nvim/eval.c b/src/nvim/eval.c index ed07de51c8..0663e19b9a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -16792,7 +16792,8 @@ void timer_teardown(void) static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), false); + rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), + false); } /* @@ -16801,7 +16802,8 @@ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), true); + rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), + true); } /* diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 5f5abbeac5..b18459a2b5 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1179,10 +1179,8 @@ int utf_fold(int a) // invalid values or can't handle latin1 when the locale is C. // Speed is most important here. -/* - * Return the upper-case equivalent of "a", which is a UCS-4 character. Use - * simple case folding. - */ +/// Return the upper-case equivalent of "a", which is a UCS-4 character. Use +/// simple case folding. int mb_toupper(int a) { /* If 'casemap' contains "keepascii" use ASCII style toupper(). */ @@ -1205,14 +1203,12 @@ int mb_toupper(int a) bool mb_islower(int a) { - /* German sharp s is lower case but has no upper case equivalent. */ + // German sharp s is lower case but has no upper case equivalent. return (mb_toupper(a) != a) || a == 0xdf; } -/* - * Return the lower-case equivalent of "a", which is a UCS-4 character. Use - * simple case folding. - */ +/// Return the lower-case equivalent of "a", which is a UCS-4 character. Use +/// simple case folding. int mb_tolower(int a) { /* If 'casemap' contains "keepascii" use ASCII style tolower(). */ diff --git a/src/nvim/message.c b/src/nvim/message.c index 2cc426cf42..3e4a1e10b6 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2730,7 +2730,7 @@ do_dialog ( break; } - /* Make the character lowercase, as chars in "hotkeys" are. */ + // Make the character lowercase, as chars in "hotkeys" are. c = mb_tolower(c); retval = 1; for (i = 0; hotkeys[i]; ++i) { diff --git a/src/nvim/ops.c b/src/nvim/ops.c index c5b7e65983..f11d6b69b2 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1957,15 +1957,17 @@ int swapchar(int op_type, pos_T *pos) return FALSE; nc = c; if (mb_islower(c)) { - if (op_type == OP_ROT13) + if (op_type == OP_ROT13) { nc = ROT13(c, 'a'); - else if (op_type != OP_LOWER) + } else if (op_type != OP_LOWER) { nc = mb_toupper(c); + } } else if (mb_isupper(c)) { - if (op_type == OP_ROT13) + if (op_type == OP_ROT13) { nc = ROT13(c, 'A'); - else if (op_type != OP_UPPER) + } else if (op_type != OP_UPPER) { nc = mb_tolower(c); + } } if (nc != c) { if (enc_utf8 && (c >= 0x80 || nc >= 0x80)) { @@ -3328,9 +3330,10 @@ void ex_display(exarg_T *eap) get_clipboard(name, &yb, true); if (name == mb_tolower(redir_reg) - || (redir_reg == '"' && yb == y_previous)) - continue; /* do not list register being written to, the - * pointer can be freed */ + || (redir_reg == '"' && yb == y_previous)) { + continue; // do not list register being written to, the + // pointer can be freed + } if (yb->y_array != NULL) { msg_putchar('\n'); diff --git a/src/nvim/path.c b/src/nvim/path.c index 781522f63f..205fc2ed62 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1865,7 +1865,7 @@ int pathcmp(const char *p, const char *q, int maxlen) if (vim_ispathsep(c2)) return 1; return p_fic ? mb_toupper(c1) - mb_toupper(c2) - : c1 - c2; /* no match */ + : c1 - c2; // no match } i += MB_PTR2LEN((char_u *)p + i); diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 7e2fc261f2..4b5e17b00b 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -4573,12 +4573,14 @@ regmatch ( if (OP(next) == EXACTLY) { rst.nextb = *OPERAND(next); if (ireg_ic) { - if (mb_isupper(rst.nextb)) + if (mb_isupper(rst.nextb)) { rst.nextb_ic = mb_tolower(rst.nextb); - else + } else { rst.nextb_ic = mb_toupper(rst.nextb); - } else + } + } else { rst.nextb_ic = rst.nextb; + } } else { rst.nextb = NUL; rst.nextb_ic = NUL; @@ -6312,14 +6314,15 @@ static char_u *cstrchr(char_u *s, int c) /* tolower() and toupper() can be slow, comparing twice should be a lot * faster (esp. when using MS Visual C++!). * For UTF-8 need to use folded case. */ - if (enc_utf8 && c > 0x80) + if (c > 0x80) { cc = utf_fold(c); - else if (mb_isupper(c)) + } else if (mb_isupper(c)) { cc = mb_tolower(c); - else if (mb_islower(c)) + } else if (mb_islower(c)) { cc = mb_toupper(c); - else + } else { return vim_strchr(s, c); + } if (has_mbyte) { for (p = s; *p != NUL; p += (*mb_ptr2len)(p)) { diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 1d57595cbe..caf26fdd35 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -4391,8 +4391,9 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_UPPER: - if (mb_isupper(c)) + if (mb_isupper(c)) { return OK; + } break; case NFA_CLASS_XDIGIT: if (ascii_isxdigit(c)) @@ -5586,16 +5587,18 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } if (ireg_ic) { int curc_low = mb_tolower(curc); - int done = FALSE; + int done = false; - for (; c1 <= c2; ++c1) + for (; c1 <= c2; c1++) { if (mb_tolower(c1) == curc_low) { result = result_if_matched; done = TRUE; break; } - if (done) + } + if (done) { break; + } } } else if (state->c < 0 ? check_char_class(state->c, curc) : (curc == state->c @@ -6003,8 +6006,9 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, #endif result = (c == curc); - if (!result && ireg_ic) + if (!result && ireg_ic) { result = mb_tolower(c) == mb_tolower(curc); + } // If ireg_icombine is not set only skip over the character // itself. When it is set skip over composing characters. diff --git a/src/nvim/search.c b/src/nvim/search.c index 4f060b2b8b..91a558045f 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -335,23 +335,26 @@ int pat_has_uppercase(char_u *pat) while (*p != NUL) { int l; - if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) { - if (enc_utf8 && mb_isupper(utf_ptr2char(p))) - return TRUE; + if ((l = mb_ptr2len(p)) > 1) { + if (mb_isupper(utf_ptr2char(p))) { + return true; + } p += l; } else if (*p == '\\') { - if (p[1] == '_' && p[2] != NUL) /* skip "\_X" */ + if (p[1] == '_' && p[2] != NUL) { // skip "\_X" p += 3; - else if (p[1] == '%' && p[2] != NUL) /* skip "\%X" */ + } else if (p[1] == '%' && p[2] != NUL) { // skip "\%X" p += 3; - else if (p[1] != NUL) /* skip "\X" */ + } else if (p[1] != NUL) { // skip "\X" p += 2; - else + } else { p += 1; - } else if (mb_isupper(*p)) - return TRUE; - else - ++p; + } + } else if (mb_isupper(*p)) { + return true; + } else { + p++; + } } return FALSE; } diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 99661d0ef5..18febda1d8 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -2526,8 +2526,7 @@ void clear_spell_chartab(spelltab_T *sp) } } -// Init the chartab used for spelling. Only depends on 'encoding'. -// Called once while starting up and when 'encoding' changes. +// Init the chartab used for spelling. Called once while starting up. // The default is to use isalpha(), but the spell file should define the word // characters to make it possible that 'encoding' differs from the current // locale. For utf-8 we don't use isalpha() but our own functions. @@ -2537,36 +2536,17 @@ void init_spell_chartab(void) did_set_spelltab = false; clear_spell_chartab(&spelltab); - if (enc_dbcs) { - // DBCS: assume double-wide characters are word characters. - for (i = 128; i <= 255; ++i) - if (MB_BYTE2LEN(i) == 2) - spelltab.st_isw[i] = true; - } else if (enc_utf8) { - for (i = 128; i < 256; ++i) { - int f = utf_fold(i); - int u = mb_toupper(i); - - spelltab.st_isu[i] = mb_isupper(i); - spelltab.st_isw[i] = spelltab.st_isu[i] || mb_islower(i); - // The folded/upper-cased value is different between latin1 and - // utf8 for 0xb5, causing E763 for no good reason. Use the latin1 - // value for utf-8 to avoid this. - spelltab.st_fold[i] = (f < 256) ? f : i; - spelltab.st_upper[i] = (u < 256) ? u : i; - } - } else { - // Rough guess: use locale-dependent library functions. - for (i = 128; i < 256; ++i) { - if (mb_isupper(i)) { - spelltab.st_isw[i] = true; - spelltab.st_isu[i] = true; - spelltab.st_fold[i] = mb_tolower(i); - } else if (mb_islower(i)) { - spelltab.st_isw[i] = true; - spelltab.st_upper[i] = mb_toupper(i); - } - } + for (i = 128; i < 256; i++) { + int f = utf_fold(i); + int u = mb_toupper(i); + + spelltab.st_isu[i] = mb_isupper(i); + spelltab.st_isw[i] = spelltab.st_isu[i] || mb_islower(i); + // The folded/upper-cased value is different between latin1 and + // utf8 for 0xb5, causing E763 for no good reason. Use the latin1 + // value for utf-8 to avoid this. + spelltab.st_fold[i] = (f < 256) ? f : i; + spelltab.st_upper[i] = (u < 256) ? u : i; } } -- cgit