diff options
35 files changed, 442 insertions, 278 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d67aebee64..9482e6d8a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 2.8.7) project (NEOVIM) # Point CMake at any custom modules we may ship -set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") # Prefer our bundled versions of dependencies. set(DEPS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.deps") @@ -12,6 +12,37 @@ set(DEPS_BIN_DIR "${DEPS_INSTALL_DIR}/bin") list(APPEND CMAKE_PREFIX_PATH ${DEPS_INSTALL_DIR}) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + # CMake tries to treat /sw and /opt/local as extension of the system path, but + # that doesn't really work out very well. Once you have a dependency that + # resides there and have to add it as an include directory, then any other + # dependency that could be satisfied from there must be--otherwise you can end + # up with conflicting versions. So, let's make them more of a priority having + # them be included as one of the first places to look for dependencies. + list(APPEND CMAKE_PREFIX_PATH /sw /opt/local) + + # Work around some old, broken detection by CMake for knowing when to use the + # isystem flag. Apple's compilers have supported this for quite some time + # now. + if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ") + endif() + if(CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ") + endif() +endif() + +# Set available build types for CMake GUIs. +# A different build type can still be set by -DCMAKE_BUILD_TYPE=... +set_property(CACHE CMAKE_BUILD_TYPE PROPERTY + STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") + +# Set default build type. +if(NOT CMAKE_BUILD_TYPE) + message(STATUS "CMAKE_BUILD_TYPE not given; setting to 'RelWithDebInfo'.") + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build." FORCE) +endif() + # Version tokens include(GetGitRevisionDescription) get_git_head_revision(GIT_REFSPEC NVIM_VERSION_COMMIT) @@ -28,20 +59,11 @@ git_timestamp(GIT_TIMESTAMP) if(GIT_TIMESTAMP) set(NVIM_VERSION_BUILD "+${GIT_TIMESTAMP}") endif() +set(NVIM_VERSION_BUILD_TYPE "${CMAKE_BUILD_TYPE}") +# NVIM_VERSION_CFLAGS set further below. set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# Work around some old, broken detection by CMake for knowing when to use the -# isystem flag. Apple's compilers have supported this for quite some time now. -if(APPLE) - if(CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ") - endif() - if(CMAKE_COMPILER_IS_GNUCXX) - set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ") - endif() -endif() - # Default to -O2 on release builds. string(REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") @@ -67,9 +89,16 @@ if(TRAVIS_CI_BUILD) add_definitions(-Werror) endif() +if(CMAKE_COMPILER_IS_GNUCC) + include(CheckCCompilerFlag) + check_c_compiler_flag(-Og HAS_OG_FLAG) +else() + set(HAS_OG_FLAG 0) +endif() + # Set custom build flags for RelWithDebInfo. # -DNDEBUG purposely omitted because we want assertions. -if(CMAKE_COMPILER_IS_GNUCC) +if(HAS_OG_FLAG) set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Og -g" CACHE STRING "Flags used by the compiler during release builds with debug info." FORCE) else() @@ -128,7 +157,12 @@ include_directories(SYSTEM ${LUAJIT_INCLUDE_DIRS}) find_package(LibIntl) if(LibIntl_FOUND) - include_directories(SYSTEM ${LibIntl_INCLUDE_DIR}) + include_directories(SYSTEM ${LibIntl_INCLUDE_DIRS}) +endif() + +find_package(Iconv) +if(Iconv_FOUND) + include_directories(SYSTEM ${Iconv_INCLUDE_DIRS}) endif() # Determine platform's threading library. Set CMAKE_THREAD_PREFER_PTHREAD @@ -215,7 +249,7 @@ foreach(PROG ${RUNTIME_PROGRAMS}) install_helper(PROGRAMS ${PROG} DESTINATION share/nvim/${BASEDIR}) endforeach() -install(SCRIPT ${CMAKE_MODULE_PATH}/GenerateHelptags.cmake) +install(SCRIPT ${PROJECT_SOURCE_DIR}/cmake/GenerateHelptags.cmake) # Unfortunately, the below does not work under Ninja. Ninja doesn't use a # pseudo-tty when launching processes, because it can put many jobs in parallel @@ -228,9 +262,14 @@ install(SCRIPT ${CMAKE_MODULE_PATH}/GenerateHelptags.cmake) # Go down the tree. -add_subdirectory(config) add_subdirectory(src/nvim) +# Read compilation flags from src/nvim, +# used in config subdirectory below. +include(GetCompileFlags) +get_compile_flags(NVIM_VERSION_CFLAGS) + add_subdirectory(test/includes) +add_subdirectory(config) # Setup some test-related bits. We do this after going down the tree because we # need some of the targets. @@ -258,7 +297,7 @@ if(BUSTED_PRG) -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test -DBUILD_DIR=${CMAKE_BINARY_DIR} -DTEST_TYPE=unit - -P ${CMAKE_MODULE_PATH}/RunTests.cmake + -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake DEPENDS nvim-test unittest-headers) add_custom_target(functionaltest @@ -270,6 +309,6 @@ if(BUSTED_PRG) -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test -DBUILD_DIR=${CMAKE_BINARY_DIR} -DTEST_TYPE=functional - -P ${CMAKE_MODULE_PATH}/RunTests.cmake + -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake DEPENDS nvim) endif() diff --git a/cmake/FindIconv.cmake b/cmake/FindIconv.cmake new file mode 100644 index 0000000000..f3a54e9d6f --- /dev/null +++ b/cmake/FindIconv.cmake @@ -0,0 +1,18 @@ +# - Try to find iconv +# Once done, this will define +# +# Iconv_FOUND - system has iconv +# Iconv_INCLUDE_DIRS - the iconv include directories +# Iconv_LIBRARIES - link these to use iconv + +include(LibFindMacros) + +find_path(ICONV_INCLUDE_DIR NAMES iconv.h) +find_library(ICONV_LIBRARY NAMES iconv) + +set(Iconv_PROCESS_INCLUDES ICONV_INCLUDE_DIR) +if(ICONV_LIBRARY) + set(Iconv_PROCESS_LIBS ICONV_LIBRARY) +endif() + +libfind_process(Iconv) diff --git a/cmake/GetCompileFlags.cmake b/cmake/GetCompileFlags.cmake new file mode 100644 index 0000000000..e0994b67bc --- /dev/null +++ b/cmake/GetCompileFlags.cmake @@ -0,0 +1,58 @@ +function(get_compile_flags _compile_flags) + # Create template akin to CMAKE_C_COMPILE_OBJECT. + set(compile_flags "<CMAKE_C_COMPILER> <CFLAGS> <BUILD_TYPE_CFLAGS> <DEFINITIONS> <INCLUDES>") + + # Get C compiler. + string(REPLACE + "<CMAKE_C_COMPILER>" + "${CMAKE_C_COMPILER}" + compile_flags + "${compile_flags}") + + # Get flags set by add_definition(). + get_directory_property(definitions + DIRECTORY "src/nvim" + DEFINITIONS) + string(REPLACE + "<DEFINITIONS>" + "${definitions}" + compile_flags + "${compile_flags}") + + # Get general C flags. + string(REPLACE + "<CFLAGS>" + "${CMAKE_C_FLAGS}" + compile_flags + "${compile_flags}") + + # Get C flags specific to build type. + string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) + string(REPLACE + "<BUILD_TYPE_CFLAGS>" + "${CMAKE_C_FLAGS_${build_type}}" + compile_flags + "${compile_flags}") + + # Get include directories. + get_directory_property(include_directories_list + DIRECTORY "src/nvim" + INCLUDE_DIRECTORIES) + foreach(include_directory ${include_directories_list}) + set(include_directories "${include_directories} -I${include_directory}") + endforeach() + string(REPLACE + "<INCLUDES>" + "${include_directories}" + compile_flags + "${compile_flags}") + + # Clean duplicate whitespace. + string(REPLACE + " " + " " + compile_flags + "${compile_flags}") + + set(${_compile_flags} "${compile_flags}" PARENT_SCOPE) +endfunction() diff --git a/cmake/InstallHelpers.cmake b/cmake/InstallHelpers.cmake index 763b2a092c..bd03ae3875 100644 --- a/cmake/InstallHelpers.cmake +++ b/cmake/InstallHelpers.cmake @@ -22,10 +22,6 @@ function(create_install_dir_with_perms) install(CODE " - if(DEFINED ENV{DESTDIR} AND NOT IS_ABSOLUTE \${CMAKE_INSTALL_PREFIX}) - message(FATAL_ERROR \"Install prefix must be absolute when using DESTDIR\") - endif() - set(_current_dir \"\${CMAKE_INSTALL_PREFIX}/${_install_dir_DESTINATION}\") set(_dir_permissions \"${_install_dir_DIRECTORY_PERMISSIONS}\") diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt index c48887548d..0f5dd7d984 100644 --- a/config/CMakeLists.txt +++ b/config/CMakeLists.txt @@ -44,12 +44,9 @@ check_function_exists(getpwent HAVE_GETPWENT) check_function_exists(getpwnam HAVE_GETPWNAM) check_function_exists(getpwuid HAVE_GETPWUID) -check_include_files(iconv.h HAVE_ICONV_H) -check_library_exists(iconv iconv "" HAVE_ICONV_LIB) -if(HAVE_ICONV_LIB) - set(CMAKE_REQUIRED_LIBRARIES iconv) +if(Iconv_FOUND) + set(HAVE_ICONV 1) endif() -check_function_exists(iconv HAVE_ICONV) check_function_exists(lstat HAVE_LSTAT) if(NOT HAVE_LSTAT) diff --git a/config/config.h.in b/config/config.h.in index 7a04837c92..79dabc61e4 100644 --- a/config/config.h.in +++ b/config/config.h.in @@ -4,6 +4,8 @@ #define NVIM_VERSION_PRERELEASE "@NVIM_VERSION_PRERELEASE@" #define NVIM_VERSION_BUILD "@NVIM_VERSION_BUILD@" #define NVIM_VERSION_COMMIT "@NVIM_VERSION_COMMIT@" +#define NVIM_VERSION_CFLAGS "@NVIM_VERSION_CFLAGS@" +#define NVIM_VERSION_BUILD_TYPE "@NVIM_VERSION_BUILD_TYPE@" #cmakedefine DEBUG @@ -29,7 +31,6 @@ #cmakedefine HAVE_GETPWNAM #cmakedefine HAVE_GETPWUID #cmakedefine HAVE_ICONV -#cmakedefine USE_ICONV #cmakedefine HAVE_ICONV_H #cmakedefine HAVE_LANGINFO_H #cmakedefine HAVE_LIBGEN_H @@ -1,42 +1,9 @@ -require "formula" +odie <<-EOS.undent -class Neovim < Formula - homepage "http://neovim.org" - head "https://github.com/neovim/neovim.git" + Whoops, the neovim Homebrew Formula has moved! Please instead run: - depends_on "cmake" => :build - depends_on "libtool" => :build - depends_on "automake" => :build - depends_on "autoconf" => :build + brew tap neovim/homebrew-neovim + brew install --HEAD neovim - resource "libuv" do - url "https://github.com/joyent/libuv/archive/v0.11.28.tar.gz" - sha1 "3b70b65467ee693228b8b8385665a52690d74092" - end - - resource "msgpack" do - url "https://github.com/msgpack/msgpack-c/archive/ecf4b09acd29746829b6a02939db91dfdec635b4.tar.gz" - sha1 "c160ff99f20d9d0a25bea0a57f4452f1c9bde370" - end - - resource "luajit" do - url "http://luajit.org/download/LuaJIT-2.0.3.tar.gz" - sha1 "2db39e7d1264918c2266b0436c313fbd12da4ceb" - end - - resource "luarocks" do - url "https://github.com/keplerproject/luarocks/archive/0587afbb5fe8ceb2f2eea16f486bd6183bf02f29.tar.gz" - sha1 "61a894fd5d61987bf7e7f9c3e0c5de16ba4b68c4" - end - - def install - ENV["GIT_DIR"] = cached_download/".git" if build.head? - ENV.deparallelize - - resources.each do |r| - r.stage(target=buildpath/".deps/build/src/#{r.name}") - end - - system "make", "CMAKE_BUILD_TYPE=RelWithDebInfo", "CMAKE_EXTRA_FLAGS=\"-DCMAKE_INSTALL_PREFIX:PATH=#{prefix}\"", "install" - end -end + Thanks! +EOS diff --git a/runtime/doc/nvim_clipboard.txt b/runtime/doc/nvim_clipboard.txt index 3dd5fb5fcb..74c9254c70 100644 --- a/runtime/doc/nvim_clipboard.txt +++ b/runtime/doc/nvim_clipboard.txt @@ -12,24 +12,24 @@ will be implemented by UI programs, which connect to Nvim via |msgpack-rpc|. Even though externalized UIs are not available yet, there's a workaround that enables clipboard usage through the python interface(which also uses |msgpack-rpc| and consequently can implement the clipboard methods required -by Nvim): +by Nvim): - Make sure you follow the setup instructions in |nvim-python-quickstart|. - Install the `xerox` python module: > $ pip install xerox < -- Create a ~/.vim/pythonx/nvim_clipboard.py file with the following contents: +- Create a ~/.nvim/pythonx/nvim_clipboard.py file with the following contents: > import xerox - + class NvimClipboard(object): def __init__(self, vim): self.provides = ['clipboard'] - + def clipboard_get(self): return xerox.paste().split('\n') - + def clipboard_set(self, lines): xerox.copy(u'\n'.join([line.decode('utf-8') for line in lines])) < diff --git a/scripts/legacy2luatest.pl b/scripts/legacy2luatest.pl index 0628ac0a1d..5979afa788 100755 --- a/scripts/legacy2luatest.pl +++ b/scripts/legacy2luatest.pl @@ -33,7 +33,52 @@ sub read_in_file { use constant EMIT_DESCRIPTION => 0; use constant EMIT_COMMAND => 1; use constant EMIT_INPUT => 2; - use constant END_INPUT => 3; + + # Push lines from current input and + # command blocks into @test_body_lines + # in the correct order. + sub end_input { + my $input_lines = $_[0]; + my $command_lines = $_[1]; + my $test_body_lines = $_[2]; + + # Only keep first input line if it is not empty. + my $first_input_line = shift @{$input_lines}; + if ($first_input_line =~ /^$/) { + unshift @{$input_lines}, $first_input_line; + } + + # If there are input lines left, wrap them with + # `insert` command and add before the previous command + # block. + if (@{$input_lines}) { + my $last_input_line = pop @{$input_lines}; + unshift @{$command_lines}, ''; + unshift @{$command_lines}, $last_input_line . ']])'; + unshift @{$command_lines}, @{$input_lines}; + unshift @{$command_lines}, "insert([["; + + push @{$test_body_lines}, @{$command_lines}; + + @{$command_lines} = (); + @{$input_lines} = (); + } + } + + sub format_comment { + # Handle empty comments. + if (/^$/) { + return ''; + } + + # Capitalize first character and emit as Lua comment. + my $comment = '-- ' . ucfirst $_; + + # Add trailing dot if not already there. + $comment .= '.' unless $comment =~ /\.$/; + + return $comment; + } my %states = ( # Add test description to @description_lines. @@ -57,56 +102,52 @@ sub read_in_file { # If line starts with ':"', emit a comment. if (/^:"/) { - # If it's an empty comment, just add an empty line - # to improve readability. - push @command_lines, (/^$/ ? '' : '-- ' . $_); - } else { - # Extract possible inline comment. - if (/^[^"]*"[^"]*$/) { - # Remove command part and prepended whitespace. - s/^(.*?)\s*"\s*//; - - # Capitalize first character and emit as Lua comment. - my $comment = '-- ' . ucfirst $_; - - # Add trailing dot if not already there. - $comment .= '.' unless $comment =~ /\.$/; - - push @command_lines, ''; - push @command_lines, $comment; - - # Set implicit variable to command without comment. - $_ = $1; + # Remove Vim comment prefix. + s/^:"\s*//; + + push @command_lines, format_comment $_; + + return EMIT_COMMAND; + } + + # Extract possible inline comment. + if (/^[^"]*"[^"]*$/) { + # Remove command part and prepended whitespace. + s/^(.*?)\s*"\s*//; + + push @command_lines, format_comment $_; + + # Set implicit variable to command without comment. + $_ = $1; + } + + # Only continue if remaining command is not empty. + if (!/^:?\s*$/) { + # Replace terminal escape characters with <esc>. + s/\e/<esc>/g; + + my $startstr = "'"; + my $endstr = "'"; + + # If line contains single quotes or backslashes, use double + # square brackets to wrap string. + if (/'/ || /\\/) { + $startstr = '[['; + $endstr = ']]'; } - # Only continue if remaining command is not empty. - if (!/^:?\s*$/) { - # Replace terminal escape characters with <esc>. - s/\e/<esc>/g; - - my $startstr = "'"; - my $endstr = "'"; - - # If line contains single quotes or backslashes, use double - # square brackets to wrap string. - if (/'/ || /\\/) { - $startstr = '[['; - $endstr = ']]'; - } - - # Emit 'feed' if not a search ('/') or ex (':') command. - if (!/^\// && !/^:/) { - # If command does not end with <esc>, insert trailing <cr>. - my $command = 'feed(' . $startstr . $_; - $command .= '<cr>' unless /<esc>$/; - $command .= $endstr . ')'; - - push @command_lines, $command; - } else { - # Remove prepending ':'. - s/^://; - push @command_lines, 'execute(' . $startstr . $_ . $endstr . ')'; - } + # Emit 'feed' if not a search ('/') or ex (':') command. + if (!/^\// && !/^:/) { + # If command does not end with <esc>, insert trailing <cr>. + my $command = 'feed(' . $startstr . $_; + $command .= '<cr>' unless /<esc>$/; + $command .= $endstr . ')'; + + push @command_lines, $command; + } else { + # Remove prepending ':'. + s/^://; + push @command_lines, 'execute(' . $startstr . $_ . $endstr . ')'; } } @@ -115,40 +156,13 @@ sub read_in_file { # Add input to @input_lines. EMIT_INPUT() => sub { if (/^STARTTEST/) { - return END_INPUT; + end_input \@input_lines, \@command_lines, \@test_body_lines; + return EMIT_COMMAND; } push @input_lines, ' ' . $_; return EMIT_INPUT; }, - # The END_INPUT state is used to push lines from current - # input and command blocks into @test_body_lines - # in the correct order. - END_INPUT() => sub { - # Only keep first input line if it is not empty. - my $first_input_line = shift @input_lines; - if ($first_input_line =~ /^$/) { - unshift @input_lines, $first_input_line; - } - - # If there are input lines left, wrap them with - # `insert` command and add before the previous command - # block. - if (@input_lines) { - my $last_input_line = pop @input_lines; - unshift @command_lines, ''; - unshift @command_lines, $last_input_line . ']])'; - unshift @command_lines, @input_lines; - unshift @command_lines, "insert([["; - - push @test_body_lines, @command_lines; - - @command_lines = (); - @input_lines = (); - } - - return EMIT_COMMAND; - } ); my $state = EMIT_DESCRIPTION; @@ -162,7 +176,7 @@ sub read_in_file { # If not all input lines have been processed, # do it now. if (@input_lines) { - $states{END_INPUT()}->(); + end_input \@input_lines, \@command_lines, \@test_body_lines; } close $in_file_handle; @@ -216,7 +230,13 @@ my ($test_name, $base_path, $suffix) = fileparse($legacy_testfile, @legacy_suffi my $in_file = catfile($base_path, $test_name . '.in'); my $ok_file = catfile($base_path, $test_name . '.ok'); -my $spec_file = catfile($out_dir, $test_name . '_spec.lua'); +my $spec_file = do { + if ($test_name =~ /^test([0-9]+)/) { + catfile($out_dir, sprintf('%03d', $1) . '_' . $test_name . '_spec.lua') + } else { + catfile($out_dir, $test_name . '_spec.lua') + } +}; if (! -f $in_file) { say "Test input file $in_file not found."; diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 5b97cf5f40..b06b4fa547 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -89,8 +89,8 @@ get_directory_property(gen_includes INCLUDE_DIRECTORIES) foreach(gen_include ${gen_includes}) set(gen_cflags "${gen_cflags} -I${gen_include}") endforeach() -string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type) -set(gen_cflags "${gen_cflags} ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}") +string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) +set(gen_cflags "${gen_cflags} ${CMAKE_C_FLAGS_${build_type}} ${CMAKE_C_FLAGS}") foreach(sfile ${NEOVIM_SOURCES} "${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c") @@ -158,8 +158,8 @@ else() endif() endif() -if(HAVE_ICONV_LIB) - list(APPEND NVIM_LINK_LIBRARIES iconv) +if(Iconv_LIBRARIES) + list(APPEND NVIM_LINK_LIBRARIES ${Iconv_LIBRARIES}) endif() # Put these last on the link line, since multiple things may depend on them. diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index 9992fbdfcf..328b751693 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -1,3 +1,4 @@ +#include <assert.h> #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/cursor_shape.h" @@ -76,6 +77,7 @@ char_u *parse_shape_opt(int what) * For the 'a' mode, we loop to handle all the modes. */ all_idx = -1; + assert(modep < colonp); while (modep < colonp || all_idx >= 0) { if (all_idx < 0) { /* Find the mode. */ diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 1d5e1a51cf..384ca9abd8 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -3231,6 +3231,7 @@ static buf_T *ins_compl_next_buf(buf_T *buf, int flag) if (flag == 'w') { /* just windows */ if (buf == curbuf) /* first call for this flag/expansion */ wp = curwin; + assert(wp); while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin && wp->w_buffer->b_scanned) ; @@ -3612,6 +3613,7 @@ static int ins_compl_get_exp(pos_T *ini) * If 'infercase' is set, don't use 'smartcase' here */ save_p_scs = p_scs; + assert(ins_buf); if (ins_buf->b_p_inf) p_scs = FALSE; @@ -3760,8 +3762,10 @@ static int ins_compl_get_exp(pos_T *ini) compl_started = TRUE; } else { /* Mark a buffer scanned when it has been scanned completely */ - if (type == 0 || type == CTRL_X_PATH_PATTERNS) + if (type == 0 || type == CTRL_X_PATH_PATTERNS) { + assert(ins_buf); ins_buf->b_scanned = TRUE; + } compl_started = FALSE; } @@ -6286,6 +6290,7 @@ static void mb_replace_pop_ins(int cc) break; } else { buf[0] = c; + assert(n > 1); for (i = 1; i < n; ++i) buf[i] = replace_pop(); if (utf_iscomposing(utf_ptr2char(buf))) @@ -6331,10 +6336,11 @@ static void replace_do_bs(int limit_col) char_u *p; int i; int vcol; + const int l_State = State; cc = replace_pop(); if (cc > 0) { - if (State & VREPLACE_FLAG) { + if (l_State & VREPLACE_FLAG) { /* Get the number of screen cells used by the character we are * going to delete. */ getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL); @@ -6342,17 +6348,17 @@ static void replace_do_bs(int limit_col) } if (has_mbyte) { (void)del_char_after_col(limit_col); - if (State & VREPLACE_FLAG) + if (l_State & VREPLACE_FLAG) orig_len = (int)STRLEN(get_cursor_pos_ptr()); replace_push(cc); } else { pchar_cursor(cc); - if (State & VREPLACE_FLAG) + if (l_State & VREPLACE_FLAG) orig_len = (int)STRLEN(get_cursor_pos_ptr()) - 1; } replace_pop_ins(); - if (State & VREPLACE_FLAG) { + if (l_State & VREPLACE_FLAG) { /* Get the number of screen cells used by the inserted characters */ p = get_cursor_pos_ptr(); ins_len = (int)STRLEN(p) - orig_len; @@ -7449,7 +7455,9 @@ static int ins_bs(int c, int mode, int *inserted_space_p) if (State & REPLACE_FLAG) replace_do_bs(-1); else { - if (enc_utf8 && p_deco) + const bool l_enc_utf8 = enc_utf8; + const int l_p_deco = p_deco; + if (l_enc_utf8 && l_p_deco) (void)utfc_ptr2char(get_cursor_pos_ptr(), cpc); (void)del_char(FALSE); /* @@ -7457,7 +7465,7 @@ static int ins_bs(int c, int mode, int *inserted_space_p) * move the cursor back. Don't back up before the base * character. */ - if (enc_utf8 && p_deco && cpc[0] != NUL) + if (l_enc_utf8 && l_p_deco && cpc[0] != NUL) inc_cursor(); if (revins_chars) { revins_chars--; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 59363a3608..fc61fed529 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -14492,6 +14492,11 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, set_vim_var_nr(VV_SHELL_ERROR, (long) status); if (res == NULL) { + if (retlist) { + // return an empty list when there's no output + rettv->v_type = VAR_LIST; + rettv->vval.v_list = list_alloc(); + } return; } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index f5fa16a139..ef9affcdf6 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -10,6 +10,7 @@ * ex_cmds.c: some functions for command line commands */ +#include <assert.h> #include <errno.h> #include <stdbool.h> #include <string.h> @@ -90,8 +91,9 @@ void do_ascii(exarg_T *eap) int cc[MAX_MCO]; int ci = 0; int len; + const bool l_enc_utf8 = enc_utf8; - if (enc_utf8) + if (l_enc_utf8) c = utfc_ptr2char(get_cursor_pos_ptr(), cc); else c = gchar_cursor(); @@ -123,20 +125,20 @@ void do_ascii(exarg_T *eap) vim_snprintf((char *)IObuff, IOSIZE, _("<%s>%s%s %d, Hex %02x, Octal %03o"), transchar(c), buf1, buf2, cval, cval, cval); - if (enc_utf8) + if (l_enc_utf8) c = cc[ci++]; else c = 0; } /* Repeat for combining characters. */ - while (has_mbyte && (c >= 0x100 || (enc_utf8 && c >= 0x80))) { + while (has_mbyte && (c >= 0x100 || (l_enc_utf8 && c >= 0x80))) { len = (int)STRLEN(IObuff); /* This assumes every multi-byte char is printable... */ if (len > 0) IObuff[len++] = ' '; IObuff[len++] = '<'; - if (enc_utf8 && utf_iscomposing(c) + if (l_enc_utf8 && utf_iscomposing(c) # ifdef USE_GUI && !gui.in_use # endif @@ -148,7 +150,7 @@ void do_ascii(exarg_T *eap) : _("> %d, Hex %08x, Octal %o"), c, c, c); if (ci == MAX_MCO) break; - if (enc_utf8) + if (l_enc_utf8) c = cc[ci++]; else c = 0; @@ -2764,9 +2766,12 @@ do_ecmd ( /* Autocommands may open a new window and leave oldwin open * which leads to crashes since the above call sets * oldwin->w_buffer to NULL. */ - if (curwin != oldwin && oldwin != aucmd_win - && win_valid(oldwin) && oldwin->w_buffer == NULL) - win_close(oldwin, FALSE); + if (curwin != oldwin && oldwin != aucmd_win && win_valid(oldwin)) { + assert(oldwin); + if (oldwin->w_buffer == NULL) { + win_close(oldwin, FALSE); + } + } if (aborting()) { /* autocmds may abort script processing */ free(new_name); diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 6e31142137..1636d62c74 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -10,6 +10,7 @@ * ex_cmds2.c: some more functions for command line commands */ +#include <assert.h> #include <errno.h> #include <inttypes.h> #include <stdbool.h> @@ -2404,11 +2405,13 @@ do_source ( // time_fd was successfully opened afterwards. proftime_T rel_time; proftime_T start_time; - if (time_fd != NULL) { + FILE * const l_time_fd = time_fd; + if (l_time_fd != NULL) { time_push(&rel_time, &start_time); } - if (do_profiling == PROF_YES) + const int l_do_profiling = do_profiling; + if (l_do_profiling == PROF_YES) prof_child_enter(&wait_start); /* entering a child now */ /* Don't use local function variables, if called from a function. @@ -2422,6 +2425,7 @@ do_source ( save_current_SID = current_SID; FileID file_id; bool file_id_ok = os_fileid((char *)fname_exp, &file_id); + assert(script_items.ga_len >= 0); for (current_SID = script_items.ga_len; current_SID > 0; --current_SID) { si = &SCRIPT_ITEM(current_SID); // Compare dev/ino when possible, it catches symbolic links. @@ -2455,7 +2459,7 @@ do_source ( new_script_vars(current_SID); } - if (do_profiling == PROF_YES) { + if (l_do_profiling == PROF_YES) { int forceit; /* Check if we do profiling for this script. */ @@ -2477,7 +2481,7 @@ do_source ( DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT); retval = OK; - if (do_profiling == PROF_YES) { + if (l_do_profiling == PROF_YES) { /* Get "si" again, "script_items" may have been reallocated. */ si = &SCRIPT_ITEM(current_SID); if (si->sn_prof_on) { @@ -2501,7 +2505,7 @@ do_source ( verbose_leave(); } - if (time_fd != NULL) { + if (l_time_fd != NULL) { vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname); time_msg((char *)IObuff, &start_time); time_pop(rel_time); @@ -2517,7 +2521,7 @@ do_source ( current_SID = save_current_SID; restore_funccal(save_funccalp); - if (do_profiling == PROF_YES) + if (l_do_profiling == PROF_YES) prof_child_exit(&wait_start); /* leaving a child now */ fclose(cookie.fp); free(cookie.nextline); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 21c877e2b9..67c346237c 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7699,6 +7699,10 @@ eval_vars ( sprintf((char *)strbuf, "%" PRId64, (int64_t)sourcing_lnum); result = strbuf; break; + default: + // should not happen + *errormsg = (char_u *)""; + return NULL; } resultlen = (int)STRLEN(result); /* length of new string */ diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 3e1672c2e7..fba0b93253 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -9,8 +9,8 @@ /* * ex_eval.c: functions for Ex command line for the +eval feature. */ +#include <assert.h> #include <stdbool.h> - #include <inttypes.h> #include "nvim/vim.h" @@ -670,6 +670,7 @@ static void report_pending(int action, int pending, void *value) char *s; int save_msg_silent; + assert(value || !(pending & CSTP_THROW)); switch (action) { case RP_MAKE: diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index b8d8837092..5feff4d456 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4245,8 +4245,10 @@ void init_history(void) for (i = newlen - 1;; --i) { if (i >= 0) /* copy newest entries */ temp[i] = history[type][j]; - else /* remove older entries */ + else { /* remove older entries */ free(history[type][j].hisstr); + history[type][j].hisstr = NULL; + } if (--j < 0) j = hislen - 1; if (j == hisidx[type]) diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index ecc05a9faa..05a0a59874 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1751,7 +1751,9 @@ failed: # ifdef USE_ICONV if (iconv_fd != (iconv_t)-1) { iconv_close(iconv_fd); +# ifndef __clang_analyzer__ iconv_fd = (iconv_t)-1; +# endif } # endif @@ -6189,12 +6191,9 @@ aucmd_prepbuf ( } } - /* Allocate "aucmd_win" when needed. If this fails (out of memory) fall - * back to using the current window. */ + /* Allocate "aucmd_win" when needed. */ if (win == NULL && aucmd_win == NULL) { win_alloc_aucmd_win(); - if (aucmd_win == NULL) - win = curwin; } if (win == NULL && aucmd_win_used) /* Strange recursive autocommand, fall back to using the current diff --git a/src/nvim/fold.c b/src/nvim/fold.c index 95f1e054b9..6014dbfd15 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -22,6 +22,7 @@ #include "nvim/diff.h" #include "nvim/eval.h" #include "nvim/ex_docmd.h" +#include "nvim/func_attr.h" #include "nvim/indent.h" #include "nvim/mark.h" #include "nvim/memline.h" @@ -1680,7 +1681,9 @@ static void foldDelMarker(linenr_T lnum, char_u *marker, int markerlen) * When 'foldtext' isn't set puts the result in "buf[51]". Otherwise the * result is in allocated memory. */ -char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T *foldinfo, char_u *buf) +char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, + foldinfo_T *foldinfo, char_u *buf) + FUNC_ATTR_NONNULL_ARG(1) { char_u *text = NULL; /* an error occurred when evaluating 'fdt' setting */ @@ -1689,8 +1692,7 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T *foldi static win_T *last_wp = NULL; static linenr_T last_lnum = 0; - if (last_wp != wp || last_wp == NULL - || last_lnum > lnum || last_lnum == 0) + if (last_wp == NULL || last_wp != wp || last_lnum > lnum || last_lnum == 0) /* window changed, try evaluating foldtext setting once again */ got_fdt_error = FALSE; diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index c6354d6c5f..2ef35fdac6 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -3006,7 +3006,7 @@ int mch_print_text_out(char_u *p, int len) /* Convert from multi-byte to 8-bit encoding */ p = string_convert(&prt_conv, p, &len); if (p == NULL) - p = (char_u *)""; + p = (char_u *)xstrdup(""); } if (prt_out_mbyte) { @@ -3054,7 +3054,7 @@ int mch_print_text_out(char_u *p, int len) } /* Need to free any translated characters */ - if (prt_do_conv && (*p != NUL)) + if (prt_do_conv) free(p); prt_text_run += char_width; diff --git a/src/nvim/memory.c b/src/nvim/memory.c index d243c4ed95..c2c406a235 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -49,17 +49,11 @@ static void try_to_free_memory(void) /// @return pointer to allocated space. NULL if out of memory void *try_malloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1) { + size = size ? size : 1; void *ret = malloc(size); - - if (!ret && !size) { - ret = malloc(1); - } if (!ret) { try_to_free_memory(); ret = malloc(size); - if (!ret && !size) { - ret = malloc(1); - } } return ret; } @@ -91,7 +85,6 @@ void *xmalloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1) FUNC_ATTR_NONNULL_RET { void *ret = try_malloc(size); - if (!ret) { OUT_STR(e_outofmem); out_char('\n'); @@ -109,23 +102,16 @@ void *xmalloc(size_t size) void *xcalloc(size_t count, size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE_PROD(1, 2) FUNC_ATTR_NONNULL_RET { - void *ret = calloc(count, size); - - if (!ret && (!count || !size)) - ret = calloc(1, 1); - + void *ret = count && size ? calloc(count, size) : calloc(1, 1); if (!ret) { try_to_free_memory(); - ret = calloc(count, size); - if (!ret && (!count || !size)) - ret = calloc(1, 1); + ret = count && size ? calloc(count, size) : calloc(1, 1); if (!ret) { OUT_STR(e_outofmem); out_char('\n'); preserve_exit(); } } - return ret; } @@ -137,23 +123,16 @@ void *xcalloc(size_t count, size_t size) void *xrealloc(void *ptr, size_t size) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALLOC_SIZE(2) FUNC_ATTR_NONNULL_RET { - void *ret = realloc(ptr, size); - - if (!ret && !size) - ret = realloc(ptr, 1); - + void *ret = size ? realloc(ptr, size) : realloc(ptr, 1); if (!ret) { try_to_free_memory(); - ret = realloc(ptr, size); - if (!ret && !size) - ret = realloc(ptr, 1); + ret = size ? realloc(ptr, size) : realloc(ptr, 1); if (!ret) { OUT_STR(e_outofmem); out_char('\n'); preserve_exit(); } } - return ret; } @@ -166,14 +145,12 @@ void *xmallocz(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT { size_t total_size = size + 1; - void *ret; - if (total_size < size) { OUT_STR(_("Vim: Data too large to fit into virtual memory space\n")); preserve_exit(); } - ret = xmalloc(total_size); + void *ret = xmalloc(total_size); ((char*)ret)[size] = 0; return ret; diff --git a/src/nvim/message.c b/src/nvim/message.c index 58dbee8cf9..ee83fd371e 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -12,6 +12,7 @@ #define MESSAGE_FILE /* don't include prototype for smsg() */ +#include <assert.h> #include <errno.h> #include <inttypes.h> #include <stdbool.h> @@ -691,8 +692,10 @@ int delete_first_msg(void) return FAIL; p = first_msg_hist; first_msg_hist = p->next; - if (first_msg_hist == NULL) - last_msg_hist = NULL; /* history is empty */ + if (first_msg_hist == NULL) { /* history is becoming empty */ + assert(msg_hist_len == 1); + last_msg_hist = NULL; + } free(p->msg); free(p); --msg_hist_len; @@ -3320,7 +3323,6 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) case 'c': case 's': case 'S': - length_modifier = '\0'; str_arg_l = 1; switch (fmt_spec) { case '%': @@ -3584,7 +3586,6 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) * zero value is formatted with an * explicit precision of zero */ precision = num_of_digits + 1; - precision_specified = 1; } } /* zero padding to specified precision? */ diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index aa6008558f..da1dc8d1b5 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -119,7 +119,7 @@ void channel_teardown(void) /// Creates an API channel by starting a job and connecting to its /// stdin/stdout. stderr is forwarded to the editor error stream. /// -/// @param argv The argument vector for the process +/// @param argv The argument vector for the process. [consumed] /// @return The channel id uint64_t channel_from_job(char **argv) { diff --git a/src/nvim/ops.c b/src/nvim/ops.c index e74fcef8d9..e7079e02d0 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -11,6 +11,7 @@ * op_change, op_yank, do_put, do_join */ +#include <assert.h> #include <inttypes.h> #include <stdbool.h> #include <string.h> @@ -3436,7 +3437,7 @@ int do_join(long count, && has_format_option(FO_REMOVE_COMS); int prev_was_comment; - + assert(count > 1); if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1), (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) return FAIL; @@ -5027,6 +5028,8 @@ void cursor_pos_info(void) pos_T min_pos, max_pos; oparg_T oparg; struct block_def bd; + const int l_VIsual_active = VIsual_active; + const int l_VIsual_mode = VIsual_mode; /* * Compute the length of the file in characters. @@ -5039,7 +5042,7 @@ void cursor_pos_info(void) else eol_size = 1; - if (VIsual_active) { + if (l_VIsual_active) { if (lt(VIsual, curwin->w_cursor)) { min_pos = VIsual; max_pos = curwin->w_cursor; @@ -5050,7 +5053,7 @@ void cursor_pos_info(void) if (*p_sel == 'e' && max_pos.col > 0) --max_pos.col; - if (VIsual_mode == Ctrl_V) { + if (l_VIsual_mode == Ctrl_V) { char_u * saved_sbr = p_sbr; /* Make 'sbr' empty for a moment to get the correct size. */ @@ -5083,12 +5086,12 @@ void cursor_pos_info(void) } /* Do extra processing for VIsual mode. */ - if (VIsual_active + if (l_VIsual_active && lnum >= min_pos.lnum && lnum <= max_pos.lnum) { char_u *s = NULL; long len = 0L; - switch (VIsual_mode) { + switch (l_VIsual_mode) { case Ctrl_V: virtual_op = virtual_active(); block_prep(&oparg, &bd, lnum, 0); @@ -5141,8 +5144,8 @@ void cursor_pos_info(void) if (!curbuf->b_p_eol && curbuf->b_p_bin) byte_count -= eol_size; - if (VIsual_active) { - if (VIsual_mode == Ctrl_V && curwin->w_curswant < MAXCOL) { + if (l_VIsual_active) { + if (l_VIsual_mode == Ctrl_V && curwin->w_curswant < MAXCOL) { getvcols(curwin, &min_pos, &max_pos, &min_pos.col, &max_pos.col); vim_snprintf((char *)buf1, sizeof(buf1), _("%" PRId64 " Cols; "), diff --git a/src/nvim/os/job.c b/src/nvim/os/job.c index 7ae2a86fc2..17872ab9c9 100644 --- a/src/nvim/os/job.c +++ b/src/nvim/os/job.c @@ -105,7 +105,8 @@ void job_teardown(void) /// Tries to start a new job. /// /// @param argv Argument vector for the process. The first item is the -/// executable to run. +/// executable to run. +/// [consumed] /// @param data Caller data that will be associated with the job /// @param writable If true the job stdin will be available for writing with /// job_write, otherwise it will be redirected to /dev/null @@ -139,6 +140,7 @@ Job *job_start(char **argv, if (i == MAX_RUNNING_JOBS) { // No free slots + shell_free_argv(argv); *status = 0; return NULL; } diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 7449ac637c..1b279f18f5 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -244,6 +244,9 @@ static int shell(const char *cmd, job_stop(job); return -1; } + // close the input stream after everything is written + job_write_cb(job, shell_write_cb); + } else { // close the input stream, let the process know that no more input is // coming job_close_in(job); @@ -447,3 +450,9 @@ static void write_output(char *output, size_t remaining) curbuf->b_no_eol_lnum = 0; } } + +static void shell_write_cb(WStream *wstream, void *data, int status) +{ + Job *job = data; + job_close_in(job); +} diff --git a/src/nvim/os/wstream.c b/src/nvim/os/wstream.c index a1f3612418..6a650ce775 100644 --- a/src/nvim/os/wstream.c +++ b/src/nvim/os/wstream.c @@ -230,7 +230,11 @@ static void write_cb(uv_write_t *req, int status) if (data->wstream->freed && data->wstream->pending_reqs == 0) { // Last pending write, free the wstream; - free(data->wstream); + if (data->wstream->free_handle) { + uv_close((uv_handle_t *)data->wstream->stream, close_cb); + } else { + free(data->wstream); + } } kmp_free(WRequestPool, wrequest_pool, data); diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt index 0ed39e8c49..6a56e302e9 100644 --- a/src/nvim/po/CMakeLists.txt +++ b/src/nvim/po/CMakeLists.txt @@ -50,7 +50,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG AND -DPOT_FILE=${NVIM_POT} -DSEARCH_DIR=${CMAKE_CURRENT_SOURCE_DIR} "'-DSOURCES=${NEOVIM_RELATIVE_SOURCES}'" - -P ${CMAKE_MODULE_PATH}/RunXgettext.cmake + -P ${PROJECT_SOURCE_DIR}/cmake/RunXgettext.cmake DEPENDS ${NEOVIM_SOURCES}) add_custom_target(potfile DEPENDS ${NVIM_POT}) @@ -68,7 +68,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG AND -DMSGFMT_PRG=${GETTEXT_MSGFMT_EXECUTABLE} -DMO_FILE=${moFile} -DPO_FILE=${poFile} - -P ${CMAKE_MODULE_PATH}/RunMsgfmt.cmake + -P ${PROJECT_SOURCE_DIR}/cmake/RunMsgfmt.cmake DEPENDS ${poFile} ${NVIM_POT}) install_helper( @@ -107,7 +107,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG AND -DINPUT_ENC=${inputEnc} -DOUTPUT_ENC=${outputEnc} -DOUTPUT_CHARSET=${outputCharSet} - -P ${CMAKE_MODULE_PATH}/ConvertPo.cmake + -P ${PROJECT_SOURCE_DIR}/cmake/ConvertPo.cmake COMMENT "Updating ${outputName}.po" DEPENDS ${inputFile}) @@ -190,7 +190,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG AND -DMSGMERGE_PRG=${GETTEXT_MSGMERGE_EXECUTABLE} -DPO_FILE=${poFile} -DPOT_FILE=${NVIM_POT} - -P ${CMAKE_MODULE_PATH}/RunMsgmerge.cmake + -P ${PROJECT_SOURCE_DIR}/cmake/RunMsgmerge.cmake COMMENT "Updating ${LANGUAGE}.po" DEPENDS ${NVIM_POT}) diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 90da02bb1b..cef2e6d9bf 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -43,6 +43,7 @@ /* #undef REGEXP_DEBUG */ /* #define REGEXP_DEBUG */ +#include <assert.h> #include <inttypes.h> #include <stdbool.h> #include <string.h> @@ -1199,10 +1200,7 @@ char_u *skip_regexp(char_u *startp, int dirc, int magic, char_u **newp) *newp = vim_strsave(startp); p = *newp + (p - startp); } - if (*newp != NULL) - STRMOVE(p, p + 1); - else - ++p; + STRMOVE(p, p + 1); } else ++p; /* skip next character */ if (*p == 'v') @@ -1300,16 +1298,18 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags) r->regstart = (*mb_ptr2char)(OPERAND(scan)); else r->regstart = *OPERAND(scan); - } else if ((OP(scan) == BOW - || OP(scan) == EOW - || OP(scan) == NOTHING - || OP(scan) == MOPEN + 0 || OP(scan) == NOPEN - || OP(scan) == MCLOSE + 0 || OP(scan) == NCLOSE) - && OP(regnext(scan)) == EXACTLY) { - if (has_mbyte) - r->regstart = (*mb_ptr2char)(OPERAND(regnext(scan))); - else - r->regstart = *OPERAND(regnext(scan)); + } else if (OP(scan) == BOW + || OP(scan) == EOW + || OP(scan) == NOTHING + || OP(scan) == MOPEN + 0 || OP(scan) == NOPEN + || OP(scan) == MCLOSE + 0 || OP(scan) == NCLOSE) { + char_u *regnext_scan = regnext(scan); + if (OP(regnext_scan) == EXACTLY) { + if (has_mbyte) + r->regstart = (*mb_ptr2char)(OPERAND(regnext_scan)); + else + r->regstart = *OPERAND(regnext_scan); + } } /* @@ -5626,6 +5626,8 @@ static int match_with_backref(linenr_T start_lnum, colnr_T start_col, linenr_T e /* Get the line to compare with. */ p = reg_getline(clnum); + assert(p); + if (clnum == end_lnum) len = end_col - ccol; else diff --git a/src/nvim/screen.c b/src/nvim/screen.c index ac726f7988..e217945ac3 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -244,6 +244,9 @@ int redraw_asap(int type) u8char_T *screenlineUC = NULL; /* copy from ScreenLinesUC[] */ u8char_T *screenlineC[MAX_MCO]; /* copy from ScreenLinesC[][] */ schar_T *screenline2 = NULL; /* copy from ScreenLines2[] */ + const bool l_enc_utf8 = enc_utf8; + const int l_enc_dbcs = enc_dbcs; + const long l_p_mco = p_mco; redraw_later(type); if (msg_scrolled || (State != NORMAL && State != NORMAL_BUSY)) @@ -254,14 +257,14 @@ int redraw_asap(int type) screenline = xmalloc((size_t)(rows * Columns * sizeof(schar_T))); screenattr = xmalloc((size_t)(rows * Columns * sizeof(sattr_T))); - if (enc_utf8) { + if (l_enc_utf8) { screenlineUC = xmalloc((size_t)(rows * Columns * sizeof(u8char_T))); - for (i = 0; i < p_mco; ++i) { + for (i = 0; i < l_p_mco; ++i) { screenlineC[i] = xmalloc((size_t)(rows * Columns * sizeof(u8char_T))); } } - if (enc_dbcs == DBCS_JPNU) { + if (l_enc_dbcs == DBCS_JPNU) { screenline2 = xmalloc((size_t)(rows * Columns * sizeof(schar_T))); } @@ -273,16 +276,16 @@ int redraw_asap(int type) memmove(screenattr + r * Columns, ScreenAttrs + LineOffset[cmdline_row + r], (size_t)Columns * sizeof(sattr_T)); - if (enc_utf8) { + if (l_enc_utf8) { memmove(screenlineUC + r * Columns, ScreenLinesUC + LineOffset[cmdline_row + r], (size_t)Columns * sizeof(u8char_T)); - for (i = 0; i < p_mco; ++i) + for (i = 0; i < l_p_mco; ++i) memmove(screenlineC[i] + r * Columns, ScreenLinesC[r] + LineOffset[cmdline_row + r], (size_t)Columns * sizeof(u8char_T)); } - if (enc_dbcs == DBCS_JPNU) + if (l_enc_dbcs == DBCS_JPNU) memmove(screenline2 + r * Columns, ScreenLines2 + LineOffset[cmdline_row + r], (size_t)Columns * sizeof(schar_T)); @@ -302,16 +305,16 @@ int redraw_asap(int type) memmove(ScreenAttrs + off, screenattr + r * Columns, (size_t)Columns * sizeof(sattr_T)); - if (enc_utf8) { + if (l_enc_utf8) { memmove(ScreenLinesUC + off, screenlineUC + r * Columns, (size_t)Columns * sizeof(u8char_T)); - for (i = 0; i < p_mco; ++i) + for (i = 0; i < l_p_mco; ++i) memmove(ScreenLinesC[i] + off, screenlineC[i] + r * Columns, (size_t)Columns * sizeof(u8char_T)); } - if (enc_dbcs == DBCS_JPNU) + if (l_enc_dbcs == DBCS_JPNU) memmove(ScreenLines2 + off, screenline2 + r * Columns, (size_t)Columns * sizeof(schar_T)); @@ -322,12 +325,12 @@ int redraw_asap(int type) free(screenline); free(screenattr); - if (enc_utf8) { + if (l_enc_utf8) { free(screenlineUC); - for (i = 0; i < p_mco; ++i) + for (i = 0; i < l_p_mco; ++i) free(screenlineC[i]); } - if (enc_dbcs == DBCS_JPNU) + if (l_enc_dbcs == DBCS_JPNU) free(screenline2); /* Show the intro message when appropriate. */ @@ -3474,7 +3477,6 @@ win_line ( n_extra = tab_len; } else { char_u *p; - int len = n_extra; int i; int saved_nextra = n_extra; @@ -3485,7 +3487,7 @@ win_line ( /* if n_extra > 0, it gives the number of chars to use for * a tab, else we need to calculate the width for a tab */ - len = (tab_len * mb_char2len(lcs_tab2)); + int len = (tab_len * mb_char2len(lcs_tab2)); if (n_extra > 0) { len += n_extra - tab_len; } @@ -3865,7 +3867,7 @@ win_line ( /* Get rid of the boguscols now, we want to draw until the right * edge for 'cursorcolumn'. */ col -= boguscols; - boguscols = 0; + // boguscols = 0; // Disabled because value never read after this if (draw_color_col) draw_color_col = advance_color_col(VCOL_HLC, &color_cols); @@ -7532,7 +7534,6 @@ int showmode(void) msg_puts_attr(edit_submode_extra, sub_attr); } } - length = 0; } else { if (State & VREPLACE_FLAG) MSG_PUTS_ATTR(_(" VREPLACE"), attr); @@ -7708,7 +7709,6 @@ static void draw_tabline(void) attr = attr_nosel; tabcount = 0; - scol = 0; FOR_ALL_TABS(tp) { if (col >= Columns - 4) { diff --git a/src/nvim/version.c b/src/nvim/version.c index 4d81cc86bf..137f85bb2b 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -21,6 +21,8 @@ char *Version = VIM_VERSION_SHORT; char *longVersion = NVIM_VERSION_LONG " (compiled " __DATE__ " " __TIME__ ")"; char *version_commit = "Commit: " NVIM_VERSION_COMMIT; +char *version_buildtype = "Build type: " NVIM_VERSION_BUILD_TYPE; +char *version_cflags = "Compilation: " NVIM_VERSION_CFLAGS; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "version.c.generated.h" @@ -778,6 +780,8 @@ void list_version(void) // internal variables in eval.c! MSG(longVersion); MSG(version_commit); + MSG(version_buildtype); + MSG(version_cflags); // Print the list of extra patch descriptions if there is at least one. char *s = ""; @@ -857,10 +861,6 @@ void list_version(void) version_msg("\"\n"); } #endif // ifdef HAVE_PATHDEF -#ifdef DEBUG - version_msg("\n"); - version_msg(_(" DEBUG BUILD")); -#endif // ifdef DEBUG } /// Output a string for the version message. If it's going to wrap, output a diff --git a/src/nvim/version_defs.h b/src/nvim/version_defs.h index d8e1b4ea82..0ba6143632 100644 --- a/src/nvim/version_defs.h +++ b/src/nvim/version_defs.h @@ -22,13 +22,19 @@ #define NVIM_VERSION_PATCH 0 #endif #ifndef NVIM_VERSION_PRERELEASE -#define NVIM_VERSION_PRERELEASE +#define NVIM_VERSION_PRERELEASE "?" #endif #ifndef NVIM_VERSION_BUILD -#define NVIM_VERSION_BUILD +#define NVIM_VERSION_BUILD "?" #endif #ifndef NVIM_VERSION_COMMIT -#define NVIM_VERSION_COMMIT +#define NVIM_VERSION_COMMIT "?" +#endif +#ifndef NVIM_VERSION_CFLAGS +#define NVIM_VERSION_CFLAGS "?" +#endif +#ifndef NVIM_VERSION_BUILD_TYPE +#define NVIM_VERSION_BUILD_TYPE "?" #endif // for the startup-screen #define NVIM_VERSION_MEDIUM STR(NVIM_VERSION_MAJOR) "." STR(NVIM_VERSION_MINOR) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index bf6e3dd38a..6c3f5190c9 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -25,7 +25,7 @@ if os.getenv('VALGRIND') then nvim_argv = valgrind_argv end -local session, loop_running, last_error +local session, loop_running, loop_stopped, last_error local function request(method, ...) local status, rv = session:request(method, ...) @@ -39,7 +39,11 @@ local function request(method, ...) end -- Make sure this will only return after all buffered characters have been -- processed - session:request('vim_eval', '1') + if not loop_stopped then + -- Except when the loop has been stopped by a notification triggered + -- by the initial request, for example. + session:request('vim_eval', '1') + end return rv end @@ -71,6 +75,7 @@ local function run(request_cb, notification_cb, setup_cb) call_and_stop_on_error(setup_cb) end + loop_stopped = false loop_running = true session:run(on_request, on_notification, on_setup) loop_running = false @@ -82,6 +87,7 @@ local function run(request_cb, notification_cb, setup_cb) end local function stop() + loop_stopped = true session:stop() end diff --git a/test/functional/shell/viml_system_spec.lua b/test/functional/shell/viml_system_spec.lua index a8bab8e26e..91e115aedf 100644 --- a/test/functional/shell/viml_system_spec.lua +++ b/test/functional/shell/viml_system_spec.lua @@ -3,8 +3,8 @@ -- - `systemlist()` local helpers = require('test.functional.helpers') -local eq, clear, eval, feed = - helpers.eq, helpers.clear, helpers.eval, helpers.feed +local eq, clear, eval, feed, nvim = + helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.nvim local function create_file_with_nuls(name) @@ -55,6 +55,21 @@ describe('system()', function() end) end) + describe('passing a lot of input', function() + it('returns the program output', function() + local input = {} + -- write more than 1mb of data, which should be enough to overcome + -- the os buffer limit and force multiple event loop iterations to write + -- everything + for i = 1, 0xffff do + input[#input + 1] = '01234567890ABCDEFabcdef' + end + input = table.concat(input, '\n') + nvim('set_var', 'input', input) + eq(input, eval('system("cat -", g:input)')) + end) + end) + describe('passing number as input', function() it('stringifies the input', function() eq('1', eval('system("cat", 1)')) @@ -129,6 +144,17 @@ describe('systemlist()', function() end) end) + describe('passing a lot of input', function() + it('returns the program output', function() + local input = {} + for i = 1, 0xffff do + input[#input + 1] = '01234567890ABCDEFabcdef' + end + nvim('set_var', 'input', input) + eq(input, eval('systemlist("cat -", g:input)')) + end) + end) + describe('with output containing NULs', function() local fname = 'Xtest' @@ -166,7 +192,7 @@ describe('systemlist()', function() if xclip then describe("with a program that doesn't close stdout", function() it('will exit properly after passing input', function() - eq(nil, eval( + eq({}, eval( "systemlist('xclip -i -selection clipboard', ['clip', 'data'])")) eq({'clip', 'data'}, eval( "systemlist('xclip -o -selection clipboard')")) |