#
#
# patch "ChangeLog"
# from [1b1b7c07088e736bb647b6e730e5461973158d8a]
# to [46322c5ce6d7212ac4d983b7e3ebf934077625e8]
#
# patch "lua.cc"
# from [6e59fe049bc11b83e177f02d9bf5620335c80488]
# to [584d32c9ad2fd3358d18116d195af8b308c1d469]
#
# patch "luaext_globish.cc"
# from [506249a961f0209231535ac1c696bda6442d22da]
# to [91142495a024ecca88d1e5caaf06259e047c2d07]
#
# patch "pcrewrap.cc"
# from [4dc70cfb7a55e24b3fd86a0324487f645e25db2c]
# to [5e175ccccd98a56490c4479e634b4547a52eb9e5]
#
# patch "pcrewrap.hh"
# from [701afe7a88a0cbb36c0b38afb6a03050f22f89b4]
# to [5b3070b3642cc669273a7347bf6feb938f465215]
#
# patch "po/POTFILES.in"
# from [76d2c8a470bc2f234c0b239155b20dbc29f59fdf]
# to [3642b5fb461f3a18033922e4e72ac081613ea8f3]
#
============================================================
--- ChangeLog 1b1b7c07088e736bb647b6e730e5461973158d8a
+++ ChangeLog 46322c5ce6d7212ac4d983b7e3ebf934077625e8
@@ -1,5 +1,19 @@ 2006-12-27 Zack Weinberg
+ * pcrewrap.hh (pcre::compile_error, pcre::match_error): Simplify.
+ Constructor now takes an i18n_format const &.
+ (pcre::study_error, pcre::fullinfo_error): Delete.
+ * pcrewrap.cc (pcre_compile_error, pcre_study_error, pcre_match_error):
+ New functions.
+ (compile, get_capturecount, match): Use them.
+ (compile_error_message, compile_error::compile_error)
+ (match_error::match_error, fullinfo_error::fullinfo_error): Delete.
+
+ * lua.cc (regex.search): Simplify error handling.
+ * luaext_globish.cc (globish.match): Likewise.
+ * po/POTFILES.in: Add pcrewrap.cc.
+
+2006-12-27 Zack Weinberg
* pcrewrap.cc, pcrewrap.hh: Change "const T" to "T const" throughout.
2006-12-27 Zack Weinberg
============================================================
--- lua.cc 6e59fe049bc11b83e177f02d9bf5620335c80488
+++ lua.cc 584d32c9ad2fd3358d18116d195af8b308c1d469
@@ -550,10 +550,10 @@ LUAEXT(search, regex)
bool result = false;
try {
result = pcre::regex(re).match(str);
- } catch (pcre::compile_error e) {
- return luaL_error(L, (string("error parsing regex: ") + e.what()).c_str());
- } catch (pcre::match_error e) {
- return luaL_error(L, (string("error during match: ") + e.what()).c_str());
+ } catch (pcre::compile_error & e) {
+ return luaL_error(L, e.what());
+ } catch (pcre::match_error & e) {
+ return luaL_error(L, e.what());
}
lua_pushboolean(L, result);
return 1;
============================================================
--- luaext_globish.cc 506249a961f0209231535ac1c696bda6442d22da
+++ luaext_globish.cc 91142495a024ecca88d1e5caaf06259e047c2d07
@@ -18,10 +18,10 @@ LUAEXT(match, globish)
result = globish_matcher(r, n)(s);
} catch (informative_failure & e) {
return luaL_error(L, e.what());
- } catch (pcre::compile_error e) {
- return luaL_error(L, (string("error parsing regex: ") + e.what()).c_str());
- } catch (pcre::match_error e) {
- return luaL_error(L, (string("error during match: ") + e.what()).c_str());
+ } catch (pcre::compile_error & e) {
+ return luaL_error(L, e.what());
+ } catch (pcre::match_error & e) {
+ return luaL_error(L, e.what());
} catch (...) {
return luaL_error(L, "Unknown error.");
}
============================================================
--- pcrewrap.cc 4dc70cfb7a55e24b3fd86a0324487f645e25db2c
+++ pcrewrap.cc 5e175ccccd98a56490c4479e634b4547a52eb9e5
@@ -1,4 +1,5 @@
#include "pcrewrap.hh"
+#include
#define pcre pcre_t
#include "pcre.h"
@@ -7,6 +8,11 @@ using std::runtime_error;
using std::string;
using std::runtime_error;
+static void pcre_compile_error(char const * err, int erroff,
+ char const * pattern) NORETURN;
+static void pcre_study_error(char const * err) NORETURN;
+static void pcre_match_error(int errcode, string const & subject) NORETURN;
+
inline unsigned int
flags_to_internal(pcre::flags f)
{
@@ -40,11 +46,11 @@ compile(const char * pattern, pcre::flag
pcre_t const * basedat = pcre_compile(pattern, flags_to_internal(options),
&err, &erroff, 0);
if (!basedat)
- throw pcre::compile_error(err, erroff, pattern);
+ pcre_compile_error(err, erroff, pattern);
pcre_extra const * extradat = pcre_study(basedat, 0, &err);
if (err)
- throw pcre::study_error(err);
+ pcre_study_error(err);
return std::make_pair(static_cast(basedat),
static_cast(extradat));
@@ -57,8 +63,7 @@ get_capturecount(void const * bd)
int err = pcre_fullinfo(static_cast(bd), 0,
PCRE_INFO_CAPTURECOUNT,
static_cast(&cc));
- if (err < 0)
- throw pcre::fullinfo_error(err);
+ I(err == 0);
return cc;
}
@@ -120,11 +125,12 @@ namespace pcre
if (ovec[i] == -1 && ovec[i+1] == -1)
result.push_back(capture(string::const_iterator(0),
string::const_iterator(0)));
- else if (ovec[i] == -1 || ovec[i+1] == -1)
- throw match_error(PCRE_ERROR_INTERNAL); // should never happen
else
- result.push_back(capture(subject.begin() + ovec[i],
- subject.begin() + ovec[i+1]));
+ {
+ I(ovec[i] != -1 && ovec[i+1] != -1);
+ result.push_back(capture(subject.begin() + ovec[i],
+ subject.begin() + ovec[i+1]));
+ }
}
for (unsigned int i = rc; i < capturecount + 1; i++)
result.push_back(capture(string::const_iterator(0),
@@ -141,7 +147,7 @@ namespace pcre
return false;
}
else
- throw match_error(rc);
+ pcre_match_error(rc, subject);
}
// This overload is for when you don't care about captures, only
@@ -164,34 +170,142 @@ namespace pcre
else if (rc == PCRE_ERROR_NOMATCH)
return false;
else
- throw match_error(rc);
+ pcre_match_error(rc, subject);
}
+} // namespace pcre
- // error handling.
+// These functions produce properly translated diagnostics from PCRE
+// internal errors.
+static void
+pcre_compile_error(char const *err, int erroff, char const * pattern)
+{
+ using std::strcmp;
+ // Special case out-of-memory ...
+ if (!strcmp(err, "failed to get memory"))
+ throw std::bad_alloc();
- static string
- compile_error_message(char const * err, int offset, char const * pattern)
- {
- return (F("parse error at char %d in pattern '%s': %s")
- % offset % pattern % err).str();
- }
+ // ... and all errors that represent program bugs.
+ I(strcmp(err, "erroffset passed as NULL"));
+ I(strcmp(err, "unknown option bit(s) set"));
+ I(strcmp(err, "this version of PCRE is not compiled with PCRE_UTF8 support"));
+ I(strcmp(err, "internal error: code overflow"));
+ I(strcmp(err, "internal error: unexpected repeat"));
+ I(strcmp(err, "spare error"));
+ I(strcmp(err, "invalid UTF-8 string"));
+ I(strcmp(err, "no error")); // because we should never get here with that
- compile_error::compile_error(char const * err, int offset,
- char const * pattern)
- : std::runtime_error(compile_error_message(err, offset, pattern))
- {}
+ // PCRE fails to distinguish between errors at no position and errors at
+ // character offset 0 in the pattern, so in practice we give the
+ // position-ful variant for all errors, but I'm leaving the == -1 check
+ // here in case PCRE gets fixed.
+ if (erroff == -1)
+ throw pcre::compile_error(F("Error in regex \"%s\": %s")
+ % pattern % gettext(err));
+ else
+ throw pcre::compile_error(F("Error at character %d of regex \"%s\": %s")
+ % (erroff + 1) % pattern % gettext(err));
+}
- match_error::match_error(int code)
- : std::runtime_error((F("Error during matching, code %d") % code).str())
- {}
+static void
+pcre_study_error(char const * err)
+{
+ // If the error is not out-of-memory, it's a bug.
+ I(!std::strcmp(err, "failed to get memory"));
+ throw std::bad_alloc();
+}
- fullinfo_error::fullinfo_error(int code)
- : std::runtime_error((F("Error getting capture count, code %d") % code)
- .str())
- {}
+static void
+pcre_match_error(int errcode, string const & subject)
+{
+ // This one actually has error codes! Almost all of which indicate bugs
+ // in monotone.
+ switch(errcode)
+ {
+ case PCRE_ERROR_NOMEMORY:
+ throw std::bad_alloc();
-} // namespace pcre
+ case PCRE_ERROR_MATCHLIMIT:
+ throw pcre::match_error(F("backtrack limit exceeded, matching \"%s\"")
+ % subject);
+
+ case PCRE_ERROR_RECURSIONLIMIT:
+ throw pcre::match_error(F("recursion limit exceeded, matching \"%s\"")
+ % subject);
+ default:
+ global_sanity.invariant_failure((FL("pcre_match returned %d") % errcode)
+ .str().c_str(), __FILE__, __LINE__);
+ }
+}
+#ifdef XGETTEXT
+// This is a copy of the error message table from pcre_compile.c, with
+// N_() applied to all the strings that the user will actually see.
+static char const * const error_texts[] = {
+ "no error",
+ N_("\\ at end of pattern"),
+ N_("\\c at end of pattern"),
+ N_("unrecognized character follows \\"),
+ N_("numbers out of order in {} quantifier"),
+ /* 5 */
+ N_("number too big in {} quantifier"),
+ N_("missing terminating ] for character class"),
+ N_("invalid escape sequence in character class"),
+ N_("range out of order in character class"),
+ N_("nothing to repeat"),
+ /* 10 */
+ N_("operand of unlimited repeat could match the empty string"),
+ "internal error: unexpected repeat",
+ N_("unrecognized character after (?"),
+ N_("POSIX named classes are supported only within a class"),
+ N_("missing )"),
+ /* 15 */
+ N_("reference to non-existent subpattern"),
+ "erroffset passed as NULL",
+ "unknown option bit(s) set",
+ N_("missing ) after comment"),
+ N_("parentheses nested too deeply"),
+ /* 20 */
+ N_("regular expression too large"),
+ "failed to get memory", // std::bad_alloc
+ N_("unmatched parentheses"),
+ "internal error: code overflow",
+ N_("unrecognized character after (?<"),
+ /* 25 */
+ N_("lookbehind assertion is not fixed length"),
+ N_("malformed number or name after (?("),
+ N_("conditional group contains more than two branches"),
+ N_("assertion expected after (?("),
+ N_("(?R or (?digits must be followed by )"),
+ /* 30 */
+ N_("unknown POSIX class name"),
+ N_("POSIX collating elements are not supported"),
+ "this version of PCRE is not compiled with PCRE_UTF8 support",
+ "spare error",
+ N_("character value in \\x{...} sequence is too large"),
+ /* 35 */
+ N_("invalid condition (?(0)"),
+ N_("\\C not allowed in lookbehind assertion"),
+ N_("PCRE does not support \\L, \\l, \\N, \\U, or \\u"),
+ N_("number after (?C is > 255"),
+ N_("closing ) for (?C expected"),
+ /* 40 */
+ N_("recursive call could loop indefinitely"),
+ N_("unrecognized character after (?P"),
+ N_("syntax error after (?P"),
+ N_("two named subpatterns have the same name"),
+ "invalid UTF-8 string",
+ /* 45 */
+ N_("support for \\P, \\p, and \\X has not been compiled"),
+ N_("malformed \\P or \\p sequence"),
+ N_("unknown property name after \\P or \\p"),
+ N_("subpattern name is too long (maximum 32 characters)"),
+ N_("too many named subpatterns (maximum 10,000)"),
+ /* 50 */
+ N_("repeated subpattern is too long"),
+ N_("octal value is greater than \\377 (not in UTF-8 mode)"),
+};
+#endif
+
// Local Variables:
// mode: C++
// fill-column: 76
============================================================
--- pcrewrap.hh 701afe7a88a0cbb36c0b38afb6a03050f22f89b4
+++ pcrewrap.hh 5b3070b3642cc669273a7347bf6feb938f465215
@@ -124,26 +124,15 @@ namespace pcre
// exceptions thrown for errors from PCRE APIs
struct compile_error : public std::runtime_error
{
- explicit compile_error(char const * error, int offset,
- char const * pattern);
+ explicit compile_error(i18n_format const & e)
+ : runtime_error(e.str().c_str()) {}
virtual ~compile_error() throw() {}
};
- struct study_error : public std::runtime_error
- {
- explicit study_error(char const * error) : runtime_error(error) {};
- virtual ~study_error() throw() {}
- };
-
- struct fullinfo_error : public std::runtime_error
- {
- explicit fullinfo_error(int code);
- virtual ~fullinfo_error() throw() {}
- };
-
struct match_error : public std::runtime_error
{
- explicit match_error(int code);
+ explicit match_error(i18n_format const & e)
+ : runtime_error(e.str().c_str()) {}
virtual ~match_error() throw() {}
};
============================================================
--- po/POTFILES.in 76d2c8a470bc2f234c0b239155b20dbc29f59fdf
+++ po/POTFILES.in 3642b5fb461f3a18033922e4e72ac081613ea8f3
@@ -57,6 +57,7 @@ packet.hh
options_list.hh
packet.cc
packet.hh
+pcrewrap.cc
platform.hh
quick_alloc.hh
randomfile.hh