diff options
author | Bartłomiej Piotrowski <b@bpiotrowski.pl> | 2016-06-18 22:15:11 +0200 |
---|---|---|
committer | Bartłomiej Piotrowski <b@bpiotrowski.pl> | 2016-06-18 22:15:45 +0200 |
commit | f697997042cf98dcfedae1fad22b0c669b5044c9 (patch) | |
tree | 97766042d56095b62aafb85a4f8c060ffe690b90 /testing/lldb/D15067.id41365.patch | |
parent | d2ce891ad820709784d0822d578fdcdb6bf03d4e (diff) | |
download | aports-f697997042cf98dcfedae1fad22b0c669b5044c9.tar.bz2 aports-f697997042cf98dcfedae1fad22b0c669b5044c9.tar.xz |
testing/lldb: new aport
next generation, high-performance debugger
http://llvm.org/
Diffstat (limited to 'testing/lldb/D15067.id41365.patch')
-rw-r--r-- | testing/lldb/D15067.id41365.patch | 3810 |
1 files changed, 3810 insertions, 0 deletions
diff --git a/testing/lldb/D15067.id41365.patch b/testing/lldb/D15067.id41365.patch new file mode 100644 index 0000000000..5217ffc717 --- /dev/null +++ b/testing/lldb/D15067.id41365.patch @@ -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<<OPSHIFT) /* endmarker - */ ++#define OCHAR (2LU<<OPSHIFT) /* character unsigned char */ ++#define OBOL (3LU<<OPSHIFT) /* left anchor - */ ++#define OEOL (4LU<<OPSHIFT) /* right anchor - */ ++#define OANY (5LU<<OPSHIFT) /* . - */ ++#define OANYOF (6LU<<OPSHIFT) /* [...] set number */ ++#define OBACK_ (7LU<<OPSHIFT) /* begin \d paren number */ ++#define O_BACK (8LU<<OPSHIFT) /* end \d paren number */ ++#define OPLUS_ (9LU<<OPSHIFT) /* + prefix fwd to suffix */ ++#define O_PLUS (10LU<<OPSHIFT) /* + suffix back to prefix */ ++#define OQUEST_ (11LU<<OPSHIFT) /* ? prefix fwd to suffix */ ++#define O_QUEST (12LU<<OPSHIFT) /* ? suffix back to prefix */ ++#define OLPAREN (13LU<<OPSHIFT) /* ( fwd to ) */ ++#define ORPAREN (14LU<<OPSHIFT) /* ) back to ( */ ++#define OCH_ (15LU<<OPSHIFT) /* begin choice fwd to OOR2 */ ++#define OOR1 (16LU<<OPSHIFT) /* | pt. 1 back to OOR1 or OCH_ */ ++#define OOR2 (17LU<<OPSHIFT) /* | pt. 2 fwd to OOR2 or O_CH */ ++#define O_CH (18LU<<OPSHIFT) /* end choice back to OOR1 */ ++#define OBOW (19LU<<OPSHIFT) /* begin word - */ ++#define OEOW (20LU<<OPSHIFT) /* end word - */ ++ ++/* ++ * Structure for [] character-set representation. Character sets are ++ * done as bit vectors, grouped 8 to a byte vector for compactness. ++ * The individual set therefore has both a pointer to the byte vector ++ * and a mask to pick out the relevant bit of each byte. A hash code ++ * simplifies testing whether two sets could be identical. ++ * ++ * This will get trickier for multicharacter collating elements. As ++ * preliminary hooks for dealing with such things, we also carry along ++ * a string of multi-character elements, and decide the size of the ++ * vectors at run time. ++ */ ++typedef struct { ++ uch *ptr; /* -> 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 <sys/types.h> ++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 <assert.h> ++ ++/* 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 <sys/types.h> ++#include <stdio.h> ++#include <string.h> ++#include <ctype.h> ++#include <limits.h> ++#include <stdlib.h> ++#include "regex_impl.h" ++ ++#include "regutils.h" ++#include "regex2.h" ++ ++#include "regcclass.h" ++#include "regcname.h" ++ ++#include <stdint.h> ++/* 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 <assert.h>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<<CHAR_BIT) ++ ++ pos = HERE(); /* repetition op, if any, covers from here */ ++ ++ assert(MORE()); /* caller should have ensured this */ ++ c = GETNEXT(); ++ if (c == '\\') { ++ REQUIRE(MORE(), REG_EESCAPE); ++ c = BACKSL | GETNEXT(); ++ } ++ switch (c) { ++ case '.': ++ if (p->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<<OPSHIFT); ++ ++ /* deal with undersized strip */ ++ if (p->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<<OPSHIFT); ++ p->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 <sys/types.h> ++#include <stdio.h> ++#include <string.h> ++#include <ctype.h> ++#include <limits.h> ++#include <stdlib.h> ++#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 <sys/types.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <limits.h> ++#include <ctype.h> ++#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 <sys/types.h> ++#include <stdio.h> ++#include <stdlib.h> ++#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 <Todd.Miller@courtesan.com> ++ * ++ * 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 <sys/types.h> ++#include <string.h> ++ ++#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" |