diff --git a/builds/posix/Makefile.in.extern.regex b/builds/posix/Makefile.in.extern.regex deleted file mode 100644 index eb1a3dad8e..0000000000 --- a/builds/posix/Makefile.in.extern.regex +++ /dev/null @@ -1,65 +0,0 @@ -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# You may obtain a copy of the Licence at -# http://www.gnu.org/licences/lgpl.html -# -# As a special exception this file can also be included in modules -# with other source code as long as that source code has been -# released under an Open Source Initiative certificed licence. -# More information about OSI certification can be found at: -# http://www.opensource.org -# -# This module is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public Licence for more details. -# -# This module was created by members of the firebird development -# team. All individual contributions remain the Copyright (C) of -# those individuals and all rights are reserved. Contributors to -# this file are either listed below or can be obtained from a CVS -# history command. -# -# Created by: Erik Kunze -# -# Contributor(s): -# Alex Peshkov -# -# -ROOT=.. -#ObjModuleType=std - -## Set your options: -## -DANSI_ARROWS ANSI arrows keys work like emacs. -## -DHIDE Make static functions static (non debug). -## -DHIST_SIZE=n History size. -## -DUNIQUE_HISTORY Don't save command if same as last one. -## -DDO_SIGTSTP Send SIGTSTP on "suspend" key -#CFLAGS:= -DANSI_ARROWS -DHIDE -DHIST_SIZE=100 -DUNIQUE_HISTORY -DSYS_UNIX - -include $(ROOT)/gen/make.defaults -include $(ROOT)/gen/make.platform -include $(ROOT)/gen/make.rules -include $(ROOT)/gen/make.shared.variables - -@SET_MAKE@ - - -.PHONY: librxspencer - - -librxspencer : $(LIB)/librxspencer.a - -LIBS_TO_COPY = librxspencer.* - -$(LIB)/librxspencer.a: - $(MAKE) -C $(ROOT)/extern/regex - (cd $(ROOT)/extern/regex/.libs/; tar cf - $(LIBS_TO_COPY) ) | (cd $(LIB); tar xf -) -# cp $(ROOT)/extern/regex/.libs/librxspencer.a $(LIB)/librxspencer.a - - -include $(ROOT)/gen/make.shared.targets - -#-include $(Dependencies) diff --git a/builds/posix/Makefile.in.fbtrace b/builds/posix/Makefile.in.fbtrace index c1a1dd09f0..900468aea4 100644 --- a/builds/posix/Makefile.in.fbtrace +++ b/builds/posix/Makefile.in.fbtrace @@ -49,8 +49,8 @@ FBTRACE_UTIL_Objects = $(addprefix $(OBJ)/, $(addsuffix .o, $(basename $(FBTRACE FBTRACE_OTHER_Sources = $(OS_SPECIFIC_Sources) $(TRACE_OS_Sources) \ - jrd/isc.cpp jrd/isc_sync.cpp jrd/isc_ipc.cpp \ - common/classes/ClumpletReader.cpp common/utils.cpp + jrd/isc.cpp jrd/isc_sync.cpp jrd/isc_ipc.cpp jrd/CharSet.cpp jrd/TextType.cpp jrd/IntlUtil.cpp \ + jrd/unicode_util.cpp common/classes/ClumpletReader.cpp common/utils.cpp FBTRACE_OTHER_Objects = $(addprefix $(OBJ)/, $(addsuffix .o, $(basename $(FBTRACE_OTHER_Sources)))) diff --git a/builds/posix/Makefile.in.firebird b/builds/posix/Makefile.in.firebird index ae6d4e54e3..c84963f479 100644 --- a/builds/posix/Makefile.in.firebird +++ b/builds/posix/Makefile.in.firebird @@ -181,7 +181,7 @@ $(GEN_ROOT)/Make.Version : $(SRC_ROOT)/misc/writeBuildNum.sh # # Libraries that come from outside the project but are built -# as part of the project are included here. Currently IBM ICU, Henry Spencer's regex and +# as part of the project are included here. Currently IBM ICU and # editline are the only externals libraries we have included. # @@ -194,7 +194,6 @@ ifeq ($(EDITLINE_FLG),Y) $(MAKE) CFLAGS="@CFLAGS@" -f $(GEN_ROOT)/Makefile.extern.editline endif endif - $(MAKE) CFLAGS="@CFLAGS@" -f $(GEN_ROOT)/Makefile.extern.regex btyacc_binary: $(BTYACC) diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults index 911b453188..27c5cb93ba 100755 --- a/builds/posix/make.defaults +++ b/builds/posix/make.defaults @@ -279,7 +279,7 @@ LINK_INTL_LIBS = -L$(LIB) $(ICU_LIBS) $(SO_LINK_LIBS) LINK_TRACE = $(LIB_LINK) $(LINK_TRACE_SYMBOLS) $(LIB_LINK_OPTIONS)\ $(call LIB_LINK_SONAME,$(LIB_PREFIX)fbtrace.$(SHRLIB_EXT).0) $(call LIB_LINK_RPATH,lib) -LINK_TRACE_LIBS = -L$(LIB) $(SO_LINK_LIBS) -lrxspencer +LINK_TRACE_LIBS = -L$(LIB) $(SO_LINK_LIBS) LINK_CLIENT = $(CLIENTLIB_LINK) $(LINK_FIREBIRD_CLIENT_SYMBOLS) $(LIB_LINK_OPTIONS)\ $(LIB_LINK_IMPLIB) $(call LIB_LINK_SONAME,$(ClientLibrarySoName)) $(call LIB_LINK_RPATH,lib) diff --git a/builds/posix/make.rules b/builds/posix/make.rules index dd7bd329a1..1909d992f6 100644 --- a/builds/posix/make.rules +++ b/builds/posix/make.rules @@ -33,7 +33,7 @@ # Please don't use compiler/platform specific flags here - nmcc 02-Nov-2002 CFLAGS:= $(CFLAGS) -I$(SRC_ROOT)/include/gen -I$(SRC_ROOT)/include -I$(SRC_ROOT)/vulcan \ - -I$(ROOT)/extern/regex -DNAMESPACE=Vulcan $(THR_FLAGS) + -DNAMESPACE=Vulcan $(THR_FLAGS) ifeq ($(STD_ICU),false) CFLAGS:= $(CFLAGS) -I$(ROOT)/extern/icu/source/common -I$(ROOT)/extern/icu/source/i18n diff --git a/builds/posix/prefix.mingw b/builds/posix/prefix.mingw index cb17459592..f416e443c4 100644 --- a/builds/posix/prefix.mingw +++ b/builds/posix/prefix.mingw @@ -78,7 +78,7 @@ LINK_UDF = $(LIB_LINK) $(LIB_LINK_OPTIONS) $(call LIB_LINK_SONAME,$(1).$(SHRLIB_ LINK_UDF_LIBS = # Special options for trace plugin link -LINK_TRACE_LIBS = -L$(LIB) $(SO_LINK_LIBS) $(LIB)/librxspencer.a +LINK_TRACE_LIBS = -L$(LIB) $(SO_LINK_LIBS) # This is ugly HACK!!! Must be removed as soon as somebody find # a way to use routines from server diff --git a/builds/win32/msvc8/Firebird2.sln b/builds/win32/msvc8/Firebird2.sln index b089850aa6..7045ec49d6 100644 --- a/builds/win32/msvc8/Firebird2.sln +++ b/builds/win32/msvc8/Firebird2.sln @@ -203,13 +203,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fbsvcmgr", "fbsvcmgr.vcproj EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fbtrace", "fbtrace.vcproj", "{53F75437-15B8-4A5C-86BF-E238CC68FCBC}" ProjectSection(ProjectDependencies) = postProject - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D} = {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D} {E83187C1-AAC2-445D-B8B2-883EFC10C39A} = {E83187C1-AAC2-445D-B8B2-883EFC10C39A} {15605F44-BFFD-444F-AD4C-55DC9D704465} = {15605F44-BFFD-444F-AD4C-55DC9D704465} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "regex", "regex.vcproj", "{34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -560,14 +557,6 @@ Global {53F75437-15B8-4A5C-86BF-E238CC68FCBC}.Release|Win32.Build.0 = Release|Win32 {53F75437-15B8-4A5C-86BF-E238CC68FCBC}.Release|x64.ActiveCfg = Release|x64 {53F75437-15B8-4A5C-86BF-E238CC68FCBC}.Release|x64.Build.0 = Release|x64 - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}.Debug|Win32.ActiveCfg = Debug|Win32 - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}.Debug|Win32.Build.0 = Debug|Win32 - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}.Debug|x64.ActiveCfg = Debug|x64 - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}.Debug|x64.Build.0 = Debug|x64 - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}.Release|Win32.ActiveCfg = Release|Win32 - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}.Release|Win32.Build.0 = Release|Win32 - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}.Release|x64.ActiveCfg = Release|x64 - {34FDEFC1-F14D-4ADD-ADC1-25134C28A73D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/builds/win32/msvc8/fbtrace.vcproj b/builds/win32/msvc8/fbtrace.vcproj index 84996af34f..6cad613365 100644 --- a/builds/win32/msvc8/fbtrace.vcproj +++ b/builds/win32/msvc8/fbtrace.vcproj @@ -1,7 +1,7 @@ - + @@ -40,7 +40,7 @@ @@ -55,8 +55,10 @@ /> @@ -125,8 +127,10 @@ /> @@ -193,8 +197,10 @@ /> + + @@ -379,6 +391,10 @@ RelativePath="..\..\..\src\jrd\gds.cpp" > + + @@ -395,6 +411,14 @@ RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp" > + + + + diff --git a/builds/win32/msvc8/regex.vcproj b/builds/win32/msvc8/regex.vcproj deleted file mode 100644 index 9d1db59c50..0000000000 --- a/builds/win32/msvc8/regex.vcproj +++ /dev/null @@ -1,366 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/configure.in b/configure.in index 5681a44904..8bce8a518f 100644 --- a/configure.in +++ b/configure.in @@ -1282,7 +1282,6 @@ gen/Makefile.embed.isql:${MAKE_SRC_DIR}/Makefile.in.embed.isql gen/Makefile.embed.gdef:${MAKE_SRC_DIR}/Makefile.in.embed.gdef gen/Makefile.embed.qli:${MAKE_SRC_DIR}/Makefile.in.embed.qli gen/Makefile.embed.gpre:${MAKE_SRC_DIR}/Makefile.in.embed.gpre -gen/Makefile.extern.regex:${MAKE_SRC_DIR}/Makefile.in.extern.regex gen/Makefile.fbtrace:${MAKE_SRC_DIR}/Makefile.in.fbtrace gen/Makefile.install:builds/install/arch-specific/${INSTALL_PREFIX}/Makefile.in Makefile:Makefile.in @@ -1316,8 +1315,6 @@ chmod +x runConfigureICU configure install-sh ./runConfigureICU "$ICU_PLATFORM" "$DEBUG_ICU" --prefix=`pwd`/..) fi -(cd extern/regex; sh configure) - dnl Print out the build configuration (the most interesting thing) echo echo diff --git a/src/jrd/Collation.cpp b/src/jrd/Collation.cpp index 8dac8fa9b0..7fa655c7d3 100644 --- a/src/jrd/Collation.cpp +++ b/src/jrd/Collation.cpp @@ -101,10 +101,10 @@ #include "../jrd/intl_classes.h" #include "../jrd/TextType.h" -using namespace Jrd; - #include "../jrd/SimilarToMatcher.h" +using namespace Jrd; + namespace { @@ -137,74 +137,6 @@ static const UCHAR SLEUTH_SPECIAL[128] = // Below are templates for functions used in Collation implementation -class NullStrConverter -{ -public: - NullStrConverter(MemoryPool& pool, const TextType* obj, const UCHAR* str, SLONG len) - { - } -}; - -template -class UpcaseConverter : public PrevConverter -{ -public: - UpcaseConverter(MemoryPool& pool, TextType* obj, const UCHAR*& str, SLONG& len) - : PrevConverter(pool, obj, str, len) - { - if (len > (int) sizeof(tempBuffer)) - out_str = FB_NEW(pool) UCHAR[len]; - else - out_str = tempBuffer; - obj->str_to_upper(len, str, len, out_str); - str = out_str; - } - - ~UpcaseConverter() - { - if (out_str != tempBuffer) - delete[] out_str; - } - -private: - UCHAR tempBuffer[100]; - UCHAR* out_str; -}; - -template -class CanonicalConverter : public PrevConverter -{ -public: - CanonicalConverter(MemoryPool& pool, TextType* obj, const UCHAR*& str, SLONG& len) - : PrevConverter(pool, obj, str, len) - { - const SLONG out_len = len / obj->getCharSet()->minBytesPerChar() * obj->getCanonicalWidth(); - - if (out_len > (int) sizeof(tempBuffer)) - out_str = FB_NEW(pool) UCHAR[out_len]; - else - out_str = tempBuffer; - - if (str) - { - len = obj->canonical(len, str, out_len, out_str) * obj->getCanonicalWidth(); - str = out_str; - } - else - len = 0; - } - - ~CanonicalConverter() - { - if (out_str != tempBuffer) - delete[] out_str; - } - -private: - UCHAR tempBuffer[100]; - UCHAR* out_str; -}; - template class LikeMatcher : public PatternMatcher { diff --git a/src/jrd/IntlUtil.cpp b/src/jrd/IntlUtil.cpp index 96a77d00d5..a47d2c1c2a 100644 --- a/src/jrd/IntlUtil.cpp +++ b/src/jrd/IntlUtil.cpp @@ -388,6 +388,8 @@ void IntlUtil::initNarrowCharset(charset* cs, const ASCII* name) bool IntlUtil::initUnicodeCollation(texttype* tt, charset* cs, const ASCII* name, USHORT attributes, const UCharBuffer& specificAttributes, const string& configInfo) { + memset(tt, 0, sizeof(*tt)); + // name comes from stack. Copy it. ASCII* nameCopy = new ASCII[strlen(name) + 1]; strcpy(nameCopy, name); diff --git a/src/jrd/SimilarToMatcher.h b/src/jrd/SimilarToMatcher.h index 14671b5e00..5467a1a0d6 100644 --- a/src/jrd/SimilarToMatcher.h +++ b/src/jrd/SimilarToMatcher.h @@ -38,9 +38,12 @@ namespace Firebird { template -class SimilarToMatcher : public PatternMatcher +class SimilarToMatcher : public Jrd::PatternMatcher { private: + typedef Jrd::CharSet CharSet; + typedef Jrd::TextType TextType; + // This class is based on work of Zafir Anjum // http://www.codeguru.com/Cpp/Cpp/string/regex/article.php/c2791 // which has been derived from work by Henry Spencer. @@ -103,7 +106,8 @@ private: len3(aLen), str4(NULL), len4(0), - ref(0) + ref(0), + branchNum(-1) { } @@ -117,7 +121,8 @@ private: len3(0), str4(NULL), len4(0), - ref(aRef) + ref(aRef), + branchNum(-1) { } @@ -131,7 +136,8 @@ private: len3(0), str4(NULL), len4(0), - ref(aRef) + ref(aRef), + branchNum(-1) { } @@ -145,7 +151,8 @@ private: len3(node.len3), str4(node.str4), len4(node.len4), - ref(node.ref) + ref(node.ref), + branchNum(node.branchNum) { } @@ -159,6 +166,7 @@ private: const UCHAR* str4; SLONG len4; int ref; + int branchNum; }; // Struct used to evaluate expressions without recursion. @@ -213,6 +221,12 @@ private: const CharType* set, SLONG setLen); private: + struct Range + { + unsigned start; + unsigned length; + }; + TextType* textType; CharType escapeChar; bool useEscape; @@ -230,6 +244,10 @@ private: const CharType* bufferEnd; const CharType* bufferPos; CharType metaCharacters[15]; + + public: + unsigned branchNum; + Range* branches; }; public: @@ -255,6 +273,18 @@ public: return evaluator.processNextChunk(str, length); } + unsigned getNumBranches() + { + return evaluator.branchNum; + } + + void getBranchInfo(unsigned n, unsigned* start, unsigned* length) + { + fb_assert(n <= evaluator.branchNum); + *start = evaluator.branches[n].start; + *length = evaluator.branches[n].length; + } + static SimilarToMatcher* create(MemoryPool& pool, TextType* ttype, const UCHAR* str, SLONG length, const UCHAR* escape, SLONG escape_length) { @@ -295,7 +325,8 @@ SimilarToMatcher::Evaluator::Evaluator( patternCvt(pool, textType, patternStr, patternLen), charSet(textType->getCharSet()), nodes(pool), - scopes(pool) + scopes(pool), + branchNum(0) { fb_assert(patternLen % sizeof(CharType) == 0); patternLen /= sizeof(CharType); @@ -339,6 +370,8 @@ SimilarToMatcher::Evaluator::Evaluator( if (patternPos < patternEnd) status_exception::raise(Arg::Gds(isc_invalid_similar_pattern)); + branches = FB_NEW(pool) Range[branchNum + 1]; + reset(); } @@ -356,11 +389,29 @@ bool SimilarToMatcher::Evaluator::getResult() bufferStart = bufferPos = (const CharType*) str; bufferEnd = bufferStart + len / sizeof(CharType); + bool matched = #ifdef RECURSIVE_SIMILAR - return match(nodes.getCount(), 0); + match(nodes.getCount(), 0); #else - return match(); + match(); #endif + +#ifdef DEBUG_SIMILAR + if (matched) + { + string s; + for (unsigned i = 0; i <= branchNum; ++i) + { + string x; + x.printf("%d: %d, %d\n\t", i, branches[i].start, branches[i].length); + s += x; + } + + gds__log("%s", s.c_str()); + } +#endif // DEBUG_SIMILAR + + return matched; } @@ -378,6 +429,8 @@ void SimilarToMatcher::Evaluator::reset() { buffer.shrink(0); scopes.shrink(0); + + memset(branches, 0, sizeof(Range) * (branchNum + 1)); } @@ -397,8 +450,10 @@ void SimilarToMatcher::Evaluator::parseExpr(int* flagp) else ++patternPos; + int thisBranchNum = branchNum; start = nodes.getCount(); nodes.push(Node(opBranch)); + nodes.back().branchNum = thisBranchNum; int flags; parseTerm(&flags); @@ -407,8 +462,8 @@ void SimilarToMatcher::Evaluator::parseExpr(int* flagp) refs.push(nodes.getCount()); nodes.push(Node(opRef)); + nodes.back().branchNum = thisBranchNum; - nodes[start].ref = nodes.getCount() - start; } nodes[start].ref = 0; @@ -832,6 +887,8 @@ void SimilarToMatcher::Evaluator::parsePrimary(int* flag } else if (op == canonicalChar(TextType::CHAR_OPEN_PAREN)) { + ++branchNum; + int flags; parseExpr(&flags); @@ -899,7 +956,10 @@ void SimilarToMatcher::Evaluator::dump() const break; case opBranch: - type.printf("opBranch(%d)", i + nodes[i].ref); + if (nodes[i].branchNum == -1) + type.printf("opBranch(%d)", i + nodes[i].ref); + else + type.printf("opBranch(%d, %d)", i + nodes[i].ref, nodes[i].branchNum); break; case opStart: @@ -911,7 +971,10 @@ void SimilarToMatcher::Evaluator::dump() const break; case opRef: - type.printf("opRef(%d)", i + nodes[i].ref); + if (nodes[i].branchNum == -1) + type.printf("opRef(%d)", i + nodes[i].ref); + else + type.printf("opRef(%d, %d)", i + nodes[i].ref, nodes[i].branchNum); break; case opNothing: @@ -993,6 +1056,9 @@ bool SimilarToMatcher::Evaluator::match(int limit, int s while (true) { + if (node->branchNum != -1) + branches[node->branchNum].start = save - bufferStart; + if (match(limit, i + 1)) return true; @@ -1022,6 +1088,12 @@ bool SimilarToMatcher::Evaluator::match(int limit, int s break; case opRef: + if (node->branchNum != -1) + { + branches[node->branchNum].length = + bufferPos - bufferStart - branches[node->branchNum].start; + } + if (node->ref == 1) // avoid recursion break; return match(limit, i + node->ref); @@ -1202,6 +1274,9 @@ bool SimilarToMatcher::Evaluator::match() case opBranch: if (state == msIterating) { + if (node->branchNum != -1) + branches[node->branchNum].start = bufferPos - bufferStart; + scope->save = bufferPos; start = scope->i + 1; limit = scope->limit; @@ -1258,6 +1333,12 @@ bool SimilarToMatcher::Evaluator::match() fb_assert(state == msIterating || state == msReturning); if (state == msIterating) { + if (node->branchNum != -1) + { + branches[node->branchNum].length = + bufferPos - bufferStart - branches[node->branchNum].start; + } + if (node->ref != 1) { state = msRecursing; diff --git a/src/jrd/intl_classes.h b/src/jrd/intl_classes.h index 94b58dadde..2ff95aff20 100644 --- a/src/jrd/intl_classes.h +++ b/src/jrd/intl_classes.h @@ -33,6 +33,9 @@ #include "../jrd/intlobj_new.h" #include "../jrd/constants.h" #include "../jrd/unicode_util.h" +#include "../jrd/CsConvert.h" +#include "../jrd/CharSet.h" +#include "../jrd/TextType.h" namespace Jrd { @@ -58,12 +61,77 @@ protected: TextType* textType; }; +class NullStrConverter +{ +public: + NullStrConverter(MemoryPool& pool, const TextType* obj, const UCHAR* str, SLONG len) + { + } +}; + +template +class UpcaseConverter : public PrevConverter +{ +public: + UpcaseConverter(MemoryPool& pool, TextType* obj, const UCHAR*& str, SLONG& len) + : PrevConverter(pool, obj, str, len) + { + if (len > (int) sizeof(tempBuffer)) + out_str = FB_NEW(pool) UCHAR[len]; + else + out_str = tempBuffer; + obj->str_to_upper(len, str, len, out_str); + str = out_str; + } + + ~UpcaseConverter() + { + if (out_str != tempBuffer) + delete[] out_str; + } + +private: + UCHAR tempBuffer[100]; + UCHAR* out_str; +}; + +template +class CanonicalConverter : public PrevConverter +{ +public: + CanonicalConverter(MemoryPool& pool, TextType* obj, const UCHAR*& str, SLONG& len) + : PrevConverter(pool, obj, str, len) + { + const SLONG out_len = len / obj->getCharSet()->minBytesPerChar() * obj->getCanonicalWidth(); + + if (out_len > (int) sizeof(tempBuffer)) + out_str = FB_NEW(pool) UCHAR[out_len]; + else + out_str = tempBuffer; + + if (str) + { + len = obj->canonical(len, str, out_len, out_str) * obj->getCanonicalWidth(); + str = out_str; + } + else + len = 0; + } + + ~CanonicalConverter() + { + if (out_str != tempBuffer) + delete[] out_str; + } + +private: + UCHAR tempBuffer[100]; + UCHAR* out_str; +}; + } // namespace Jrd -#include "../jrd/CsConvert.h" -#include "../jrd/CharSet.h" -#include "../jrd/TextType.h" #include "../jrd/Collation.h" diff --git a/src/utilities/ntrace/TraceConfiguration.cpp b/src/utilities/ntrace/TraceConfiguration.cpp index cce826e395..8c6a82ea8a 100644 --- a/src/utilities/ntrace/TraceConfiguration.cpp +++ b/src/utilities/ntrace/TraceConfiguration.cpp @@ -26,9 +26,14 @@ */ #include "TraceConfiguration.h" +#include "../../jrd/intl_classes.h" +#include "../../jrd/evl_string.h" +#include "../../jrd/TextType.h" +#include "../../jrd/SimilarToMatcher.h" using namespace Firebird; + void TraceCfgReader::readTraceConfiguration(const char* text, const PathName& databaseName, TracePluginConfig& config) @@ -67,14 +72,21 @@ void TraceCfgReader::readConfig() cfgFile->addText(m_text); cfgFile->parse(); - m_subpatterns[0].rm_so = 0; - m_subpatterns[0].rm_eo = m_databaseName.length(); + m_subpatterns[0].start = 0; + m_subpatterns[0].end = m_databaseName.length(); for (size_t i = 1; i < FB_NELEM(m_subpatterns); i++) { - m_subpatterns[i].rm_so = -1; - m_subpatterns[i].rm_eo = -1; + m_subpatterns[i].start = -1; + m_subpatterns[i].end = -1; } + charset cs; + IntlUtil::initAsciiCharset(&cs); + texttype tt; + IntlUtil::initUnicodeCollation(&tt, &cs, "UNICODE", 0, UCharBuffer(), string()); + AutoPtr charSet(Jrd::CharSet::createInstance(*getDefaultMemoryPool(), 0, &cs)); + Jrd::TextType textType(0, &tt, charSet); + bool defDB = false, defSvc = false, exactMatch = false; const Element* section = cfgFile->getObjects()->children; for (; section && !exactMatch; section = section->sibling) @@ -115,34 +127,38 @@ void TraceCfgReader::readConfig() match = exactMatch = true; else { - regex_t matcher; - int flags = REG_EXTENDED; - if (!CASE_SENSITIVITY) - flags |= REG_ICASE; - int errorCode = regcomp(&matcher, pattern.c_str(), flags); - - if (errorCode) + try { - char errBuf[256]; - regerror(errorCode, NULL, errBuf, sizeof(errBuf)); - fatal_exception::raiseFmt( - "line %d: error \"%s\" while compiling regular expression \"%s\"", - section->lineNumber + 1, errBuf, pattern.c_str()); +#ifdef WIN_NT // !CASE_SENSITIVITY + typedef Jrd::UpcaseConverter SimilarConverter; +#else + typedef Jrd::NullStrConverter SimilarConverter; +#endif + SimilarToMatcher matcher(*getDefaultMemoryPool(), + &textType, (const UCHAR*) pattern.c_str(), pattern.length(), '\\', true); + + matcher.process((const UCHAR*) m_databaseName.c_str(), m_databaseName.length()); + if (matcher.result()) + { + for (unsigned i = 0; + i <= matcher.getNumBranches() && i < FB_NELEM(m_subpatterns); ++i) + { + unsigned start, length; + matcher.getBranchInfo(i, &start, &length); + + m_subpatterns[i].start = start; + m_subpatterns[i].end = start + length; + } + + match = exactMatch = true; + } } - - errorCode = regexec(&matcher, m_databaseName.c_str(), FB_NELEM(m_subpatterns), m_subpatterns, 0); - - if (errorCode && errorCode != REG_NOMATCH) + catch (const Exception&) { - char errBuf[256]; - regerror(errorCode, NULL, errBuf, sizeof(errBuf)); fatal_exception::raiseFmt( - "line %d: error \"%s\" while applying regular expression \"%s\" to database \"%s\"", - section->lineNumber + 1, errBuf, pattern.c_str(), m_databaseName.c_str()); + "line %d: error while compiling regular expression \"%s\"", + section->lineNumber + 1, pattern.c_str()); } - - if (errorCode == 0) - match = exactMatch = true; } } @@ -214,45 +230,35 @@ void TraceCfgReader::expandPattern(string& valueToExpand) while (pos < valueToExpand.length()) { string::char_type c = valueToExpand[pos]; - if (c == '$') + if (c == '\\') { if (pos + 1 >= valueToExpand.length()) fatal_exception::raiseFmt("pattern is invalid"); c = valueToExpand[pos + 1]; - if (c == '$') + if (c == '\\') { - // Kill one of the dollar signs and loop again + // Kill one of the backslash signs and loop again valueToExpand.erase(pos, 1); continue; } if (c >= '0' && c <= '9') { - regmatch_t* subpattern = m_subpatterns + (c - '0'); + MatchPos* subpattern = m_subpatterns + (c - '0'); // Replace value with piece of database name valueToExpand.erase(pos, 2); - if (subpattern->rm_eo != -1 && subpattern->rm_so != -1) + if (subpattern->end != -1 && subpattern->start != -1) { - off_t subpattern_len = subpattern->rm_eo - subpattern->rm_so; + off_t subpattern_len = subpattern->end - subpattern->start; valueToExpand.insert(pos, - m_databaseName.substr(subpattern->rm_so, subpattern_len).c_str(), + m_databaseName.substr(subpattern->start, subpattern_len).c_str(), subpattern_len); pos += subpattern_len; } continue; } - if (c == '&') - { - // Replace value with whole database file name - valueToExpand.erase(pos, 2); - const Firebird::PathName& filename = m_databaseName; - valueToExpand.insert(pos, filename.c_str(), filename.length()); - pos += filename.length(); - continue; - } - fatal_exception::raiseFmt("pattern is invalid"); } diff --git a/src/utilities/ntrace/TraceConfiguration.h b/src/utilities/ntrace/TraceConfiguration.h index b6c4f3b593..4ea5273b9f 100644 --- a/src/utilities/ntrace/TraceConfiguration.h +++ b/src/utilities/ntrace/TraceConfiguration.h @@ -39,7 +39,6 @@ #include "TracePluginConfig.h" #include -#include "regex.h" class TraceCfgReader @@ -47,6 +46,13 @@ class TraceCfgReader public: static void readTraceConfiguration(const char* text, const Firebird::PathName& databaseName, TracePluginConfig& config); +private: + struct MatchPos + { + int start; + int end; + }; + private: TraceCfgReader(const char* text, const Firebird::PathName& databaseName, TracePluginConfig& config) : m_text(text), @@ -62,7 +68,7 @@ private: const char* const m_text; const Firebird::PathName& m_databaseName; - regmatch_t m_subpatterns[10]; + MatchPos m_subpatterns[10]; TracePluginConfig& m_config; }; diff --git a/src/utilities/ntrace/TracePluginImpl.cpp b/src/utilities/ntrace/TracePluginImpl.cpp index 5611f6e9b2..5c6a3cb78b 100644 --- a/src/utilities/ntrace/TracePluginImpl.cpp +++ b/src/utilities/ntrace/TracePluginImpl.cpp @@ -137,30 +137,41 @@ TracePluginImpl::TracePluginImpl(const TracePluginConfig &configuration, TraceIn PluginLogWriter(logname.c_str(), config.max_log_size * 1024 * 1024); } + IntlUtil::initAsciiCharset(&cs); + IntlUtil::initUnicodeCollation(&tt, &cs, "UNICODE", 0, UCharBuffer(), string()); + charSet = Jrd::CharSet::createInstance(*getDefaultMemoryPool(), 0, &cs); + textType = FB_NEW(*getDefaultMemoryPool()) Jrd::TextType(0, &tt, charSet); + // Compile filtering regular expressions if (config.include_filter.hasData()) { - int errorCode = regcomp(&include_matcher, config.include_filter.c_str(), REG_EXTENDED | REG_ICASE); - if (errorCode) + try { - char errBuf[256]; - regerror(errorCode, NULL, errBuf, sizeof(errBuf)); - Firebird::fatal_exception::raiseFmt( - "error \"%s\" while compiling regular expression \"%s\" for database \"%s\"", - errBuf, config.include_filter.c_str(), config.db_filename.c_str()); + include_matcher = new SimilarToMatcher, UCHAR>( + *getDefaultMemoryPool(), textType, (const UCHAR*) config.include_filter.c_str(), + config.include_filter.length(), '\\', true); + } + catch (const Exception&) + { + fatal_exception::raiseFmt( + "error while compiling regular expression \"%s\" for database \"%s\"", + config.include_filter.c_str(), config.db_filename.c_str()); } } if (config.exclude_filter.hasData()) { - int errorCode = regcomp(&exclude_matcher, config.exclude_filter.c_str(), REG_EXTENDED | REG_ICASE); - if (errorCode) + try { - char errBuf[256]; - regerror(errorCode, NULL, errBuf, sizeof(errBuf)); - Firebird::fatal_exception::raiseFmt( - "error \"%s\" while compiling regular expression \"%s\" for database \"%s\"", - errBuf, config.exclude_filter.c_str(), config.db_filename.c_str()); + exclude_matcher = new SimilarToMatcher, UCHAR>( + *getDefaultMemoryPool(), textType, (const UCHAR*) config.exclude_filter.c_str(), + config.exclude_filter.length(), '\\', true); + } + catch (const Exception&) + { + fatal_exception::raiseFmt( + "error while compiling regular expression \"%s\" for database \"%s\"", + config.exclude_filter.c_str(), config.db_filename.c_str()); } } @@ -1229,32 +1240,16 @@ void TracePluginImpl::register_sql_statement(TraceSQLStatement* statement) { if (config.include_filter.hasData()) { - const int errorCode = regexec(&include_matcher, sql, 0, NULL, 0); - if (errorCode && errorCode != REG_NOMATCH) - { - char errBuf[256]; - regerror(errorCode, NULL, errBuf, sizeof(errBuf)); - Firebird::fatal_exception::raiseFmt( - "error \"%s\" while applying regular expression \"%s\" for database \"%s\"", - errBuf, config.include_filter.c_str(), config.db_filename.c_str()); - } - need_statement = !errorCode; + include_matcher->reset(); + include_matcher->process((const UCHAR*) sql, sql_length); + need_statement = include_matcher->result(); } if (need_statement && config.exclude_filter.hasData()) { - const int errorCode = regexec(&exclude_matcher, sql, 0, NULL, 0); - if (errorCode && errorCode != REG_NOMATCH) - { - char errBuf[256]; - regerror(errorCode, NULL, errBuf, sizeof(errBuf)); - Firebird::fatal_exception::raiseFmt( - "error \"%s\" while applying regular expression \"%s\" for database \"%s\"", - errBuf, config.exclude_filter.c_str(), config.db_filename.c_str()); - } - - if (!errorCode) - need_statement = false; + exclude_matcher->reset(); + exclude_matcher->process((const UCHAR*) sql, sql_length); + need_statement = !exclude_matcher->result(); } } diff --git a/src/utilities/ntrace/TracePluginImpl.h b/src/utilities/ntrace/TracePluginImpl.h index a5a3dedec6..9dd46e1911 100644 --- a/src/utilities/ntrace/TracePluginImpl.h +++ b/src/utilities/ntrace/TracePluginImpl.h @@ -31,14 +31,17 @@ #include "../../jrd/ntrace.h" #include "TracePluginConfig.h" +#include "../../jrd/intl_classes.h" +#include "../../jrd/evl_string.h" +#include "../../jrd/TextType.h" +#include "../../jrd/SimilarToMatcher.h" #include "../../common/classes/rwlock.h" #include "../../common/classes/GenericMap.h" #include "../../common/classes/locks.h" - // Bring in off_t #include -#include "regex.h" + class TracePluginImpl { @@ -161,8 +164,13 @@ private: // Lock for log rotation Firebird::RWLock renameLock; - regex_t include_matcher; - regex_t exclude_matcher; + charset cs; + texttype tt; + Firebird::AutoPtr charSet; + Firebird::AutoPtr textType; + + Firebird::AutoPtr, UCHAR> > + include_matcher, exclude_matcher; void appendGlobalCounts(const PerformanceInfo* info); void appendTableCounts(const PerformanceInfo* info); diff --git a/src/utilities/ntrace/fbtrace.conf b/src/utilities/ntrace/fbtrace.conf index 72f545c40c..e7f4617ac6 100644 --- a/src/utilities/ntrace/fbtrace.conf +++ b/src/utilities/ntrace/fbtrace.conf @@ -7,13 +7,12 @@ # - if database name matches pattern, options are immediately applied and # search does not continue # -# Pattern is either database name without path or POSIX 1002.3 extended regular -# expression in square braces which is matched against fully qualified database -# path name. +# Pattern is either database name without path or "SIMILAR TO"-based regular +# expression which is matched against fully qualified database path name. # -# For log file name Apache/Perl syntax for substitutions is supported. -# I.e. $& - whole matched string, $1 ... $9 - braced subexpressions. -# $$ is dollar sign. +# For log file name Sed syntax for substitutions is supported. +# I.e. \0 - whole matched string, \1 ... \9 - parenthesis subexpressions. +# \\ is backslash. # default database section @@ -155,7 +154,7 @@ # into log file name matching database name - test.log, azk2.log and # rulez.log appropriately # - + enabled true - log_filename $1.log + log_filename \1.log