[build] remove pcrecpp and other stuff

Linking against a binary c++ lib suuuucckkkkkssss...
pull/835/head
Timothy Stack 3 years ago
parent 2b9f4c6d3a
commit 49ebde5953

@ -11,8 +11,8 @@ set(CMAKE_CXX_FLAGS_RELEASE "-O3")
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.269.tar.gz"
SHA1 "64024b7b95b4c86d50ae05b926814448c93a70a0"
URL "https://github.com/cpp-pm/hunter/archive/v0.23.291.tar.gz"
SHA1 "4f57243b24a02b9c7ec5ea02c09d5c77c6a97cba"
LOCAL
)
@ -20,12 +20,14 @@ set(CMAKE_CXX_STANDARD 14)
project(lnav
VERSION 0.9.1)
# include(cmake/CodeCoverage.cmake)
# append_coverage_compiler_flags()
include(CTest)
include(GNUInstallDirs)
hunter_add_package(libpcre)
find_package(libpcre CONFIG REQUIRED)
find_package(libpcrecpp CONFIG REQUIRED)
hunter_add_package(BZip2)
find_package(BZip2 CONFIG REQUIRED)
@ -45,16 +47,19 @@ find_package(ncursesw CONFIG REQUIRED)
hunter_add_package(readline)
find_package(readline REQUIRED)
hunter_add_package(libarchive)
find_package(libarchive CONFIG REQUIRED)
set(lnav_LIBS
ZLIB::zlib
BZip2::bz2
sqlite3::sqlite3
PkgConfig::libpcrecpp
PkgConfig::libpcre
CURL::libcurl
readline::readline
readline::history
PkgConfig::ncursesw)
PkgConfig::ncursesw
PkgConfig::libarchive)
add_subdirectory(src)
add_subdirectory(test)

@ -64,7 +64,7 @@ Alternatively, you can get the generated binary from [AppVeyor](https://ci.appve
Remember that you still need the lnav dependencies under Cygwin, here is a quick way to do it:
setup-x86_64.exe -q -P libpcre1 -P libpcrecpp0 -P libsqlite3_0 -P libstdc++6
setup-x86_64.exe -q -P libpcre1 -P libsqlite3_0 -P libstdc++6
Currently, the x64 version seems to be working better than the x86 one.

@ -0,0 +1,126 @@
# aminclude_static.am generated automatically by Autoconf
# from AX_AM_MACROS_STATIC on Thu Jan 28 11:06:02 PST 2021
# Code coverage
#
# Optional:
# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
# Multiple directories may be specified, separated by whitespace.
# (Default: $(top_builddir))
# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
# by lcov for code coverage. (Default:
# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info)
# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
# reports to be created. (Default:
# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage)
# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage,
# set to 0 to disable it and leave empty to stay with the default.
# (Default: empty)
# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov
# instances. (Default: based on )
# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov
# instances. (Default: )
# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov
# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the
# collecting lcov instance. (Default: )
# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov
# instance. (Default: )
# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering
# lcov instance. (Default: empty)
# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov
# instance. (Default: )
# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the
# genhtml instance. (Default: based on )
# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
# instance. (Default: )
# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
#
# The generated report will be titled using the $(PACKAGE_NAME) and
# $(PACKAGE_VERSION). In order to add the current git hash to the title,
# use the git-version-gen script, available online.
# Optional variables
# run only on top dir
if CODE_COVERAGE_ENABLED
ifeq ($(abs_builddir), $(abs_top_builddir))
CODE_COVERAGE_DIRECTORY ?= $(top_builddir)
CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
CODE_COVERAGE_BRANCH_COVERAGE ?=
CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)"
CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?=
CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=$(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
CODE_COVERAGE_IGNORE_PATTERN ?=
GITIGNOREFILES := $(GITIGNOREFILES) $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY)
code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V))
code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_lcov_cap_0 = @echo " LCOV --capture" $(CODE_COVERAGE_OUTPUT_FILE);
code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V))
code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN);
code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V))
code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_genhtml_0 = @echo " GEN " "$(CODE_COVERAGE_OUTPUT_DIRECTORY)";
code_coverage_quiet = $(code_coverage_quiet_$(V))
code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY))
code_coverage_quiet_0 = --quiet
# sanitizes the test-name: replaces with underscores: dashes and dots
code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1)))
# Use recursive makes in order to ignore errors during check
check-code-coverage:
-$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture
# Capture code coverage data
code-coverage-capture: code-coverage-capture-hook
$(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS)
$(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS)
-@rm -f "$(CODE_COVERAGE_OUTPUT_FILE).tmp"
$(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
@echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
code-coverage-clean:
-$(LCOV) --directory $(top_builddir) -z
-rm -rf "$(CODE_COVERAGE_OUTPUT_FILE)" "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "$(CODE_COVERAGE_OUTPUT_DIRECTORY)"
-find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete
code-coverage-dist-clean:
AM_DISTCHECK_CONFIGURE_FLAGS := $(AM_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage
else # ifneq ($(abs_builddir), $(abs_top_builddir))
check-code-coverage:
code-coverage-capture: code-coverage-capture-hook
code-coverage-clean:
code-coverage-dist-clean:
endif # ifeq ($(abs_builddir), $(abs_top_builddir))
else #! CODE_COVERAGE_ENABLED
# Use recursive makes in order to ignore errors during check
check-code-coverage:
@echo "Need to reconfigure with --enable-code-coverage"
# Capture code coverage data
code-coverage-capture: code-coverage-capture-hook
@echo "Need to reconfigure with --enable-code-coverage"
code-coverage-clean:
code-coverage-dist-clean:
endif #CODE_COVERAGE_ENABLED
# Hook rule executed before code-coverage-capture, overridable by the user
code-coverage-capture-hook:
.PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook

@ -0,0 +1,438 @@
# Copyright (c) 2012 - 2017, Lars Bilke
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# CHANGES:
#
# 2012-01-31, Lars Bilke
# - Enable Code Coverage
#
# 2013-09-17, Joakim Söderberg
# - Added support for Clang.
# - Some additional usage instructions.
#
# 2016-02-03, Lars Bilke
# - Refactored functions to use named parameters
#
# 2017-06-02, Lars Bilke
# - Merged with modified version from github.com/ufz/ogs
#
# 2019-05-06, Anatolii Kurotych
# - Remove unnecessary --coverage flag
#
# 2019-12-13, FeRD (Frank Dana)
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
# - Set lcov basedir with -b argument
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
# - Delete output dir, .info file on 'make clean'
# - Remove Python detection, since version mismatches will break gcovr
# - Minor cleanup (lowercase function names, update examples...)
#
# 2019-12-19, FeRD (Frank Dana)
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
#
# 2020-01-19, Bob Apthorpe
# - Added gfortran support
#
# 2020-02-17, FeRD (Frank Dana)
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
# in EXCLUDEs, and remove manual escaping from gcovr targets
#
# USAGE:
#
# 1. Copy this file into your cmake modules path.
#
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
# using a CMake option() to enable it just optionally):
# include(CodeCoverage)
#
# 3. Append necessary compiler flags:
# append_coverage_compiler_flags()
#
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
#
# 4. If you need to exclude additional directories from the report, specify them
# using full paths in the COVERAGE_EXCLUDES variable before calling
# setup_target_for_coverage_*().
# Example:
# set(COVERAGE_EXCLUDES
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
# '/path/to/my/src/dir2/*')
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
# Example:
# setup_target_for_coverage_lcov(
# NAME coverage
# EXECUTABLE testrunner
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
#
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
# Example:
# set(COVERAGE_EXCLUDES "dir1/*")
# setup_target_for_coverage_gcovr_html(
# NAME coverage
# EXECUTABLE testrunner
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
# EXCLUDE "dir2/*")
#
# 5. Use the functions described below to create a custom make target which
# runs your test executable and produces a code coverage report.
#
# 6. Build a Debug build:
# cmake -DCMAKE_BUILD_TYPE=Debug ..
# make
# make my_coverage_target
#
include(CMakeParseArguments)
# Check prereqs
find_program( GCOV_PATH gcov )
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
find_program( CPPFILT_PATH NAMES c++filt )
if(NOT GCOV_PATH)
message(FATAL_ERROR "gcov not found! Aborting...")
endif() # NOT GCOV_PATH
message("foo ${CMAKE_CXX_COMPILER_ID}")
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif()
elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
if("${CMAKE_Fortran_COMPILER_ID}" MATCHES "[Ff]lang")
# Do nothing; exit conditional without error if true
elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU")
# Do nothing; exit conditional without error if true
else()
message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
endif()
endif()
set(COVERAGE_COMPILER_FLAGS "-g -fprofile-arcs -ftest-coverage"
CACHE INTERNAL "")
set(CMAKE_Fortran_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
FORCE )
set(CMAKE_CXX_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C++ compiler during coverage builds."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C compiler during coverage builds."
FORCE )
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used for linking binaries during coverage builds."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
FORCE )
mark_as_advanced(
CMAKE_Fortran_FLAGS_COVERAGE
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
link_libraries(gcov)
endif()
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_lcov(
# NAME testrunner_coverage # New target name
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES testrunner # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# NO_DEMANGLE # Don't demangle C++ symbols
# # even if c++filt is found
# )
function(setup_target_for_coverage_lcov)
set(options NO_DEMANGLE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT LCOV_PATH)
message(FATAL_ERROR "lcov not found! Aborting...")
endif() # NOT LCOV_PATH
if(NOT GENHTML_PATH)
message(FATAL_ERROR "genhtml not found! Aborting...")
endif() # NOT GENHTML_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(${Coverage_BASE_DIRECTORY})
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(LCOV_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES LCOV_EXCLUDES)
# Conditional arguments
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
endif()
# Setup target
add_custom_target(${Coverage_NAME}
# Cleanup lcov
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . -b ${BASEDIR} --zerocounters
# Create baseline to make sure untouched files show up in the report
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b ${BASEDIR} -o ${Coverage_NAME}.base
# Run tests
COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
# Capturing lcov counters and generating report
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b ${BASEDIR} --capture --output-file ${Coverage_NAME}.capture
# add baseline counters
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total
# filter collected data to final coverage report
COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info
# Generate HTML output
COMMAND ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${Coverage_NAME}.info
# Set output files as GENERATED (will be removed on 'make clean')
BYPRODUCTS
${Coverage_NAME}.base
${Coverage_NAME}.capture
${Coverage_NAME}.total
${Coverage_NAME}.info
${Coverage_NAME} # report directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)
# Show where to find the lcov info report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
endfunction() # setup_target_for_coverage_lcov
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr_xml(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
function(setup_target_for_coverage_gcovr_xml)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(${Coverage_BASE_DIRECTORY})
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
add_custom_target(${Coverage_NAME}
# Run tests
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
# Running gcovr
COMMAND ${GCOVR_PATH} --xml
-r ${BASEDIR} ${GCOVR_EXCLUDE_ARGS}
--object-directory=${PROJECT_BINARY_DIR}
-o ${Coverage_NAME}.xml
BYPRODUCTS ${Coverage_NAME}.xml
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce Cobertura code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
)
endfunction() # setup_target_for_coverage_gcovr_xml
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr_html(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
function(setup_target_for_coverage_gcovr_html)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(${Coverage_BASE_DIRECTORY})
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
add_custom_target(${Coverage_NAME}
# Run tests
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
# Create folder
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
# Running gcovr
COMMAND ${GCOVR_PATH} --html --html-details
-r ${BASEDIR} ${GCOVR_EXCLUDE_ARGS}
--object-directory=${PROJECT_BINARY_DIR}
-o ${Coverage_NAME}/index.html
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME} # report directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce HTML code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
endfunction() # setup_target_for_coverage_gcovr_html
function(append_coverage_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
endfunction() # append_coverage_compiler_flags

@ -168,6 +168,8 @@ AX_PATH_LIB_ARCHIVE
AX_PATH_LIB_PCRE([], [AC_MSG_ERROR([pcre required to build])])
AX_PATH_LIB_READLINE
AX_CODE_COVERAGE
LNAV_WITH_SQLITE3("3.9.0")
dnl case "$host_os" in
@ -185,7 +187,7 @@ AS_VAR_SET(ALL_LDFLAGS, "$SQLITE3_LDFLAGS $READLINE_LDFLAGS $LDFLAGS")
AS_VAR_SET(static_lib_list,
["libncurses.a libncursesw.a libreadline.a libsqlite3.a libz.a libtinfo.a libtinfow.a"])
AS_VAR_SET(static_lib_list,
["$static_lib_list libpcre.a libpcrecpp.a libncursesw.a libbz2.a"])
["$static_lib_list libpcre.a libncursesw.a libbz2.a"])
AS_VAR_SET(static_lib_list,
["$static_lib_list libgpm.a libcurl.a libcrypto.a libssl.a libssh2.a"])
AS_VAR_SET(static_lib_list,

@ -0,0 +1,32 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_ac_append_to_file.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_AC_APPEND_TO_FILE([FILE],[DATA])
#
# DESCRIPTION
#
# Appends the specified data to the specified Autoconf is run. If you want
# to append to a file when configure is run use AX_APPEND_TO_FILE instead.
#
# LICENSE
#
# Copyright (c) 2009 Allan Caffee <allan.caffee@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 10
AC_DEFUN([AX_AC_APPEND_TO_FILE],[
AC_REQUIRE([AX_FILE_ESCAPES])
m4_esyscmd(
AX_FILE_ESCAPES
[
printf "%s" "$2" >> "$1"
])
])

@ -0,0 +1,32 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_ac_print_to_file.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_AC_PRINT_TO_FILE([FILE],[DATA])
#
# DESCRIPTION
#
# Writes the specified data to the specified file when Autoconf is run. If
# you want to print to a file when configure is run use AX_PRINT_TO_FILE
# instead.
#
# LICENSE
#
# Copyright (c) 2009 Allan Caffee <allan.caffee@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 10
AC_DEFUN([AX_AC_PRINT_TO_FILE],[
m4_esyscmd(
AC_REQUIRE([AX_FILE_ESCAPES])
[
printf "%s" "$2" > "$1"
])
])

@ -0,0 +1,28 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_add_am_macro_static.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_ADD_AM_MACRO_STATIC([RULE])
#
# DESCRIPTION
#
# Adds the specified rule to $AMINCLUDE.
#
# LICENSE
#
# Copyright (c) 2009 Tom Howard <tomhoward@users.sf.net>
# Copyright (c) 2009 Allan Caffee <allan.caffee@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 8
AC_DEFUN([AX_ADD_AM_MACRO_STATIC],[
AC_REQUIRE([AX_AM_MACROS_STATIC])
AX_AC_APPEND_TO_FILE(AMINCLUDE_STATIC,[$1])
])

@ -0,0 +1,38 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_am_macros_static.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_AM_MACROS_STATIC
#
# DESCRIPTION
#
# Adds support for macros that create Automake rules. You must manually
# add the following line
#
# include $(top_srcdir)/aminclude_static.am
#
# to your Makefile.am files.
#
# LICENSE
#
# Copyright (c) 2009 Tom Howard <tomhoward@users.sf.net>
# Copyright (c) 2009 Allan Caffee <allan.caffee@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 11
AC_DEFUN([AMINCLUDE_STATIC],[aminclude_static.am])
AC_DEFUN([AX_AM_MACROS_STATIC],
[
AX_AC_PRINT_TO_FILE(AMINCLUDE_STATIC,[
# ]AMINCLUDE_STATIC[ generated automatically by Autoconf
# from AX_AM_MACROS_STATIC on ]m4_esyscmd([LC_ALL=C date])[
])
])

@ -0,0 +1,95 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_check_gnu_make.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_GNU_MAKE([run-if-true],[run-if-false])
#
# DESCRIPTION
#
# This macro searches for a GNU version of make. If a match is found:
#
# * The makefile variable `ifGNUmake' is set to the empty string, otherwise
# it is set to "#". This is useful for including a special features in a
# Makefile, which cannot be handled by other versions of make.
# * The makefile variable `ifnGNUmake' is set to #, otherwise
# it is set to the empty string. This is useful for including a special
# features in a Makefile, which can be handled
# by other versions of make or to specify else like clause.
# * The variable `_cv_gnu_make_command` is set to the command to invoke
# GNU make if it exists, the empty string otherwise.
# * The variable `ax_cv_gnu_make_command` is set to the command to invoke
# GNU make by copying `_cv_gnu_make_command`, otherwise it is unset.
# * If GNU Make is found, its version is extracted from the output of
# `make --version` as the last field of a record of space-separated
# columns and saved into the variable `ax_check_gnu_make_version`.
# * Additionally if GNU Make is found, run shell code run-if-true
# else run shell code run-if-false.
#
# Here is an example of its use:
#
# Makefile.in might contain:
#
# # A failsafe way of putting a dependency rule into a makefile
# $(DEPEND):
# $(CC) -MM $(srcdir)/*.c > $(DEPEND)
#
# @ifGNUmake@ ifeq ($(DEPEND),$(wildcard $(DEPEND)))
# @ifGNUmake@ include $(DEPEND)
# @ifGNUmake@ else
# fallback code
# @ifGNUmake@ endif
#
# Then configure.in would normally contain:
#
# AX_CHECK_GNU_MAKE()
# AC_OUTPUT(Makefile)
#
# Then perhaps to cause gnu make to override any other make, we could do
# something like this (note that GNU make always looks for GNUmakefile
# first):
#
# if ! test x$_cv_gnu_make_command = x ; then
# mv Makefile GNUmakefile
# echo .DEFAULT: > Makefile ;
# echo \ $_cv_gnu_make_command \$@ >> Makefile;
# fi
#
# Then, if any (well almost any) other make is called, and GNU make also
# exists, then the other make wraps the GNU make.
#
# LICENSE
#
# Copyright (c) 2008 John Darrington <j.darrington@elvis.murdoch.edu.au>
# Copyright (c) 2015 Enrico M. Crisostomo <enrico.m.crisostomo@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 12
AC_DEFUN([AX_CHECK_GNU_MAKE],dnl
[AC_PROG_AWK
AC_CACHE_CHECK([for GNU make],[_cv_gnu_make_command],[dnl
_cv_gnu_make_command="" ;
dnl Search all the common names for GNU make
for a in "$MAKE" make gmake gnumake ; do
if test -z "$a" ; then continue ; fi ;
if "$a" --version 2> /dev/null | grep GNU 2>&1 > /dev/null ; then
_cv_gnu_make_command=$a ;
AX_CHECK_GNU_MAKE_HEADLINE=$("$a" --version 2> /dev/null | grep "GNU Make")
ax_check_gnu_make_version=$(echo ${AX_CHECK_GNU_MAKE_HEADLINE} | ${AWK} -F " " '{ print $(NF); }')
break ;
fi
done ;])
dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, '#' otherwise
AS_VAR_IF([_cv_gnu_make_command], [""], [AS_VAR_SET([ifGNUmake], ["#"])], [AS_VAR_SET([ifGNUmake], [""])])
AS_VAR_IF([_cv_gnu_make_command], [""], [AS_VAR_SET([ifnGNUmake], [""])], [AS_VAR_SET([ifnGNUmake], ["#"])])
AS_VAR_IF([_cv_gnu_make_command], [""], [AS_UNSET(ax_cv_gnu_make_command)], [AS_VAR_SET([ax_cv_gnu_make_command], [${_cv_gnu_make_command}])])
AS_VAR_IF([_cv_gnu_make_command], [""],[$2],[$1])
AC_SUBST([ifGNUmake])
AC_SUBST([ifnGNUmake])
])

@ -0,0 +1,272 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_code_coverage.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CODE_COVERAGE()
#
# DESCRIPTION
#
# Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS,
# CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included
# in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every
# build target (program or library) which should be built with code
# coverage support. Also add rules using AX_ADD_AM_MACRO_STATIC; and
# $enable_code_coverage which can be used in subsequent configure output.
# CODE_COVERAGE_ENABLED is defined and substituted, and corresponds to the
# value of the --enable-code-coverage option, which defaults to being
# disabled.
#
# Test also for gcov program and create GCOV variable that could be
# substituted.
#
# Note that all optimization flags in CFLAGS must be disabled when code
# coverage is enabled.
#
# Usage example:
#
# configure.ac:
#
# AX_CODE_COVERAGE
#
# Makefile.am:
#
# include $(top_srcdir)/aminclude_static.am
#
# my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ...
# my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ...
# my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ...
# my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ...
#
# clean-local: code-coverage-clean
# distclean-local: code-coverage-dist-clean
#
# This results in a "check-code-coverage" rule being added to any
# Makefile.am which do "include $(top_srcdir)/aminclude_static.am"
# (assuming the module has been configured with --enable-code-coverage).
# Running `make check-code-coverage` in that directory will run the
# module's test suite (`make check`) and build a code coverage report
# detailing the code which was touched, then print the URI for the report.
#
# This code was derived from Makefile.decl in GLib, originally licensed
# under LGPLv2.1+.
#
# LICENSE
#
# Copyright (c) 2012, 2016 Philip Withnall
# Copyright (c) 2012 Xan Lopez
# Copyright (c) 2012 Christian Persch
# Copyright (c) 2012 Paolo Borelli
# Copyright (c) 2012 Dan Winship
# Copyright (c) 2015,2018 Bastien ROUCARIES
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or (at
# your option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#serial 34
m4_define(_AX_CODE_COVERAGE_RULES,[
AX_ADD_AM_MACRO_STATIC([
# Code coverage
#
# Optional:
# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
# Multiple directories may be specified, separated by whitespace.
# (Default: \$(top_builddir))
# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
# by lcov for code coverage. (Default:
# \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info)
# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
# reports to be created. (Default:
# \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage)
# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage,
# set to 0 to disable it and leave empty to stay with the default.
# (Default: empty)
# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov
# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov
# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov
# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the
# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov
# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering
# lcov instance. (Default: empty)
# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov
# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the
# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
#
# The generated report will be titled using the \$(PACKAGE_NAME) and
# \$(PACKAGE_VERSION). In order to add the current git hash to the title,
# use the git-version-gen script, available online.
# Optional variables
# run only on top dir
if CODE_COVERAGE_ENABLED
ifeq (\$(abs_builddir), \$(abs_top_builddir))
CODE_COVERAGE_DIRECTORY ?= \$(top_builddir)
CODE_COVERAGE_OUTPUT_FILE ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info
CODE_COVERAGE_OUTPUT_DIRECTORY ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage
CODE_COVERAGE_BRANCH_COVERAGE ?=
CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= \$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\
--rc lcov_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE))
CODE_COVERAGE_LCOV_SHOPTS ?= \$(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool \"\$(GCOV)\"
CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= \$(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
CODE_COVERAGE_LCOV_OPTIONS ?= \$(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?=
CODE_COVERAGE_LCOV_RMOPTS ?= \$(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\
\$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\
--rc genhtml_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE))
CODE_COVERAGE_GENHTML_OPTIONS ?= \$(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
CODE_COVERAGE_IGNORE_PATTERN ?=
GITIGNOREFILES := \$(GITIGNOREFILES) \$(CODE_COVERAGE_OUTPUT_FILE) \$(CODE_COVERAGE_OUTPUT_DIRECTORY)
code_coverage_v_lcov_cap = \$(code_coverage_v_lcov_cap_\$(V))
code_coverage_v_lcov_cap_ = \$(code_coverage_v_lcov_cap_\$(AM_DEFAULT_VERBOSITY))
code_coverage_v_lcov_cap_0 = @echo \" LCOV --capture\" \$(CODE_COVERAGE_OUTPUT_FILE);
code_coverage_v_lcov_ign = \$(code_coverage_v_lcov_ign_\$(V))
code_coverage_v_lcov_ign_ = \$(code_coverage_v_lcov_ign_\$(AM_DEFAULT_VERBOSITY))
code_coverage_v_lcov_ign_0 = @echo \" LCOV --remove /tmp/*\" \$(CODE_COVERAGE_IGNORE_PATTERN);
code_coverage_v_genhtml = \$(code_coverage_v_genhtml_\$(V))
code_coverage_v_genhtml_ = \$(code_coverage_v_genhtml_\$(AM_DEFAULT_VERBOSITY))
code_coverage_v_genhtml_0 = @echo \" GEN \" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\";
code_coverage_quiet = \$(code_coverage_quiet_\$(V))
code_coverage_quiet_ = \$(code_coverage_quiet_\$(AM_DEFAULT_VERBOSITY))
code_coverage_quiet_0 = --quiet
# sanitizes the test-name: replaces with underscores: dashes and dots
code_coverage_sanitize = \$(subst -,_,\$(subst .,_,\$(1)))
# Use recursive makes in order to ignore errors during check
check-code-coverage:
-\$(AM_V_at)\$(MAKE) \$(AM_MAKEFLAGS) -k check
\$(AM_V_at)\$(MAKE) \$(AM_MAKEFLAGS) code-coverage-capture
# Capture code coverage data
code-coverage-capture: code-coverage-capture-hook
\$(code_coverage_v_lcov_cap)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --capture --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" --test-name \"\$(call code_coverage_sanitize,\$(PACKAGE_NAME)-\$(PACKAGE_VERSION))\" --no-checksum --compat-libtool \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_OPTIONS)
\$(code_coverage_v_lcov_ign)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --remove \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"/tmp/*\" \$(CODE_COVERAGE_IGNORE_PATTERN) --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_RMOPTS)
-@rm -f \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\"
\$(code_coverage_v_genhtml)LANG=C \$(GENHTML) \$(code_coverage_quiet) \$(addprefix --prefix ,\$(CODE_COVERAGE_DIRECTORY)) --output-directory \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" --title \"\$(PACKAGE_NAME)-\$(PACKAGE_VERSION) Code Coverage\" --legend --show-details \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_GENHTML_OPTIONS)
@echo \"file://\$(abs_builddir)/\$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html\"
code-coverage-clean:
-\$(LCOV) --directory \$(top_builddir) -z
-rm -rf \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\"
-find . \\( -name \"*.gcda\" -o -name \"*.gcno\" -o -name \"*.gcov\" \\) -delete
code-coverage-dist-clean:
A][M_DISTCHECK_CONFIGURE_FLAGS := \$(A][M_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage
else # ifneq (\$(abs_builddir), \$(abs_top_builddir))
check-code-coverage:
code-coverage-capture: code-coverage-capture-hook
code-coverage-clean:
code-coverage-dist-clean:
endif # ifeq (\$(abs_builddir), \$(abs_top_builddir))
else #! CODE_COVERAGE_ENABLED
# Use recursive makes in order to ignore errors during check
check-code-coverage:
@echo \"Need to reconfigure with --enable-code-coverage\"
# Capture code coverage data
code-coverage-capture: code-coverage-capture-hook
@echo \"Need to reconfigure with --enable-code-coverage\"
code-coverage-clean:
code-coverage-dist-clean:
endif #CODE_COVERAGE_ENABLED
# Hook rule executed before code-coverage-capture, overridable by the user
code-coverage-capture-hook:
.PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook
])
])
AC_DEFUN([_AX_CODE_COVERAGE_ENABLED],[
AX_CHECK_GNU_MAKE([],[AC_MSG_ERROR([not using GNU make that is needed for coverage])])
AC_REQUIRE([AX_ADD_AM_MACRO_STATIC])
# check for gcov
AC_CHECK_TOOL([GCOV],
[$_AX_CODE_COVERAGE_GCOV_PROG_WITH],
[:])
AS_IF([test "X$GCOV" = "X:"],
[AC_MSG_ERROR([gcov is needed to do coverage])])
AC_SUBST([GCOV])
dnl Check if gcc is being used
AS_IF([ test "$GCC" = "no" ], [
AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
])
AC_CHECK_PROG([LCOV], [lcov], [lcov])
AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
AS_IF([ test x"$LCOV" = x ], [
AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed])
])
AS_IF([ test x"$GENHTML" = x ], [
AC_MSG_ERROR([Could not find genhtml from the lcov package])
])
dnl Build the code coverage flags
dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility
CODE_COVERAGE_CPPFLAGS="-DNDEBUG"
CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
CODE_COVERAGE_LIBS="-lgcov"
AC_SUBST([CODE_COVERAGE_CPPFLAGS])
AC_SUBST([CODE_COVERAGE_CFLAGS])
AC_SUBST([CODE_COVERAGE_CXXFLAGS])
AC_SUBST([CODE_COVERAGE_LIBS])
])
AC_DEFUN([AX_CODE_COVERAGE],[
dnl Check for --enable-code-coverage
# allow to override gcov location
AC_ARG_WITH([gcov],
[AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])],
[_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov],
[_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov])
AC_MSG_CHECKING([whether to build with code coverage support])
AC_ARG_ENABLE([code-coverage],
AS_HELP_STRING([--enable-code-coverage],
[Whether to enable code coverage support]),,
enable_code_coverage=no)
AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test "x$enable_code_coverage" = xyes])
AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
AC_MSG_RESULT($enable_code_coverage)
AS_IF([ test "x$enable_code_coverage" = xyes ], [
_AX_CODE_COVERAGE_ENABLED
])
_AX_CODE_COVERAGE_RULES
])

@ -0,0 +1,30 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_file_escapes.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_FILE_ESCAPES
#
# DESCRIPTION
#
# Writes the specified data to the specified file.
#
# LICENSE
#
# Copyright (c) 2008 Tom Howard <tomhoward@users.sf.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 8
AC_DEFUN([AX_FILE_ESCAPES],[
AX_DOLLAR="\$"
AX_SRB="\\135"
AX_SLB="\\133"
AX_BS="\\\\"
AX_DQ="\""
])

@ -54,5 +54,4 @@ parts:
- zlib1g
- libncursesw5
- libpcre3
- libpcrecpp0v5
- libgpm2

@ -1,4 +1,6 @@
include $(top_srcdir)/aminclude_static.am
SUBDIRS = base fmtlib pcrepp pugixml yajl yajlpp .
bin_PROGRAMS = lnav
@ -203,6 +205,10 @@ LNAV_BUILT_FILES = \
xterm-palette-json.h \
xterm-palette-json.cc
AM_LIBS = $(CODE_COVERAGE_LIBS)
AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
AM_LDFLAGS = \
$(STATIC_LDFLAGS) \
$(LIBARCHIVE_LDFLAGS) \
@ -214,6 +220,7 @@ AM_CPPFLAGS = \
-DSYSCONFDIR='"$(sysconfdir)"' \
-I$(srcdir)/fmtlib \
-Wall \
$(CODE_COVERAGE_CPPFLAGS) \
$(LIBARCHIVE_CFLAGS) \
$(READLINE_CFLAGS) \
$(SQLITE3_CFLAGS) \
@ -231,8 +238,7 @@ LDADD = \
$(CURSES_LIB) \
$(SQLITE3_LIBS) \
$(LIBARCHIVE_LIBS) \
$(LIBCURL) \
-lpcrecpp
$(LIBCURL)
dist_noinst_DATA = \
alpha-release.sh \
@ -397,6 +403,8 @@ libdiag_a_SOURCES = \
column_namer.cc \
command_executor.cc \
curl_looper.cc \
data_scanner.cc \
data_scanner_re.cc \
db_sub_source.cc \
elem_to_json.cc \
environ_vtab.cc \
@ -435,8 +443,6 @@ libdiag_a_SOURCES = \
logfile.cc \
logfile_sub_source.cc \
network-extension-functions.cc \
data_scanner.cc \
data_scanner_re.cc \
data_parser.cc \
papertrail_proc.cc \
pretty_printer.cc \

@ -31,7 +31,6 @@
#include "config.h"
#include <vector>
#include <algorithm>
#include "base/opt_util.hh"

@ -76,7 +76,9 @@ public:
return *this;
};
auto_mem &operator =(auto_mem & am)
auto_mem &operator=(auto_mem &) = delete;
auto_mem &operator =(auto_mem && am) noexcept
{
this->reset(am.release());
this->am_free_func = am.am_free_func;

@ -1,9 +1,16 @@
include $(top_srcdir)/aminclude_static.am
AM_CPPFLAGS = \
$(CODE_COVERAGE_CPPFLAGS) \
-Wall \
-I$(top_srcdir)/src/ \
-I$(top_srcdir)/src/fmtlib
AM_LIBS = $(CODE_COVERAGE_LIBS)
AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
noinst_LIBRARIES = libbase.a
noinst_HEADERS = \

@ -140,6 +140,7 @@ static struct {
0,
BUFFER_SIZE,
0,
{}
};
static const char *LEVEL_NAMES[] = {

@ -856,7 +856,7 @@ struct Result {
>::type
unwrap() const {
if (isOk()) {
return storage().template get<U>();
return std::move(storage().template get<U>());
}
::fprintf(stderr, "Attempting to unwrap an error Result\n");

@ -33,7 +33,6 @@
#include "base/string_util.hh"
#include "yajlpp/json_ptr.hh"
#include "pcrecpp.h"
#include "lnav.hh"
#include "log_format_loader.hh"
#include "shlex.hh"

@ -1,5 +1,5 @@
/* Generated by re2c 2.0.3 on Thu Sep 10 10:03:52 2020 */
#line 1 "../../lnav2/src/data_scanner_re.re"
/* Generated by re2c 2.0.3 on Wed Jan 27 16:33:33 2021 */
#line 1 "../../lnav/src/data_scanner_re.re"
/**
* Copyright (c) 2015, Timothy Stack
*
@ -105,7 +105,7 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
cap[1].c_begin = pi.pi_next_offset;
#line 109 "../../lnav2/src/data_scanner_re.cc"
#line 109 "../../lnav/src/data_scanner_re.cc"
{
YYCTYPE yych;
unsigned int yyaccept = 0;
@ -360,9 +360,9 @@ yy2:
}
yy3:
++YYCURSOR;
#line 132 "../../lnav2/src/data_scanner_re.re"
#line 132 "../../lnav/src/data_scanner_re.re"
{ return false; }
#line 366 "../../lnav2/src/data_scanner_re.cc"
#line 366 "../../lnav/src/data_scanner_re.cc"
yy5:
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
@ -520,11 +520,11 @@ yy6:
default: goto yy7;
}
yy7:
#line 226 "../../lnav2/src/data_scanner_re.re"
#line 226 "../../lnav/src/data_scanner_re.re"
{
RET(DT_SYMBOL);
}
#line 528 "../../lnav2/src/data_scanner_re.cc"
#line 528 "../../lnav/src/data_scanner_re.cc"
yy8:
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
@ -543,14 +543,14 @@ yy8:
default: goto yy74;
}
yy9:
#line 231 "../../lnav2/src/data_scanner_re.re"
#line 231 "../../lnav/src/data_scanner_re.re"
{ RET(DT_WHITE); }
#line 549 "../../lnav2/src/data_scanner_re.cc"
#line 549 "../../lnav/src/data_scanner_re.cc"
yy10:
++YYCURSOR;
#line 230 "../../lnav2/src/data_scanner_re.re"
#line 230 "../../lnav/src/data_scanner_re.re"
{ RET(DT_LINE); }
#line 554 "../../lnav2/src/data_scanner_re.cc"
#line 554 "../../lnav/src/data_scanner_re.cc"
yy12:
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
@ -572,9 +572,9 @@ yy12:
yy13:
++YYCURSOR;
yy14:
#line 233 "../../lnav2/src/data_scanner_re.re"
#line 233 "../../lnav/src/data_scanner_re.re"
{ RET(DT_GARBAGE); }
#line 578 "../../lnav2/src/data_scanner_re.cc"
#line 578 "../../lnav/src/data_scanner_re.cc"
yy15:
yyaccept = 2;
yych = *(YYMARKER = ++YYCURSOR);
@ -1024,19 +1024,19 @@ yy18:
default: goto yy19;
}
yy19:
#line 198 "../../lnav2/src/data_scanner_re.re"
#line 198 "../../lnav/src/data_scanner_re.re"
{ RET(DT_LPAREN); }
#line 1030 "../../lnav2/src/data_scanner_re.cc"
#line 1030 "../../lnav/src/data_scanner_re.cc"
yy20:
++YYCURSOR;
#line 199 "../../lnav2/src/data_scanner_re.re"
#line 199 "../../lnav/src/data_scanner_re.re"
{ RET(DT_RPAREN); }
#line 1035 "../../lnav2/src/data_scanner_re.cc"
#line 1035 "../../lnav/src/data_scanner_re.cc"
yy22:
++YYCURSOR;
#line 191 "../../lnav2/src/data_scanner_re.re"
#line 191 "../../lnav/src/data_scanner_re.re"
{ RET(DT_COMMA); }
#line 1040 "../../lnav2/src/data_scanner_re.cc"
#line 1040 "../../lnav/src/data_scanner_re.cc"
yy24:
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
@ -1351,9 +1351,9 @@ yy26:
default: goto yy28;
}
yy28:
#line 162 "../../lnav2/src/data_scanner_re.re"
#line 162 "../../lnav/src/data_scanner_re.re"
{ RET(DT_PATH); }
#line 1357 "../../lnav2/src/data_scanner_re.cc"
#line 1357 "../../lnav/src/data_scanner_re.cc"
yy29:
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
@ -1513,9 +1513,9 @@ yy29:
default: goto yy30;
}
yy30:
#line 217 "../../lnav2/src/data_scanner_re.re"
#line 217 "../../lnav/src/data_scanner_re.re"
{ RET(DT_NUMBER); }
#line 1519 "../../lnav2/src/data_scanner_re.cc"
#line 1519 "../../lnav/src/data_scanner_re.cc"
yy31:
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
@ -1998,14 +1998,14 @@ yy34:
default: goto yy35;
}
yy35:
#line 189 "../../lnav2/src/data_scanner_re.re"
#line 189 "../../lnav/src/data_scanner_re.re"
{ RET(DT_COLON); }
#line 2004 "../../lnav2/src/data_scanner_re.cc"
#line 2004 "../../lnav/src/data_scanner_re.cc"
yy36:
++YYCURSOR;
#line 192 "../../lnav2/src/data_scanner_re.re"
#line 192 "../../lnav/src/data_scanner_re.re"
{ RET(DT_SEMI); }
#line 2009 "../../lnav2/src/data_scanner_re.cc"
#line 2009 "../../lnav/src/data_scanner_re.cc"
yy38:
yyaccept = 6;
yych = *(YYMARKER = ++YYCURSOR);
@ -2080,19 +2080,19 @@ yy38:
default: goto yy39;
}
yy39:
#line 200 "../../lnav2/src/data_scanner_re.re"
#line 200 "../../lnav/src/data_scanner_re.re"
{ RET(DT_LANGLE); }
#line 2086 "../../lnav2/src/data_scanner_re.cc"
#line 2086 "../../lnav/src/data_scanner_re.cc"
yy40:
++YYCURSOR;
#line 190 "../../lnav2/src/data_scanner_re.re"
#line 190 "../../lnav/src/data_scanner_re.re"
{ RET(DT_EQUALS); }
#line 2091 "../../lnav2/src/data_scanner_re.cc"
#line 2091 "../../lnav/src/data_scanner_re.cc"
yy42:
++YYCURSOR;
#line 201 "../../lnav2/src/data_scanner_re.re"
#line 201 "../../lnav/src/data_scanner_re.re"
{ RET(DT_RANGLE); }
#line 2096 "../../lnav2/src/data_scanner_re.cc"
#line 2096 "../../lnav/src/data_scanner_re.cc"
yy44:
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
@ -2556,9 +2556,9 @@ yy50:
default: goto yy51;
}
yy51:
#line 196 "../../lnav2/src/data_scanner_re.re"
#line 196 "../../lnav/src/data_scanner_re.re"
{ RET(DT_LSQUARE); }
#line 2562 "../../lnav2/src/data_scanner_re.cc"
#line 2562 "../../lnav/src/data_scanner_re.cc"
yy52:
yych = *++YYCURSOR;
switch (yych) {
@ -2567,9 +2567,9 @@ yy52:
}
yy53:
++YYCURSOR;
#line 197 "../../lnav2/src/data_scanner_re.re"
#line 197 "../../lnav/src/data_scanner_re.re"
{ RET(DT_RSQUARE); }
#line 2573 "../../lnav2/src/data_scanner_re.cc"
#line 2573 "../../lnav/src/data_scanner_re.cc"
yy55:
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
@ -3116,14 +3116,14 @@ yy62:
default: goto yy63;
}
yy63:
#line 194 "../../lnav2/src/data_scanner_re.re"
#line 194 "../../lnav/src/data_scanner_re.re"
{ RET(DT_LCURLY); }
#line 3122 "../../lnav2/src/data_scanner_re.cc"
#line 3122 "../../lnav/src/data_scanner_re.cc"
yy64:
++YYCURSOR;
#line 195 "../../lnav2/src/data_scanner_re.re"
#line 195 "../../lnav/src/data_scanner_re.re"
{ RET(DT_RCURLY); }
#line 3127 "../../lnav2/src/data_scanner_re.cc"
#line 3127 "../../lnav/src/data_scanner_re.cc"
yy66:
yych = *++YYCURSOR;
switch (yych) {
@ -3670,7 +3670,7 @@ yy79:
default: goto yy80;
}
yy80:
#line 134 "../../lnav2/src/data_scanner_re.re"
#line 134 "../../lnav/src/data_scanner_re.re"
{
CAPTURE(DT_QUOTED_STRING);
switch (pi.get_string()[cap[1].c_begin]) {
@ -3683,7 +3683,7 @@ yy80:
cap[1].c_end -= 1;
return true;
}
#line 3687 "../../lnav2/src/data_scanner_re.cc"
#line 3687 "../../lnav/src/data_scanner_re.cc"
yy81:
yych = *++YYCURSOR;
switch (yych) {
@ -5152,9 +5152,9 @@ yy102:
}
yy103:
++YYCURSOR;
#line 193 "../../lnav2/src/data_scanner_re.re"
#line 193 "../../lnav/src/data_scanner_re.re"
{ RET(DT_EMPTY_CONTAINER); }
#line 5158 "../../lnav2/src/data_scanner_re.cc"
#line 5158 "../../lnav/src/data_scanner_re.cc"
yy105:
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
@ -5780,9 +5780,9 @@ yy114:
default: goto yy115;
}
yy115:
#line 216 "../../lnav2/src/data_scanner_re.re"
#line 216 "../../lnav/src/data_scanner_re.re"
{ RET(DT_PERCENTAGE); }
#line 5786 "../../lnav2/src/data_scanner_re.cc"
#line 5786 "../../lnav/src/data_scanner_re.cc"
yy116:
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
@ -6016,9 +6016,9 @@ yy117:
default: goto yy118;
}
yy118:
#line 215 "../../lnav2/src/data_scanner_re.re"
#line 215 "../../lnav/src/data_scanner_re.re"
{ RET(DT_OCTAL_NUMBER); }
#line 6022 "../../lnav2/src/data_scanner_re.cc"
#line 6022 "../../lnav/src/data_scanner_re.cc"
yy119:
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
@ -6364,9 +6364,9 @@ yy121:
default: goto yy122;
}
yy122:
#line 218 "../../lnav2/src/data_scanner_re.re"
#line 218 "../../lnav/src/data_scanner_re.re"
{ RET(DT_HEX_NUMBER); }
#line 6370 "../../lnav2/src/data_scanner_re.cc"
#line 6370 "../../lnav/src/data_scanner_re.cc"
yy123:
yyaccept = 10;
yych = *(YYMARKER = ++YYCURSOR);
@ -7489,11 +7489,11 @@ yy133:
default: goto yy134;
}
yy134:
#line 146 "../../lnav2/src/data_scanner_re.re"
#line 146 "../../lnav/src/data_scanner_re.re"
{
CAPTURE(DT_WORD);
}
#line 7497 "../../lnav2/src/data_scanner_re.cc"
#line 7497 "../../lnav/src/data_scanner_re.cc"
yy135:
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
@ -9296,7 +9296,7 @@ yy160:
yyt1 = yyt2;
yy161:
YYCURSOR = yyt1;
#line 149 "../../lnav2/src/data_scanner_re.re"
#line 149 "../../lnav/src/data_scanner_re.re"
{
CAPTURE(DT_QUOTED_STRING);
switch (pi.get_string()[cap[1].c_begin]) {
@ -9309,7 +9309,7 @@ yy161:
cap[1].c_end -= 1;
return true;
}
#line 9313 "../../lnav2/src/data_scanner_re.cc"
#line 9313 "../../lnav/src/data_scanner_re.cc"
yy162:
yyaccept = 12;
yych = *(YYMARKER = ++YYCURSOR);
@ -12758,9 +12758,9 @@ yy200:
++YYCURSOR;
yy201:
YYCURSOR = yyt2;
#line 175 "../../lnav2/src/data_scanner_re.re"
#line 175 "../../lnav/src/data_scanner_re.re"
{ RET(DT_IPV6_ADDRESS); }
#line 12764 "../../lnav2/src/data_scanner_re.cc"
#line 12764 "../../lnav/src/data_scanner_re.cc"
yy202:
yych = *++YYCURSOR;
switch (yych) {
@ -14038,11 +14038,11 @@ yy217:
yy218:
++YYCURSOR;
yy219:
#line 181 "../../lnav2/src/data_scanner_re.re"
#line 181 "../../lnav/src/data_scanner_re.re"
{
RET(DT_XML_OPEN_TAG);
}
#line 14046 "../../lnav2/src/data_scanner_re.cc"
#line 14046 "../../lnav/src/data_scanner_re.cc"
yy220:
yych = *++YYCURSOR;
switch (yych) {
@ -14191,9 +14191,9 @@ yy223:
yyt3 = yyt4;
yy224:
YYCURSOR = yyt3;
#line 224 "../../lnav2/src/data_scanner_re.re"
#line 224 "../../lnav/src/data_scanner_re.re"
{ RET(DT_WORD); }
#line 14197 "../../lnav2/src/data_scanner_re.cc"
#line 14197 "../../lnav/src/data_scanner_re.cc"
yy225:
yych = *++YYCURSOR;
switch (yych) {
@ -21698,11 +21698,11 @@ yy310:
yy311:
++YYCURSOR;
yy312:
#line 177 "../../lnav2/src/data_scanner_re.re"
#line 177 "../../lnav/src/data_scanner_re.re"
{
RET(DT_XML_EMPTY_TAG);
}
#line 21706 "../../lnav2/src/data_scanner_re.cc"
#line 21706 "../../lnav/src/data_scanner_re.cc"
yy313:
yych = *++YYCURSOR;
switch (yych) {
@ -21714,11 +21714,11 @@ yy313:
}
yy315:
++YYCURSOR;
#line 185 "../../lnav2/src/data_scanner_re.re"
#line 185 "../../lnav/src/data_scanner_re.re"
{
RET(DT_XML_CLOSE_TAG);
}
#line 21722 "../../lnav2/src/data_scanner_re.cc"
#line 21722 "../../lnav/src/data_scanner_re.cc"
yy317:
yych = *++YYCURSOR;
yy318:
@ -22883,9 +22883,9 @@ yy332:
default: goto yy334;
}
yy334:
#line 220 "../../lnav2/src/data_scanner_re.re"
#line 220 "../../lnav/src/data_scanner_re.re"
{ RET(DT_EMAIL); }
#line 22889 "../../lnav2/src/data_scanner_re.cc"
#line 22889 "../../lnav/src/data_scanner_re.cc"
yy335:
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
@ -23273,11 +23273,11 @@ yy338:
default: goto yy340;
}
yy340:
#line 211 "../../lnav2/src/data_scanner_re.re"
#line 211 "../../lnav/src/data_scanner_re.re"
{
RET(DT_VERSION_NUMBER);
}
#line 23281 "../../lnav2/src/data_scanner_re.cc"
#line 23281 "../../lnav/src/data_scanner_re.cc"
yy341:
yyaccept = 18;
yych = *(YYMARKER = ++YYCURSOR);
@ -25711,7 +25711,7 @@ yy362:
default: goto yy363;
}
yy363:
#line 165 "../../lnav2/src/data_scanner_re.re"
#line 165 "../../lnav/src/data_scanner_re.re"
{
if ((YYCURSOR - (const unsigned char *) pi.get_string()) == 17) {
RET(DT_MAC_ADDRESS);
@ -25719,7 +25719,7 @@ yy363:
RET(DT_HEX_DUMP);
}
}
#line 25723 "../../lnav2/src/data_scanner_re.cc"
#line 25723 "../../lnav/src/data_scanner_re.cc"
yy364:
yyaccept = 19;
yych = *(YYMARKER = ++YYCURSOR);
@ -29755,9 +29755,9 @@ yy414:
++YYCURSOR;
yy415:
YYCURSOR = yyt1;
#line 222 "../../lnav2/src/data_scanner_re.re"
#line 222 "../../lnav/src/data_scanner_re.re"
{ RET(DT_CONSTANT); }
#line 29761 "../../lnav2/src/data_scanner_re.cc"
#line 29761 "../../lnav/src/data_scanner_re.cc"
yy416:
yych = *++YYCURSOR;
switch (yych) {
@ -30086,9 +30086,9 @@ yy422:
++YYCURSOR;
yy423:
YYCURSOR = yyt1;
#line 163 "../../lnav2/src/data_scanner_re.re"
#line 163 "../../lnav/src/data_scanner_re.re"
{ RET(DT_TIME); }
#line 30092 "../../lnav2/src/data_scanner_re.cc"
#line 30092 "../../lnav/src/data_scanner_re.cc"
yy424:
yych = *++YYCURSOR;
switch (yych) {
@ -31042,9 +31042,9 @@ yy436:
default: goto yy438;
}
yy438:
#line 209 "../../lnav2/src/data_scanner_re.re"
#line 209 "../../lnav/src/data_scanner_re.re"
{ RET(DT_NUMBER); }
#line 31048 "../../lnav2/src/data_scanner_re.cc"
#line 31048 "../../lnav/src/data_scanner_re.cc"
yy439:
yyaccept = 21;
yych = *(YYMARKER = ++YYCURSOR);
@ -32454,9 +32454,9 @@ yy453:
default: goto yy455;
}
yy455:
#line 161 "../../lnav2/src/data_scanner_re.re"
#line 161 "../../lnav/src/data_scanner_re.re"
{ RET(DT_URL); }
#line 32460 "../../lnav2/src/data_scanner_re.cc"
#line 32460 "../../lnav/src/data_scanner_re.cc"
yy456:
yych = *++YYCURSOR;
switch (yych) {
@ -46940,9 +46940,9 @@ yy625:
yyt1 = yyt2;
yy626:
YYCURSOR = yyt1;
#line 164 "../../lnav2/src/data_scanner_re.re"
#line 164 "../../lnav/src/data_scanner_re.re"
{ RET(DT_TIME); }
#line 46946 "../../lnav2/src/data_scanner_re.cc"
#line 46946 "../../lnav/src/data_scanner_re.cc"
yy627:
yyaccept = 26;
yych = *(YYMARKER = ++YYCURSOR);
@ -47282,11 +47282,11 @@ yy634:
++YYCURSOR;
yy635:
YYCURSOR = yyt1;
#line 203 "../../lnav2/src/data_scanner_re.re"
#line 203 "../../lnav/src/data_scanner_re.re"
{
RET(DT_IPV4_ADDRESS);
}
#line 47290 "../../lnav2/src/data_scanner_re.cc"
#line 47290 "../../lnav/src/data_scanner_re.cc"
yy636:
yyaccept = 27;
yych = *(YYMARKER = ++YYCURSOR);
@ -49067,11 +49067,11 @@ yy652:
default: goto yy653;
}
yy653:
#line 172 "../../lnav2/src/data_scanner_re.re"
#line 172 "../../lnav/src/data_scanner_re.re"
{
RET(DT_DATE);
}
#line 49075 "../../lnav2/src/data_scanner_re.cc"
#line 49075 "../../lnav/src/data_scanner_re.cc"
yy654:
yyaccept = 28;
yych = *(YYMARKER = ++YYCURSOR);
@ -82935,10 +82935,10 @@ yy990:
default: goto yy991;
}
yy991:
#line 207 "../../lnav2/src/data_scanner_re.re"
#line 207 "../../lnav/src/data_scanner_re.re"
{ RET(DT_UUID); }
#line 82941 "../../lnav2/src/data_scanner_re.cc"
#line 82941 "../../lnav/src/data_scanner_re.cc"
}
#line 235 "../../lnav2/src/data_scanner_re.re"
#line 235 "../../lnav/src/data_scanner_re.re"
}

@ -253,7 +253,7 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
}
char old_timestamp[64], curr_timestamp[64], orig_timestamp[64];
struct timeval curr_tv, offset_tv, orig_tv, diff_tv = { 0 };
struct timeval curr_tv, offset_tv, orig_tv, diff_tv = { 0, 0 };
attr_line_t time_line;
string &time_str = time_line.get_string();
struct line_range time_lr;

@ -49,6 +49,10 @@ highlighter::highlighter(const highlighter &other)
highlighter &highlighter::operator=(const highlighter &other)
{
if (this == &other) {
return *this;
}
if (this->h_code != nullptr && pcre_refcount(this->h_code, -1) == 0) {
free(this->h_code);
this->h_code = nullptr;

@ -100,7 +100,6 @@
#include "bottom_status_source.hh"
#include "piper_proc.hh"
#include "log_vtab_impl.hh"
#include "pcrecpp.h"
#include "termios_guard.hh"
#include "xterm_mouse.hh"
#include "lnav_commands.hh"
@ -153,6 +152,7 @@
using namespace std;
using namespace std::literals::chrono_literals;
static bool initial_build = false;
static multimap<lnav_flags_t, string> DEFAULT_FILES;
struct lnav_data_t lnav_data;
@ -420,7 +420,7 @@ private:
for (auto &sc : lnav_data.ld_status) {
sc.do_update();
}
if (lnav_data.ld_mode == LNM_FILES && !lnav_data.ld_session_loaded) {
if (lnav_data.ld_mode == LNM_FILES && !initial_build) {
auto &fc = lnav_data.ld_active_files;
auto iter = std::find(fc.fc_files.begin(),
fc.fc_files.end(), lf);
@ -1401,8 +1401,6 @@ static void looper()
rlc.do_update();
while (lnav_data.ld_looping) {
static bool initial_build = false;
vector<struct pollfd> pollfds;
auto poll_to = initial_rescan_completed ?
timeval{ 0, 333000 } :

@ -34,13 +34,13 @@
#include <fnmatch.h>
#include <termios.h>
#include <regex>
#include <string>
#include <utility>
#include <vector>
#include <fstream>
#include <unordered_map>
#include <pcrecpp.h>
#include <yajl/api/yajl_tree.h>
#include "bound_tags.hh"
@ -499,11 +499,10 @@ static bool csv_needs_quoting(const string &str)
static string csv_quote_string(const string &str)
{
static pcrecpp::RE csv_column_quoter("\"");
static std::regex csv_column_quoter("\"");
string retval = str;
string retval = std::regex_replace(str, csv_column_quoter, "\"\"");
csv_column_quoter.GlobalReplace("\"\"", &retval);
retval.insert(0, 1, '\"');
retval.append(1, '\"');
@ -1684,11 +1683,7 @@ static Result<string, string> com_create_search_table(exec_context &ec, string c
}
else if (args.size() >= 2) {
std::shared_ptr<log_search_table> lst;
auto_mem<pcre> code;
const char *errptr;
string regex;
int eoff;
if (args.size() >= 3) {
regex = remaining_args(cmdline, args, 2);
@ -1697,29 +1692,21 @@ static Result<string, string> com_create_search_table(exec_context &ec, string c
regex = lnav_data.ld_views[LNV_LOG].get_current_search();
}
if ((code = pcre_compile(regex.c_str(),
PCRE_CASELESS,
&errptr,
&eoff,
NULL)) == NULL) {
return ec.make_error("{}", errptr);
}
auto re_res = pcrepp::from_str(regex, log_search_table::pattern_options());
try {
lst = std::make_shared<log_search_table>(
regex.c_str(), intern_string::lookup(args[1]));
} catch (pcrepp::error &e) {
return ec.make_error("unable to compile regex -- {}", regex);
if (re_res.isErr()) {
return ec.make_error("{}", re_res.unwrapErr().ce_msg);
}
auto re = re_res.unwrap();
auto lst = std::make_shared<log_search_table>(
re, intern_string::lookup(args[1]));
if (ec.ec_dry_run) {
textview_curses *tc = &lnav_data.ld_views[LNV_LOG];
auto &hm = tc->get_highlights();
view_colors &vc = view_colors::singleton();
highlighter hl(code.release());
highlighter hl(re.p_code);
hl.with_attrs(
vc.ansi_color_pair(COLOR_BLACK, COLOR_CYAN) | A_BLINK);
hl.with_attrs(view_colors::ansi_color_pair(COLOR_BLACK, COLOR_CYAN) | A_BLINK);
hm[{highlight_source_t::PREVIEW, "preview"}] = hl;
tc->reload_data();
@ -4283,12 +4270,11 @@ static void search_filters_prompt(vector<string> &args)
static void search_files_prompt(vector<string> &args)
{
static pcrecpp::RE re_escape(R"(([.\^$*+?()\[\]{}\\|]))");
static std::regex re_escape(R"(([.\^$*+?()\[\]{}\\|]))");
lnav_data.ld_mode = LNM_SEARCH_FILES;
for (const auto& lf : lnav_data.ld_active_files.fc_files) {
auto path = lf->get_unique_path();
re_escape.GlobalReplace(R"(\\\1)", &path);
auto path = pcrepp::quote(lf->get_unique_path());
lnav_data.ld_rl_view->add_possibility(LNM_SEARCH_FILES,
"*",
path);

@ -40,13 +40,12 @@
#include <unistd.h>
#include <libgen.h>
#include <regex>
#include <chrono>
#include <iostream>
#include <stdexcept>
#include <fmt/format.h>
#include "pcrecpp.h"
#include "auto_fd.hh"
#include "base/injector.hh"
#include "base/injector.bind.hh"
@ -192,14 +191,12 @@ void ensure_dotlnav()
bool install_from_git(const char *repo)
{
static pcrecpp::RE repo_name_converter("[^\\w]");
static std::regex repo_name_converter("[^\\w]");
auto formats_path = dotlnav_path() / "formats";
auto configs_path = dotlnav_path() / "configs";
auto staging_path = dotlnav_path() / "staging";
string local_name = repo;
repo_name_converter.GlobalReplace("_", &local_name);
string local_name = std::regex_replace(repo, repo_name_converter, "_");
auto local_formats_path = formats_path / local_name;
auto local_configs_path = configs_path / local_name;

@ -2000,26 +2000,25 @@ void external_log_format::build(std::vector<std::string> &errors) {
void external_log_format::register_vtabs(log_vtab_manager *vtab_manager,
std::vector<std::string> &errors)
{
vector<pair<intern_string_t, string> >::iterator search_iter;
vector<pair<intern_string_t, string>>::iterator search_iter;
for (search_iter = this->elf_search_tables.begin();
search_iter != this->elf_search_tables.end();
++search_iter) {
std::shared_ptr<log_search_table> lst;
try {
lst = std::make_shared<log_search_table>(
search_iter->second.c_str(), search_iter->first);
} catch (pcrepp::error &e) {
errors.push_back(
"error:" +
this->elf_name.to_string() +
":" +
search_iter->first.to_string() +
":unable to compile regex -- " +
search_iter->second);
auto re_res = pcrepp::from_str(search_iter->second,
log_search_table::pattern_options());
if (re_res.isErr()) {
errors.push_back(fmt::format(
"error:{}:{}:unable to compile regex '{}': {}",
this->elf_name.get(),
search_iter->first.get(),
search_iter->second,
re_res.unwrapErr().ce_msg));
continue;
}
auto lst = std::make_shared<log_search_table>(
re_res.unwrap(), search_iter->first);
string errmsg;
errmsg = vtab_manager->register_vtab(lst);

@ -1,5 +1,5 @@
/* Generated by re2c 2.0.3 on Tue Nov 3 13:27:28 2020 */
#line 1 "../../lnav2/src/log_level_re.re"
/* Generated by re2c 2.0.3 on Wed Jan 27 16:33:33 2021 */
#line 1 "../../lnav/src/log_level_re.re"
/**
* Copyright (c) 2018, Timothy Stack
*
@ -67,7 +67,7 @@ log_level_t string2level(const char *levelstr, ssize_t len, bool exact)
loop:
#line 71 "../../lnav2/src/log_level_re.cc"
#line 71 "../../lnav/src/log_level_re.cc"
{
YYCTYPE yych;
unsigned int yyaccept = 0;
@ -96,15 +96,15 @@ log_level_t string2level(const char *levelstr, ssize_t len, bool exact)
}
yy2:
YYSKIP();
#line 73 "../../lnav2/src/log_level_re.re"
#line 73 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_UNKNOWN); }
#line 102 "../../lnav2/src/log_level_re.cc"
#line 102 "../../lnav/src/log_level_re.cc"
yy4:
YYSKIP();
yy5:
#line 100 "../../lnav2/src/log_level_re.re"
#line 100 "../../lnav/src/log_level_re.re"
{ goto loop; }
#line 108 "../../lnav2/src/log_level_re.cc"
#line 108 "../../lnav/src/log_level_re.cc"
yy6:
yyaccept = 0;
YYSKIP();
@ -314,9 +314,9 @@ yy28:
default: goto yy29;
}
yy29:
#line 96 "../../lnav2/src/log_level_re.re"
#line 96 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_ERROR); }
#line 320 "../../lnav2/src/log_level_re.cc"
#line 320 "../../lnav/src/log_level_re.cc"
yy30:
YYSKIP();
yych = YYPEEK();
@ -407,9 +407,9 @@ yy40:
}
yy41:
YYSKIP();
#line 92 "../../lnav2/src/log_level_re.re"
#line 92 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_INFO); }
#line 413 "../../lnav2/src/log_level_re.cc"
#line 413 "../../lnav/src/log_level_re.cc"
yy43:
YYSKIP();
yych = YYPEEK();
@ -453,9 +453,9 @@ yy47:
default: goto yy48;
}
yy48:
#line 95 "../../lnav2/src/log_level_re.re"
#line 95 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_WARNING); }
#line 459 "../../lnav2/src/log_level_re.cc"
#line 459 "../../lnav/src/log_level_re.cc"
yy49:
YYSKIP();
yych = YYPEEK();
@ -476,7 +476,7 @@ yy50:
}
yy51:
YYSTAGP(debug_level);
#line 75 "../../lnav2/src/log_level_re.re"
#line 75 "../../lnav/src/log_level_re.re"
{
if (debug_level == nullptr) {
RET(LEVEL_DEBUG);
@ -494,15 +494,15 @@ yy51:
RET(LEVEL_DEBUG);
}
}
#line 498 "../../lnav2/src/log_level_re.cc"
#line 498 "../../lnav/src/log_level_re.cc"
yy52:
YYSKIP();
goto yy29;
yy53:
YYSKIP();
#line 99 "../../lnav2/src/log_level_re.re"
#line 99 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_FATAL); }
#line 506 "../../lnav2/src/log_level_re.cc"
#line 506 "../../lnav/src/log_level_re.cc"
yy55:
YYSKIP();
yych = YYPEEK();
@ -521,14 +521,14 @@ yy56:
}
yy57:
YYSKIP();
#line 94 "../../lnav2/src/log_level_re.re"
#line 94 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_STATS); }
#line 527 "../../lnav2/src/log_level_re.cc"
#line 527 "../../lnav/src/log_level_re.cc"
yy59:
YYSKIP();
#line 74 "../../lnav2/src/log_level_re.re"
#line 74 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_TRACE); }
#line 532 "../../lnav2/src/log_level_re.cc"
#line 532 "../../lnav/src/log_level_re.cc"
yy61:
YYSKIP();
yych = YYPEEK();
@ -550,14 +550,14 @@ yy63:
goto yy51;
yy64:
YYSKIP();
#line 93 "../../lnav2/src/log_level_re.re"
#line 93 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_NOTICE); }
#line 556 "../../lnav2/src/log_level_re.cc"
#line 556 "../../lnav/src/log_level_re.cc"
yy66:
YYSKIP();
#line 98 "../../lnav2/src/log_level_re.re"
#line 98 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_CRITICAL); }
#line 561 "../../lnav2/src/log_level_re.cc"
#line 561 "../../lnav/src/log_level_re.cc"
yy68:
YYSKIP();
yych = YYPEEK();
@ -579,10 +579,10 @@ yy70:
goto yy48;
yy71:
YYSKIP();
#line 97 "../../lnav2/src/log_level_re.re"
#line 97 "../../lnav/src/log_level_re.re"
{ RET(LEVEL_CRITICAL); }
#line 585 "../../lnav2/src/log_level_re.cc"
#line 585 "../../lnav/src/log_level_re.cc"
}
#line 102 "../../lnav2/src/log_level_re.re"
#line 102 "../../lnav/src/log_level_re.re"
}

@ -39,11 +39,10 @@ static auto instance_meta = logline_value_meta(
instance_name, value_kind_t::VALUE_INTEGER, 0);
static auto empty = intern_string::lookup("", 0);
log_search_table::log_search_table(const char *regex,
log_search_table::log_search_table(pcrepp pattern,
intern_string_t table_name)
: log_vtab_impl(table_name),
lst_regex_string(regex),
lst_regex(regex, PCRE_CASELESS),
lst_regex(std::move(pattern)),
lst_instance(-1)
{
this->vi_supports_indexes = false;
@ -64,8 +63,8 @@ void log_search_table::get_columns_int(std::vector<vtab_column> &cols)
if (this->lst_regex.captures().size() ==
(size_t) this->lst_regex.get_capture_count()) {
auto iter = this->lst_regex.cap_begin() + lpc;
auto cap_re = this->lst_regex_string.substr(iter->c_begin,
iter->length());
auto cap_re = this->lst_regex.get_pattern()
.substr(iter->c_begin, iter->length());
sqlite_type = guess_type_from_pcre(cap_re, collator);
switch (sqlite_type) {
case SQLITE_FLOAT:

@ -35,13 +35,17 @@
#include <string>
#include <vector>
#include "pcrepp/pcrepp.hh"
#include "shared_buffer.hh"
#include "log_vtab_impl.hh"
class log_search_table : public log_vtab_impl {
public:
static int pattern_options() {
return PCRE_CASELESS;
}
log_search_table(const char *regex, intern_string_t table_name);
log_search_table(pcrepp pattern, intern_string_t table_name);
void get_columns_int(std::vector<vtab_column> &cols);
@ -58,7 +62,6 @@ public:
shared_buffer_ref &line,
std::vector<logline_value> &values) override;
std::string lst_regex_string;
pcrepp lst_regex;
shared_buffer_ref lst_current_line;
pcre_context_static<128> lst_match_context;

@ -31,8 +31,6 @@
#include "config.h"
#include <pcrecpp.h>
#include "pcrepp.hh"
using namespace std;
@ -42,7 +40,7 @@ const int JIT_STACK_MAX_SIZE = 512 * 1024;
pcre_context::capture_t *pcre_context::operator[](const char *name) const
{
capture_t *retval = NULL;
capture_t *retval = nullptr;
int index;
index = this->pc_pcre->name_index(name);
@ -53,23 +51,61 @@ pcre_context::capture_t *pcre_context::operator[](const char *name) const
return retval;
}
std::string pcrepp::quote(const char *unquoted)
{
std::string retval;
for (int lpc = 0; unquoted[lpc]; lpc++) {
if (isalnum(unquoted[lpc]) ||
unquoted[lpc] == '_' ||
unquoted[lpc] & 0x80) {
retval.push_back(unquoted[lpc]);
} else {
retval.push_back('\\');
retval.push_back(unquoted[lpc]);
}
}
return retval;
}
Result<pcrepp, pcrepp::compile_error> pcrepp::from_str(std::string pattern, int options)
{
const char *errptr;
int eoff;
auto code = pcre_compile(pattern.c_str(),
options | PCRE_UTF8,
&errptr,
&eoff,
nullptr);
if (!code) {
return Err(compile_error{errptr, eoff});
}
return Ok(pcrepp(std::move(pattern), code));
}
void pcrepp::find_captures(const char *pattern)
{
bool in_class = false, in_escape = false, in_literal = false;
vector<pcre_context::capture> cap_in_progress;
for (int lpc = 0; pattern[lpc]; lpc++) {
if (in_class) {
if (pattern[lpc] == ']') {
in_class = false;
}
}
else if (in_escape) {
if (in_escape) {
in_escape = false;
if (pattern[lpc] == 'Q') {
in_literal = true;
}
}
else if (in_class) {
if (pattern[lpc] == ']') {
in_class = false;
}
if (pattern[lpc] == '\\') {
in_escape = true;
}
}
else if (in_literal) {
if (pattern[lpc] == '\\' && pattern[lpc + 1] == 'E') {
in_literal = false;
@ -104,7 +140,11 @@ void pcrepp::find_captures(const char *pattern)
third = pattern[cap.c_begin + 3];
}
if (first == '?') {
if (second == '<' || second == '\'') {
if (second == '\'') {
is_cap = true;
}
if (second == '<' &&
(isalpha(third) || third == '_')) {
is_cap = true;
}
if (second == 'P' && third == '<') {
@ -124,6 +164,8 @@ void pcrepp::find_captures(const char *pattern)
}
}
}
ensure(this->p_capture_count == this->p_captures.size());
}
bool pcrepp::match(pcre_context &pc, pcre_input &pi, int options) const
@ -175,6 +217,9 @@ bool pcrepp::match(pcre_context &pc, pcre_input &pi, int options) const
}
else if (pc.all()->c_begin == pc.all()->c_end) {
rc = 0;
if (pi.pi_next_offset + 1 < pi.pi_length) {
pi.pi_next_offset += 1;
}
}
else {
if (options & PCRE_ANCHORED) {
@ -194,6 +239,62 @@ bool pcrepp::match(pcre_context &pc, pcre_input &pi, int options) const
return rc > 0;
}
std::string pcrepp::replace(const char *str, const char *repl) const
{
pcre_context_static<30> pc;
pcre_input pi(str);
std::string retval;
std::string::size_type start = 0;
while (pi.pi_offset < pi.pi_length) {
this->match(pc, pi);
auto all = pc.all();
bool in_escape = false;
if (pc.get_count() < 0) {
break;
}
retval.append(str, start, (all->c_begin - start));
start = all->c_end;
for (int lpc = 0; repl[lpc]; lpc++) {
auto ch = repl[lpc];
if (in_escape) {
if (isdigit(ch)) {
auto capture_index = (ch - '0');
if (capture_index < pc.get_count()) {
retval.append(pi.get_substr_start(&all[capture_index]),
pi.get_substr_len(&all[capture_index]));
} else if (capture_index > this->p_capture_count) {
retval.push_back('\\');
retval.push_back(ch);
}
} else {
if (ch != '\\') {
retval.push_back('\\');
}
retval.push_back(ch);
}
in_escape = false;
} else {
switch (ch) {
case '\\':
in_escape = true;
break;
default:
retval.push_back(ch);
break;
}
}
}
}
retval.append(str, start, std::string::npos);
return retval;
}
void pcrepp::study()
{
const char *errptr;
@ -208,7 +309,7 @@ void pcrepp::study()
if (!this->p_code_extra && errptr) {
log_error("pcre_study error: %s", errptr);
}
if (this->p_code_extra != NULL) {
if (this->p_code_extra != nullptr) {
pcre_extra *extra = this->p_code_extra;
extra->flags |= (PCRE_EXTRA_MATCH_LIMIT |
@ -216,9 +317,13 @@ void pcrepp::study()
extra->match_limit = 10000;
extra->match_limit_recursion = 500;
#ifdef PCRE_STUDY_JIT_COMPILE
// pcre_assign_jit_stack(extra, NULL, jit_stack());
// pcre_assign_jit_stack(extra, nullptr, jit_stack());
#endif
}
pcre_fullinfo(this->p_code,
this->p_code_extra,
PCRE_INFO_OPTIONS,
&this->p_options);
pcre_fullinfo(this->p_code,
this->p_code_extra,
PCRE_INFO_CAPTURECOUNT,
@ -240,9 +345,9 @@ void pcrepp::study()
#ifdef PCRE_STUDY_JIT_COMPILE
pcre_jit_stack *pcrepp::jit_stack()
{
static pcre_jit_stack *retval = NULL;
static pcre_jit_stack *retval = nullptr;
if (retval == NULL) {
if (retval == nullptr) {
retval = pcre_jit_stack_alloc(JIT_STACK_MIN_SIZE, JIT_STACK_MAX_SIZE);
}

@ -58,6 +58,7 @@
#include "base/lnav_log.hh"
#include "auto_mem.hh"
#include "base/intern_string.hh"
#include "base/result.h"
#include <stdio.h>
@ -96,6 +97,8 @@ public:
bool is_valid() const { return this->c_begin != -1; };
int length() const { return this->c_end - this->c_begin; };
bool empty() const { return this->c_begin == this->c_end; };
} capture_t;
typedef capture_t *iterator;
typedef const capture_t *const_iterator;
@ -252,7 +255,7 @@ public:
iter->length());
};
const intern_string_t get_substr_i(pcre_context::const_iterator iter) const {
intern_string_t get_substr_i(pcre_context::const_iterator iter) const {
return intern_string::lookup(&this->pi_string[iter->c_begin], iter->length());
};
@ -364,12 +367,35 @@ public:
int e_offset;
};
static std::string quote(const char *unquoted);
static std::string quote(const std::string& unquoted) {
return quote(unquoted.c_str());
}
struct compile_error {
const char *ce_msg;
int ce_offset;
};
static Result<pcrepp, compile_error> from_str(std::string pattern, int options = 0);
pcrepp(pcre *code) : p_code(code), p_code_extra(pcre_free_study)
{
pcre_refcount(this->p_code, 1);
this->study();
};
pcrepp(std::string pattern, pcre *code)
: p_code(code),
p_pattern(std::move(pattern)),
p_code_extra(pcre_free_study)
{
pcre_refcount(this->p_code, 1);
this->study();
this->find_captures(this->p_pattern.c_str());
};
explicit pcrepp(const char *pattern, int options = 0)
: p_pattern(pattern), p_code_extra(pcre_free_study)
{
@ -408,22 +434,79 @@ public:
this->find_captures(pattern.c_str());
};
pcrepp() {
}
pcrepp(const pcrepp &other)
: p_code(other.p_code),
p_pattern(other.p_pattern),
p_code_extra(pcre_free_study)
p_code_extra(pcre_free_study),
p_captures(other.p_captures)
{
pcre_refcount(this->p_code, 1);
this->study();
};
pcrepp(pcrepp &&other)
: p_code(other.p_code),
p_pattern(std::move(other.p_pattern)),
p_code_extra(pcre_free_study),
p_capture_count(other.p_capture_count),
p_named_count(other.p_named_count),
p_name_len(other.p_name_len),
p_options(other.p_options),
p_named_entries(other.p_named_entries),
p_captures(std::move(other.p_captures)) {
pcre_refcount(this->p_code, 1);
this->p_code_extra = std::move(other.p_code_extra);
}
virtual ~pcrepp()
{
if (pcre_refcount(this->p_code, -1) == 0) {
this->clear();
};
pcrepp& operator=(pcrepp&& other) noexcept {
if (this == &other) {
return *this;
}
this->p_code = other.p_code;
pcre_refcount(this->p_code, 1);
this->p_pattern = std::move(other.p_pattern);
this->p_code_extra = std::move(other.p_code_extra);
this->p_capture_count = other.p_capture_count;
this->p_named_count = other.p_named_count;
this->p_name_len = other.p_name_len;
this->p_options = other.p_options;
this->p_named_entries = other.p_named_entries;
this->p_captures = std::move(other.p_captures);
return *this;
}
const std::string& get_pattern() const {
return this->p_pattern;
}
bool empty() const {
return this->p_pattern.empty();
}
void clear() {
if (this->p_code && pcre_refcount(this->p_code, -1) == 0) {
free(this->p_code);
this->p_code = 0;
this->p_code = nullptr;
}
};
this->p_pattern.clear();
this->p_code_extra.reset();
this->p_capture_count = 0;
this->p_named_count = 0;
this->p_name_len = 0;
this->p_options = 0;
this->p_named_entries = nullptr;
this->p_captures.clear();
}
pcre_named_capture::iterator named_begin() const {
return {this->p_named_entries, static_cast<size_t>(this->p_name_len)};
@ -480,6 +563,8 @@ public:
bool match(pcre_context &pc, pcre_input &pi, int options = 0) const;
std::string replace(const char *str, const char *repl) const;
size_t match_partial(pcre_input &pi) const {
size_t length = pi.pi_length;
int rc;
@ -516,13 +601,14 @@ public:
void find_captures(const char *pattern);
pcre *p_code;
const std::string p_pattern;
pcre *p_code{nullptr};
std::string p_pattern;
auto_mem<pcre_extra> p_code_extra;
int p_capture_count;
int p_named_count;
int p_name_len;
pcre_named_capture *p_named_entries;
int p_capture_count{0};
int p_named_count{0};
int p_name_len{0};
unsigned long p_options{0};
pcre_named_capture *p_named_entries{nullptr};
std::vector<pcre_context::capture> p_captures;
};

@ -39,7 +39,6 @@
#include "command_executor.hh"
#include "readline_curses.hh"
#include "readline_highlighters.hh"
#include "log_search_table.hh"
#include "log_format_loader.hh"
#include "help_text_formatter.hh"
#include "sqlite-extension-func.hh"

@ -29,8 +29,7 @@
#include "config.h"
#include <pcrecpp.h>
#include <regex>
#include <string>
#include "lnav.hh"
@ -125,8 +124,8 @@ struct sqlite_metadata_callbacks lnav_sql_meta_callbacks = {
static void add_text_possibilities(readline_curses *rlc, int context, const string &type, const std::string &str)
{
static pcrecpp::RE re_escape(R"(([.\^$*+?()\[\]{}\\|]))");
static pcrecpp::RE re_escape_no_dot(R"(([\^$*+?()\[\]{}\\|]))");
static std::regex re_escape(R"(([.\^$*+?()\[\]{}\\|]))");
static std::regex re_escape_no_dot(R"(([\^$*+?()\[\]{}\\|]))");
pcre_context_static<30> pc;
data_scanner ds(str);
@ -160,8 +159,8 @@ static void add_text_possibilities(readline_curses *rlc, int context, const stri
token_value_no_dot = token_value =
ds.get_input().get_substr(pc.all());
re_escape.GlobalReplace(R"(\\\1)", &token_value);
re_escape_no_dot.GlobalReplace(R"(\\\1)", &token_value_no_dot);
token_value = std::regex_replace(token_value, re_escape, R"(\\\1)");
token_value_no_dot = std::regex_replace(token_value_no_dot, re_escape_no_dot, R"(\\\1)");
rlc->add_possibility(context, type, token_value);
if (token_value != token_value_no_dot) {
rlc->add_possibility(context, type, token_value_no_dot);
@ -364,7 +363,7 @@ void add_filter_possibilities(textview_curses *tc)
void add_file_possibilities()
{
static pcrecpp::RE sh_escape(R"(([\s\'\"]+))");
static std::regex sh_escape(R"(([\s\'\"]+))");
readline_curses *rc = lnav_data.ld_rl_view;
@ -376,8 +375,7 @@ void add_file_possibilities()
}
lnav_data.ld_log_source.find_data(lf) | [&lf, rc](auto ld) {
auto escaped_fn = lf->get_filename();
sh_escape.GlobalReplace(R"(\\\1)", &escaped_fn);
auto escaped_fn = std::regex_replace(lf->get_filename(), sh_escape, R"(\\\1)");
rc->add_possibility(LNM_COMMAND,
ld->is_visible() ? "visible-files" : "hidden-files",

@ -68,10 +68,9 @@ CREATE TABLE regexp_capture (
struct cursor {
sqlite3_vtab_cursor base;
unique_ptr<pcrepp> c_pattern;
pcrepp c_pattern;
pcre_context_static<30> c_context;
unique_ptr<pcre_input> c_input;
string c_pattern_string;
string c_content;
int c_index;
int c_start_index;
@ -95,12 +94,12 @@ CREATE TABLE regexp_capture (
int next() {
if (this->c_index >= (this->c_context.get_count() - 1)) {
this->c_input->pi_offset = this->c_input->pi_next_offset;
this->c_matched = this->c_pattern->match(this->c_context, *(this->c_input));
this->c_matched = this->c_pattern.match(this->c_context, *(this->c_input));
this->c_index = -1;
this->c_match_index += 1;
}
if (!this->c_pattern || !this->c_matched) {
if (this->c_pattern.empty() || !this->c_matched) {
return SQLITE_OK;
}
@ -110,7 +109,7 @@ CREATE TABLE regexp_capture (
};
int eof() {
return !this->c_pattern || !this->c_matched;
return this->c_pattern.empty() || !this->c_matched;
};
int get_rowid(sqlite3_int64 &rowid_out) {
@ -134,7 +133,7 @@ CREATE TABLE regexp_capture (
if (vc.c_index == 0) {
sqlite3_result_null(ctx);
} else {
sqlite3_result_text(ctx, vc.c_pattern->name_for_capture(
sqlite3_result_text(ctx, vc.c_pattern.name_for_capture(
vc.c_index - 1), -1, SQLITE_TRANSIENT);
}
break;
@ -163,12 +162,13 @@ CREATE TABLE regexp_capture (
vc.c_content.length(),
SQLITE_TRANSIENT);
break;
case RC_COL_PATTERN:
sqlite3_result_text(ctx,
vc.c_pattern_string.c_str(),
vc.c_pattern_string.length(),
case RC_COL_PATTERN: {
auto str = vc.c_pattern.get_pattern();
sqlite3_result_text(ctx, str.c_str(), str.length(),
SQLITE_TRANSIENT);
break;
}
}
return SQLITE_OK;
@ -205,7 +205,7 @@ static int rcFilter(sqlite3_vtab_cursor *pVtabCursor,
if (argc != 2) {
pCur->c_content.clear();
pCur->c_pattern.reset();
pCur->c_pattern.clear();
return SQLITE_OK;
}
@ -214,20 +214,20 @@ static int rcFilter(sqlite3_vtab_cursor *pVtabCursor,
pCur->c_content = value;
try {
pCur->c_pattern = make_unique<pcrepp>(pattern);
pCur->c_pattern_string = pattern;
} catch (const pcrepp::error &e) {
auto re_res = pcrepp::from_str(pattern);
if (re_res.isErr()) {
pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
"Invalid regular expression: %s", e.e_msg.c_str());
"Invalid regular expression: %s", re_res.unwrapErr().ce_msg);
return SQLITE_ERROR;
}
pCur->c_pattern = re_res.unwrap();
pCur->c_index = 0;
pCur->c_context.set_count(0);
pCur->c_input = make_unique<pcre_input>(pCur->c_content);
pCur->c_matched = pCur->c_pattern->match(pCur->c_context, *(pCur->c_input));
pCur->c_matched = pCur->c_pattern.match(pCur->c_context, *(pCur->c_input));
return SQLITE_OK;
}

@ -34,8 +34,8 @@
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <pcrecpp.h>
#include <regex>
#include <algorithm>
#include <vector>
@ -471,7 +471,7 @@ void dump_sqlite_schema(sqlite3 *db, std::string &schema_out)
void attach_sqlite_db(sqlite3 *db, const std::string &filename)
{
static pcrecpp::RE db_name_converter("[^\\w]");
static std::regex db_name_converter("[^\\w]");
auto_mem<sqlite3_stmt> stmt(sqlite3_finalize);
@ -503,7 +503,7 @@ void attach_sqlite_db(sqlite3 *db, const std::string &filename)
db_name = filename.substr(base_start + 1);
}
db_name_converter.GlobalReplace("_", &db_name);
db_name = std::regex_replace(db_name, db_name_converter, "_");
if (sqlite3_bind_text(stmt.in(), 2,
db_name.c_str(), db_name.length(),
@ -820,7 +820,7 @@ static struct {
int guess_type_from_pcre(const string &pattern, std::string &collator)
{
try {
pcrepp re(pattern.c_str());
pcrepp re(pattern);
vector<int> matches;
int retval = SQLITE3_TEXT;
int index = 0;

@ -58,7 +58,7 @@ struct sqlite_metadata_callbacks {
sqlite_exec_callback smc_table_info;
sqlite_exec_callback smc_foreign_key_list;
void *smc_userdata{nullptr};
db_table_map_t smc_db_list;
db_table_map_t smc_db_list{};
};
int walk_sqlite_metadata(sqlite3 *db, struct sqlite_metadata_callbacks &smc);

@ -41,12 +41,12 @@
#include "help_text_formatter.hh"
struct FuncDef {
const char *zName;
signed char nArg;
int eTextRep; /* 1: UTF-16. 0: UTF-8 */
uint8_t needCollSeq;
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
help_text fd_help;
const char *zName{nullptr};
signed char nArg{0};
int eTextRep{0}; /* 1: UTF-16. 0: UTF-8 */
uint8_t needCollSeq{0};
void (*xFunc)(sqlite3_context*,int,sqlite3_value **){nullptr};
help_text fd_help{};
FuncDef &with_flags(int flags) {
this->eTextRep = flags;
@ -55,12 +55,12 @@ struct FuncDef {
};
struct FuncDefAgg {
const char *zName;
signed char nArg;
uint8_t needCollSeq;
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
void (*xFinalize)(sqlite3_context*);
help_text fda_help;
const char *zName{nullptr};
signed char nArg{0};
uint8_t needCollSeq{0};
void (*xStep)(sqlite3_context*,int,sqlite3_value**){nullptr};
void (*xFinalize)(sqlite3_context*){nullptr};
help_text fda_help{};
};
typedef int (*sqlite_registration_func_t)(struct FuncDef **basic_funcs,

@ -12,7 +12,6 @@
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include <pcrecpp.h>
#include <unordered_map>
@ -38,7 +37,6 @@ using namespace std;
using namespace mapbox;
typedef struct {
shared_ptr<pcrecpp::RE> re;
shared_ptr<pcrepp> re2;
} cache_entry;
@ -55,13 +53,6 @@ static cache_entry *find_re(const char *re)
cache_entry c;
c.re2 = make_shared<pcrepp>(re_str);
c.re = make_shared<pcrecpp::RE>(re);
if (!c.re->error().empty()) {
auto_mem<char, sqlite3_free> e2;
e2 = sqlite3_mprintf("%s: %s", re, c.re->error().c_str());
throw pcrepp::error(e2.in(), 0);
}
auto pair = wcache->insert(std::make_pair(re_str, c));
iter = pair.first;
@ -73,8 +64,10 @@ static cache_entry *find_re(const char *re)
static bool regexp(const char *re, const char *str)
{
cache_entry *reobj = find_re(re);
pcre_context_static<30> pc;
pcre_input pi(str);
return reobj->re->PartialMatch(str);
return reobj->re2->match(pc, pi);
}
static
@ -193,10 +186,8 @@ static
string regexp_replace(const char *str, const char *re, const char *repl)
{
cache_entry *reobj = find_re(re);
string dest(str);
reobj->re->GlobalReplace(repl, &dest);
return dest;
return reobj->re2->replace(str, repl);
}
static

@ -32,8 +32,6 @@
#include <vector>
#include <algorithm>
#include <pcrecpp.h>
#include "base/time_util.hh"
#include "shlex.hh"
#include "fmt/format.h"
@ -257,10 +255,10 @@ void textview_curses::grep_end_batch(grep_proc<vis_line_t> &gp)
} else {
if (this->tc_follow_func) {
if (this->tc_follow_func()) {
this->tc_follow_deadline = {0};
this->tc_follow_deadline = {0, 0};
}
} else {
this->tc_follow_deadline = {0};
this->tc_follow_deadline = {0, 0};
}
}
}
@ -532,7 +530,7 @@ void textview_curses::execute_search(const std::string &regex_orig)
nullptr)) == nullptr) {
string errmsg = string(errptr);
regex = pcrecpp::RE::QuoteMeta(regex);
regex = pcrepp::quote(regex);
log_info("invalid search regex, using quoted: %s", regex.c_str());
if ((code = pcre_compile(regex.c_str(),

@ -1,8 +1,11 @@
include $(top_srcdir)/aminclude_static.am
TESTS_ENVIRONMENT = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT
LOG_COMPILER = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT
AM_CPPFLAGS = \
$(CODE_COVERAGE_CPPFLAGS) \
-Wall \
$(LIBARCHIVE_CFLAGS) \
-I$(top_srcdir)/src/ \
@ -12,6 +15,10 @@ AM_LDFLAGS = \
$(LIBARCHIVE_LDFLAGS) \
$(STATIC_LDFLAGS)
AM_LIBS = $(CODE_COVERAGE_LIBS)
AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
noinst_LIBRARIES = libyajlpp.a
noinst_HEADERS = \

@ -31,7 +31,8 @@
#include "config.h"
#include <pcrecpp.h>
#include <regex>
#include <utility>
#include "fmt/format.h"
@ -47,7 +48,7 @@ json_path_handler_base::json_path_handler_base(const string &property)
: jph_property(property.back() == '#' ?
property.substr(0, property.size() - 1) :
property),
jph_regex(pcrecpp::RE::QuoteMeta(property), PCRE_ANCHORED),
jph_regex(pcrepp::quote(property), PCRE_ANCHORED),
jph_is_array(property.back() == '#')
{
memset(&this->jph_callbacks, 0, sizeof(this->jph_callbacks));
@ -55,12 +56,9 @@ json_path_handler_base::json_path_handler_base(const string &property)
static std::string scrub_pattern(const std::string &pattern)
{
static pcrecpp::RE CAPTURE(R"(\(\?\<\w+\>)");
std::string retval = pattern;
static std::regex CAPTURE(R"(\(\?\<\w+\>)");
CAPTURE.GlobalReplace("(", &retval);
return retval;
return std::regex_replace(pattern, CAPTURE, "(");
}
json_path_handler_base::json_path_handler_base(const pcrepp &property)
@ -72,9 +70,9 @@ json_path_handler_base::json_path_handler_base(const pcrepp &property)
memset(&this->jph_callbacks, 0, sizeof(this->jph_callbacks));
}
json_path_handler_base::json_path_handler_base(const string &property,
json_path_handler_base::json_path_handler_base(string property,
const pcrepp &property_re)
: jph_property(property),
: jph_property(std::move(property)),
jph_regex(property_re),
jph_is_array(property_re.p_pattern.find('#') != string::npos)
{

@ -136,7 +136,7 @@ struct json_path_handler_base {
explicit json_path_handler_base(const pcrepp& property);
json_path_handler_base(const std::string &property,
json_path_handler_base(std::string property,
const pcrepp& property_re);
bool is_array() const {

@ -1,4 +1,6 @@
include $(top_srcdir)/aminclude_static.am
TESTS_ENVIRONMENT = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT
LOG_COMPILER = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT
@ -6,10 +8,15 @@ RM_V = $(RM_V_@AM_V@)
RM_V_ = $(RM_V_@AM_DEFAULT_V@)
RM_V_0 = @echo " RM " $@;
AM_LIBS = $(CODE_COVERAGE_LIBS)
AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
AM_CPPFLAGS = \
-Wall \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/fmtlib \
$(CODE_COVERAGE_CPPFLAGS) \
$(LIBARCHIVE_CFLAGS) \
$(READLINE_CFLAGS) \
$(SQLITE3_CFLAGS)
@ -83,8 +90,7 @@ LDADD = \
$(SQLITE3_LIBS) \
$(PCRE_LIBS) \
$(READLINE_LIBS) \
$(LIBCURL) \
-lpcrecpp
$(LIBCURL)
test_ansi_scrubber_SOURCES = test_ansi_scrubber.cc

@ -44,6 +44,7 @@ static struct test_data {
{ "no dots in here", "no dots in here", 5 },
};
int main(int argc, char *argv[])
{
for (const auto& td : TEST_DATA) {

@ -29,11 +29,8 @@
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include "auto_mem.hh"
@ -59,7 +56,7 @@ int main(int argc, char *argv[])
md1 = &md1_val;
assert(free_count == 0);
md1 = md2;
md1 = std::move(md2);
assert(free_count == 1);
assert(last_free == &md1_val);
assert(md1 == NULL);

@ -41,7 +41,7 @@ int main(int argc, char *argv[])
{
pcre_context_static<30> context;
int retval = EXIT_SUCCESS;
{
pcrepp nomatch("nothing-to-match");
pcre_input pi("dummy");

@ -77,6 +77,41 @@ Row 0:
Column regexp_replace('test 1 2 3', '\d+', 'N'): test N N N
EOF
run_test ./drive_sql "select regexp_replace('test 1 2 3', '\\s+', '{\\0}') as repl"
check_output "" <<EOF
Row 0:
Column repl: test{ }1{ }2{ }3
EOF
run_test ./drive_sql "select regexp_replace('test 1 2 3', '\\w*', '{\\0}') as repl"
check_output "" <<EOF
Row 0:
Column repl: {test}{} {1}{} {2}{} {3}{}
EOF
run_test ./drive_sql "select regexp_replace('123 abc', '(\w*)', '<\3>') as repl"
check_output "" <<EOF
Row 0:
Column repl: <\3><\3> <\3><\3>
EOF
run_test ./drive_sql "select regexp_replace('123 abc', '(\w*)', '<\\\\>') as repl"
check_output "" <<EOF
Row 0:
Column repl: <\><\> <\><\>
EOF
run_test ./drive_sql "select regexp_replace('abc: def', '(\w*):\s*(.*)', '\1=\2') as repl"
check_output "" <<EOF
Row 0:
Column repl: abc=def
EOF
run_test ./drive_sql "select regexp_match('abc', 'abc')"

Loading…
Cancel
Save