diff --git a/build/bakefiles/regex.bkl b/build/bakefiles/regex.bkl index fa9a7ce92d..b93a2fc24c 100644 --- a/build/bakefiles/regex.bkl +++ b/build/bakefiles/regex.bkl @@ -10,7 +10,7 @@ builtin - wxregex$(WXDEBUGFLAG)$(HOST_SUFFIX) + wxregex$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(HOST_SUFFIX) $(TOP_SRCDIR)src/regex @@ -18,11 +18,12 @@ + $(id)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(HOST_SUFFIX) $(TOP_SRCDIR)include $(SETUPHDIR) $(UNICODE_DEFINE) $(LIBDIRNAME) - -w-8004 -w-8012 -w-8057 -w-8066 + -w-8008 -w-8012 -w-8057 -w-8064 -w-8066 -w-8070 src/regex/regcomp.c src/regex/regexec.c diff --git a/include/wx/features.h b/include/wx/features.h index 80d7e6b317..fec65015ba 100644 --- a/include/wx/features.h +++ b/include/wx/features.h @@ -56,5 +56,13 @@ #undef wxHAS_CRASH_REPORT #endif +/* wxRE_ADVANCED is not always available, depending on regex library used + * (it's unavailable only if compiling via configure against system library) */ +#ifndef WX_NO_REGEX_ADVANCED + #define wxHAS_REGEX_ADVANCED +#else + #undef wxHAS_REGEX_ADVANCED +#endif + #endif /* _WX_FEATURES_H_ */ diff --git a/include/wx/regex.h b/include/wx/regex.h index 78224ca942..1656008c5a 100644 --- a/include/wx/regex.h +++ b/include/wx/regex.h @@ -29,8 +29,13 @@ class WXDLLIMPEXP_BASE wxString; // flags for regex compilation: these can be used with Compile() enum { - // use extended regex syntax (default) + // use extended regex syntax wxRE_EXTENDED = 0, + + // use advanced RE syntax (built-in regex only) +#ifdef wxHAS_REGEX_ADVANCED + wxRE_ADVANCED = 1, +#endif // use basic RE syntax wxRE_BASIC = 2, diff --git a/src/common/regex.cpp b/src/common/regex.cpp index 12d49ee971..2cd6afafce 100644 --- a/src/common/regex.cpp +++ b/src/common/regex.cpp @@ -73,7 +73,7 @@ public: private: // return the string containing the error message for the given err code - wxString GetErrorMsg(int errorcode) const; + wxString GetErrorMsg(int errorcode, bool badconv) const; // init the members void Init() @@ -131,8 +131,19 @@ wxRegExImpl::~wxRegExImpl() Free(); } -wxString wxRegExImpl::GetErrorMsg(int errorcode) const +wxString wxRegExImpl::GetErrorMsg(int errorcode, bool badconv) const { +#if wxUSE_UNICODE && !defined(__REG_NOFRONT) + // currently only needed when using system library in Unicode mode + if ( badconv ) + { + return _("conversion to 8-bit encoding failed"); + } +#else + // 'use' badconv to avoid a compiler warning + (void)badconv; +#endif + wxString szError; // first get the string length needed @@ -158,14 +169,25 @@ bool wxRegExImpl::Compile(const wxString& expr, int flags) { Reinit(); - // translate our flags to regcomp() ones - wxASSERT_MSG( !(flags & - ~(wxRE_BASIC | wxRE_ICASE | wxRE_NOSUB | wxRE_NEWLINE)), +#ifdef WX_NO_REGEX_ADVANCED +# define FLAVORS wxRE_BASIC +#else +# define FLAVORS (wxRE_ADVANCED | wxRE_BASIC) + wxASSERT_MSG( (flags & FLAVORS) != FLAVORS, + _T("incompatible flags in wxRegEx::Compile") ); +#endif + wxASSERT_MSG( !(flags & ~(FLAVORS | wxRE_ICASE | wxRE_NOSUB | wxRE_NEWLINE)), _T("unrecognized flags in wxRegEx::Compile") ); + // translate our flags to regcomp() ones int flagsRE = 0; if ( !(flags & wxRE_BASIC) ) - flagsRE |= REG_EXTENDED; +#ifndef WX_NO_REGEX_ADVANCED + if (flags & wxRE_ADVANCED) + flagsRE |= REG_ADVANCED; + else +#endif + flagsRE |= REG_EXTENDED; if ( flags & wxRE_ICASE ) flagsRE |= REG_ICASE; if ( flags & wxRE_NOSUB ) @@ -173,14 +195,19 @@ bool wxRegExImpl::Compile(const wxString& expr, int flags) if ( flags & wxRE_NEWLINE ) flagsRE |= REG_NEWLINE; + // compile it +#ifdef __REG_NOFRONT + bool conv = true; + int errorcode = re_comp(&m_RegEx, expr, expr.length(), flagsRE); +#else + const wxWX2MBbuf conv = expr.mbc_str(); + int errorcode = conv ? regcomp(&m_RegEx, conv, flagsRE) : REG_BADPAT; +#endif - - int errorcode = regcomp(&m_RegEx, expr, flagsRE); - - if ( errorcode ) + if ( errorcode ) { wxLogError(_("Invalid regular expression '%s': %s"), - expr.c_str(), GetErrorMsg(errorcode).c_str()); + expr.c_str(), GetErrorMsg(errorcode, !conv).c_str()); m_isCompiled = FALSE; } @@ -250,7 +277,13 @@ bool wxRegExImpl::Matches(const wxChar *str, int flags) const } // do match it - int rc = regexec(&self->m_RegEx, str, m_nMatches, m_Matches, flagsRE); +#ifdef __REG_NOFRONT + bool conv = true; + int rc = re_exec(&self->m_RegEx, str, wxStrlen(str), NULL, m_nMatches, m_Matches, flagsRE); +#else + const wxWX2MBbuf conv = wxConvertWX2MB(str); + int rc = conv ? regexec(&self->m_RegEx, conv, m_nMatches, m_Matches, flagsRE) : REG_BADPAT; +#endif switch ( rc ) { @@ -261,7 +294,7 @@ bool wxRegExImpl::Matches(const wxChar *str, int flags) const default: // an error occured wxLogError(_("Failed to match '%s' in regular expression: %s"), - str, GetErrorMsg(rc).c_str()); + str, GetErrorMsg(rc, !conv).c_str()); // fall through case REG_NOMATCH: diff --git a/src/regex/splice.sh b/src/regex/splice.sh new file mode 100755 index 0000000000..02fad6de19 --- /dev/null +++ b/src/regex/splice.sh @@ -0,0 +1,69 @@ +#!/bin/sh +############################################################################# +# Name: splice +# Purpose: Splice a marked section of regcustom.h into regex.h +# Author: Mike Wetherell +# RCS-ID: $Id$ +# Copyright: (c) 2004 Mike Wetherell +# Licence: wxWindows licence +############################################################################# + +# +# Works by greping for the marks then passing their line numbers to sed. Which +# is slighly the long way round, but allows some error checking. +# + +SRC=regcustom.h +DST=regex.h +MARK1='^/\* --- begin --- \*/$' +MARK2='^/\* --- end --- \*/$' +PROG=`basename $0` +TMP=$DST.tmp + +# findline(pattern, file) +# Prints the line number of the 1st line matching the pattern in the file +# +findline() { + if ! LINE=`grep -n -- "$1" "$2"`; then + echo "$PROG: marker '$1' not found in '$2'" >&2 + return 1 + fi + echo $LINE | sed -n '1s/[^0-9].*//p' # take just the line number +} + +# findmarkers([out] line1, [out] line2, pattern1, pattern2, file) +# Returns (via the variables named in the 1st two parameters) the line +# numbers of the lines matching the patterns in file. Checks pattern1 comes +# before pattern2. +# +findmarkers() { + if ! LINE1=`findline "$3" "$5"` || ! LINE2=`findline "$4" "$5"`; then + return 1 + fi + if [ $LINE1 -ge $LINE2 ]; then + echo "$PROG: marker '$3' not before '$4' in '$5'" >&2 + return 1 + fi + eval $1=$LINE1 + eval $2=$LINE2 +} + +# find markers +# +if findmarkers SRCLINE1 SRCLINE2 "$MARK1" "$MARK2" $SRC && + findmarkers DSTLINE1 DSTLINE2 "$MARK1" "$MARK2" $DST +then + # do splice + # + if (sed $DSTLINE1,\$d $DST && + sed -n $SRCLINE1,${SRCLINE2}p $SRC && + sed 1,${DSTLINE2}d $DST) > $TMP + then + mv $TMP $DST + exit 0 + else + rm $TMP + fi +fi + +exit 1