From 67046f993ea2be9e3913f4a6689017e6e77e3d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0abata?= Date: Thu, 15 Oct 2020 18:25:19 +0200 Subject: [PATCH] RHEL 9.0.0 Alpha bootstrap The content of this branch was automatically imported from Fedora ELN with the following as its source: https://src.fedoraproject.org/rpms/lldb#2dde36ca67a5249132a21f77da0b2b0ae26d4b27 --- .gitignore | 53 + 0001-Fix-build-with-gcc-7.patch | 24 + 0001-Fix-test-deps.patch | 35 + ...port-linking-against-clang-cpp-dylib.patch | 321 ++ D15067.id41365.diff | 3810 +++++++++++++++++ hans-gpg-key.asc | 52 + lldb.spec | 372 ++ r303907-libedit.patch | 92 + sources | 2 + tests/python-embedded-interpreter/runtest.sh | 11 + tests/python-embedded-interpreter/test.cpp | 9 + tests/tests.yml | 25 + 12 files changed, 4806 insertions(+) create mode 100644 0001-Fix-build-with-gcc-7.patch create mode 100644 0001-Fix-test-deps.patch create mode 100644 0001-lldb-cmake-Support-linking-against-clang-cpp-dylib.patch create mode 100644 D15067.id41365.diff create mode 100644 hans-gpg-key.asc create mode 100644 lldb.spec create mode 100644 r303907-libedit.patch create mode 100644 sources create mode 100755 tests/python-embedded-interpreter/runtest.sh create mode 100644 tests/python-embedded-interpreter/test.cpp create mode 100644 tests/tests.yml diff --git a/.gitignore b/.gitignore index e69de29..3962f4d 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,53 @@ +/lldb-3.7.1.src.tar.xz +/lldb-3.8.0rc2.src.tar.xz +/lldb-3.8.0rc3.src.tar.xz +/lldb-3.8.0.src.tar.xz +/lldb-3.9.0.src.tar.xz +/lldb-3.9.1.src.tar.xz +/lldb-4.0.0.src.tar.xz +/lldb-4.0.1.src.tar.xz +/lldb-5.0.0.src.tar.xz +/lldb-5.0.1.src.tar.xz +/lldb-6.0.0rc1.src.tar.xz +/lldb-6.0.0rc2.src.tar.xz +/lldb-6.0.0.src.tar.xz +/lldb-6.0.1rc1.src.tar.xz +/lldb-6.0.1.src.tar.xz +/lldb-7.0.0rc1.src.tar.xz +/lldb-7.0.0rc2.src.tar.xz +/lldb-7.0.0rc3.src.tar.xz +/lldb-7.0.0.src.tar.xz +/lldb-7.0.1.src.tar.xz +/lldb-8.0.0rc1.src.tar.xz +/lldb-8.0.0rc2.src.tar.xz +/lldb-8.0.0rc4.src.tar.xz +/lldb-8.0.0.src.tar.xz +/lldb-9.0.0rc3.src.tar.xz +/lldb-9.0.0.src.tar.xz +/lldb-9.0.1.src.tar.xz +/lldb-10.0.0rc1.src.tar.xz +/lldb-10.0.0rc1.src.tar.xz.sig +/lldb-10.0.0rc2.src.tar.xz +/lldb-10.0.0rc2.src.tar.xz.sig +/lldb-10.0.0rc3.src.tar.xz +/lldb-10.0.0rc3.src.tar.xz.sig +/lldb-10.0.0rc4.src.tar.xz +/lldb-10.0.0rc4.src.tar.xz.sig +/lldb-10.0.0rc5.src.tar.xz +/lldb-10.0.0rc5.src.tar.xz.sig +/lldb-10.0.0rc6.src.tar.xz +/lldb-10.0.0rc6.src.tar.xz.sig +/lldb-10.0.0.src.tar.xz +/lldb-10.0.0.src.tar.xz.sig +/lldb-11.0.0rc1.src.tar.xz.sig +/lldb-11.0.0rc1.src.tar.xz +/lldb-11.0.0rc2.src.tar.xz +/lldb-11.0.0rc2.src.tar.xz.sig +/lldb-11.0.0rc3.src.tar.xz +/lldb-11.0.0rc3.src.tar.xz.sig +/lldb-11.0.0rc5.src.tar.xz +/lldb-11.0.0rc5.src.tar.xz.sig +/lldb-11.0.0rc6.src.tar.xz +/lldb-11.0.0rc6.src.tar.xz.sig +/lldb-11.0.0.src.tar.xz +/lldb-11.0.0.src.tar.xz.sig diff --git a/0001-Fix-build-with-gcc-7.patch b/0001-Fix-build-with-gcc-7.patch new file mode 100644 index 0000000..b21fa93 --- /dev/null +++ b/0001-Fix-build-with-gcc-7.patch @@ -0,0 +1,24 @@ +From 7ef45eab67114ce1ed136f0666f34aafd0dab89d Mon Sep 17 00:00:00 2001 +From: Tom Stellard +Date: Tue, 14 Mar 2017 14:54:10 -0400 +Subject: [PATCH] Fix build with gcc 7 + +--- + include/lldb/Utility/TaskPool.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/lldb/Utility/TaskPool.h b/include/lldb/Utility/TaskPool.h +index 3ad9c7c..bcd8186 100644 +--- a/include/lldb/Utility/TaskPool.h ++++ b/include/lldb/Utility/TaskPool.h +@@ -12,6 +12,7 @@ + + #include + #include ++#include + #include + #include + #include +-- +1.8.3.1 + diff --git a/0001-Fix-test-deps.patch b/0001-Fix-test-deps.patch new file mode 100644 index 0000000..684d44c --- /dev/null +++ b/0001-Fix-test-deps.patch @@ -0,0 +1,35 @@ +diff -ru lldb-8.0.0rc1.src.orig/lit/CMakeLists.txt lldb-8.0.0rc1.src/lit/CMakeLists.txt +--- lldb-8.0.0rc1.src.orig/lit/CMakeLists.txt 2019-02-13 13:55:19.983186453 +0000 ++++ lldb-8.0.0rc1.src/lit/CMakeLists.txt 2019-02-13 13:58:01.783865287 +0000 +@@ -19,18 +19,23 @@ + + list(APPEND LLDB_TEST_DEPS + LLDBUnitTests +- dsymutil +- llc + lldb + lldb-test +- llvm-config +- llvm-mc +- llvm-objcopy +- FileCheck +- count +- not + ) + ++if (NOT LLDB_BUILT_STANDALONE) ++ list(APPEND LLDB_TEST_DEPS ++ dsymutil ++ llc ++ llvm-config ++ llvm-mc ++ llvm-objcopy ++ FileCheck ++ count ++ not ++ ) ++endif() ++ + if(TARGET lld) + list(APPEND LLDB_TEST_DEPS lld) + endif() diff --git a/0001-lldb-cmake-Support-linking-against-clang-cpp-dylib.patch b/0001-lldb-cmake-Support-linking-against-clang-cpp-dylib.patch new file mode 100644 index 0000000..31e8548 --- /dev/null +++ b/0001-lldb-cmake-Support-linking-against-clang-cpp-dylib.patch @@ -0,0 +1,321 @@ +From 8f442727f2e8d6d426ae9cef42434ef538d1ed13 Mon Sep 17 00:00:00 2001 +From: Michal Gorny +Date: Fri, 4 Oct 2019 12:03:03 +0000 +Subject: [PATCH] [lldb] [cmake] Support linking against clang-cpp dylib + +Link against clang-cpp dylib rather than split libs when +CLANG_LINK_CLANG_DYLIB is enabled. + +Differential Revision: https://reviews.llvm.org/D68456 + +llvm-svn: 373734 +--- + lldb/cmake/modules/AddLLDB.cmake | 15 +++++++++++++-- + lldb/source/Core/CMakeLists.txt | 4 +++- + .../Plugins/ExpressionParser/Clang/CMakeLists.txt | 19 ++++++++++--------- + lldb/source/Plugins/Language/ObjC/CMakeLists.txt | 3 ++- + .../ObjC/AppleObjCRuntime/CMakeLists.txt | 3 ++- + .../RenderScript/RenderScriptRuntime/CMakeLists.txt | 3 ++- + lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt | 3 ++- + lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt | 5 +++-- + .../Plugins/SymbolFile/NativePDB/CMakeLists.txt | 5 +++-- + lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt | 7 ++++--- + lldb/source/Symbol/CMakeLists.txt | 8 +++++--- + lldb/tools/lldb-instr/CMakeLists.txt | 2 +- + 12 files changed, 50 insertions(+), 27 deletions(-) + +diff --git a/lldb/cmake/modules/AddLLDB.cmake b/lldb/cmake/modules/AddLLDB.cmake +index 4c99278..35a8097 100644 +--- a/lldb/cmake/modules/AddLLDB.cmake ++++ b/lldb/cmake/modules/AddLLDB.cmake +@@ -37,7 +37,7 @@ function(add_lldb_library name) + cmake_parse_arguments(PARAM + "MODULE;SHARED;STATIC;OBJECT;PLUGIN" + "INSTALL_PREFIX;ENTITLEMENTS" +- "EXTRA_CXXFLAGS;DEPENDS;LINK_LIBS;LINK_COMPONENTS" ++ "EXTRA_CXXFLAGS;DEPENDS;LINK_LIBS;LINK_COMPONENTS;CLANG_LIBS" + ${ARGN}) + llvm_process_sources(srcs ${PARAM_UNPARSED_ARGUMENTS}) + list(APPEND LLVM_LINK_COMPONENTS ${PARAM_LINK_COMPONENTS}) +@@ -91,6 +91,12 @@ function(add_lldb_library name) + ${pass_ENTITLEMENTS} + ${pass_NO_INSTALL_RPATH} + ) ++ ++ if(CLANG_LINK_CLANG_DYLIB) ++ target_link_libraries(${name} PRIVATE clang-cpp) ++ else() ++ target_link_libraries(${name} PRIVATE ${PARAM_CLANG_LIBS}) ++ endif() + endif() + + if(PARAM_SHARED) +@@ -132,7 +138,7 @@ function(add_lldb_executable name) + cmake_parse_arguments(ARG + "GENERATE_INSTALL" + "INSTALL_PREFIX;ENTITLEMENTS" +- "LINK_LIBS;LINK_COMPONENTS" ++ "LINK_LIBS;CLANG_LIBS;LINK_COMPONENTS" + ${ARGN} + ) + +@@ -152,6 +158,11 @@ function(add_lldb_executable name) + ) + + target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS}) ++ if(CLANG_LINK_CLANG_DYLIB) ++ target_link_libraries(${name} PRIVATE clang-cpp) ++ else() ++ target_link_libraries(${name} PRIVATE ${ARG_CLANG_LIBS}) ++ endif() + set_target_properties(${name} PROPERTIES FOLDER "lldb executables") + + if(ARG_GENERATE_INSTALL) +diff --git a/lldb/source/Core/CMakeLists.txt b/lldb/source/Core/CMakeLists.txt +index 7ca37f9..2e05fa3 100644 +--- a/lldb/source/Core/CMakeLists.txt ++++ b/lldb/source/Core/CMakeLists.txt +@@ -58,7 +58,6 @@ add_lldb_library(lldbCore + ValueObjectVariable.cpp + + LINK_LIBS +- clangAST + lldbBreakpoint + lldbDataFormatters + lldbExpression +@@ -71,6 +70,9 @@ add_lldb_library(lldbCore + lldbPluginObjCLanguage + ${LLDB_CURSES_LIBS} + ++ CLANG_LIBS ++ clangDriver ++ + LINK_COMPONENTS + Support + Demangle +diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt b/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt +index 950dae6..3fc1e0d 100644 +--- a/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt ++++ b/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt +@@ -25,6 +25,16 @@ add_lldb_library(lldbPluginExpressionParserClang PLUGIN + ${tablegen_deps} + + LINK_LIBS ++ lldbCore ++ lldbExpression ++ lldbHost ++ lldbInterpreter ++ lldbSymbol ++ lldbTarget ++ lldbUtility ++ lldbPluginCPlusPlusLanguage ++ lldbPluginCPPRuntime ++ CLANG_LIBS + clangAST + clangCodeGen + clangDriver +@@ -36,15 +46,6 @@ add_lldb_library(lldbPluginExpressionParserClang PLUGIN + clangRewriteFrontend + clangSema + clangSerialization +- lldbCore +- lldbExpression +- lldbHost +- lldbInterpreter +- lldbSymbol +- lldbTarget +- lldbUtility +- lldbPluginCPlusPlusLanguage +- lldbPluginCPPRuntime + LINK_COMPONENTS + Core + ExecutionEngine +diff --git a/lldb/source/Plugins/Language/ObjC/CMakeLists.txt b/lldb/source/Plugins/Language/ObjC/CMakeLists.txt +index afb68d4..ebb96c2 100644 +--- a/lldb/source/Plugins/Language/ObjC/CMakeLists.txt ++++ b/lldb/source/Plugins/Language/ObjC/CMakeLists.txt +@@ -22,7 +22,6 @@ add_lldb_library(lldbPluginObjCLanguage PLUGIN + NSString.cpp + + LINK_LIBS +- clangAST + lldbCore + lldbDataFormatters + lldbExpression +@@ -32,6 +31,8 @@ add_lldb_library(lldbPluginObjCLanguage PLUGIN + lldbUtility + lldbPluginAppleObjCRuntime + lldbPluginClangCommon ++ CLANG_LIBS ++ clangAST + + EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} + ) +diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt +index 29d9ba1..bcf3240 100644 +--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt ++++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt +@@ -9,7 +9,6 @@ add_lldb_library(lldbPluginAppleObjCRuntime PLUGIN + AppleObjCTypeEncodingParser.cpp + + LINK_LIBS +- clangAST + lldbBreakpoint + lldbCore + lldbExpression +@@ -20,6 +19,8 @@ add_lldb_library(lldbPluginAppleObjCRuntime PLUGIN + lldbUtility + lldbPluginExpressionParserClang + lldbPluginCPPRuntime ++ CLANG_LIBS ++ clangAST + LINK_COMPONENTS + Support + ) +diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt +index 1a6c499..c122e09 100644 +--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt ++++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt +@@ -13,7 +13,6 @@ add_lldb_library(lldbPluginRenderScriptRuntime PLUGIN + ${tablegen_deps} + + LINK_LIBS +- clangBasic + lldbBreakpoint + lldbCore + lldbDataFormatters +@@ -22,6 +21,8 @@ add_lldb_library(lldbPluginRenderScriptRuntime PLUGIN + lldbInterpreter + lldbSymbol + lldbTarget ++ CLANG_LIBS ++ clangBasic + LINK_COMPONENTS + Core + IRReader +diff --git a/lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt b/lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt +index 6f0d952..dc04693 100644 +--- a/lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt ++++ b/lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt +@@ -31,7 +31,6 @@ add_lldb_library(lldbPluginPlatformMacOSX PLUGIN + ${PLUGIN_PLATFORM_MACOSX_SOURCES} + + LINK_LIBS +- clangBasic + lldbBreakpoint + lldbCore + lldbHost +@@ -41,6 +40,8 @@ add_lldb_library(lldbPluginPlatformMacOSX PLUGIN + lldbUtility + lldbPluginPlatformPOSIX + ${OBJC_LIBS} ++ CLANG_LIBS ++ clangBasic + LINK_COMPONENTS + Support + ) +diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +index cd588cb..69d2d21 100644 +--- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt ++++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +@@ -36,8 +36,6 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN + UniqueDWARFASTType.cpp + + LINK_LIBS +- clangAST +- clangBasic + lldbCore + lldbExpression + lldbHost +@@ -48,6 +46,9 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN + lldbPluginObjCLanguage + lldbPluginCPlusPlusLanguage + lldbPluginExpressionParserClang ++ CLANG_LIBS ++ clangAST ++ clangBasic + LINK_COMPONENTS + DebugInfoDWARF + Support +diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt +index 52b431d..aaecec4 100644 +--- a/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt ++++ b/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt +@@ -11,11 +11,12 @@ add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN + UdtRecordCompleter.cpp + + LINK_LIBS +- clangAST +- clangLex + lldbCore + lldbSymbol + lldbUtility ++ CLANG_LIBS ++ clangAST ++ clangLex + LINK_COMPONENTS + DebugInfoCodeView + DebugInfoPDB +diff --git a/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt +index 64168d0..79bdce42 100644 +--- a/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt ++++ b/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt +@@ -4,12 +4,13 @@ add_lldb_library(lldbPluginSymbolFilePDB PLUGIN + SymbolFilePDB.cpp + + LINK_LIBS +- clangAST +- clangLex + lldbCore ++ lldbPluginSymbolFileNativePDB + lldbSymbol + lldbUtility +- lldbPluginSymbolFileNativePDB ++ CLANG_LIBS ++ clangAST ++ clangLex + LINK_COMPONENTS + DebugInfoPDB + Support +diff --git a/lldb/source/Symbol/CMakeLists.txt b/lldb/source/Symbol/CMakeLists.txt +index 4b922c2..8614172 100644 +--- a/lldb/source/Symbol/CMakeLists.txt ++++ b/lldb/source/Symbol/CMakeLists.txt +@@ -47,9 +47,6 @@ add_lldb_library(lldbSymbol + ${PLATFORM_SOURCES} + + LINK_LIBS +- clangAST +- clangBasic +- clangFrontend + lldbCore + lldbExpression + lldbHost +@@ -61,6 +58,11 @@ add_lldb_library(lldbSymbol + lldbPluginObjCLanguage + lldbPluginObjCRuntime + ++ CLANG_LIBS ++ clangAST ++ clangBasic ++ clangFrontend ++ + LINK_COMPONENTS + Support + ) +diff --git a/lldb/tools/lldb-instr/CMakeLists.txt b/lldb/tools/lldb-instr/CMakeLists.txt +index e3dbeba..8da453b 100644 +--- a/lldb/tools/lldb-instr/CMakeLists.txt ++++ b/lldb/tools/lldb-instr/CMakeLists.txt +@@ -1,7 +1,7 @@ + add_lldb_tool(lldb-instr + Instrument.cpp + +- LINK_LIBS ++ CLANG_LIBS + clangAST + clangBasic + clangCodeGen +-- +1.8.3.1 + diff --git a/D15067.id41365.diff b/D15067.id41365.diff new file mode 100644 index 0000000..5217ffc --- /dev/null +++ b/D15067.id41365.diff @@ -0,0 +1,3810 @@ +diff -up lldb-3.8.0rc2.src/cmake/modules/LLDBStandalone.cmake.dave lldb-3.8.0rc2.src/cmake/modules/LLDBStandalone.cmake +--- lldb-3.8.0rc2.src/cmake/modules/LLDBStandalone.cmake.dave 2015-11-10 13:09:14.000000000 -0500 ++++ lldb-3.8.0rc2.src/cmake/modules/LLDBStandalone.cmake 2016-02-17 23:19:05.371675721 -0500 +@@ -6,57 +6,77 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURR + + option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF) + +- set(LLDB_PATH_TO_LLVM_SOURCE "" CACHE PATH +- "Path to LLVM source code. Not necessary if using an installed LLVM.") +- set(LLDB_PATH_TO_LLVM_BUILD "" CACHE PATH +- "Path to the directory where LLVM was built or installed.") +- +- set(LLDB_PATH_TO_CLANG_SOURCE "" CACHE PATH +- "Path to Clang source code. Not necessary if using an installed Clang.") +- set(LLDB_PATH_TO_CLANG_BUILD "" CACHE PATH +- "Path to the directory where Clang was built or installed.") +- +- if (LLDB_PATH_TO_LLVM_SOURCE) +- if (NOT EXISTS "${LLDB_PATH_TO_LLVM_SOURCE}/cmake/config-ix.cmake") +- message(FATAL_ERROR "Please set LLDB_PATH_TO_LLVM_SOURCE to the root " +- "directory of LLVM source code.") ++ # Rely on llvm-config. ++ set(CONFIG_OUTPUT) ++ find_program(LLVM_CONFIG "llvm-config") ++ if(LLVM_CONFIG) ++ message(STATUS "Found LLVM_CONFIG as ${LLVM_CONFIG}") ++ set(CONFIG_COMMAND ${LLVM_CONFIG} ++ "--assertion-mode" ++ "--bindir" ++ "--libdir" ++ "--includedir" ++ "--prefix" ++ "--src-root") ++ execute_process( ++ COMMAND ${CONFIG_COMMAND} ++ RESULT_VARIABLE HAD_ERROR ++ OUTPUT_VARIABLE CONFIG_OUTPUT ++ ) ++ if(NOT HAD_ERROR) ++ string(REGEX REPLACE ++ "[ \t]*[\r\n]+[ \t]*" ";" ++ CONFIG_OUTPUT ${CONFIG_OUTPUT}) + else() +- get_filename_component(LLVM_MAIN_SRC_DIR ${LLDB_PATH_TO_LLVM_SOURCE} +- ABSOLUTE) +- set(LLVM_MAIN_INCLUDE_DIR "${LLVM_MAIN_SRC_DIR}/include") +- list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") ++ string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}") ++ message(STATUS "${CONFIG_COMMAND_STR}") ++ message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") + endif() +- endif() +- +- if (LLDB_PATH_TO_CLANG_SOURCE) +- get_filename_component(CLANG_MAIN_SRC_DIR ${LLDB_PATH_TO_CLANG_SOURCE} +- ABSOLUTE) +- set(CLANG_MAIN_INCLUDE_DIR "${CLANG_MAIN_SRC_DIR}/include") +- endif() +- +- list(APPEND CMAKE_MODULE_PATH "${LLDB_PATH_TO_LLVM_BUILD}/share/llvm/cmake") +- +- if (LLDB_PATH_TO_LLVM_BUILD) +- get_filename_component(PATH_TO_LLVM_BUILD ${LLDB_PATH_TO_LLVM_BUILD} +- ABSOLUTE) + else() +- message(FATAL_ERROR "Please set LLDB_PATH_TO_LLVM_BUILD to the root " +- "directory of LLVM build or install site.") ++ message(FATAL_ERROR "llvm-config not found -- ${LLVM_CONFIG}") + endif() + +- if (LLDB_PATH_TO_CLANG_BUILD) +- get_filename_component(PATH_TO_CLANG_BUILD ${LLDB_PATH_TO_CLANG_BUILD} +- ABSOLUTE) ++ list(GET CONFIG_OUTPUT 0 ENABLE_ASSERTIONS) ++ list(GET CONFIG_OUTPUT 1 TOOLS_BINARY_DIR) ++ list(GET CONFIG_OUTPUT 2 LIBRARY_DIR) ++ list(GET CONFIG_OUTPUT 3 INCLUDE_DIR) ++ list(GET CONFIG_OUTPUT 4 LLVM_OBJ_ROOT) ++ list(GET CONFIG_OUTPUT 5 MAIN_SRC_DIR) ++ ++ if(NOT MSVC_IDE) ++ set(LLVM_ENABLE_ASSERTIONS ${ENABLE_ASSERTIONS} ++ CACHE BOOL "Enable assertions") ++ # Assertions should follow llvm-config's. ++ mark_as_advanced(LLVM_ENABLE_ASSERTIONS) ++ endif() ++ ++ set(LLVM_TOOLS_BINARY_DIR ${TOOLS_BINARY_DIR} CACHE PATH "Path to llvm/bin") ++ set(LLVM_LIBRARY_DIR ${LIBRARY_DIR} CACHE PATH "Path to llvm/lib") ++ set(LLVM_MAIN_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include") ++ set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree") ++ set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") ++ ++ find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR} ++ NO_DEFAULT_PATH) ++ ++ set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR}/share/llvm/cmake") ++ set(LLVMCONFIG_FILE "${LLVM_CMAKE_PATH}/LLVMConfig.cmake") ++ if(EXISTS ${LLVMCONFIG_FILE}) ++ list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") ++ include(${LLVMCONFIG_FILE}) + else() +- message(FATAL_ERROR "Please set LLDB_PATH_TO_CLANG_BUILD to the root " +- "directory of Clang build or install site.") ++ message(FATAL_ERROR "Not found: ${LLVMCONFIG_FILE}") + endif() + +- +- # These variables are used by add_llvm_library. ++ # They are used as destination of target generators. + set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) + set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) +- set(LLVM_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) ++ if(WIN32 OR CYGWIN) ++ # DLL platform -- put DLLs into bin. ++ set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) ++ else() ++ set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) ++ endif() + + include(AddLLVM) + include(HandleLLVMOptions) +@@ -73,9 +93,9 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURR + message("-- Found PythonInterp: ${PYTHON_EXECUTABLE}") + endif() + # Import CMake library targets from LLVM and Clang. +- include("${LLDB_PATH_TO_LLVM_BUILD}/share/llvm/cmake/LLVMConfig.cmake") +- if (EXISTS "${LLDB_PATH_TO_CLANG_BUILD}/share/clang/cmake/ClangConfig.cmake") +- include("${LLDB_PATH_TO_CLANG_BUILD}/share/clang/cmake/ClangConfig.cmake") ++ include("${LLVM_OBJ_ROOT}/share/llvm/cmake/LLVMConfig.cmake") ++ if (EXISTS "${LLVM_OBJ_ROOT}/share/clang/cmake/ClangConfig.cmake") ++ include("${LLVM_OBJ_ROOT}/share/clang/cmake/ClangConfig.cmake") + endif() + + set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") +@@ -83,13 +103,8 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURR + set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR}) + + set(CMAKE_INCLUDE_CURRENT_DIR ON) +- include_directories("${PATH_TO_LLVM_BUILD}/include" +- "${LLVM_MAIN_INCLUDE_DIR}" +- "${PATH_TO_CLANG_BUILD}/include" +- "${CLANG_MAIN_INCLUDE_DIR}" +- "${CMAKE_CURRENT_SOURCE_DIR}/source") +- link_directories("${PATH_TO_LLVM_BUILD}/lib${LLVM_LIBDIR_SUFFIX}" +- "${PATH_TO_CLANG_BUILD}/lib${LLVM_LIBDIR_SUFFIX}") ++ include_directories("${LLVM_BINARY_DIR}/include" "${LLVM_MAIN_INCLUDE_DIR}") ++ link_directories("${LLVM_LIBRARY_DIR}") + + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}) +diff -up lldb-3.8.0rc2.src/include/lldb/Utility/regcclass.h.dave lldb-3.8.0rc2.src/include/lldb/Utility/regcclass.h +--- lldb-3.8.0rc2.src/include/lldb/Utility/regcclass.h.dave 2016-02-17 23:19:05.371675721 -0500 ++++ lldb-3.8.0rc2.src/include/lldb/Utility/regcclass.h 2016-02-17 23:19:05.371675721 -0500 +@@ -0,0 +1,75 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)cclass.h 8.3 (Berkeley) 3/20/94 ++ */ ++ ++#ifndef LLVM_SUPPORT_REGCCLASS_H ++#define LLVM_SUPPORT_REGCCLASS_H ++ ++/* character-class table */ ++static struct cclass { ++ const char *name; ++ const char *chars; ++ const char *multis; ++} cclasses[] = { ++ { "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ ++0123456789", ""} , ++ { "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", ++ ""} , ++ { "blank", " \t", ""} , ++ { "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\ ++\25\26\27\30\31\32\33\34\35\36\37\177", ""} , ++ { "digit", "0123456789", ""} , ++ { "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ ++0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", ++ ""} , ++ { "lower", "abcdefghijklmnopqrstuvwxyz", ++ ""} , ++ { "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ ++0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", ++ ""} , ++ { "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", ++ ""} , ++ { "space", "\t\n\v\f\r ", ""} , ++ { "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", ++ ""} , ++ { "xdigit", "0123456789ABCDEFabcdef", ++ ""} , ++ { NULL, 0, "" } ++}; ++ ++#endif +diff -up lldb-3.8.0rc2.src/include/lldb/Utility/regcname.h.dave lldb-3.8.0rc2.src/include/lldb/Utility/regcname.h +--- lldb-3.8.0rc2.src/include/lldb/Utility/regcname.h.dave 2016-02-17 23:19:05.371675721 -0500 ++++ lldb-3.8.0rc2.src/include/lldb/Utility/regcname.h 2016-02-17 23:19:05.371675721 -0500 +@@ -0,0 +1,144 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)cname.h 8.3 (Berkeley) 3/20/94 ++ */ ++ ++#ifndef LLVM_SUPPORT_REGCNAME_H ++#define LLVM_SUPPORT_REGCNAME_H ++ ++/* character-name table */ ++static struct cname { ++ const char *name; ++ char code; ++} cnames[] = { ++ { "NUL", '\0' }, ++ { "SOH", '\001' }, ++ { "STX", '\002' }, ++ { "ETX", '\003' }, ++ { "EOT", '\004' }, ++ { "ENQ", '\005' }, ++ { "ACK", '\006' }, ++ { "BEL", '\007' }, ++ { "alert", '\007' }, ++ { "BS", '\010' }, ++ { "backspace", '\b' }, ++ { "HT", '\011' }, ++ { "tab", '\t' }, ++ { "LF", '\012' }, ++ { "newline", '\n' }, ++ { "VT", '\013' }, ++ { "vertical-tab", '\v' }, ++ { "FF", '\014' }, ++ { "form-feed", '\f' }, ++ { "CR", '\015' }, ++ { "carriage-return", '\r' }, ++ { "SO", '\016' }, ++ { "SI", '\017' }, ++ { "DLE", '\020' }, ++ { "DC1", '\021' }, ++ { "DC2", '\022' }, ++ { "DC3", '\023' }, ++ { "DC4", '\024' }, ++ { "NAK", '\025' }, ++ { "SYN", '\026' }, ++ { "ETB", '\027' }, ++ { "CAN", '\030' }, ++ { "EM", '\031' }, ++ { "SUB", '\032' }, ++ { "ESC", '\033' }, ++ { "IS4", '\034' }, ++ { "FS", '\034' }, ++ { "IS3", '\035' }, ++ { "GS", '\035' }, ++ { "IS2", '\036' }, ++ { "RS", '\036' }, ++ { "IS1", '\037' }, ++ { "US", '\037' }, ++ { "space", ' ' }, ++ { "exclamation-mark", '!' }, ++ { "quotation-mark", '"' }, ++ { "number-sign", '#' }, ++ { "dollar-sign", '$' }, ++ { "percent-sign", '%' }, ++ { "ampersand", '&' }, ++ { "apostrophe", '\'' }, ++ { "left-parenthesis", '(' }, ++ { "right-parenthesis", ')' }, ++ { "asterisk", '*' }, ++ { "plus-sign", '+' }, ++ { "comma", ',' }, ++ { "hyphen", '-' }, ++ { "hyphen-minus", '-' }, ++ { "period", '.' }, ++ { "full-stop", '.' }, ++ { "slash", '/' }, ++ { "solidus", '/' }, ++ { "zero", '0' }, ++ { "one", '1' }, ++ { "two", '2' }, ++ { "three", '3' }, ++ { "four", '4' }, ++ { "five", '5' }, ++ { "six", '6' }, ++ { "seven", '7' }, ++ { "eight", '8' }, ++ { "nine", '9' }, ++ { "colon", ':' }, ++ { "semicolon", ';' }, ++ { "less-than-sign", '<' }, ++ { "equals-sign", '=' }, ++ { "greater-than-sign", '>' }, ++ { "question-mark", '?' }, ++ { "commercial-at", '@' }, ++ { "left-square-bracket", '[' }, ++ { "backslash", '\\' }, ++ { "reverse-solidus", '\\' }, ++ { "right-square-bracket", ']' }, ++ { "circumflex", '^' }, ++ { "circumflex-accent", '^' }, ++ { "underscore", '_' }, ++ { "low-line", '_' }, ++ { "grave-accent", '`' }, ++ { "left-brace", '{' }, ++ { "left-curly-bracket", '{' }, ++ { "vertical-line", '|' }, ++ { "right-brace", '}' }, ++ { "right-curly-bracket", '}' }, ++ { "tilde", '~' }, ++ { "DEL", '\177' }, ++ { NULL, 0 } ++}; ++ ++#endif +diff -up lldb-3.8.0rc2.src/include/lldb/Utility/regengine.inc.dave lldb-3.8.0rc2.src/include/lldb/Utility/regengine.inc +--- lldb-3.8.0rc2.src/include/lldb/Utility/regengine.inc.dave 2016-02-17 23:19:05.371675721 -0500 ++++ lldb-3.8.0rc2.src/include/lldb/Utility/regengine.inc 2016-02-17 23:19:05.371675721 -0500 +@@ -0,0 +1,1034 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)engine.c 8.5 (Berkeley) 3/20/94 ++ */ ++ ++/* ++ * The matching engine and friends. This file is #included by regexec.c ++ * after suitable #defines of a variety of macros used herein, so that ++ * different state representations can be used without duplicating masses ++ * of code. ++ */ ++ ++#ifdef SNAMES ++#define matcher smatcher ++#define fast sfast ++#define slow sslow ++#define dissect sdissect ++#define backref sbackref ++#define step sstep ++#define print sprint ++#define at sat ++#define match smat ++#define nope snope ++#endif ++#ifdef LNAMES ++#define matcher lmatcher ++#define fast lfast ++#define slow lslow ++#define dissect ldissect ++#define backref lbackref ++#define step lstep ++#define print lprint ++#define at lat ++#define match lmat ++#define nope lnope ++#endif ++ ++/* another structure passed up and down to avoid zillions of parameters */ ++struct match { ++ struct re_guts *g; ++ int eflags; ++ llvm_regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ ++ const char *offp; /* offsets work from here */ ++ const char *beginp; /* start of string -- virtual NUL precedes */ ++ const char *endp; /* end of string -- virtual NUL here */ ++ const char *coldp; /* can be no match starting before here */ ++ const char **lastpos; /* [nplus+1] */ ++ STATEVARS; ++ states st; /* current states */ ++ states fresh; /* states for a fresh start */ ++ states tmp; /* temporary */ ++ states empty; /* empty set of states */ ++}; ++ ++static int matcher(struct re_guts *, const char *, size_t, ++ llvm_regmatch_t[], int); ++static const char *dissect(struct match *, const char *, const char *, sopno, ++ sopno); ++static const char *backref(struct match *, const char *, const char *, sopno, ++ sopno, sopno, int); ++static const char *fast(struct match *, const char *, const char *, sopno, sopno); ++static const char *slow(struct match *, const char *, const char *, sopno, sopno); ++static states step(struct re_guts *, sopno, sopno, states, int, states); ++#define MAX_RECURSION 100 ++#define BOL (OUT+1) ++#define EOL (BOL+1) ++#define BOLEOL (BOL+2) ++#define NOTHING (BOL+3) ++#define BOW (BOL+4) ++#define EOW (BOL+5) ++#define CODEMAX (BOL+5) /* highest code used */ ++#define NONCHAR(c) ((c) > CHAR_MAX) ++#define NNONCHAR (CODEMAX-CHAR_MAX) ++#ifdef REDEBUG ++static void print(struct match *, char *, states, int, FILE *); ++#endif ++#ifdef REDEBUG ++static void at(struct match *, char *, char *, char *, sopno, sopno); ++#endif ++#ifdef REDEBUG ++static char *pchar(int); ++#endif ++ ++#ifdef REDEBUG ++#define SP(t, s, c) print(m, t, s, c, stdout) ++#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2) ++#define NOTE(str) { if (m->eflags®_TRACE) (void)printf("=%s\n", (str)); } ++static int nope = 0; ++#else ++#define SP(t, s, c) /* nothing */ ++#define AT(t, p1, p2, s1, s2) /* nothing */ ++#define NOTE(s) /* nothing */ ++#endif ++ ++/* ++ - matcher - the actual matching engine ++ */ ++static int /* 0 success, REG_NOMATCH failure */ ++matcher(struct re_guts *g, const char *string, size_t nmatch, ++ llvm_regmatch_t pmatch[], ++ int eflags) ++{ ++ const char *endp; ++ size_t i; ++ struct match mv; ++ struct match *m = &mv; ++ const char *dp; ++ const sopno gf = g->firststate+1; /* +1 for OEND */ ++ const sopno gl = g->laststate; ++ const char *start; ++ const char *stop; ++ ++ /* simplify the situation where possible */ ++ if (g->cflags®_NOSUB) ++ nmatch = 0; ++ if (eflags®_STARTEND) { ++ start = string + pmatch[0].rm_so; ++ stop = string + pmatch[0].rm_eo; ++ } else { ++ start = string; ++ stop = start + strlen(start); ++ } ++ if (stop < start) ++ return(REG_INVARG); ++ ++ /* prescreening; this does wonders for this rather slow code */ ++ if (g->must != NULL) { ++ for (dp = start; dp < stop; dp++) ++ if (*dp == g->must[0] && stop - dp >= g->mlen && ++ memcmp(dp, g->must, (size_t)g->mlen) == 0) ++ break; ++ if (dp == stop) /* we didn't find g->must */ ++ return(REG_NOMATCH); ++ } ++ ++ /* match struct setup */ ++ m->g = g; ++ m->eflags = eflags; ++ m->pmatch = NULL; ++ m->lastpos = NULL; ++ m->offp = string; ++ m->beginp = start; ++ m->endp = stop; ++ STATESETUP(m, 4); ++ SETUP(m->st); ++ SETUP(m->fresh); ++ SETUP(m->tmp); ++ SETUP(m->empty); ++ CLEAR(m->empty); ++ ++ /* this loop does only one repetition except for backrefs */ ++ for (;;) { ++ endp = fast(m, start, stop, gf, gl); ++ if (endp == NULL) { /* a miss */ ++ free(m->pmatch); ++ free((void*)m->lastpos); ++ STATETEARDOWN(m); ++ return(REG_NOMATCH); ++ } ++ if (nmatch == 0 && !g->backrefs) ++ break; /* no further info needed */ ++ ++ /* where? */ ++ assert(m->coldp != NULL); ++ for (;;) { ++ NOTE("finding start"); ++ endp = slow(m, m->coldp, stop, gf, gl); ++ if (endp != NULL) ++ break; ++ assert(m->coldp < m->endp); ++ m->coldp++; ++ } ++ if (nmatch == 1 && !g->backrefs) ++ break; /* no further info needed */ ++ ++ /* oh my, they want the subexpressions... */ ++ if (m->pmatch == NULL) ++ m->pmatch = (llvm_regmatch_t *)malloc((m->g->nsub + 1) * ++ sizeof(llvm_regmatch_t)); ++ if (m->pmatch == NULL) { ++ STATETEARDOWN(m); ++ return(REG_ESPACE); ++ } ++ for (i = 1; i <= m->g->nsub; i++) ++ m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1; ++ if (!g->backrefs && !(m->eflags®_BACKR)) { ++ NOTE("dissecting"); ++ dp = dissect(m, m->coldp, endp, gf, gl); ++ } else { ++ if (g->nplus > 0 && m->lastpos == NULL) ++ m->lastpos = (const char **)malloc((g->nplus+1) * ++ sizeof(char *)); ++ if (g->nplus > 0 && m->lastpos == NULL) { ++ free(m->pmatch); ++ STATETEARDOWN(m); ++ return(REG_ESPACE); ++ } ++ NOTE("backref dissect"); ++ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0); ++ } ++ if (dp != NULL) ++ break; ++ ++ /* uh-oh... we couldn't find a subexpression-level match */ ++ assert(g->backrefs); /* must be back references doing it */ ++ assert(g->nplus == 0 || m->lastpos != NULL); ++ for (;;) { ++ if (dp != NULL || endp <= m->coldp) ++ break; /* defeat */ ++ NOTE("backoff"); ++ endp = slow(m, m->coldp, endp-1, gf, gl); ++ if (endp == NULL) ++ break; /* defeat */ ++ /* try it on a shorter possibility */ ++#ifndef NDEBUG ++ for (i = 1; i <= m->g->nsub; i++) { ++ assert(m->pmatch[i].rm_so == -1); ++ assert(m->pmatch[i].rm_eo == -1); ++ } ++#endif ++ NOTE("backoff dissect"); ++ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0); ++ } ++ assert(dp == NULL || dp == endp); ++ if (dp != NULL) /* found a shorter one */ ++ break; ++ ++ /* despite initial appearances, there is no match here */ ++ NOTE("false alarm"); ++ if (m->coldp == stop) ++ break; ++ start = m->coldp + 1; /* recycle starting later */ ++ } ++ ++ /* fill in the details if requested */ ++ if (nmatch > 0) { ++ pmatch[0].rm_so = m->coldp - m->offp; ++ pmatch[0].rm_eo = endp - m->offp; ++ } ++ if (nmatch > 1) { ++ assert(m->pmatch != NULL); ++ for (i = 1; i < nmatch; i++) ++ if (i <= m->g->nsub) ++ pmatch[i] = m->pmatch[i]; ++ else { ++ pmatch[i].rm_so = -1; ++ pmatch[i].rm_eo = -1; ++ } ++ } ++ ++ if (m->pmatch != NULL) ++ free((char *)m->pmatch); ++ if (m->lastpos != NULL) ++ free((char *)m->lastpos); ++ STATETEARDOWN(m); ++ return(0); ++} ++ ++/* ++ - dissect - figure out what matched what, no back references ++ */ ++static const char * /* == stop (success) always */ ++dissect(struct match *m, const char *start, const char *stop, sopno startst, ++ sopno stopst) ++{ ++ int i; ++ sopno ss; /* start sop of current subRE */ ++ sopno es; /* end sop of current subRE */ ++ const char *sp; /* start of string matched by it */ ++ const char *stp; /* string matched by it cannot pass here */ ++ const char *rest; /* start of rest of string */ ++ const char *tail; /* string unmatched by rest of RE */ ++ sopno ssub; /* start sop of subsubRE */ ++ sopno esub; /* end sop of subsubRE */ ++ const char *ssp; /* start of string matched by subsubRE */ ++ const char *sep; /* end of string matched by subsubRE */ ++ const char *oldssp; /* previous ssp */ ++ ++ AT("diss", start, stop, startst, stopst); ++ sp = start; ++ for (ss = startst; ss < stopst; ss = es) { ++ /* identify end of subRE */ ++ es = ss; ++ switch (OP(m->g->strip[es])) { ++ case OPLUS_: ++ case OQUEST_: ++ es += OPND(m->g->strip[es]); ++ break; ++ case OCH_: ++ while (OP(m->g->strip[es]) != O_CH) ++ es += OPND(m->g->strip[es]); ++ break; ++ } ++ es++; ++ ++ /* figure out what it matched */ ++ switch (OP(m->g->strip[ss])) { ++ case OEND: ++ assert(nope); ++ break; ++ case OCHAR: ++ sp++; ++ break; ++ case OBOL: ++ case OEOL: ++ case OBOW: ++ case OEOW: ++ break; ++ case OANY: ++ case OANYOF: ++ sp++; ++ break; ++ case OBACK_: ++ case O_BACK: ++ assert(nope); ++ break; ++ /* cases where length of match is hard to find */ ++ case OQUEST_: ++ stp = stop; ++ for (;;) { ++ /* how long could this one be? */ ++ rest = slow(m, sp, stp, ss, es); ++ assert(rest != NULL); /* it did match */ ++ /* could the rest match the rest? */ ++ tail = slow(m, rest, stop, es, stopst); ++ if (tail == stop) ++ break; /* yes! */ ++ /* no -- try a shorter match for this one */ ++ stp = rest - 1; ++ assert(stp >= sp); /* it did work */ ++ } ++ ssub = ss + 1; ++ esub = es - 1; ++ /* did innards match? */ ++ if (slow(m, sp, rest, ssub, esub) != NULL) { ++ const char *dp = dissect(m, sp, rest, ssub, esub); ++ (void)dp; /* avoid warning if assertions off */ ++ assert(dp == rest); ++ } else /* no */ ++ assert(sp == rest); ++ sp = rest; ++ break; ++ case OPLUS_: ++ stp = stop; ++ for (;;) { ++ /* how long could this one be? */ ++ rest = slow(m, sp, stp, ss, es); ++ assert(rest != NULL); /* it did match */ ++ /* could the rest match the rest? */ ++ tail = slow(m, rest, stop, es, stopst); ++ if (tail == stop) ++ break; /* yes! */ ++ /* no -- try a shorter match for this one */ ++ stp = rest - 1; ++ assert(stp >= sp); /* it did work */ ++ } ++ ssub = ss + 1; ++ esub = es - 1; ++ ssp = sp; ++ oldssp = ssp; ++ for (;;) { /* find last match of innards */ ++ sep = slow(m, ssp, rest, ssub, esub); ++ if (sep == NULL || sep == ssp) ++ break; /* failed or matched null */ ++ oldssp = ssp; /* on to next try */ ++ ssp = sep; ++ } ++ if (sep == NULL) { ++ /* last successful match */ ++ sep = ssp; ++ ssp = oldssp; ++ } ++ assert(sep == rest); /* must exhaust substring */ ++ assert(slow(m, ssp, sep, ssub, esub) == rest); ++ { ++ const char *dp = dissect(m, ssp, sep, ssub, esub); ++ (void)dp; /* avoid warning if assertions off */ ++ assert(dp == sep); ++ } ++ sp = rest; ++ break; ++ case OCH_: ++ stp = stop; ++ for (;;) { ++ /* how long could this one be? */ ++ rest = slow(m, sp, stp, ss, es); ++ assert(rest != NULL); /* it did match */ ++ /* could the rest match the rest? */ ++ tail = slow(m, rest, stop, es, stopst); ++ if (tail == stop) ++ break; /* yes! */ ++ /* no -- try a shorter match for this one */ ++ stp = rest - 1; ++ assert(stp >= sp); /* it did work */ ++ } ++ ssub = ss + 1; ++ esub = ss + OPND(m->g->strip[ss]) - 1; ++ assert(OP(m->g->strip[esub]) == OOR1); ++ for (;;) { /* find first matching branch */ ++ if (slow(m, sp, rest, ssub, esub) == rest) ++ break; /* it matched all of it */ ++ /* that one missed, try next one */ ++ assert(OP(m->g->strip[esub]) == OOR1); ++ esub++; ++ assert(OP(m->g->strip[esub]) == OOR2); ++ ssub = esub + 1; ++ esub += OPND(m->g->strip[esub]); ++ if (OP(m->g->strip[esub]) == OOR2) ++ esub--; ++ else ++ assert(OP(m->g->strip[esub]) == O_CH); ++ } ++ { ++ const char *dp = dissect(m, sp, rest, ssub, esub); ++ (void)dp; /* avoid warning if assertions off */ ++ assert(dp == rest); ++ } ++ sp = rest; ++ break; ++ case O_PLUS: ++ case O_QUEST: ++ case OOR1: ++ case OOR2: ++ case O_CH: ++ assert(nope); ++ break; ++ case OLPAREN: ++ i = OPND(m->g->strip[ss]); ++ assert(0 < i && i <= m->g->nsub); ++ m->pmatch[i].rm_so = sp - m->offp; ++ break; ++ case ORPAREN: ++ i = OPND(m->g->strip[ss]); ++ assert(0 < i && i <= m->g->nsub); ++ m->pmatch[i].rm_eo = sp - m->offp; ++ break; ++ default: /* uh oh */ ++ assert(nope); ++ break; ++ } ++ } ++ ++ assert(sp == stop); ++ return(sp); ++} ++ ++/* ++ - backref - figure out what matched what, figuring in back references ++ */ ++static const char * /* == stop (success) or NULL (failure) */ ++backref(struct match *m, const char *start, const char *stop, sopno startst, ++ sopno stopst, sopno lev, int rec) /* PLUS nesting level */ ++{ ++ int i; ++ sopno ss; /* start sop of current subRE */ ++ const char *sp; /* start of string matched by it */ ++ sopno ssub; /* start sop of subsubRE */ ++ sopno esub; /* end sop of subsubRE */ ++ const char *ssp; /* start of string matched by subsubRE */ ++ const char *dp; ++ size_t len; ++ int hard; ++ sop s; ++ llvm_regoff_t offsave; ++ cset *cs; ++ ++ AT("back", start, stop, startst, stopst); ++ sp = start; ++ ++ /* get as far as we can with easy stuff */ ++ hard = 0; ++ for (ss = startst; !hard && ss < stopst; ss++) ++ switch (OP(s = m->g->strip[ss])) { ++ case OCHAR: ++ if (sp == stop || *sp++ != (char)OPND(s)) ++ return(NULL); ++ break; ++ case OANY: ++ if (sp == stop) ++ return(NULL); ++ sp++; ++ break; ++ case OANYOF: ++ cs = &m->g->sets[OPND(s)]; ++ if (sp == stop || !CHIN(cs, *sp++)) ++ return(NULL); ++ break; ++ case OBOL: ++ if ( (sp == m->beginp && !(m->eflags®_NOTBOL)) || ++ (sp < m->endp && *(sp-1) == '\n' && ++ (m->g->cflags®_NEWLINE)) ) ++ { /* yes */ } ++ else ++ return(NULL); ++ break; ++ case OEOL: ++ if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || ++ (sp < m->endp && *sp == '\n' && ++ (m->g->cflags®_NEWLINE)) ) ++ { /* yes */ } ++ else ++ return(NULL); ++ break; ++ case OBOW: ++ if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || ++ (sp < m->endp && *(sp-1) == '\n' && ++ (m->g->cflags®_NEWLINE)) || ++ (sp > m->beginp && ++ !ISWORD(*(sp-1))) ) && ++ (sp < m->endp && ISWORD(*sp)) ) ++ { /* yes */ } ++ else ++ return(NULL); ++ break; ++ case OEOW: ++ if (( (sp == m->endp && !(m->eflags®_NOTEOL)) || ++ (sp < m->endp && *sp == '\n' && ++ (m->g->cflags®_NEWLINE)) || ++ (sp < m->endp && !ISWORD(*sp)) ) && ++ (sp > m->beginp && ISWORD(*(sp-1))) ) ++ { /* yes */ } ++ else ++ return(NULL); ++ break; ++ case O_QUEST: ++ break; ++ case OOR1: /* matches null but needs to skip */ ++ ss++; ++ s = m->g->strip[ss]; ++ do { ++ assert(OP(s) == OOR2); ++ ss += OPND(s); ++ } while (OP(s = m->g->strip[ss]) != O_CH); ++ /* note that the ss++ gets us past the O_CH */ ++ break; ++ default: /* have to make a choice */ ++ hard = 1; ++ break; ++ } ++ if (!hard) { /* that was it! */ ++ if (sp != stop) ++ return(NULL); ++ return(sp); ++ } ++ ss--; /* adjust for the for's final increment */ ++ ++ /* the hard stuff */ ++ AT("hard", sp, stop, ss, stopst); ++ s = m->g->strip[ss]; ++ switch (OP(s)) { ++ case OBACK_: /* the vilest depths */ ++ i = OPND(s); ++ assert(0 < i && i <= m->g->nsub); ++ if (m->pmatch[i].rm_eo == -1) ++ return(NULL); ++ assert(m->pmatch[i].rm_so != -1); ++ len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so; ++ if (len == 0 && rec++ > MAX_RECURSION) ++ return(NULL); ++ assert(stop - m->beginp >= len); ++ if (sp > stop - len) ++ return(NULL); /* not enough left to match */ ++ ssp = m->offp + m->pmatch[i].rm_so; ++ if (memcmp(sp, ssp, len) != 0) ++ return(NULL); ++ while (m->g->strip[ss] != SOP(O_BACK, i)) ++ ss++; ++ return(backref(m, sp+len, stop, ss+1, stopst, lev, rec)); ++ break; ++ case OQUEST_: /* to null or not */ ++ dp = backref(m, sp, stop, ss+1, stopst, lev, rec); ++ if (dp != NULL) ++ return(dp); /* not */ ++ return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec)); ++ break; ++ case OPLUS_: ++ assert(m->lastpos != NULL); ++ assert(lev+1 <= m->g->nplus); ++ m->lastpos[lev+1] = sp; ++ return(backref(m, sp, stop, ss+1, stopst, lev+1, rec)); ++ break; ++ case O_PLUS: ++ if (sp == m->lastpos[lev]) /* last pass matched null */ ++ return(backref(m, sp, stop, ss+1, stopst, lev-1, rec)); ++ /* try another pass */ ++ m->lastpos[lev] = sp; ++ dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec); ++ if (dp == NULL) ++ return(backref(m, sp, stop, ss+1, stopst, lev-1, rec)); ++ else ++ return(dp); ++ break; ++ case OCH_: /* find the right one, if any */ ++ ssub = ss + 1; ++ esub = ss + OPND(s) - 1; ++ assert(OP(m->g->strip[esub]) == OOR1); ++ for (;;) { /* find first matching branch */ ++ dp = backref(m, sp, stop, ssub, esub, lev, rec); ++ if (dp != NULL) ++ return(dp); ++ /* that one missed, try next one */ ++ if (OP(m->g->strip[esub]) == O_CH) ++ return(NULL); /* there is none */ ++ esub++; ++ assert(OP(m->g->strip[esub]) == OOR2); ++ ssub = esub + 1; ++ esub += OPND(m->g->strip[esub]); ++ if (OP(m->g->strip[esub]) == OOR2) ++ esub--; ++ else ++ assert(OP(m->g->strip[esub]) == O_CH); ++ } ++ break; ++ case OLPAREN: /* must undo assignment if rest fails */ ++ i = OPND(s); ++ assert(0 < i && i <= m->g->nsub); ++ offsave = m->pmatch[i].rm_so; ++ m->pmatch[i].rm_so = sp - m->offp; ++ dp = backref(m, sp, stop, ss+1, stopst, lev, rec); ++ if (dp != NULL) ++ return(dp); ++ m->pmatch[i].rm_so = offsave; ++ return(NULL); ++ break; ++ case ORPAREN: /* must undo assignment if rest fails */ ++ i = OPND(s); ++ assert(0 < i && i <= m->g->nsub); ++ offsave = m->pmatch[i].rm_eo; ++ m->pmatch[i].rm_eo = sp - m->offp; ++ dp = backref(m, sp, stop, ss+1, stopst, lev, rec); ++ if (dp != NULL) ++ return(dp); ++ m->pmatch[i].rm_eo = offsave; ++ return(NULL); ++ break; ++ default: /* uh oh */ ++ assert(nope); ++ break; ++ } ++ ++ /* "can't happen" */ ++ assert(nope); ++ /* NOTREACHED */ ++ return NULL; ++} ++ ++/* ++ - fast - step through the string at top speed ++ */ ++static const char * /* where tentative match ended, or NULL */ ++fast(struct match *m, const char *start, const char *stop, sopno startst, ++ sopno stopst) ++{ ++ states st = m->st; ++ states fresh = m->fresh; ++ states tmp = m->tmp; ++ const char *p = start; ++ int c = (start == m->beginp) ? OUT : *(start-1); ++ int lastc; /* previous c */ ++ int flagch; ++ int i; ++ const char *coldp; /* last p after which no match was underway */ ++ ++ CLEAR(st); ++ SET1(st, startst); ++ st = step(m->g, startst, stopst, st, NOTHING, st); ++ ASSIGN(fresh, st); ++ SP("start", st, *p); ++ coldp = NULL; ++ for (;;) { ++ /* next character */ ++ lastc = c; ++ c = (p == m->endp) ? OUT : *p; ++ if (EQ(st, fresh)) ++ coldp = p; ++ ++ /* is there an EOL and/or BOL between lastc and c? */ ++ flagch = '\0'; ++ i = 0; ++ if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || ++ (lastc == OUT && !(m->eflags®_NOTBOL)) ) { ++ flagch = BOL; ++ i = m->g->nbol; ++ } ++ if ( (c == '\n' && m->g->cflags®_NEWLINE) || ++ (c == OUT && !(m->eflags®_NOTEOL)) ) { ++ flagch = (flagch == BOL) ? BOLEOL : EOL; ++ i += m->g->neol; ++ } ++ if (i != 0) { ++ for (; i > 0; i--) ++ st = step(m->g, startst, stopst, st, flagch, st); ++ SP("boleol", st, c); ++ } ++ ++ /* how about a word boundary? */ ++ if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && ++ (c != OUT && ISWORD(c)) ) { ++ flagch = BOW; ++ } ++ if ( (lastc != OUT && ISWORD(lastc)) && ++ (flagch == EOL || (c != OUT && !ISWORD(c))) ) { ++ flagch = EOW; ++ } ++ if (flagch == BOW || flagch == EOW) { ++ st = step(m->g, startst, stopst, st, flagch, st); ++ SP("boweow", st, c); ++ } ++ ++ /* are we done? */ ++ if (ISSET(st, stopst) || p == stop) ++ break; /* NOTE BREAK OUT */ ++ ++ /* no, we must deal with this character */ ++ ASSIGN(tmp, st); ++ ASSIGN(st, fresh); ++ assert(c != OUT); ++ st = step(m->g, startst, stopst, tmp, c, st); ++ SP("aft", st, c); ++ assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); ++ p++; ++ } ++ ++ assert(coldp != NULL); ++ m->coldp = coldp; ++ if (ISSET(st, stopst)) ++ return(p+1); ++ else ++ return(NULL); ++} ++ ++/* ++ - slow - step through the string more deliberately ++ */ ++static const char * /* where it ended */ ++slow(struct match *m, const char *start, const char *stop, sopno startst, ++ sopno stopst) ++{ ++ states st = m->st; ++ states empty = m->empty; ++ states tmp = m->tmp; ++ const char *p = start; ++ int c = (start == m->beginp) ? OUT : *(start-1); ++ int lastc; /* previous c */ ++ int flagch; ++ int i; ++ const char *matchp; /* last p at which a match ended */ ++ ++ AT("slow", start, stop, startst, stopst); ++ CLEAR(st); ++ SET1(st, startst); ++ SP("sstart", st, *p); ++ st = step(m->g, startst, stopst, st, NOTHING, st); ++ matchp = NULL; ++ for (;;) { ++ /* next character */ ++ lastc = c; ++ c = (p == m->endp) ? OUT : *p; ++ ++ /* is there an EOL and/or BOL between lastc and c? */ ++ flagch = '\0'; ++ i = 0; ++ if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || ++ (lastc == OUT && !(m->eflags®_NOTBOL)) ) { ++ flagch = BOL; ++ i = m->g->nbol; ++ } ++ if ( (c == '\n' && m->g->cflags®_NEWLINE) || ++ (c == OUT && !(m->eflags®_NOTEOL)) ) { ++ flagch = (flagch == BOL) ? BOLEOL : EOL; ++ i += m->g->neol; ++ } ++ if (i != 0) { ++ for (; i > 0; i--) ++ st = step(m->g, startst, stopst, st, flagch, st); ++ SP("sboleol", st, c); ++ } ++ ++ /* how about a word boundary? */ ++ if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && ++ (c != OUT && ISWORD(c)) ) { ++ flagch = BOW; ++ } ++ if ( (lastc != OUT && ISWORD(lastc)) && ++ (flagch == EOL || (c != OUT && !ISWORD(c))) ) { ++ flagch = EOW; ++ } ++ if (flagch == BOW || flagch == EOW) { ++ st = step(m->g, startst, stopst, st, flagch, st); ++ SP("sboweow", st, c); ++ } ++ ++ /* are we done? */ ++ if (ISSET(st, stopst)) ++ matchp = p; ++ if (EQ(st, empty) || p == stop) ++ break; /* NOTE BREAK OUT */ ++ ++ /* no, we must deal with this character */ ++ ASSIGN(tmp, st); ++ ASSIGN(st, empty); ++ assert(c != OUT); ++ st = step(m->g, startst, stopst, tmp, c, st); ++ SP("saft", st, c); ++ assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); ++ p++; ++ } ++ ++ return(matchp); ++} ++ ++ ++/* ++ - step - map set of states reachable before char to set reachable after ++ */ ++static states ++step(struct re_guts *g, ++ sopno start, /* start state within strip */ ++ sopno stop, /* state after stop state within strip */ ++ states bef, /* states reachable before */ ++ int ch, /* character or NONCHAR code */ ++ states aft) /* states already known reachable after */ ++{ ++ cset *cs; ++ sop s; ++ sopno pc; ++ onestate here; /* note, macros know this name */ ++ sopno look; ++ int i; ++ ++ for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) { ++ s = g->strip[pc]; ++ switch (OP(s)) { ++ case OEND: ++ assert(pc == stop-1); ++ break; ++ case OCHAR: ++ /* only characters can match */ ++ assert(!NONCHAR(ch) || ch != (char)OPND(s)); ++ if (ch == (char)OPND(s)) ++ FWD(aft, bef, 1); ++ break; ++ case OBOL: ++ if (ch == BOL || ch == BOLEOL) ++ FWD(aft, bef, 1); ++ break; ++ case OEOL: ++ if (ch == EOL || ch == BOLEOL) ++ FWD(aft, bef, 1); ++ break; ++ case OBOW: ++ if (ch == BOW) ++ FWD(aft, bef, 1); ++ break; ++ case OEOW: ++ if (ch == EOW) ++ FWD(aft, bef, 1); ++ break; ++ case OANY: ++ if (!NONCHAR(ch)) ++ FWD(aft, bef, 1); ++ break; ++ case OANYOF: ++ cs = &g->sets[OPND(s)]; ++ if (!NONCHAR(ch) && CHIN(cs, ch)) ++ FWD(aft, bef, 1); ++ break; ++ case OBACK_: /* ignored here */ ++ case O_BACK: ++ FWD(aft, aft, 1); ++ break; ++ case OPLUS_: /* forward, this is just an empty */ ++ FWD(aft, aft, 1); ++ break; ++ case O_PLUS: /* both forward and back */ ++ FWD(aft, aft, 1); ++ i = ISSETBACK(aft, OPND(s)); ++ BACK(aft, aft, OPND(s)); ++ if (!i && ISSETBACK(aft, OPND(s))) { ++ /* oho, must reconsider loop body */ ++ pc -= OPND(s) + 1; ++ INIT(here, pc); ++ } ++ break; ++ case OQUEST_: /* two branches, both forward */ ++ FWD(aft, aft, 1); ++ FWD(aft, aft, OPND(s)); ++ break; ++ case O_QUEST: /* just an empty */ ++ FWD(aft, aft, 1); ++ break; ++ case OLPAREN: /* not significant here */ ++ case ORPAREN: ++ FWD(aft, aft, 1); ++ break; ++ case OCH_: /* mark the first two branches */ ++ FWD(aft, aft, 1); ++ assert(OP(g->strip[pc+OPND(s)]) == OOR2); ++ FWD(aft, aft, OPND(s)); ++ break; ++ case OOR1: /* done a branch, find the O_CH */ ++ if (ISSTATEIN(aft, here)) { ++ for (look = 1; ++ OP(s = g->strip[pc+look]) != O_CH; ++ look += OPND(s)) ++ assert(OP(s) == OOR2); ++ FWD(aft, aft, look); ++ } ++ break; ++ case OOR2: /* propagate OCH_'s marking */ ++ FWD(aft, aft, 1); ++ if (OP(g->strip[pc+OPND(s)]) != O_CH) { ++ assert(OP(g->strip[pc+OPND(s)]) == OOR2); ++ FWD(aft, aft, OPND(s)); ++ } ++ break; ++ case O_CH: /* just empty */ ++ FWD(aft, aft, 1); ++ break; ++ default: /* ooooops... */ ++ assert(nope); ++ break; ++ } ++ } ++ ++ return(aft); ++} ++ ++#ifdef REDEBUG ++/* ++ - print - print a set of states ++ */ ++static void ++print(struct match *m, char *caption, states st, int ch, FILE *d) ++{ ++ struct re_guts *g = m->g; ++ int i; ++ int first = 1; ++ ++ if (!(m->eflags®_TRACE)) ++ return; ++ ++ (void)fprintf(d, "%s", caption); ++ if (ch != '\0') ++ (void)fprintf(d, " %s", pchar(ch)); ++ for (i = 0; i < g->nstates; i++) ++ if (ISSET(st, i)) { ++ (void)fprintf(d, "%s%d", (first) ? "\t" : ", ", i); ++ first = 0; ++ } ++ (void)fprintf(d, "\n"); ++} ++ ++/* ++ - at - print current situation ++ */ ++static void ++at(struct match *m, char *title, char *start, char *stop, sopno startst, ++ sopno stopst) ++{ ++ if (!(m->eflags®_TRACE)) ++ return; ++ ++ (void)printf("%s %s-", title, pchar(*start)); ++ (void)printf("%s ", pchar(*stop)); ++ (void)printf("%ld-%ld\n", (long)startst, (long)stopst); ++} ++ ++#ifndef PCHARDONE ++#define PCHARDONE /* never again */ ++/* ++ - pchar - make a character printable ++ * ++ * Is this identical to regchar() over in debug.c? Well, yes. But a ++ * duplicate here avoids having a debugging-capable regexec.o tied to ++ * a matching debug.o, and this is convenient. It all disappears in ++ * the non-debug compilation anyway, so it doesn't matter much. ++ */ ++static char * /* -> representation */ ++pchar(int ch) ++{ ++ static char pbuf[10]; ++ ++ if (isprint(ch) || ch == ' ') ++ (void)snprintf(pbuf, sizeof pbuf, "%c", ch); ++ else ++ (void)snprintf(pbuf, sizeof pbuf, "\\%o", ch); ++ return(pbuf); ++} ++#endif ++#endif ++ ++#undef matcher ++#undef fast ++#undef slow ++#undef dissect ++#undef backref ++#undef step ++#undef print ++#undef at ++#undef match ++#undef nope +diff -up lldb-3.8.0rc2.src/include/lldb/Utility/regex2.h.dave lldb-3.8.0rc2.src/include/lldb/Utility/regex2.h +--- lldb-3.8.0rc2.src/include/lldb/Utility/regex2.h.dave 2016-02-17 23:19:05.372675749 -0500 ++++ lldb-3.8.0rc2.src/include/lldb/Utility/regex2.h 2016-02-17 23:19:05.372675749 -0500 +@@ -0,0 +1,162 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)regex2.h 8.4 (Berkeley) 3/20/94 ++ */ ++ ++#ifndef LLVM_SUPPORT_REGEX2_H ++#define LLVM_SUPPORT_REGEX2_H ++ ++/* ++ * internals of regex_t ++ */ ++#define MAGIC1 ((('r'^0200)<<8) | 'e') ++ ++/* ++ * The internal representation is a *strip*, a sequence of ++ * operators ending with an endmarker. (Some terminology etc. is a ++ * historical relic of earlier versions which used multiple strips.) ++ * Certain oddities in the representation are there to permit running ++ * the machinery backwards; in particular, any deviation from sequential ++ * flow must be marked at both its source and its destination. Some ++ * fine points: ++ * ++ * - OPLUS_ and O_PLUS are *inside* the loop they create. ++ * - OQUEST_ and O_QUEST are *outside* the bypass they create. ++ * - OCH_ and O_CH are *outside* the multi-way branch they create, while ++ * OOR1 and OOR2 are respectively the end and the beginning of one of ++ * the branches. Note that there is an implicit OOR2 following OCH_ ++ * and an implicit OOR1 preceding O_CH. ++ * ++ * In state representations, an operator's bit is on to signify a state ++ * immediately *preceding* "execution" of that operator. ++ */ ++typedef unsigned long sop; /* strip operator */ ++typedef long sopno; ++#define OPRMASK 0xf8000000LU ++#define OPDMASK 0x07ffffffLU ++#define OPSHIFT ((unsigned)27) ++#define OP(n) ((n)&OPRMASK) ++#define OPND(n) ((n)&OPDMASK) ++#define SOP(op, opnd) ((op)|(opnd)) ++/* operators meaning operand */ ++/* (back, fwd are offsets) */ ++#define OEND (1LU< uch [csetsize] */ ++ uch mask; /* bit within array */ ++ uch hash; /* hash code */ ++ size_t smultis; ++ char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ ++} cset; ++/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ ++#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c)) ++#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c)) ++#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) ++#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* llvm_regcomp() internal fns */ ++#define MCsub(p, cs, cp) mcsub(p, cs, cp) ++#define MCin(p, cs, cp) mcin(p, cs, cp) ++ ++/* stuff for character categories */ ++typedef unsigned char cat_t; ++ ++/* ++ * main compiled-expression structure ++ */ ++struct re_guts { ++ int magic; ++# define MAGIC2 ((('R'^0200)<<8)|'E') ++ sop *strip; /* malloced area for strip */ ++ int csetsize; /* number of bits in a cset vector */ ++ int ncsets; /* number of csets in use */ ++ cset *sets; /* -> cset [ncsets] */ ++ uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ ++ int cflags; /* copy of llvm_regcomp() cflags argument */ ++ sopno nstates; /* = number of sops */ ++ sopno firststate; /* the initial OEND (normally 0) */ ++ sopno laststate; /* the final OEND */ ++ int iflags; /* internal flags */ ++# define USEBOL 01 /* used ^ */ ++# define USEEOL 02 /* used $ */ ++# define REGEX_BAD 04 /* something wrong */ ++ int nbol; /* number of ^ used */ ++ int neol; /* number of $ used */ ++ int ncategories; /* how many character categories */ ++ cat_t *categories; /* ->catspace[-CHAR_MIN] */ ++ char *must; /* match must contain this string */ ++ int mlen; /* length of must */ ++ size_t nsub; /* copy of re_nsub */ ++ int backrefs; /* does it use back references? */ ++ sopno nplus; /* how deep does it nest +s? */ ++ /* catspace must be last */ ++ cat_t catspace[1]; /* actually [NC] */ ++}; ++ ++/* misc utilities */ ++#define OUT (CHAR_MAX+1) /* a non-character value */ ++#define ISWORD(c) (isalnum(c&0xff) || (c) == '_') ++ ++#endif +diff -up lldb-3.8.0rc2.src/include/lldb/Utility/regex_impl.h.dave lldb-3.8.0rc2.src/include/lldb/Utility/regex_impl.h +--- lldb-3.8.0rc2.src/include/lldb/Utility/regex_impl.h.dave 2016-02-17 23:19:05.372675749 -0500 ++++ lldb-3.8.0rc2.src/include/lldb/Utility/regex_impl.h 2016-02-17 23:19:05.372675749 -0500 +@@ -0,0 +1,108 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992 Henry Spencer. ++ * Copyright (c) 1992, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer of the University of Toronto. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)regex.h 8.1 (Berkeley) 6/2/93 ++ */ ++ ++#ifndef _REGEX_H_ ++#define _REGEX_H_ ++ ++#include ++typedef off_t llvm_regoff_t; ++typedef struct { ++ llvm_regoff_t rm_so; /* start of match */ ++ llvm_regoff_t rm_eo; /* end of match */ ++} llvm_regmatch_t; ++ ++typedef struct llvm_regex { ++ int re_magic; ++ size_t re_nsub; /* number of parenthesized subexpressions */ ++ const char *re_endp; /* end pointer for REG_PEND */ ++ struct re_guts *re_g; /* none of your business :-) */ ++} llvm_regex_t; ++ ++/* llvm_regcomp() flags */ ++#define REG_BASIC 0000 ++#define REG_EXTENDED 0001 ++#define REG_ICASE 0002 ++#define REG_NOSUB 0004 ++#define REG_NEWLINE 0010 ++#define REG_NOSPEC 0020 ++#define REG_PEND 0040 ++#define REG_DUMP 0200 ++ ++/* llvm_regerror() flags */ ++#define REG_NOMATCH 1 ++#define REG_BADPAT 2 ++#define REG_ECOLLATE 3 ++#define REG_ECTYPE 4 ++#define REG_EESCAPE 5 ++#define REG_ESUBREG 6 ++#define REG_EBRACK 7 ++#define REG_EPAREN 8 ++#define REG_EBRACE 9 ++#define REG_BADBR 10 ++#define REG_ERANGE 11 ++#define REG_ESPACE 12 ++#define REG_BADRPT 13 ++#define REG_EMPTY 14 ++#define REG_ASSERT 15 ++#define REG_INVARG 16 ++#define REG_ATOI 255 /* convert name to number (!) */ ++#define REG_ITOA 0400 /* convert number to name (!) */ ++ ++/* llvm_regexec() flags */ ++#define REG_NOTBOL 00001 ++#define REG_NOTEOL 00002 ++#define REG_STARTEND 00004 ++#define REG_TRACE 00400 /* tracing of execution */ ++#define REG_LARGE 01000 /* force large representation */ ++#define REG_BACKR 02000 /* force use of backref code */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int llvm_regcomp(llvm_regex_t *, const char *, int); ++size_t llvm_regerror(int, const llvm_regex_t *, char *, size_t); ++int llvm_regexec(const llvm_regex_t *, const char *, size_t, ++ llvm_regmatch_t [], int); ++void llvm_regfree(llvm_regex_t *); ++size_t llvm_strlcpy(char *dst, const char *src, size_t siz); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* !_REGEX_H_ */ +diff -up lldb-3.8.0rc2.src/include/lldb/Utility/regutils.h.dave lldb-3.8.0rc2.src/include/lldb/Utility/regutils.h +--- lldb-3.8.0rc2.src/include/lldb/Utility/regutils.h.dave 2016-02-17 23:19:05.372675749 -0500 ++++ lldb-3.8.0rc2.src/include/lldb/Utility/regutils.h 2016-02-17 23:19:05.372675749 -0500 +@@ -0,0 +1,58 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)utils.h 8.3 (Berkeley) 3/20/94 ++ */ ++ ++#ifndef LLVM_SUPPORT_REGUTILS_H ++#define LLVM_SUPPORT_REGUTILS_H ++ ++/* utility definitions */ ++#define NC (CHAR_MAX - CHAR_MIN + 1) ++typedef unsigned char uch; ++ ++/* switch off assertions (if not already off) if no REDEBUG */ ++#ifndef REDEBUG ++#ifndef NDEBUG ++#define NDEBUG /* no assertions please */ ++#endif ++#endif ++#include ++ ++/* for old systems with bcopy() but no memmove() */ ++#ifdef USEBCOPY ++#define memmove(d, s, c) bcopy(s, d, c) ++#endif ++ ++#endif +diff -up lldb-3.8.0rc2.src/scripts/CMakeLists.txt.dave lldb-3.8.0rc2.src/scripts/CMakeLists.txt +--- lldb-3.8.0rc2.src/scripts/CMakeLists.txt.dave 2015-11-18 17:21:47.000000000 -0500 ++++ lldb-3.8.0rc2.src/scripts/CMakeLists.txt 2016-02-17 23:19:05.372675749 -0500 +@@ -9,6 +9,8 @@ set(SWIG_HEADERS + ${LLDB_SOURCE_DIR}/include/lldb/lldb-versioning.h + ) + ++include(FindPythonInterp) ++ + find_package(SWIG REQUIRED) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapPython.cpp +diff -up lldb-3.8.0rc2.src/source/Utility/CMakeLists.txt.dave lldb-3.8.0rc2.src/source/Utility/CMakeLists.txt +--- lldb-3.8.0rc2.src/source/Utility/CMakeLists.txt.dave 2015-10-20 08:42:05.000000000 -0400 ++++ lldb-3.8.0rc2.src/source/Utility/CMakeLists.txt 2016-02-17 23:19:05.372675749 -0500 +@@ -1,3 +1,5 @@ ++include_directories(../../include/lldb/Utility) ++ + add_lldb_library(lldbUtility + ARM_DWARF_Registers.cpp + ARM64_DWARF_Registers.cpp +@@ -17,4 +19,9 @@ add_lldb_library(lldbUtility + TaskPool.cpp + TimeSpecTimeout.cpp + UriParser.cpp ++ regcomp.c ++ regerror.c ++ regexec.c ++ regfree.c ++ regstrlcpy.c + ) +diff -up lldb-3.8.0rc2.src/source/Utility/regcomp.c.dave lldb-3.8.0rc2.src/source/Utility/regcomp.c +--- lldb-3.8.0rc2.src/source/Utility/regcomp.c.dave 2016-02-17 23:19:05.372675749 -0500 ++++ lldb-3.8.0rc2.src/source/Utility/regcomp.c 2016-02-17 23:19:05.372675749 -0500 +@@ -0,0 +1,1570 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)regcomp.c 8.5 (Berkeley) 3/20/94 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "regex_impl.h" ++ ++#include "regutils.h" ++#include "regex2.h" ++ ++#include "regcclass.h" ++#include "regcname.h" ++ ++#include ++/* Pessimistically bound memory use */ ++#define SIZE_MAX UINT_MAX ++ ++/* ++ * parse structure, passed up and down to avoid global variables and ++ * other clumsinesses ++ */ ++struct parse { ++ char *next; /* next character in RE */ ++ char *end; /* end of string (-> NUL normally) */ ++ int error; /* has an error been seen? */ ++ sop *strip; /* malloced strip */ ++ sopno ssize; /* malloced strip size (allocated) */ ++ sopno slen; /* malloced strip length (used) */ ++ int ncsalloc; /* number of csets allocated */ ++ struct re_guts *g; ++# define NPAREN 10 /* we need to remember () 1-9 for back refs */ ++ sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ ++ sopno pend[NPAREN]; /* -> ) ([0] unused) */ ++}; ++ ++static void p_ere(struct parse *, int); ++static void p_ere_exp(struct parse *); ++static void p_str(struct parse *); ++static void p_bre(struct parse *, int, int); ++static int p_simp_re(struct parse *, int); ++static int p_count(struct parse *); ++static void p_bracket(struct parse *); ++static void p_b_term(struct parse *, cset *); ++static void p_b_cclass(struct parse *, cset *); ++static void p_b_eclass(struct parse *, cset *); ++static char p_b_symbol(struct parse *); ++static char p_b_coll_elem(struct parse *, int); ++static char othercase(int); ++static void bothcases(struct parse *, int); ++static void ordinary(struct parse *, int); ++static void nonnewline(struct parse *); ++static void repeat(struct parse *, sopno, int, int); ++static int seterr(struct parse *, int); ++static cset *allocset(struct parse *); ++static void freeset(struct parse *, cset *); ++static int freezeset(struct parse *, cset *); ++static int firstch(struct parse *, cset *); ++static int nch(struct parse *, cset *); ++static void mcadd(struct parse *, cset *, const char *); ++static void mcinvert(struct parse *, cset *); ++static void mccase(struct parse *, cset *); ++static int isinsets(struct re_guts *, int); ++static int samesets(struct re_guts *, int, int); ++static void categorize(struct parse *, struct re_guts *); ++static sopno dupl(struct parse *, sopno, sopno); ++static void doemit(struct parse *, sop, size_t); ++static void doinsert(struct parse *, sop, size_t, sopno); ++static void dofwd(struct parse *, sopno, sop); ++static void enlarge(struct parse *, sopno); ++static void stripsnug(struct parse *, struct re_guts *); ++static void findmust(struct parse *, struct re_guts *); ++static sopno pluscount(struct parse *, struct re_guts *); ++ ++static char nuls[10]; /* place to point scanner in event of error */ ++ ++/* ++ * macros for use with parse structure ++ * BEWARE: these know that the parse structure is named `p' !!! ++ */ ++#define PEEK() (*p->next) ++#define PEEK2() (*(p->next+1)) ++#define MORE() (p->next < p->end) ++#define MORE2() (p->next+1 < p->end) ++#define SEE(c) (MORE() && PEEK() == (c)) ++#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b)) ++#define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0) ++#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) ++#define NEXT() (p->next++) ++#define NEXT2() (p->next += 2) ++#define NEXTn(n) (p->next += (n)) ++#define GETNEXT() (*p->next++) ++#define SETERROR(e) seterr(p, (e)) ++#define REQUIRE(co, e) (void)((co) || SETERROR(e)) ++#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) ++#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) ++#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) ++#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) ++#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) ++#define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) ++#define ASTERN(sop, pos) EMIT(sop, HERE()-pos) ++#define HERE() (p->slen) ++#define THERE() (p->slen - 1) ++#define THERETHERE() (p->slen - 2) ++#define DROP(n) (p->slen -= (n)) ++ ++#ifdef _POSIX2_RE_DUP_MAX ++#define DUPMAX _POSIX2_RE_DUP_MAX ++#else ++#define DUPMAX 255 ++#endif ++#define INFINITY (DUPMAX + 1) ++ ++#ifndef NDEBUG ++static int never = 0; /* for use in asserts; shuts lint up */ ++#else ++#define never 0 /* some s have bugs too */ ++#endif ++ ++/* ++ - llvm_regcomp - interface for parser and compilation ++ */ ++int /* 0 success, otherwise REG_something */ ++llvm_regcomp(llvm_regex_t *preg, const char *pattern, int cflags) ++{ ++ struct parse pa; ++ struct re_guts *g; ++ struct parse *p = &pa; ++ int i; ++ size_t len; ++#ifdef REDEBUG ++# define GOODFLAGS(f) (f) ++#else ++# define GOODFLAGS(f) ((f)&~REG_DUMP) ++#endif ++ ++ cflags = GOODFLAGS(cflags); ++ if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) ++ return(REG_INVARG); ++ ++ if (cflags®_PEND) { ++ if (preg->re_endp < pattern) ++ return(REG_INVARG); ++ len = preg->re_endp - pattern; ++ } else ++ len = strlen((const char *)pattern); ++ ++ /* do the mallocs early so failure handling is easy */ ++ g = (struct re_guts *)malloc(sizeof(struct re_guts) + ++ (NC-1)*sizeof(cat_t)); ++ if (g == NULL) ++ return(REG_ESPACE); ++ p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ ++ p->strip = (sop *)calloc(p->ssize, sizeof(sop)); ++ p->slen = 0; ++ if (p->strip == NULL) { ++ free((char *)g); ++ return(REG_ESPACE); ++ } ++ ++ /* set things up */ ++ p->g = g; ++ p->next = (char *)pattern; /* convenience; we do not modify it */ ++ p->end = p->next + len; ++ p->error = 0; ++ p->ncsalloc = 0; ++ for (i = 0; i < NPAREN; i++) { ++ p->pbegin[i] = 0; ++ p->pend[i] = 0; ++ } ++ g->csetsize = NC; ++ g->sets = NULL; ++ g->setbits = NULL; ++ g->ncsets = 0; ++ g->cflags = cflags; ++ g->iflags = 0; ++ g->nbol = 0; ++ g->neol = 0; ++ g->must = NULL; ++ g->mlen = 0; ++ g->nsub = 0; ++ g->ncategories = 1; /* category 0 is "everything else" */ ++ g->categories = &g->catspace[-(CHAR_MIN)]; ++ (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); ++ g->backrefs = 0; ++ ++ /* do it */ ++ EMIT(OEND, 0); ++ g->firststate = THERE(); ++ if (cflags®_EXTENDED) ++ p_ere(p, OUT); ++ else if (cflags®_NOSPEC) ++ p_str(p); ++ else ++ p_bre(p, OUT, OUT); ++ EMIT(OEND, 0); ++ g->laststate = THERE(); ++ ++ /* tidy up loose ends and fill things in */ ++ categorize(p, g); ++ stripsnug(p, g); ++ findmust(p, g); ++ g->nplus = pluscount(p, g); ++ g->magic = MAGIC2; ++ preg->re_nsub = g->nsub; ++ preg->re_g = g; ++ preg->re_magic = MAGIC1; ++#ifndef REDEBUG ++ /* not debugging, so can't rely on the assert() in llvm_regexec() */ ++ if (g->iflags®EX_BAD) ++ SETERROR(REG_ASSERT); ++#endif ++ ++ /* win or lose, we're done */ ++ if (p->error != 0) /* lose */ ++ llvm_regfree(preg); ++ return(p->error); ++} ++ ++/* ++ - p_ere - ERE parser top level, concatenation and alternation ++ */ ++static void ++p_ere(struct parse *p, int stop) /* character this ERE should end at */ ++{ ++ char c; ++ sopno prevback = 0; ++ sopno prevfwd = 0; ++ sopno conc; ++ int first = 1; /* is this the first alternative? */ ++ ++ for (;;) { ++ /* do a bunch of concatenated expressions */ ++ conc = HERE(); ++ while (MORE() && (c = PEEK()) != '|' && c != stop) ++ p_ere_exp(p); ++ REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ ++ ++ if (!EAT('|')) ++ break; /* NOTE BREAK OUT */ ++ ++ if (first) { ++ INSERT(OCH_, conc); /* offset is wrong */ ++ prevfwd = conc; ++ prevback = conc; ++ first = 0; ++ } ++ ASTERN(OOR1, prevback); ++ prevback = THERE(); ++ AHEAD(prevfwd); /* fix previous offset */ ++ prevfwd = HERE(); ++ EMIT(OOR2, 0); /* offset is very wrong */ ++ } ++ ++ if (!first) { /* tail-end fixups */ ++ AHEAD(prevfwd); ++ ASTERN(O_CH, prevback); ++ } ++ ++ assert(!MORE() || SEE(stop)); ++} ++ ++/* ++ - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op ++ */ ++static void ++p_ere_exp(struct parse *p) ++{ ++ char c; ++ sopno pos; ++ int count; ++ int count2; ++ int backrefnum; ++ sopno subno; ++ int wascaret = 0; ++ ++ assert(MORE()); /* caller should have ensured this */ ++ c = GETNEXT(); ++ ++ pos = HERE(); ++ switch (c) { ++ case '(': ++ REQUIRE(MORE(), REG_EPAREN); ++ p->g->nsub++; ++ subno = p->g->nsub; ++ if (subno < NPAREN) ++ p->pbegin[subno] = HERE(); ++ EMIT(OLPAREN, subno); ++ if (!SEE(')')) ++ p_ere(p, ')'); ++ if (subno < NPAREN) { ++ p->pend[subno] = HERE(); ++ assert(p->pend[subno] != 0); ++ } ++ EMIT(ORPAREN, subno); ++ MUSTEAT(')', REG_EPAREN); ++ break; ++#ifndef POSIX_MISTAKE ++ case ')': /* happens only if no current unmatched ( */ ++ /* ++ * You may ask, why the ifndef? Because I didn't notice ++ * this until slightly too late for 1003.2, and none of the ++ * other 1003.2 regular-expression reviewers noticed it at ++ * all. So an unmatched ) is legal POSIX, at least until ++ * we can get it fixed. ++ */ ++ SETERROR(REG_EPAREN); ++ break; ++#endif ++ case '^': ++ EMIT(OBOL, 0); ++ p->g->iflags |= USEBOL; ++ p->g->nbol++; ++ wascaret = 1; ++ break; ++ case '$': ++ EMIT(OEOL, 0); ++ p->g->iflags |= USEEOL; ++ p->g->neol++; ++ break; ++ case '|': ++ SETERROR(REG_EMPTY); ++ break; ++ case '*': ++ case '+': ++ case '?': ++ SETERROR(REG_BADRPT); ++ break; ++ case '.': ++ if (p->g->cflags®_NEWLINE) ++ nonnewline(p); ++ else ++ EMIT(OANY, 0); ++ break; ++ case '[': ++ p_bracket(p); ++ break; ++ case '\\': ++ REQUIRE(MORE(), REG_EESCAPE); ++ c = GETNEXT(); ++ if (c >= '1' && c <= '9') { ++ /* \[0-9] is taken to be a back-reference to a previously specified ++ * matching group. backrefnum will hold the number. The matching ++ * group must exist (i.e. if \4 is found there must have been at ++ * least 4 matching groups specified in the pattern previously). ++ */ ++ backrefnum = c - '0'; ++ if (p->pend[backrefnum] == 0) { ++ SETERROR(REG_ESUBREG); ++ break; ++ } ++ ++ /* Make sure everything checks out and emit the sequence ++ * that marks a back-reference to the parse structure. ++ */ ++ assert(backrefnum <= p->g->nsub); ++ EMIT(OBACK_, backrefnum); ++ assert(p->pbegin[backrefnum] != 0); ++ assert(OP(p->strip[p->pbegin[backrefnum]]) != OLPAREN); ++ assert(OP(p->strip[p->pend[backrefnum]]) != ORPAREN); ++ (void) dupl(p, p->pbegin[backrefnum]+1, p->pend[backrefnum]); ++ EMIT(O_BACK, backrefnum); ++ p->g->backrefs = 1; ++ } else { ++ /* Other chars are simply themselves when escaped with a backslash. ++ */ ++ ordinary(p, c); ++ } ++ break; ++ case '{': /* okay as ordinary except if digit follows */ ++ REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT); ++ /* FALLTHROUGH */ ++ default: ++ ordinary(p, c); ++ break; ++ } ++ ++ if (!MORE()) ++ return; ++ c = PEEK(); ++ /* we call { a repetition if followed by a digit */ ++ if (!( c == '*' || c == '+' || c == '?' || ++ (c == '{' && MORE2() && isdigit((uch)PEEK2())) )) ++ return; /* no repetition, we're done */ ++ NEXT(); ++ ++ REQUIRE(!wascaret, REG_BADRPT); ++ switch (c) { ++ case '*': /* implemented as +? */ ++ /* this case does not require the (y|) trick, noKLUDGE */ ++ INSERT(OPLUS_, pos); ++ ASTERN(O_PLUS, pos); ++ INSERT(OQUEST_, pos); ++ ASTERN(O_QUEST, pos); ++ break; ++ case '+': ++ INSERT(OPLUS_, pos); ++ ASTERN(O_PLUS, pos); ++ break; ++ case '?': ++ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ ++ INSERT(OCH_, pos); /* offset slightly wrong */ ++ ASTERN(OOR1, pos); /* this one's right */ ++ AHEAD(pos); /* fix the OCH_ */ ++ EMIT(OOR2, 0); /* offset very wrong... */ ++ AHEAD(THERE()); /* ...so fix it */ ++ ASTERN(O_CH, THERETHERE()); ++ break; ++ case '{': ++ count = p_count(p); ++ if (EAT(',')) { ++ if (isdigit((uch)PEEK())) { ++ count2 = p_count(p); ++ REQUIRE(count <= count2, REG_BADBR); ++ } else /* single number with comma */ ++ count2 = INFINITY; ++ } else /* just a single number */ ++ count2 = count; ++ repeat(p, pos, count, count2); ++ if (!EAT('}')) { /* error heuristics */ ++ while (MORE() && PEEK() != '}') ++ NEXT(); ++ REQUIRE(MORE(), REG_EBRACE); ++ SETERROR(REG_BADBR); ++ } ++ break; ++ } ++ ++ if (!MORE()) ++ return; ++ c = PEEK(); ++ if (!( c == '*' || c == '+' || c == '?' || ++ (c == '{' && MORE2() && isdigit((uch)PEEK2())) ) ) ++ return; ++ SETERROR(REG_BADRPT); ++} ++ ++/* ++ - p_str - string (no metacharacters) "parser" ++ */ ++static void ++p_str(struct parse *p) ++{ ++ REQUIRE(MORE(), REG_EMPTY); ++ while (MORE()) ++ ordinary(p, GETNEXT()); ++} ++ ++/* ++ - p_bre - BRE parser top level, anchoring and concatenation ++ * Giving end1 as OUT essentially eliminates the end1/end2 check. ++ * ++ * This implementation is a bit of a kludge, in that a trailing $ is first ++ * taken as an ordinary character and then revised to be an anchor. The ++ * only undesirable side effect is that '$' gets included as a character ++ * category in such cases. This is fairly harmless; not worth fixing. ++ * The amount of lookahead needed to avoid this kludge is excessive. ++ */ ++static void ++p_bre(struct parse *p, ++ int end1, /* first terminating character */ ++ int end2) /* second terminating character */ ++{ ++ sopno start = HERE(); ++ int first = 1; /* first subexpression? */ ++ int wasdollar = 0; ++ ++ if (EAT('^')) { ++ EMIT(OBOL, 0); ++ p->g->iflags |= USEBOL; ++ p->g->nbol++; ++ } ++ while (MORE() && !SEETWO(end1, end2)) { ++ wasdollar = p_simp_re(p, first); ++ first = 0; ++ } ++ if (wasdollar) { /* oops, that was a trailing anchor */ ++ DROP(1); ++ EMIT(OEOL, 0); ++ p->g->iflags |= USEEOL; ++ p->g->neol++; ++ } ++ ++ REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ ++} ++ ++/* ++ - p_simp_re - parse a simple RE, an atom possibly followed by a repetition ++ */ ++static int /* was the simple RE an unbackslashed $? */ ++p_simp_re(struct parse *p, ++ int starordinary) /* is a leading * an ordinary character? */ ++{ ++ int c; ++ int count; ++ int count2; ++ sopno pos; ++ int i; ++ sopno subno; ++# define BACKSL (1<g->cflags®_NEWLINE) ++ nonnewline(p); ++ else ++ EMIT(OANY, 0); ++ break; ++ case '[': ++ p_bracket(p); ++ break; ++ case BACKSL|'{': ++ SETERROR(REG_BADRPT); ++ break; ++ case BACKSL|'(': ++ p->g->nsub++; ++ subno = p->g->nsub; ++ if (subno < NPAREN) ++ p->pbegin[subno] = HERE(); ++ EMIT(OLPAREN, subno); ++ /* the MORE here is an error heuristic */ ++ if (MORE() && !SEETWO('\\', ')')) ++ p_bre(p, '\\', ')'); ++ if (subno < NPAREN) { ++ p->pend[subno] = HERE(); ++ assert(p->pend[subno] != 0); ++ } ++ EMIT(ORPAREN, subno); ++ REQUIRE(EATTWO('\\', ')'), REG_EPAREN); ++ break; ++ case BACKSL|')': /* should not get here -- must be user */ ++ case BACKSL|'}': ++ SETERROR(REG_EPAREN); ++ break; ++ case BACKSL|'1': ++ case BACKSL|'2': ++ case BACKSL|'3': ++ case BACKSL|'4': ++ case BACKSL|'5': ++ case BACKSL|'6': ++ case BACKSL|'7': ++ case BACKSL|'8': ++ case BACKSL|'9': ++ i = (c&~BACKSL) - '0'; ++ assert(i < NPAREN); ++ if (p->pend[i] != 0) { ++ assert(i <= p->g->nsub); ++ EMIT(OBACK_, i); ++ assert(p->pbegin[i] != 0); ++ assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); ++ assert(OP(p->strip[p->pend[i]]) == ORPAREN); ++ (void) dupl(p, p->pbegin[i]+1, p->pend[i]); ++ EMIT(O_BACK, i); ++ } else ++ SETERROR(REG_ESUBREG); ++ p->g->backrefs = 1; ++ break; ++ case '*': ++ REQUIRE(starordinary, REG_BADRPT); ++ /* FALLTHROUGH */ ++ default: ++ ordinary(p, (char)c); ++ break; ++ } ++ ++ if (EAT('*')) { /* implemented as +? */ ++ /* this case does not require the (y|) trick, noKLUDGE */ ++ INSERT(OPLUS_, pos); ++ ASTERN(O_PLUS, pos); ++ INSERT(OQUEST_, pos); ++ ASTERN(O_QUEST, pos); ++ } else if (EATTWO('\\', '{')) { ++ count = p_count(p); ++ if (EAT(',')) { ++ if (MORE() && isdigit((uch)PEEK())) { ++ count2 = p_count(p); ++ REQUIRE(count <= count2, REG_BADBR); ++ } else /* single number with comma */ ++ count2 = INFINITY; ++ } else /* just a single number */ ++ count2 = count; ++ repeat(p, pos, count, count2); ++ if (!EATTWO('\\', '}')) { /* error heuristics */ ++ while (MORE() && !SEETWO('\\', '}')) ++ NEXT(); ++ REQUIRE(MORE(), REG_EBRACE); ++ SETERROR(REG_BADBR); ++ } ++ } else if (c == '$') /* $ (but not \$) ends it */ ++ return(1); ++ ++ return(0); ++} ++ ++/* ++ - p_count - parse a repetition count ++ */ ++static int /* the value */ ++p_count(struct parse *p) ++{ ++ int count = 0; ++ int ndigits = 0; ++ ++ while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) { ++ count = count*10 + (GETNEXT() - '0'); ++ ndigits++; ++ } ++ ++ REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); ++ return(count); ++} ++ ++/* ++ - p_bracket - parse a bracketed character list ++ * ++ * Note a significant property of this code: if the allocset() did SETERROR, ++ * no set operations are done. ++ */ ++static void ++p_bracket(struct parse *p) ++{ ++ cset *cs; ++ int invert = 0; ++ ++ /* Dept of Truly Sickening Special-Case Kludges */ ++ if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { ++ EMIT(OBOW, 0); ++ NEXTn(6); ++ return; ++ } ++ if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { ++ EMIT(OEOW, 0); ++ NEXTn(6); ++ return; ++ } ++ ++ if ((cs = allocset(p)) == NULL) { ++ /* allocset did set error status in p */ ++ return; ++ } ++ ++ if (EAT('^')) ++ invert++; /* make note to invert set at end */ ++ if (EAT(']')) ++ CHadd(cs, ']'); ++ else if (EAT('-')) ++ CHadd(cs, '-'); ++ while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) ++ p_b_term(p, cs); ++ if (EAT('-')) ++ CHadd(cs, '-'); ++ MUSTEAT(']', REG_EBRACK); ++ ++ if (p->error != 0) { /* don't mess things up further */ ++ freeset(p, cs); ++ return; ++ } ++ ++ if (p->g->cflags®_ICASE) { ++ int i; ++ int ci; ++ ++ for (i = p->g->csetsize - 1; i >= 0; i--) ++ if (CHIN(cs, i) && isalpha(i)) { ++ ci = othercase(i); ++ if (ci != i) ++ CHadd(cs, ci); ++ } ++ if (cs->multis != NULL) ++ mccase(p, cs); ++ } ++ if (invert) { ++ int i; ++ ++ for (i = p->g->csetsize - 1; i >= 0; i--) ++ if (CHIN(cs, i)) ++ CHsub(cs, i); ++ else ++ CHadd(cs, i); ++ if (p->g->cflags®_NEWLINE) ++ CHsub(cs, '\n'); ++ if (cs->multis != NULL) ++ mcinvert(p, cs); ++ } ++ ++ assert(cs->multis == NULL); /* xxx */ ++ ++ if (nch(p, cs) == 1) { /* optimize singleton sets */ ++ ordinary(p, firstch(p, cs)); ++ freeset(p, cs); ++ } else ++ EMIT(OANYOF, freezeset(p, cs)); ++} ++ ++/* ++ - p_b_term - parse one term of a bracketed character list ++ */ ++static void ++p_b_term(struct parse *p, cset *cs) ++{ ++ char c; ++ char start, finish; ++ int i; ++ ++ /* classify what we've got */ ++ switch ((MORE()) ? PEEK() : '\0') { ++ case '[': ++ c = (MORE2()) ? PEEK2() : '\0'; ++ break; ++ case '-': ++ SETERROR(REG_ERANGE); ++ return; /* NOTE RETURN */ ++ break; ++ default: ++ c = '\0'; ++ break; ++ } ++ ++ switch (c) { ++ case ':': /* character class */ ++ NEXT2(); ++ REQUIRE(MORE(), REG_EBRACK); ++ c = PEEK(); ++ REQUIRE(c != '-' && c != ']', REG_ECTYPE); ++ p_b_cclass(p, cs); ++ REQUIRE(MORE(), REG_EBRACK); ++ REQUIRE(EATTWO(':', ']'), REG_ECTYPE); ++ break; ++ case '=': /* equivalence class */ ++ NEXT2(); ++ REQUIRE(MORE(), REG_EBRACK); ++ c = PEEK(); ++ REQUIRE(c != '-' && c != ']', REG_ECOLLATE); ++ p_b_eclass(p, cs); ++ REQUIRE(MORE(), REG_EBRACK); ++ REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); ++ break; ++ default: /* symbol, ordinary character, or range */ ++/* xxx revision needed for multichar stuff */ ++ start = p_b_symbol(p); ++ if (SEE('-') && MORE2() && PEEK2() != ']') { ++ /* range */ ++ NEXT(); ++ if (EAT('-')) ++ finish = '-'; ++ else ++ finish = p_b_symbol(p); ++ } else ++ finish = start; ++/* xxx what about signed chars here... */ ++ REQUIRE(start <= finish, REG_ERANGE); ++ for (i = start; i <= finish; i++) ++ CHadd(cs, i); ++ break; ++ } ++} ++ ++/* ++ - p_b_cclass - parse a character-class name and deal with it ++ */ ++static void ++p_b_cclass(struct parse *p, cset *cs) ++{ ++ char *sp = p->next; ++ struct cclass *cp; ++ size_t len; ++ const char *u; ++ char c; ++ ++ while (MORE() && isalpha((uch)PEEK())) ++ NEXT(); ++ len = p->next - sp; ++ for (cp = cclasses; cp->name != NULL; cp++) ++ if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') ++ break; ++ if (cp->name == NULL) { ++ /* oops, didn't find it */ ++ SETERROR(REG_ECTYPE); ++ return; ++ } ++ ++ u = cp->chars; ++ while ((c = *u++) != '\0') ++ CHadd(cs, c); ++ for (u = cp->multis; *u != '\0'; u += strlen(u) + 1) ++ MCadd(p, cs, u); ++} ++ ++/* ++ - p_b_eclass - parse an equivalence-class name and deal with it ++ * ++ * This implementation is incomplete. xxx ++ */ ++static void ++p_b_eclass(struct parse *p, cset *cs) ++{ ++ char c; ++ ++ c = p_b_coll_elem(p, '='); ++ CHadd(cs, c); ++} ++ ++/* ++ - p_b_symbol - parse a character or [..]ed multicharacter collating symbol ++ */ ++static char /* value of symbol */ ++p_b_symbol(struct parse *p) ++{ ++ char value; ++ ++ REQUIRE(MORE(), REG_EBRACK); ++ if (!EATTWO('[', '.')) ++ return(GETNEXT()); ++ ++ /* collating symbol */ ++ value = p_b_coll_elem(p, '.'); ++ REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); ++ return(value); ++} ++ ++/* ++ - p_b_coll_elem - parse a collating-element name and look it up ++ */ ++static char /* value of collating element */ ++p_b_coll_elem(struct parse *p, ++ int endc) /* name ended by endc,']' */ ++{ ++ char *sp = p->next; ++ struct cname *cp; ++ int len; ++ ++ while (MORE() && !SEETWO(endc, ']')) ++ NEXT(); ++ if (!MORE()) { ++ SETERROR(REG_EBRACK); ++ return(0); ++ } ++ len = p->next - sp; ++ for (cp = cnames; cp->name != NULL; cp++) ++ if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') ++ return(cp->code); /* known name */ ++ if (len == 1) ++ return(*sp); /* single character */ ++ SETERROR(REG_ECOLLATE); /* neither */ ++ return(0); ++} ++ ++/* ++ - othercase - return the case counterpart of an alphabetic ++ */ ++static char /* if no counterpart, return ch */ ++othercase(int ch) ++{ ++ ch = (uch)ch; ++ assert(isalpha(ch)); ++ if (isupper(ch)) ++ return ((uch)tolower(ch)); ++ else if (islower(ch)) ++ return ((uch)toupper(ch)); ++ else /* peculiar, but could happen */ ++ return(ch); ++} ++ ++/* ++ - bothcases - emit a dualcase version of a two-case character ++ * ++ * Boy, is this implementation ever a kludge... ++ */ ++static void ++bothcases(struct parse *p, int ch) ++{ ++ char *oldnext = p->next; ++ char *oldend = p->end; ++ char bracket[3]; ++ ++ ch = (uch)ch; ++ assert(othercase(ch) != ch); /* p_bracket() would recurse */ ++ p->next = bracket; ++ p->end = bracket+2; ++ bracket[0] = ch; ++ bracket[1] = ']'; ++ bracket[2] = '\0'; ++ p_bracket(p); ++ assert(p->next == bracket+2); ++ p->next = oldnext; ++ p->end = oldend; ++} ++ ++/* ++ - ordinary - emit an ordinary character ++ */ ++static void ++ordinary(struct parse *p, int ch) ++{ ++ cat_t *cap = p->g->categories; ++ ++ if ((p->g->cflags®_ICASE) && isalpha((uch)ch) && othercase(ch) != ch) ++ bothcases(p, ch); ++ else { ++ EMIT(OCHAR, (uch)ch); ++ if (cap[ch] == 0) ++ cap[ch] = p->g->ncategories++; ++ } ++} ++ ++/* ++ - nonnewline - emit REG_NEWLINE version of OANY ++ * ++ * Boy, is this implementation ever a kludge... ++ */ ++static void ++nonnewline(struct parse *p) ++{ ++ char *oldnext = p->next; ++ char *oldend = p->end; ++ char bracket[4]; ++ ++ p->next = bracket; ++ p->end = bracket+3; ++ bracket[0] = '^'; ++ bracket[1] = '\n'; ++ bracket[2] = ']'; ++ bracket[3] = '\0'; ++ p_bracket(p); ++ assert(p->next == bracket+3); ++ p->next = oldnext; ++ p->end = oldend; ++} ++ ++/* ++ - repeat - generate code for a bounded repetition, recursively if needed ++ */ ++static void ++repeat(struct parse *p, ++ sopno start, /* operand from here to end of strip */ ++ int from, /* repeated from this number */ ++ int to) /* to this number of times (maybe INFINITY) */ ++{ ++ sopno finish = HERE(); ++# define N 2 ++# define INF 3 ++# define REP(f, t) ((f)*8 + (t)) ++# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) ++ sopno copy; ++ ++ if (p->error != 0) /* head off possible runaway recursion */ ++ return; ++ ++ assert(from <= to); ++ ++ switch (REP(MAP(from), MAP(to))) { ++ case REP(0, 0): /* must be user doing this */ ++ DROP(finish-start); /* drop the operand */ ++ break; ++ case REP(0, 1): /* as x{1,1}? */ ++ case REP(0, N): /* as x{1,n}? */ ++ case REP(0, INF): /* as x{1,}? */ ++ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ ++ INSERT(OCH_, start); /* offset is wrong... */ ++ repeat(p, start+1, 1, to); ++ ASTERN(OOR1, start); ++ AHEAD(start); /* ... fix it */ ++ EMIT(OOR2, 0); ++ AHEAD(THERE()); ++ ASTERN(O_CH, THERETHERE()); ++ break; ++ case REP(1, 1): /* trivial case */ ++ /* done */ ++ break; ++ case REP(1, N): /* as x?x{1,n-1} */ ++ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ ++ INSERT(OCH_, start); ++ ASTERN(OOR1, start); ++ AHEAD(start); ++ EMIT(OOR2, 0); /* offset very wrong... */ ++ AHEAD(THERE()); /* ...so fix it */ ++ ASTERN(O_CH, THERETHERE()); ++ copy = dupl(p, start+1, finish+1); ++ assert(copy == finish+4); ++ repeat(p, copy, 1, to-1); ++ break; ++ case REP(1, INF): /* as x+ */ ++ INSERT(OPLUS_, start); ++ ASTERN(O_PLUS, start); ++ break; ++ case REP(N, N): /* as xx{m-1,n-1} */ ++ copy = dupl(p, start, finish); ++ repeat(p, copy, from-1, to-1); ++ break; ++ case REP(N, INF): /* as xx{n-1,INF} */ ++ copy = dupl(p, start, finish); ++ repeat(p, copy, from-1, to); ++ break; ++ default: /* "can't happen" */ ++ SETERROR(REG_ASSERT); /* just in case */ ++ break; ++ } ++} ++ ++/* ++ - seterr - set an error condition ++ */ ++static int /* useless but makes type checking happy */ ++seterr(struct parse *p, int e) ++{ ++ if (p->error == 0) /* keep earliest error condition */ ++ p->error = e; ++ p->next = nuls; /* try to bring things to a halt */ ++ p->end = nuls; ++ return(0); /* make the return value well-defined */ ++} ++ ++/* ++ - allocset - allocate a set of characters for [] ++ */ ++static cset * ++allocset(struct parse *p) ++{ ++ int no = p->g->ncsets++; ++ size_t nc; ++ size_t nbytes; ++ cset *cs; ++ size_t css = (size_t)p->g->csetsize; ++ int i; ++ ++ if (no >= p->ncsalloc) { /* need another column of space */ ++ void *ptr; ++ ++ p->ncsalloc += CHAR_BIT; ++ nc = p->ncsalloc; ++ if (nc > SIZE_MAX / sizeof(cset)) ++ goto nomem; ++ assert(nc % CHAR_BIT == 0); ++ nbytes = nc / CHAR_BIT * css; ++ ++ ptr = (cset *)realloc((char *)p->g->sets, nc * sizeof(cset)); ++ if (ptr == NULL) ++ goto nomem; ++ p->g->sets = ptr; ++ ++ ptr = (uch *)realloc((char *)p->g->setbits, nbytes); ++ if (ptr == NULL) ++ goto nomem; ++ p->g->setbits = ptr; ++ ++ for (i = 0; i < no; i++) ++ p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); ++ ++ (void) memset((char *)p->g->setbits + (nbytes - css), 0, css); ++ } ++ /* XXX should not happen */ ++ if (p->g->sets == NULL || p->g->setbits == NULL) ++ goto nomem; ++ ++ cs = &p->g->sets[no]; ++ cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); ++ cs->mask = 1 << ((no) % CHAR_BIT); ++ cs->hash = 0; ++ cs->smultis = 0; ++ cs->multis = NULL; ++ ++ return(cs); ++nomem: ++ free(p->g->sets); ++ p->g->sets = NULL; ++ free(p->g->setbits); ++ p->g->setbits = NULL; ++ ++ SETERROR(REG_ESPACE); ++ /* caller's responsibility not to do set ops */ ++ return(NULL); ++} ++ ++/* ++ - freeset - free a now-unused set ++ */ ++static void ++freeset(struct parse *p, cset *cs) ++{ ++ size_t i; ++ cset *top = &p->g->sets[p->g->ncsets]; ++ size_t css = (size_t)p->g->csetsize; ++ ++ for (i = 0; i < css; i++) ++ CHsub(cs, i); ++ if (cs == top-1) /* recover only the easy case */ ++ p->g->ncsets--; ++} ++ ++/* ++ - freezeset - final processing on a set of characters ++ * ++ * The main task here is merging identical sets. This is usually a waste ++ * of time (although the hash code minimizes the overhead), but can win ++ * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash ++ * is done using addition rather than xor -- all ASCII [aA] sets xor to ++ * the same value! ++ */ ++static int /* set number */ ++freezeset(struct parse *p, cset *cs) ++{ ++ uch h = cs->hash; ++ size_t i; ++ cset *top = &p->g->sets[p->g->ncsets]; ++ cset *cs2; ++ size_t css = (size_t)p->g->csetsize; ++ ++ /* look for an earlier one which is the same */ ++ for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) ++ if (cs2->hash == h && cs2 != cs) { ++ /* maybe */ ++ for (i = 0; i < css; i++) ++ if (!!CHIN(cs2, i) != !!CHIN(cs, i)) ++ break; /* no */ ++ if (i == css) ++ break; /* yes */ ++ } ++ ++ if (cs2 < top) { /* found one */ ++ freeset(p, cs); ++ cs = cs2; ++ } ++ ++ return((int)(cs - p->g->sets)); ++} ++ ++/* ++ - firstch - return first character in a set (which must have at least one) ++ */ ++static int /* character; there is no "none" value */ ++firstch(struct parse *p, cset *cs) ++{ ++ size_t i; ++ size_t css = (size_t)p->g->csetsize; ++ ++ for (i = 0; i < css; i++) ++ if (CHIN(cs, i)) ++ return((char)i); ++ assert(never); ++ return(0); /* arbitrary */ ++} ++ ++/* ++ - nch - number of characters in a set ++ */ ++static int ++nch(struct parse *p, cset *cs) ++{ ++ size_t i; ++ size_t css = (size_t)p->g->csetsize; ++ int n = 0; ++ ++ for (i = 0; i < css; i++) ++ if (CHIN(cs, i)) ++ n++; ++ return(n); ++} ++ ++/* ++ - mcadd - add a collating element to a cset ++ */ ++static void ++mcadd( struct parse *p, cset *cs, const char *cp) ++{ ++ size_t oldend = cs->smultis; ++ void *np; ++ ++ cs->smultis += strlen(cp) + 1; ++ np = realloc(cs->multis, cs->smultis); ++ if (np == NULL) { ++ if (cs->multis) ++ free(cs->multis); ++ cs->multis = NULL; ++ SETERROR(REG_ESPACE); ++ return; ++ } ++ cs->multis = np; ++ ++ llvm_strlcpy(cs->multis + oldend - 1, cp, cs->smultis - oldend + 1); ++} ++ ++/* ++ - mcinvert - invert the list of collating elements in a cset ++ * ++ * This would have to know the set of possibilities. Implementation ++ * is deferred. ++ */ ++/* ARGSUSED */ ++static void ++mcinvert(struct parse *p, cset *cs) ++{ ++ assert(cs->multis == NULL); /* xxx */ ++} ++ ++/* ++ - mccase - add case counterparts of the list of collating elements in a cset ++ * ++ * This would have to know the set of possibilities. Implementation ++ * is deferred. ++ */ ++/* ARGSUSED */ ++static void ++mccase(struct parse *p, cset *cs) ++{ ++ assert(cs->multis == NULL); /* xxx */ ++} ++ ++/* ++ - isinsets - is this character in any sets? ++ */ ++static int /* predicate */ ++isinsets(struct re_guts *g, int c) ++{ ++ uch *col; ++ int i; ++ int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; ++ unsigned uc = (uch)c; ++ ++ for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) ++ if (col[uc] != 0) ++ return(1); ++ return(0); ++} ++ ++/* ++ - samesets - are these two characters in exactly the same sets? ++ */ ++static int /* predicate */ ++samesets(struct re_guts *g, int c1, int c2) ++{ ++ uch *col; ++ int i; ++ int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; ++ unsigned uc1 = (uch)c1; ++ unsigned uc2 = (uch)c2; ++ ++ for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) ++ if (col[uc1] != col[uc2]) ++ return(0); ++ return(1); ++} ++ ++/* ++ - categorize - sort out character categories ++ */ ++static void ++categorize(struct parse *p, struct re_guts *g) ++{ ++ cat_t *cats = g->categories; ++ int c; ++ int c2; ++ cat_t cat; ++ ++ /* avoid making error situations worse */ ++ if (p->error != 0) ++ return; ++ ++ for (c = CHAR_MIN; c <= CHAR_MAX; c++) ++ if (cats[c] == 0 && isinsets(g, c)) { ++ cat = g->ncategories++; ++ cats[c] = cat; ++ for (c2 = c+1; c2 <= CHAR_MAX; c2++) ++ if (cats[c2] == 0 && samesets(g, c, c2)) ++ cats[c2] = cat; ++ } ++} ++ ++/* ++ - dupl - emit a duplicate of a bunch of sops ++ */ ++static sopno /* start of duplicate */ ++dupl(struct parse *p, ++ sopno start, /* from here */ ++ sopno finish) /* to this less one */ ++{ ++ sopno ret = HERE(); ++ sopno len = finish - start; ++ ++ assert(finish >= start); ++ if (len == 0) ++ return(ret); ++ enlarge(p, p->ssize + len); /* this many unexpected additions */ ++ assert(p->ssize >= p->slen + len); ++ (void) memmove((char *)(p->strip + p->slen), ++ (char *)(p->strip + start), (size_t)len*sizeof(sop)); ++ p->slen += len; ++ return(ret); ++} ++ ++/* ++ - doemit - emit a strip operator ++ * ++ * It might seem better to implement this as a macro with a function as ++ * hard-case backup, but it's just too big and messy unless there are ++ * some changes to the data structures. Maybe later. ++ */ ++static void ++doemit(struct parse *p, sop op, size_t opnd) ++{ ++ /* avoid making error situations worse */ ++ if (p->error != 0) ++ return; ++ ++ /* deal with oversize operands ("can't happen", more or less) */ ++ assert(opnd < 1<slen >= p->ssize) ++ enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */ ++ assert(p->slen < p->ssize); ++ ++ /* finally, it's all reduced to the easy case */ ++ p->strip[p->slen++] = SOP(op, opnd); ++} ++ ++/* ++ - doinsert - insert a sop into the strip ++ */ ++static void ++doinsert(struct parse *p, sop op, size_t opnd, sopno pos) ++{ ++ sopno sn; ++ sop s; ++ int i; ++ ++ /* avoid making error situations worse */ ++ if (p->error != 0) ++ return; ++ ++ sn = HERE(); ++ EMIT(op, opnd); /* do checks, ensure space */ ++ assert(HERE() == sn+1); ++ s = p->strip[sn]; ++ ++ /* adjust paren pointers */ ++ assert(pos > 0); ++ for (i = 1; i < NPAREN; i++) { ++ if (p->pbegin[i] >= pos) { ++ p->pbegin[i]++; ++ } ++ if (p->pend[i] >= pos) { ++ p->pend[i]++; ++ } ++ } ++ ++ memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], ++ (HERE()-pos-1)*sizeof(sop)); ++ p->strip[pos] = s; ++} ++ ++/* ++ - dofwd - complete a forward reference ++ */ ++static void ++dofwd(struct parse *p, sopno pos, sop value) ++{ ++ /* avoid making error situations worse */ ++ if (p->error != 0) ++ return; ++ ++ assert(value < 1<strip[pos] = OP(p->strip[pos]) | value; ++} ++ ++/* ++ - enlarge - enlarge the strip ++ */ ++static void ++enlarge(struct parse *p, sopno size) ++{ ++ sop *sp; ++ ++ if (p->ssize >= size) ++ return; ++ ++ if ((uintptr_t)size > SIZE_MAX / sizeof(sop)) { ++ SETERROR(REG_ESPACE); ++ return; ++ } ++ ++ sp = (sop *)realloc(p->strip, size*sizeof(sop)); ++ if (sp == NULL) { ++ SETERROR(REG_ESPACE); ++ return; ++ } ++ p->strip = sp; ++ p->ssize = size; ++} ++ ++/* ++ - stripsnug - compact the strip ++ */ ++static void ++stripsnug(struct parse *p, struct re_guts *g) ++{ ++ g->nstates = p->slen; ++ if ((uintptr_t)p->slen > SIZE_MAX / sizeof(sop)) { ++ g->strip = p->strip; ++ SETERROR(REG_ESPACE); ++ return; ++ } ++ ++ g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); ++ if (g->strip == NULL) { ++ SETERROR(REG_ESPACE); ++ g->strip = p->strip; ++ } ++} ++ ++/* ++ - findmust - fill in must and mlen with longest mandatory literal string ++ * ++ * This algorithm could do fancy things like analyzing the operands of | ++ * for common subsequences. Someday. This code is simple and finds most ++ * of the interesting cases. ++ * ++ * Note that must and mlen got initialized during setup. ++ */ ++static void ++findmust(struct parse *p, struct re_guts *g) ++{ ++ sop *scan; ++ sop *start = 0; /* start initialized in the default case, after that */ ++ sop *newstart = 0; /* newstart was initialized in the OCHAR case */ ++ sopno newlen; ++ sop s; ++ char *cp; ++ sopno i; ++ ++ /* avoid making error situations worse */ ++ if (p->error != 0) ++ return; ++ ++ /* find the longest OCHAR sequence in strip */ ++ newlen = 0; ++ scan = g->strip + 1; ++ do { ++ s = *scan++; ++ switch (OP(s)) { ++ case OCHAR: /* sequence member */ ++ if (newlen == 0) /* new sequence */ ++ newstart = scan - 1; ++ newlen++; ++ break; ++ case OPLUS_: /* things that don't break one */ ++ case OLPAREN: ++ case ORPAREN: ++ break; ++ case OQUEST_: /* things that must be skipped */ ++ case OCH_: ++ scan--; ++ do { ++ scan += OPND(s); ++ s = *scan; ++ /* assert() interferes w debug printouts */ ++ if (OP(s) != O_QUEST && OP(s) != O_CH && ++ OP(s) != OOR2) { ++ g->iflags |= REGEX_BAD; ++ return; ++ } ++ } while (OP(s) != O_QUEST && OP(s) != O_CH); ++ /* fallthrough */ ++ default: /* things that break a sequence */ ++ if (newlen > g->mlen) { /* ends one */ ++ start = newstart; ++ g->mlen = newlen; ++ } ++ newlen = 0; ++ break; ++ } ++ } while (OP(s) != OEND); ++ ++ if (g->mlen == 0) /* there isn't one */ ++ return; ++ ++ /* turn it into a character string */ ++ g->must = malloc((size_t)g->mlen + 1); ++ if (g->must == NULL) { /* argh; just forget it */ ++ g->mlen = 0; ++ return; ++ } ++ cp = g->must; ++ scan = start; ++ for (i = g->mlen; i > 0; i--) { ++ while (OP(s = *scan++) != OCHAR) ++ continue; ++ assert(cp < g->must + g->mlen); ++ *cp++ = (char)OPND(s); ++ } ++ assert(cp == g->must + g->mlen); ++ *cp++ = '\0'; /* just on general principles */ ++} ++ ++/* ++ - pluscount - count + nesting ++ */ ++static sopno /* nesting depth */ ++pluscount(struct parse *p, struct re_guts *g) ++{ ++ sop *scan; ++ sop s; ++ sopno plusnest = 0; ++ sopno maxnest = 0; ++ ++ if (p->error != 0) ++ return(0); /* there may not be an OEND */ ++ ++ scan = g->strip + 1; ++ do { ++ s = *scan++; ++ switch (OP(s)) { ++ case OPLUS_: ++ plusnest++; ++ break; ++ case O_PLUS: ++ if (plusnest > maxnest) ++ maxnest = plusnest; ++ plusnest--; ++ break; ++ } ++ } while (OP(s) != OEND); ++ if (plusnest != 0) ++ g->iflags |= REGEX_BAD; ++ return(maxnest); ++} +diff -up lldb-3.8.0rc2.src/source/Utility/regerror.c.dave lldb-3.8.0rc2.src/source/Utility/regerror.c +--- lldb-3.8.0rc2.src/source/Utility/regerror.c.dave 2016-02-17 23:19:05.373675777 -0500 ++++ lldb-3.8.0rc2.src/source/Utility/regerror.c 2016-02-17 23:19:05.373675777 -0500 +@@ -0,0 +1,135 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)regerror.c 8.4 (Berkeley) 3/20/94 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "regex_impl.h" ++ ++#include "regutils.h" ++ ++#ifdef _MSC_VER ++#define snprintf _snprintf ++#endif ++ ++static const char *regatoi(const llvm_regex_t *, char *, int); ++ ++static struct rerr { ++ int code; ++ const char *name; ++ const char *explain; ++} rerrs[] = { ++ { REG_NOMATCH, "REG_NOMATCH", "llvm_regexec() failed to match" }, ++ { REG_BADPAT, "REG_BADPAT", "invalid regular expression" }, ++ { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element" }, ++ { REG_ECTYPE, "REG_ECTYPE", "invalid character class" }, ++ { REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)" }, ++ { REG_ESUBREG, "REG_ESUBREG", "invalid backreference number" }, ++ { REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced" }, ++ { REG_EPAREN, "REG_EPAREN", "parentheses not balanced" }, ++ { REG_EBRACE, "REG_EBRACE", "braces not balanced" }, ++ { REG_BADBR, "REG_BADBR", "invalid repetition count(s)" }, ++ { REG_ERANGE, "REG_ERANGE", "invalid character range" }, ++ { REG_ESPACE, "REG_ESPACE", "out of memory" }, ++ { REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid" }, ++ { REG_EMPTY, "REG_EMPTY", "empty (sub)expression" }, ++ { REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug" }, ++ { REG_INVARG, "REG_INVARG", "invalid argument to regex routine" }, ++ { 0, "", "*** unknown regexp error code ***" } ++}; ++ ++/* ++ - llvm_regerror - the interface to error numbers ++ = extern size_t llvm_regerror(int, const llvm_regex_t *, char *, size_t); ++ */ ++/* ARGSUSED */ ++size_t ++llvm_regerror(int errcode, const llvm_regex_t *preg, char *errbuf, size_t errbuf_size) ++{ ++ struct rerr *r; ++ size_t len; ++ int target = errcode &~ REG_ITOA; ++ const char *s; ++ char convbuf[50]; ++ ++ if (errcode == REG_ATOI) ++ s = regatoi(preg, convbuf, sizeof convbuf); ++ else { ++ for (r = rerrs; r->code != 0; r++) ++ if (r->code == target) ++ break; ++ ++ if (errcode®_ITOA) { ++ if (r->code != 0) { ++ assert(strlen(r->name) < sizeof(convbuf)); ++ (void) llvm_strlcpy(convbuf, r->name, sizeof convbuf); ++ } else ++ (void)snprintf(convbuf, sizeof convbuf, ++ "REG_0x%x", target); ++ s = convbuf; ++ } else ++ s = r->explain; ++ } ++ ++ len = strlen(s) + 1; ++ if (errbuf_size > 0) { ++ llvm_strlcpy(errbuf, s, errbuf_size); ++ } ++ ++ return(len); ++} ++ ++/* ++ - regatoi - internal routine to implement REG_ATOI ++ */ ++static const char * ++regatoi(const llvm_regex_t *preg, char *localbuf, int localbufsize) ++{ ++ struct rerr *r; ++ ++ for (r = rerrs; r->code != 0; r++) ++ if (strcmp(r->name, preg->re_endp) == 0) ++ break; ++ if (r->code == 0) ++ return("0"); ++ ++ (void)snprintf(localbuf, localbufsize, "%d", r->code); ++ return(localbuf); ++} +diff -up lldb-3.8.0rc2.src/source/Utility/regexec.c.dave lldb-3.8.0rc2.src/source/Utility/regexec.c +--- lldb-3.8.0rc2.src/source/Utility/regexec.c.dave 2016-02-17 23:19:05.373675777 -0500 ++++ lldb-3.8.0rc2.src/source/Utility/regexec.c 2016-02-17 23:19:05.373675777 -0500 +@@ -0,0 +1,162 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)regexec.c 8.3 (Berkeley) 3/20/94 ++ */ ++ ++/* ++ * the outer shell of llvm_regexec() ++ * ++ * This file includes engine.inc *twice*, after muchos fiddling with the ++ * macros that code uses. This lets the same code operate on two different ++ * representations for state sets. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "regex_impl.h" ++ ++#include "regutils.h" ++#include "regex2.h" ++ ++/* macros for manipulating states, small version */ ++/* FIXME: 'states' is assumed as 'long' on small version. */ ++#define states1 long /* for later use in llvm_regexec() decision */ ++#define states states1 ++#define CLEAR(v) ((v) = 0) ++#define SET0(v, n) ((v) &= ~((unsigned long)1 << (n))) ++#define SET1(v, n) ((v) |= (unsigned long)1 << (n)) ++#define ISSET(v, n) (((v) & ((unsigned long)1 << (n))) != 0) ++#define ASSIGN(d, s) ((d) = (s)) ++#define EQ(a, b) ((a) == (b)) ++#define STATEVARS long dummy /* dummy version */ ++#define STATESETUP(m, n) /* nothing */ ++#define STATETEARDOWN(m) /* nothing */ ++#define SETUP(v) ((v) = 0) ++#define onestate long ++#define INIT(o, n) ((o) = (unsigned long)1 << (n)) ++#define INC(o) ((o) = (unsigned long)(o) << 1) ++#define ISSTATEIN(v, o) (((v) & (o)) != 0) ++/* some abbreviations; note that some of these know variable names! */ ++/* do "if I'm here, I can also be there" etc without branches */ ++#define FWD(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) << (n)) ++#define BACK(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) >> (n)) ++#define ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0) ++/* function names */ ++#define SNAMES /* engine.inc looks after details */ ++ ++#include "regengine.inc" ++ ++/* now undo things */ ++#undef states ++#undef CLEAR ++#undef SET0 ++#undef SET1 ++#undef ISSET ++#undef ASSIGN ++#undef EQ ++#undef STATEVARS ++#undef STATESETUP ++#undef STATETEARDOWN ++#undef SETUP ++#undef onestate ++#undef INIT ++#undef INC ++#undef ISSTATEIN ++#undef FWD ++#undef BACK ++#undef ISSETBACK ++#undef SNAMES ++ ++/* macros for manipulating states, large version */ ++#define states char * ++#define CLEAR(v) memset(v, 0, m->g->nstates) ++#define SET0(v, n) ((v)[n] = 0) ++#define SET1(v, n) ((v)[n] = 1) ++#define ISSET(v, n) ((v)[n]) ++#define ASSIGN(d, s) memmove(d, s, m->g->nstates) ++#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) ++#define STATEVARS long vn; char *space ++#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ ++ if ((m)->space == NULL) return(REG_ESPACE); \ ++ (m)->vn = 0; } ++#define STATETEARDOWN(m) { free((m)->space); } ++#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) ++#define onestate long ++#define INIT(o, n) ((o) = (n)) ++#define INC(o) ((o)++) ++#define ISSTATEIN(v, o) ((v)[o]) ++/* some abbreviations; note that some of these know variable names! */ ++/* do "if I'm here, I can also be there" etc without branches */ ++#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) ++#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) ++#define ISSETBACK(v, n) ((v)[here - (n)]) ++/* function names */ ++#define LNAMES /* flag */ ++ ++#include "regengine.inc" ++ ++/* ++ - llvm_regexec - interface for matching ++ * ++ * We put this here so we can exploit knowledge of the state representation ++ * when choosing which matcher to call. Also, by this point the matchers ++ * have been prototyped. ++ */ ++int /* 0 success, REG_NOMATCH failure */ ++llvm_regexec(const llvm_regex_t *preg, const char *string, size_t nmatch, ++ llvm_regmatch_t pmatch[], int eflags) ++{ ++ struct re_guts *g = preg->re_g; ++#ifdef REDEBUG ++# define GOODFLAGS(f) (f) ++#else ++# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) ++#endif ++ ++ if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) ++ return(REG_BADPAT); ++ assert(!(g->iflags®EX_BAD)); ++ if (g->iflags®EX_BAD) /* backstop for no-debug case */ ++ return(REG_BADPAT); ++ eflags = GOODFLAGS(eflags); ++ ++ if (g->nstates <= (long)(CHAR_BIT*sizeof(states1)) && !(eflags®_LARGE)) ++ return(smatcher(g, string, nmatch, pmatch, eflags)); ++ else ++ return(lmatcher(g, string, nmatch, pmatch, eflags)); ++} +diff -up lldb-3.8.0rc2.src/source/Utility/regfree.c.dave lldb-3.8.0rc2.src/source/Utility/regfree.c +--- lldb-3.8.0rc2.src/source/Utility/regfree.c.dave 2016-02-17 23:19:05.373675777 -0500 ++++ lldb-3.8.0rc2.src/source/Utility/regfree.c 2016-02-17 23:19:05.373675777 -0500 +@@ -0,0 +1,72 @@ ++/*- ++ * This code is derived from OpenBSD's libc/regex, original license follows: ++ * ++ * Copyright (c) 1992, 1993, 1994 Henry Spencer. ++ * Copyright (c) 1992, 1993, 1994 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Henry Spencer. ++ * ++ * 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 University 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 REGENTS 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 REGENTS 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. ++ * ++ * @(#)regfree.c 8.3 (Berkeley) 3/20/94 ++ */ ++ ++#include ++#include ++#include ++#include "regex_impl.h" ++ ++#include "regutils.h" ++#include "regex2.h" ++ ++/* ++ - llvm_regfree - free everything ++ */ ++void ++llvm_regfree(llvm_regex_t *preg) ++{ ++ struct re_guts *g; ++ ++ if (preg->re_magic != MAGIC1) /* oops */ ++ return; /* nice to complain, but hard */ ++ ++ g = preg->re_g; ++ if (g == NULL || g->magic != MAGIC2) /* oops again */ ++ return; ++ preg->re_magic = 0; /* mark it invalid */ ++ g->magic = 0; /* mark it invalid */ ++ ++ if (g->strip != NULL) ++ free((char *)g->strip); ++ if (g->sets != NULL) ++ free((char *)g->sets); ++ if (g->setbits != NULL) ++ free((char *)g->setbits); ++ if (g->must != NULL) ++ free(g->must); ++ free((char *)g); ++} +diff -up lldb-3.8.0rc2.src/source/Utility/regstrlcpy.c.dave lldb-3.8.0rc2.src/source/Utility/regstrlcpy.c +--- lldb-3.8.0rc2.src/source/Utility/regstrlcpy.c.dave 2016-02-17 23:19:05.373675777 -0500 ++++ lldb-3.8.0rc2.src/source/Utility/regstrlcpy.c 2016-02-17 23:19:05.373675777 -0500 +@@ -0,0 +1,52 @@ ++/* ++ * This code is derived from OpenBSD's libc, original license follows: ++ * ++ * Copyright (c) 1998 Todd C. Miller ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "regex_impl.h" ++/* ++ * Copy src to string dst of size siz. At most siz-1 characters ++ * will be copied. Always NUL terminates (unless siz == 0). ++ * Returns strlen(src); if retval >= siz, truncation occurred. ++ */ ++size_t ++llvm_strlcpy(char *dst, const char *src, size_t siz) ++{ ++ char *d = dst; ++ const char *s = src; ++ size_t n = siz; ++ ++ /* Copy as many bytes as will fit */ ++ if (n != 0) { ++ while (--n != 0) { ++ if ((*d++ = *s++) == '\0') ++ break; ++ } ++ } ++ ++ /* Not enough room in dst, add NUL and traverse rest of src */ ++ if (n == 0) { ++ if (siz != 0) ++ *d = '\0'; /* NUL-terminate dst */ ++ while (*s++) ++ ; ++ } ++ ++ return(s - src - 1); /* count does not include NUL */ ++} +diff -up lldb-3.8.0rc2.src/tools/lldb-mi/MIUtilParse.h.dave lldb-3.8.0rc2.src/tools/lldb-mi/MIUtilParse.h +--- lldb-3.8.0rc2.src/tools/lldb-mi/MIUtilParse.h.dave 2016-02-17 23:27:41.706021170 -0500 ++++ lldb-3.8.0rc2.src/tools/lldb-mi/MIUtilParse.h 2016-02-17 23:29:13.806580026 -0500 +@@ -10,7 +10,7 @@ + #pragma once + + // Third party headers: +-#include "../lib/Support/regex_impl.h" ++#include "../include/lldb/Utility/regex_impl.h" + + // In-house headers: + #include "MIUtilString.h" diff --git a/hans-gpg-key.asc b/hans-gpg-key.asc new file mode 100644 index 0000000..4b3cdde --- /dev/null +++ b/hans-gpg-key.asc @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFS+1SABEACnmkESkY7eZq0GhDjbkWpKmURGk9+ycsfAhA44NqUvf4tk1GPM +5SkJ/fYedYZJaDVhIp98fHgucD0O+vjOzghtgwtITusYjiPHPFBd/MN+MQqSEAP+ +LUa/kjHLjgyXxKhFUIDGVaDWL5tKOA7/AQKl1TyJ8lz89NHQoUHFsF/hu10+qhJe +V65d32MXFehIUSvegh8DrPuExrliSiORO4HOhuc6151dWA4YBWVg4rX5kfKrGMMT +pTWnSSZtgoRhkKW2Ey8cmZUqPuUJIfWyeNVu1e4SFtAivLvu/Ymz2WBJcNA1ZlTr +RCOR5SIRgZ453pQnI/Bzna2nnJ/TV1gGJIGRahj/ini0cs2x1CILfS/YJQ3rWGGo +OxwG0BVmPk0cmLVtyTq8gUPwxcPUd6WcBKhot3TDMlrffZACnQwQjlVjk5S1dEEz +atUfpEuNitU9WOM4jr/gjv36ZNCOWm95YwLhsuci/NddBN8HXhyvs+zYTVZEXa2W +l/FqOdQsQqZBcJjjWckGKhESdd7934+cesGD3O8KaeSGxww7slJrS0+6QJ8oBoAB +P/WCn/y2AiY2syEKp3wYIGJyAbsm542zMZ4nc7pYfSu49mcyhQQICmqN5QvOyYUx +OSqwbAOUNtlOyeRLZNIKoXtTqWDEu5aEiDROTw6Rkq+dIcxPNgOLdeQ3HwARAQAB +tCFIYW5zIFdlbm5ib3JnIDxoYW5zQGNocm9taXVtLm9yZz6JAlUEEwECAD8CGwMG +CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEEtsj5goK5ROOw1cJTD8MELjRa0F0F +Alpd+i0FCQ8FJo0ACgkQD8MELjRa0F3X3A//dBQLm6GmXlQFjxZbukTw0lZsevFR +M/6ljZTxp7bsC+HFzYoaCKv6rikaWzytxk//SOaLKrB4Z9HjAlpBMtyLl2Hk7tcZ +bPpFafNmQ+4KgWNjLXCvt9se8BGrQvGQUrbE6YowbXa2YIgxIVEncFzIECAsp/+N +xbMcZN5/X1PJxKi/N22gP4nn47muN6L3pKez3CXgWnhGYSc7BuD5ALWYH7yMYUem +d4jlXfu5xkBIqirj1arIYC9wmF4ldbLNDPuracc8LmXcSqa5Rpao0s4iVzAD+tkX +vE/73m3rhepwBXxrfk0McXuI9aucf5h4/KkIBzZsaJ6JM1tzlrJzzjaBKJF9OI5T +jA0qTxdGzdPztS8gPaPcMkRFfh9ti0ZDx4VeF3s8sOtmMRHeGEWfxqUAbBUbwFsa +JDu/+8/VO4KijfcuUi8tqJ/JHeosCuGE7TM93LwJu6ZcqMYOPDROE/hsnGm0ZU92 +xedu+07/X1ESHkSFPoaSHD5/DCNa/tXIyJZ8X7gF3eoDP5mSmrJqIqsOBR9WOVYv +dI8i0GHTXbrZj8WXdoS+N8wlyMLLbAS2jvTe7M5RoqbLz4ABOUUnLVoEE0CiccVZ +bW75BPxOfaD0szbinAeX6HDPI7St0MbKrRPjuDXjD0JVkLqFINtZfYLGMLss4tgn +suefr0Bo9ISwG3u5Ag0EVL7VIAEQAOxBxrQesChjrCqKjY5PnSsSYpeb4froucrC +898AFw2DgN/Zz+W7wtSTbtz/GRcCurjzZvN7o2rCuNk0j0+s1sgZZm2BdldlabLy ++UF/kSW1rb5qhfXcGGubu48OMdtSfok9lOc0Q1L4HNlGE4lUBkZzmI7Ykqfl+Bwr +m9rpi54g4ua9PIiiHIAmMoZIcbtOG1KaDr6CoXRk/3g2ZiGUwhq3jFGroiBsKEap +2FJ1bh5NJk2Eg8pV7fMOF7hUQKBZrNOtIPu8hA5WEgku3U3VYjRSI3SDi6QXnDL+ +xHxajiWpKtF3JjZh8y/CCTD8PyP34YjfZuFmkdske5cdx6H0V2UCiH453ncgFVdQ +DXkY4n+0MTzhy2xu0IVVnBxYDYNhi+3MjTHJd9C4xMi9t+5IuEvDAPhgfZjDpQak +EPz6hVmgj0mlKIgRilBRK9/kOxky9utBpGk3jEJGru/hKNloFNspoYtY6zATAr8E +cOgoCFQE0nIktcg3wF9+OCEnV28/a7XZwUZ7Gl/qfOHtdr374wo8kd8R3V8d2G9q +5w0/uCV9NNQ0fGWZDPDoYt6wnPL6gZv/nJM8oZY+u0rC24WwScZIniaryC4JHDas +Ahr2S2CtgCvBgslK6f3gD16KHxPZMBpX73TzOYIhMEP/vXgVJbUD6dYht+U9c4Oh +EDJown0dABEBAAGJAjwEGAECACYCGwwWIQS2yPmCgrlE47DVwlMPwwQuNFrQXQUC +Wl36SwUJDwUmqwAKCRAPwwQuNFrQXT1/D/9YpRDNgaJl3YVDtVZoeQwh7BQ6ULZT +eXFPogYkF2j3VWg8s9UmAs4sg/4a+9KLSantXjX+JFsRv0lQe5Gr/Vl8VQ4LKEXB +fiGmSivjIZ7eopdd3YP2w6G5T3SA4d2CQfsg4rnJPnXIjzKNiSOi368ybnt9fL0Y +2r2aqLTmP6Y7issDUO+J1TW1XHm349JPR0Hl4cTuNnWm4JuX2m2CJEc5XBlDAha9 +pUVs+J5C2D0UFFkyeOzeJPwy6x5ApWHm84n8AjhQSpu1qRKxKXdwei6tkQWWMHui ++TgSY/zCkmD9/oY15Ei5avJ4WgIbTLJUoZMi70riPmU8ThjpzA7S+Nk0g7rMPq+X +l1whjKU/u0udlsrIJjzkh6ftqKUmIkbxYTpjhnEujNrEr5m2S6Z6x3y9E5QagBMR +dxRhfk+HbyACcP/p9rXOzl4M291DoKeAAH70GHniGxyNs9rAoMr/hD5XW/Wrz3dc +KMc2s555E6MZILE2ZiolcRn+bYOMPZtWlbx98t8uqMf49gY4FGQBZAwPglMrx7mr +m7HTIiXahThQGOJg6izJDAD5RwSEGlAcL28T8KAuM6CLLkhlBfQwiKsUBNnh9r8w +V3lB+pV0GhL+3i077gTYfZBRwLzjFdhm9xUKEaZ6rN1BX9lzix4eSNK5nln0jUq1 +67H2IH//2sf8dw== +=ADVe +-----END PGP PUBLIC KEY BLOCK----- diff --git a/lldb.spec b/lldb.spec new file mode 100644 index 0000000..693a9e6 --- /dev/null +++ b/lldb.spec @@ -0,0 +1,372 @@ +#%%global rc_ver 6 +%global baserelease 1 +%global lldb_srcdir %{name}-%{version}%{?rc_ver:rc%{rc_ver}}.src + +Name: lldb +Version: 11.0.0 +Release: %{baserelease}%{?rc_ver:.rc%{rc_ver}}%{?dist} +Summary: Next generation high-performance debugger + +License: NCSA +URL: http://lldb.llvm.org/ +Source0: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{version}%{?rc_ver:-rc%{rc_ver}}/%{lldb_srcdir}.tar.xz +Source1: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{version}%{?rc_ver:-rc%{rc_ver}}/%{lldb_srcdir}.tar.xz.sig +Source2: https://prereleases.llvm.org/%{version}/hans-gpg-key.asc + +BuildRequires: gcc +BuildRequires: gcc-c++ +BuildRequires: cmake +BuildRequires: ninja-build +BuildRequires: llvm-devel = %{version} +BuildRequires: llvm-test = %{version} +BuildRequires: clang-devel = %{version} +BuildRequires: ncurses-devel +BuildRequires: swig +BuildRequires: llvm-static = %{version} +BuildRequires: libffi-devel +BuildRequires: zlib-devel +BuildRequires: libxml2-devel +BuildRequires: libedit-devel +BuildRequires: python3-lit +BuildRequires: multilib-rpm-config + +Requires: python3-lldb + +# For origin certification +BuildRequires: gnupg2 + +%description +LLDB is a next generation, high-performance debugger. It is built as a set +of reusable components which highly leverage existing libraries in the +larger LLVM Project, such as the Clang expression parser and LLVM +disassembler. + +%package devel +Summary: Development header files for LLDB +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The package contains header files for the LLDB debugger. + +%package -n python3-lldb +%{?python_provide:%python_provide python3-lldb} +Summary: Python module for LLDB +BuildRequires: python3-devel +Requires: python3-six +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description -n python3-lldb +The package contains the LLDB Python module. + +%prep +%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' +%autosetup -n %{lldb_srcdir} -p2 + +%build + +CFLAGS="%{optflags} -Wno-error=format-security" +CXXFLAGS="%{optflags} -Wno-error=format-security" + +%cmake -GNinja \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_SKIP_RPATH:BOOL=ON \ + -DLLVM_LINK_LLVM_DYLIB:BOOL=ON \ + -DLLVM_CONFIG:FILEPATH=/usr/bin/llvm-config-%{__isa_bits} \ + \ + -DLLDB_DISABLE_CURSES:BOOL=OFF \ + -DLLDB_DISABLE_LIBEDIT:BOOL=OFF \ + -DLLDB_DISABLE_PYTHON:BOOL=OFF \ +%if 0%{?__isa_bits} == 64 + -DLLVM_LIBDIR_SUFFIX=64 \ +%else + -DLLVM_LIBDIR_SUFFIX= \ +%endif + \ + -DPYTHON_EXECUTABLE:STRING=%{__python3} \ + -DPYTHON_VERSION_MAJOR:STRING=$(%{__python3} -c "import sys; print(sys.version_info.major)") \ + -DPYTHON_VERSION_MINOR:STRING=$(%{__python3} -c "import sys; print(sys.version_info.minor)") \ + -DLLVM_EXTERNAL_LIT=%{_bindir}/lit \ + -DCLANG_LINK_CLANG_DYLIB=ON \ + -DLLVM_LIT_ARGS="-sv \ + --path %{_libdir}/llvm" \ + +%cmake_build + +%install +%cmake_install + +%multilib_fix_c_header --file %{_includedir}/lldb/Host/Config.h + +# remove static libraries +rm -fv %{buildroot}%{_libdir}/*.a + +# python: fix binary libraries location +liblldb=$(basename $(readlink -e %{buildroot}%{_libdir}/liblldb.so)) +ln -vsf "../../../${liblldb}" %{buildroot}%{python3_sitearch}/lldb/_lldb.so +%py_byte_compile %{__python3} %{buildroot}%{python3_sitearch}/lldb + +# remove bundled six.py +rm -f %{buildroot}%{python3_sitearch}/six.* + +%ldconfig_scriptlets + +%check + + +%files +%license LICENSE.TXT +%{_bindir}/lldb* +%{_libdir}/liblldb.so.* +%{_libdir}/liblldbIntelFeatures.so.* + +%files devel +%{_includedir}/lldb +%{_libdir}/*.so + +%files -n python3-lldb +%{python3_sitearch}/lldb + +%changelog +* Thu Oct 15 2020 sguelton@redhat.com - 11.0.0-1 +- Fix NVR + +* Mon Oct 12 2020 sguelton@redhat.com - 11.0.0-0.5 +- llvm 11.0.0 - final release + +* Thu Oct 08 2020 sguelton@redhat.com - 11.0.0-0.4.rc6 +- 11.0.0-rc6 + +* Fri Oct 02 2020 sguelton@redhat.com - 11.0.0-0.3.rc5 +- 11.0.0-rc5 Release + +* Sun Sep 27 2020 sguelton@redhat.com - 11.0.0-0.2.rc3 +- Fix NVR + +* Thu Sep 24 2020 sguelton@redhat.com - 11.0.0-0.1.rc3 +- 11.0.0-rc3 Release + +* Tue Sep 01 2020 sguelton@redhat.com - 11.0.0-0.1.rc2 +- 11.0.0-rc2 Release + +* Mon Aug 10 2020 Tom Stellard - 11.0.0-0.1.rc1 +- 11.0.0-rc1 Release + +* Wed Jul 29 2020 sguelton@redhat.com - 10.0.0-8 +- Make gcc dependency explicit, see https://fedoraproject.org/wiki/Packaging:C_and_C%2B%2B#BuildRequires_and_Requires +- use %%license macro + +* Tue Jul 28 2020 Fedora Release Engineering - 10.0.0-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Fri Jul 17 2020 sguelton@redhat.com - 10.0.0-6 +- Use ninja and according macros as build system + +* Tue Jun 16 2020 sguelton@redhat.com - 10.0.0-5 +- Finer grain specification of python3-lldb deps + +* Tue Jun 02 2020 sguelton@redhat.com - 10.0.0-4 +- Fix arch-dependent header + +* Tue Jun 02 2020 sguelton@redhat.com - 10.0.0-3 +- Instruct cmake not to generate RPATH + +* Tue May 26 2020 Miro Hrončok - 10.0.0-2 +- Rebuilt for Python 3.9 + +* Mon Mar 30 2020 sguelton@redhat.com - 10.0.0-1 +- 10.0.0 final + +* Wed Mar 25 2020 sguelton@redhat.com - 10.0.0-0.6.rc6 +- 10.0.0 rc6 + +* Fri Mar 20 2020 sguelton@redhat.com - 10.0.0-0.5.rc5 +- 10.0.0 rc5 + +* Sun Mar 15 2020 sguelton@redhat.com - 10.0.0-0.4.rc4 +- 10.0.0 rc4 + +* Thu Mar 05 2020 sguelton@redhat.com - 10.0.0-0.3.rc3 +- 10.0.0 rc3 + +* Fri Feb 14 2020 sguelton@redhat.com - 10.0.0-0.2.rc2 +- 10.0.0 rc2 + +* Fri Jan 31 2020 sguelton@redhat.com - 10.0.0-0.1.rc1 +- 10.0.0 rc1 + +* Wed Jan 29 2020 Tom Stellard - 9.0.1-4 +- Link against libclang-cpp.so +- https://fedoraproject.org/wiki/Changes/Stop-Shipping-Individual-Component-Libraries-In-clang-lib-Package + +* Wed Jan 29 2020 Fedora Release Engineering - 9.0.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Sat Dec 21 2019 Tom Stellard - 9.0.1-2 +- 9.0.1 Release + +* Thu Sep 19 2019 Tom Stellard - 9.0.0-1 +- 9.0.0 Release + +* Thu Aug 22 2019 Tom Stellard - 9.0.0-0.1.rc3 +- 9.0.0-rc3 Release + +* Mon Aug 19 2019 Miro Hrončok - 8.0.0-2.2 +- Rebuilt for Python 3.8 + +* Thu Jul 25 2019 Fedora Release Engineering - 8.0.0-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Tue Mar 26 2019 sguelton@redhat.com - 8.0.0-2 +- Only depend on Python3 + +* Wed Mar 20 2019 sguelton@redhat.com - 8.0.0-1 +- 8.0.0 final + +* Tue Mar 12 2019 sguelton@redhat.com - 8.0.0-0.4.rc4 +- 8.0.0 Release candidate 4 + +* Tue Mar 5 2019 sguelton@redhat.com - 8.0.0-0.3.rc3 +- 8.0.0 Release candidate 3 + +* Fri Feb 22 2019 sguelton@redhat.com - 8.0.0-0.2.rc2 +- 8.0.0 Release candidate 2 + +* Mon Feb 11 2019 sguelton@redhat.com - 8.0.0-0.1.rc1 +- 8.0.0 Release candidate 1 + +* Fri Feb 01 2019 Fedora Release Engineering - 7.0.1-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Dec 17 2018 sguelton@redhat.com - 7.0.1-1 +- 7.0.1 Release + +* Tue Dec 04 2018 sguelton@redhat.com - 7.0.0-2 +- Ensure rpmlint passes on specfile + +* Tue Sep 25 2018 Tom Stellard - 7.0.0-1 +- 7.0.0 Release + +* Fri Sep 21 2018 Tom Stellard - 7.0.0-0.5.rc3 +- lldb should depend on python2-lldb + +* Mon Sep 17 2018 Tom Stellard - 7.0.0-0.4.rc3 +- 7.0.0-rc3 Release + +* Wed Sep 12 2018 Tom Stellard - 7.0.0-0.3.rc2 +- Enable build on s390x + +* Fri Aug 31 2018 Tom Stellard - 7.0.0-0.2.rc2 +- 7.0.0-rc2 Release + +* Tue Aug 14 2018 Tom Stellard - 7.0.0-0.1.rc1 +- 7.0.1-rc1 Release + +* Tue Aug 07 2018 Tom Stellard - 6.0.1-3 +- Enable ppc64le arch + +* Fri Jul 13 2018 Fedora Release Engineering - 6.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Mon May 21 2018 Tom Stellard - 6.0.1-1 +- 6.0.1 Release + +* Mon May 21 2018 Tom Stellard - 6.0.1-0.1.rc1 +- 6.0.1-rc1 Release + +* Sat May 05 2018 Miro Hrončok - 6.0.0-4 +- Update Python macros to new packaging standards + (See https://fedoraproject.org/wiki/Changes/Avoid_usr_bin_python_in_RPM_Build) + +* Tue Mar 20 2018 Tom Stellard - 6.0.0-3 +- Rebuild against llvm with the rhbz#1558657 fix + +* Wed Mar 14 2018 Tilmann Scheller - 6.0.0-2 +- Restore LLDB SB API headers, fixes rhbz#1548758 + +* Fri Mar 09 2018 Tom Stellard - 6.0.0-1 +- 6.0.0 Release + +* Tue Feb 13 2018 Tom Stellard - 6.0.0-0.3.rc2 +- 6.0.0-rc2 release + +* Thu Feb 08 2018 Fedora Release Engineering - 6.0.0-0.2.rc1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Jan 25 2018 Tom Stellard - 6.0.0-0.1.rc1 +- 6.0.1-rc1 Release + +* Thu Dec 21 2017 Tom Stellard - 5.0.1-1 +- 5.0.1 Release + +* Fri Oct 06 2017 Tom Stellard - 5.0.0-1 +- 5.0.0 Release + +* Sat Aug 19 2017 Zbigniew Jędrzejewski-Szmek - 4.0.1-4 +- Python 2 binary package renamed to python2-lldb + See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3 + +* Mon Jul 31 2017 Jan Kratochvil - 4.0.1-3 +- Backport lldb r303907 + Resolves rhbz #1356140 + +* Wed Jul 26 2017 Fedora Release Engineering - 4.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Mon Jun 26 2017 Tom Stellard - 4.0.1-1 +- 4.0.1 Release + +* Mon May 15 2017 Fedora Release Engineering - 4.0.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_27_Mass_Rebuild + +* Fri Mar 24 2017 Tom Stellard - 4.0.0-1 +- lldb 4.0.0 + +* Tue Mar 21 2017 Tom Stellard - 3.9.1-4 +- Add explicit Requires for llvm-libs and clang-libs + +* Fri Mar 17 2017 Tom Stellard - 3.9.1-3 +- Adjust python sys.path so lldb can find readline.so + +* Tue Mar 14 2017 Tom Stellard - 3.9.1-2 +- Fix build with gcc 7 + +* Thu Mar 02 2017 Dave Airlie - 3.9.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Mon Nov 14 2016 Nathaniel McCallum - 3.9.0-3 +- Disable libedit support until upstream fixes it (#1356140) + +* Wed Nov 2 2016 Peter Robinson 3.9.0-2 +- Set upstream supported architectures in an ExclusiveArch + +* Wed Oct 26 2016 Dave Airlie - 3.9.0-1 +- lldb 3.9.0 +- fixup some issues with MIUtilParse by removing it +- build with -fno-rtti + +* Tue Jul 19 2016 Fedora Release Engineering - 3.8.0-2 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Thu Mar 10 2016 Dave Airlie 3.8.0-1 +- lldb 3.8.0 + +* Thu Mar 03 2016 Dave Airlie 3.8.0-0.3 +- lldb 3.8.0 rc3 + +* Wed Feb 24 2016 Dave Airlie - 3.8.0-0.2 +- dynamically link to llvm + +* Thu Feb 18 2016 Dave Airlie - 3.8.0-0.1 +- lldb 3.8.0 rc2 + +* Sun Feb 14 2016 Dave Airlie 3.7.1-3 +- rebuild lldb against latest llvm + +* Thu Feb 04 2016 Fedora Release Engineering - 3.7.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Tue Oct 06 2015 Jan Vcelak 3.7.0-100 +- initial version using cmake build system diff --git a/r303907-libedit.patch b/r303907-libedit.patch new file mode 100644 index 0000000..942c425 --- /dev/null +++ b/r303907-libedit.patch @@ -0,0 +1,92 @@ +commit 9ad9480c3a380a04b3dbe869c0675d6bba37247b +Author: Kamil Rytarowski +Date: Thu May 25 20:12:30 2017 +0000 + + Fix bug #28898 + lldb: libedit produces garbled, unusable input on Linux + + Apply patch from Christos Zoulas, upstream libedit developer. + It has been tested on NetBSD/amd64. + + New code supports combination of wide libedit and disabled + LLDB_EDITLINE_USE_WCHAR, which was the popular case on Linux + systems. + + + git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@303907 91177308-0d34-0410-b5e6-96231b3b80d8 + +diff --git a/include/lldb/Host/Editline.h b/include/lldb/Host/Editline.h +index 2b1a8e0..0b75e9c 100644 +--- a/include/lldb/Host/Editline.h ++++ b/include/lldb/Host/Editline.h +@@ -82,8 +82,14 @@ using EditLineStringStreamType = std::stringstream; + using EditLineCharType = char; + #endif + ++#ifdef EL_CLIENTDATA /* editline with wide support + wide char read function */ ++using EditLineGetCharType = wchar_t; ++#else ++using EditLineGetCharType = char; ++#endif ++ + typedef int (*EditlineGetCharCallbackType)(::EditLine *editline, +- EditLineCharType *c); ++ EditLineGetCharType *c); + typedef unsigned char (*EditlineCommandCallbackType)(::EditLine *editline, + int ch); + typedef const char *(*EditlinePromptCallbackType)(::EditLine *editline); +@@ -270,7 +276,7 @@ private: + + /// Character reading implementation for EditLine that supports our multi-line + /// editing trickery. +- int GetCharacter(EditLineCharType *c); ++ int GetCharacter(EditLineGetCharType *c); + + /// Prompt implementation for EditLine. + const char *Prompt(); +@@ -323,7 +329,7 @@ private: + /// single or multi-line editing. + void ConfigureEditor(bool multiline); + +- bool CompleteCharacter(char ch, EditLineCharType &out); ++ bool CompleteCharacter(char ch, EditLineGetCharType &out); + + private: + #if LLDB_EDITLINE_USE_WCHAR +diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp +index 7d4b398..7b580dd 100644 +--- a/source/Host/common/Editline.cpp ++++ b/source/Host/common/Editline.cpp +@@ -474,7 +474,7 @@ unsigned char Editline::RecallHistory(bool earlier) { + return CC_NEWLINE; + } + +-int Editline::GetCharacter(EditLineCharType *c) { ++int Editline::GetCharacter(EditLineGetCharType *c) { + const LineInfoW *info = el_wline(m_editline); + + // Paint a faint version of the desired prompt over the version libedit draws +@@ -969,7 +969,7 @@ void Editline::ConfigureEditor(bool multiline) { + })); + + el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([]( +- EditLine *editline, EditLineCharType *c) { ++ EditLine *editline, EditLineGetCharType *c) { + return Editline::InstanceFor(editline)->GetCharacter(c); + })); + +@@ -1360,12 +1360,12 @@ void Editline::PrintAsync(Stream *stream, const char *s, size_t len) { + } + } + +-bool Editline::CompleteCharacter(char ch, EditLineCharType &out) { ++bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) { + #if !LLDB_EDITLINE_USE_WCHAR + if (ch == (char)EOF) + return false; + +- out = ch; ++ out = (unsigned char)ch; + return true; + #else + std::codecvt_utf8 cvt; diff --git a/sources b/sources new file mode 100644 index 0000000..fc29b32 --- /dev/null +++ b/sources @@ -0,0 +1,2 @@ +SHA512 (lldb-11.0.0.src.tar.xz) = e781d70de2b59142779503df6078ff118e49a0f8053e9296c34251a4c3ddb9676b375a7a6f94de61e472209bba72d719744b143990d4fdaea722fd0997e99920 +SHA512 (lldb-11.0.0.src.tar.xz.sig) = 7a290ecc885eadfb163b9d1b624c40a94a6ae08daae9dbd7907cd3b427a7de9264c01bdab5932a336e16e4cf6cef88336591651d5f7fe9a743e1a71ff0c56684 diff --git a/tests/python-embedded-interpreter/runtest.sh b/tests/python-embedded-interpreter/runtest.sh new file mode 100755 index 0000000..164ff13 --- /dev/null +++ b/tests/python-embedded-interpreter/runtest.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -ex + +g++ -g test.cpp + +test `lldb -b -o 'breakpoint set --file test.cpp --line 7' -o run -o 'p v' -- a.out \ + | grep \ + -e '(std::vector >) $0 = size=1 {' \ + -e '\[0\] = 2' \ + | wc -l` -eq 2 diff --git a/tests/python-embedded-interpreter/test.cpp b/tests/python-embedded-interpreter/test.cpp new file mode 100644 index 0000000..397efa4 --- /dev/null +++ b/tests/python-embedded-interpreter/test.cpp @@ -0,0 +1,9 @@ +#include +#include +int +main () +{ + std::vector v (1, 2); + std::vector::iterator it(v.begin()); + return 0; +} diff --git a/tests/tests.yml b/tests/tests.yml new file mode 100644 index 0000000..b7b389b --- /dev/null +++ b/tests/tests.yml @@ -0,0 +1,25 @@ +- hosts: localhost + pre_tasks: + # We want to be able to check that the sub-package dependencies are correct. + # The CI system installs all sub-packages, so we remove them so we can + # test them individually. + - name: Remove RPMS installed by CI + package: + name: + - python2-lldb + - lldb + - lldb-devel + state: absent + tags: classic + roles: + - role: standard-test-basic + tags: + - classic + required_packages: + - gcc-c++ + - lldb + tests: + # rhbz#1567262 + - python-embedded-interpreter: + dir: python-embedded-interpreter + run: ./runtest.sh