diff --git a/classpath/java/util/regex/Pattern.java b/classpath/java/util/regex/Pattern.java index 9c0bd680fd..b9c84eb6f3 100644 --- a/classpath/java/util/regex/Pattern.java +++ b/classpath/java/util/regex/Pattern.java @@ -35,20 +35,38 @@ public class Pattern { private final String pattern; protected Pattern(String pattern, int flags) { - this.pattern = pattern; + this.pattern = trivial(pattern); this.patternFlags = flags; - - if (! trivial(pattern)) { - throw new UnsupportedOperationException - ("only trivial regular expressions are supported so far"); - } } - private static boolean trivial(String pattern) { + private static String trivial(String pattern) { + StringBuffer buffer = new StringBuffer(); for (int i = 0; i < pattern.length(); ++i) { char c = pattern.charAt(i); switch (c) { case '\\': + if (++i == pattern.length()) { + break; + } + c = pattern.charAt(i); + if (c == '0') { + int len = digits(pattern, ++i, 3, 8); + if (len == 3 && pattern.charAt(i) > '3') { + --len; + } + c = (char)Integer.parseInt(pattern.substring(i, i + len), 8); + i += len - 1; + } else if (c == 'x' || c == 'u') { + int len = digits(pattern, ++i, 4, 16); + c = (char)Integer.parseInt(pattern.substring(i, i + len), 16); + i += len - 1; + } else { + c = unescape(pattern.charAt(i)); + } + if (c != -1) { + break; + } + // fallthru case '.': case '*': case '+': @@ -62,10 +80,50 @@ public class Pattern { case ')': case '^': case '$': - return false; + throw new UnsupportedOperationException + ("only trivial regular expressions are supported so far (" + pattern + ")"); + } + buffer.append(c); + } + return buffer.toString(); + } + + private static int digits(String s, int offset, int maxLength, int base) { + for (int i = 0; ; ++i) { + if (i == maxLength || offset + i >= s.length()) { + return i; + } + int value = s.charAt(offset + i) - '0'; + if (value < 0) { + return i; + } + if (base > 10 && value >= 10) { + value += 10 - (value >= 'a' - '0' ? 'a' - '0' : 'A' - '0'); + } + if (value >= base) { + return i; } } - return true; + } + + private static char unescape(char c) { + switch (c) { + case '\\': + return c; + case 'a': + return 0x0007; + case 'e': + return 0x001B; + case 'f': + return 0x000C; + case 'n': + return 0x000A; + case 'r': + return 0x000D; + case 't': + return 0x0009; + } + return (char)-1; } public static Pattern compile(String regex) { diff --git a/test/Strings.java b/test/Strings.java index 7ba502b9d5..30a85163c9 100644 --- a/test/Strings.java +++ b/test/Strings.java @@ -105,6 +105,15 @@ public class Strings { (prematureEOS ? "\u00ae\ufffd" : "\u00ae\uaeaf")); } + public static void testTrivialPattern() throws Exception { + expect("?7".matches("\\0777")); + expect("\007".matches("\\a")); + expect("\\".matches("\\\\")); + expect("J".matches("\\x4A")); + expect("a".matches("\\x61")); + expect("\0078".matches("\\078")); + } + public static void main(String[] args) throws Exception { expect(new String(new byte[] { 99, 111, 109, 46, 101, 99, 111, 118, 97, 116, 101, 46, 110, 97, 116, 46, 98, 117, @@ -193,5 +202,7 @@ public class Strings { 32, 110, 117, 116, 115 }, System.getProperty("line.separator").getBytes()))); } + + testTrivialPattern(); } }