needed for applet search
authoramwaterhouse <Andrew Waterhouse>
Thu, 9 Jun 2005 15:29:47 +0000 (15:29 +0000)
committeramwaterhouse <Andrew Waterhouse>
Thu, 9 Jun 2005 15:29:47 +0000 (15:29 +0000)
83 files changed:
src/com/stevesoft/pat/AmpersandRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Any.java [new file with mode: 0755]
src/com/stevesoft/pat/BackG.java [new file with mode: 0755]
src/com/stevesoft/pat/BackMatch.java [new file with mode: 0755]
src/com/stevesoft/pat/BackRefRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Backup.java [new file with mode: 0755]
src/com/stevesoft/pat/BasicStringBufferLike.java [new file with mode: 0755]
src/com/stevesoft/pat/Bits.java [new file with mode: 0755]
src/com/stevesoft/pat/Boundary.java [new file with mode: 0755]
src/com/stevesoft/pat/Bracket.java [new file with mode: 0755]
src/com/stevesoft/pat/CaseMgr.java [new file with mode: 0755]
src/com/stevesoft/pat/ChangeRule.java [new file with mode: 0755]
src/com/stevesoft/pat/CodeRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Ctrl.java [new file with mode: 0755]
src/com/stevesoft/pat/Custom.java [new file with mode: 0755]
src/com/stevesoft/pat/CustomEndpoint.java [new file with mode: 0755]
src/com/stevesoft/pat/DirFileRegex.java [new file with mode: 0755]
src/com/stevesoft/pat/DotMulti.java [new file with mode: 0755]
src/com/stevesoft/pat/End.java [new file with mode: 0755]
src/com/stevesoft/pat/FastBracket.java [new file with mode: 0755]
src/com/stevesoft/pat/FastMulti.java [new file with mode: 0755]
src/com/stevesoft/pat/FileRegex.java [new file with mode: 0755]
src/com/stevesoft/pat/Group.java [new file with mode: 0755]
src/com/stevesoft/pat/LeftRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Multi.java [new file with mode: 0755]
src/com/stevesoft/pat/MultiMin.java [new file with mode: 0755]
src/com/stevesoft/pat/Multi_stage2.java [new file with mode: 0755]
src/com/stevesoft/pat/NoPattern.java [new file with mode: 0755]
src/com/stevesoft/pat/NonDirFileRegex.java [new file with mode: 0755]
src/com/stevesoft/pat/NotImplementedError.java [new file with mode: 0755]
src/com/stevesoft/pat/NullPattern.java [new file with mode: 0755]
src/com/stevesoft/pat/NullRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Or.java [new file with mode: 0755]
src/com/stevesoft/pat/OrMark.java [new file with mode: 0755]
src/com/stevesoft/pat/PartialBuffer.java [new file with mode: 0755]
src/com/stevesoft/pat/Pattern.java [new file with mode: 0755]
src/com/stevesoft/pat/PatternSub.java [new file with mode: 0755]
src/com/stevesoft/pat/PopRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Prop.java [new file with mode: 0755]
src/com/stevesoft/pat/Pthings.java [new file with mode: 0755]
src/com/stevesoft/pat/PushRule.java [new file with mode: 0755]
src/com/stevesoft/pat/RBuffer.java [new file with mode: 0755]
src/com/stevesoft/pat/Range.java [new file with mode: 0755]
src/com/stevesoft/pat/RegOpt.java [new file with mode: 0755]
src/com/stevesoft/pat/RegRes.java [new file with mode: 0755]
src/com/stevesoft/pat/RegSyntax.java [new file with mode: 0755]
src/com/stevesoft/pat/RegSyntaxError.java [new file with mode: 0755]
src/com/stevesoft/pat/Regex.java [new file with mode: 0755]
src/com/stevesoft/pat/RegexReader.java [new file with mode: 0755]
src/com/stevesoft/pat/RegexTokenizer.java [new file with mode: 0755]
src/com/stevesoft/pat/RegexWriter.java [new file with mode: 0755]
src/com/stevesoft/pat/ReplaceRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Replacer.java [new file with mode: 0755]
src/com/stevesoft/pat/RightRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Rthings.java [new file with mode: 0755]
src/com/stevesoft/pat/RuleHolder.java [new file with mode: 0755]
src/com/stevesoft/pat/Skip.java [new file with mode: 0755]
src/com/stevesoft/pat/Skip2.java [new file with mode: 0755]
src/com/stevesoft/pat/SkipBMH.java [new file with mode: 0755]
src/com/stevesoft/pat/Skipped.java [new file with mode: 0755]
src/com/stevesoft/pat/SpecialRule.java [new file with mode: 0755]
src/com/stevesoft/pat/Start.java [new file with mode: 0755]
src/com/stevesoft/pat/StrPos.java [new file with mode: 0755]
src/com/stevesoft/pat/StringBufferLike.java [new file with mode: 0755]
src/com/stevesoft/pat/StringLike.java [new file with mode: 0755]
src/com/stevesoft/pat/StringRule.java [new file with mode: 0755]
src/com/stevesoft/pat/SubMark.java [new file with mode: 0755]
src/com/stevesoft/pat/TransPat.java [new file with mode: 0755]
src/com/stevesoft/pat/Transformer.java [new file with mode: 0755]
src/com/stevesoft/pat/UniValidator.java [new file with mode: 0755]
src/com/stevesoft/pat/Validator.java [new file with mode: 0755]
src/com/stevesoft/pat/WantMoreTextReplaceRule.java [new file with mode: 0755]
src/com/stevesoft/pat/lookAhead.java [new file with mode: 0755]
src/com/stevesoft/pat/oneChar.java [new file with mode: 0755]
src/com/stevesoft/pat/parsePerl.java [new file with mode: 0755]
src/com/stevesoft/pat/patInf.java [new file with mode: 0755]
src/com/stevesoft/pat/patInt.java [new file with mode: 0755]
src/com/stevesoft/pat/wrap/CharArrayBufferWrap.java [new file with mode: 0755]
src/com/stevesoft/pat/wrap/CharArrayWrap.java [new file with mode: 0755]
src/com/stevesoft/pat/wrap/RandomAccessFileWrap.java [new file with mode: 0755]
src/com/stevesoft/pat/wrap/StringBufferWrap.java [new file with mode: 0755]
src/com/stevesoft/pat/wrap/StringWrap.java [new file with mode: 0755]
src/com/stevesoft/pat/wrap/WriterWrap.java [new file with mode: 0755]

diff --git a/src/com/stevesoft/pat/AmpersandRule.java b/src/com/stevesoft/pat/AmpersandRule.java
new file mode 100755 (executable)
index 0000000..934d9c0
--- /dev/null
@@ -0,0 +1,20 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This implements the $& element of the second argument to\r
+  * Regex.\r
+  * @see com.stevesoft.pat.ReplaceRule\r
+  */\r
+public final class AmpersandRule extends ReplaceRule {\r
+    public AmpersandRule() {}\r
+    public void apply(StringBufferLike sb,RegRes res) {\r
+        sb.append(res.stringMatched());\r
+    }\r
+    public String toString1() { return "$&"; }\r
+}\r
diff --git a/src/com/stevesoft/pat/Any.java b/src/com/stevesoft/pat/Any.java
new file mode 100755 (executable)
index 0000000..234c343
--- /dev/null
@@ -0,0 +1,28 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** This is the '.' character in a Pattern.  It\r
+ matches any character. */\r
+class Any extends Pattern {\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(pos < pt.src.length())\r
+            if(pt.dotDoesntMatchCR) {\r
+                if(pt.src.charAt(pos) != '\n')\r
+                    return nextMatch(pos+1,pt);\r
+            } else return nextMatch(pos+1,pt);\r
+        return -1;\r
+    }\r
+    public String toString() {\r
+        return "."+nextString();\r
+    }\r
+    public patInt minChars() { return new patInt(1); }\r
+    public patInt maxChars() { return new patInt(1); }\r
+    public Pattern clone1(Hashtable h) { return new Any(); }\r
+};\r
diff --git a/src/com/stevesoft/pat/BackG.java b/src/com/stevesoft/pat/BackG.java
new file mode 100755 (executable)
index 0000000..78115f8
--- /dev/null
@@ -0,0 +1,26 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** This class represents the \G pattern element. */\r
+class BackG extends Pattern {\r
+    char c,altc,altc2;\r
+    int mask;\r
+    public BackG() {\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        return pos==pt.lastPos ? nextMatch(pos,pt) : -1;\r
+    }\r
+    public String toString() {\r
+        return "\\G"+nextString();\r
+    }\r
+    public patInt minChars() { return new patInt(1); }\r
+    public patInt maxChars() { return new patInt(1); }\r
+    Pattern clone1(Hashtable h) { return new BackG(); }\r
+}\r
diff --git a/src/com/stevesoft/pat/BackMatch.java b/src/com/stevesoft/pat/BackMatch.java
new file mode 100755 (executable)
index 0000000..168faec
--- /dev/null
@@ -0,0 +1,33 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** Provides the ability to match a backreference from within\r
+  * a Pattern.\r
+  */\r
+class BackMatch extends Pattern {\r
+    int id;\r
+    BackMatch(int id) { this.id = id; }\r
+    public String toString() { return "\\"+(id)+nextString(); }\r
+    public int matchInternal(int pos,Pthings p) {\r
+        int i1 = p.marks[id];\r
+        int i2 = p.marks[id+p.nMarks];\r
+        int imax = i2-i1;\r
+        if(i1<0||imax < 0||pos+imax>p.src.length()) return -1;\r
+        int ns = p.src.length()-pos;\r
+        if(imax < ns) ns = imax;\r
+        for(int i=0;i<ns;i++) {\r
+            if(p.src.charAt(i+i1) != p.src.charAt(pos+i))\r
+                return -1;\r
+        }\r
+        return nextMatch(pos+imax,p);\r
+    }\r
+    Pattern clone1(Hashtable h) { return new BackMatch(id); }\r
+}\r
+\r
diff --git a/src/com/stevesoft/pat/BackRefRule.java b/src/com/stevesoft/pat/BackRefRule.java
new file mode 100755 (executable)
index 0000000..64a5d6e
--- /dev/null
@@ -0,0 +1,23 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This method implements the pattern elements $1, $2, etc in\r
+    a substitution rule. The apply(StringBufferLike sb,RegRes rr) method of this ReplaceRule\r
+    simply appends the contents of rr.stringMatched(n), where n is\r
+    the integer supplied to the constructor. */\r
+public class BackRefRule extends ReplaceRule {\r
+    int n;\r
+    public BackRefRule(int n) { this.n = n; }\r
+    public void apply(StringBufferLike sb,RegRes res) {\r
+        String x = res.stringMatched(n);\r
+        sb.append(x == null ? "" : x);\r
+    }\r
+    public String toString1() { return "$"+n; }\r
+    public Object clone1() { return new BackRefRule(n); }\r
+}\r
diff --git a/src/com/stevesoft/pat/Backup.java b/src/com/stevesoft/pat/Backup.java
new file mode 100755 (executable)
index 0000000..df480ea
--- /dev/null
@@ -0,0 +1,27 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** Implements the (?&lt;number) Pattern, where number is\r
+ an integer telling us how far to back up in the Pattern.\r
+ Not in perl 5. It also allows (?&gt;number). */\r
+class Backup extends Pattern {\r
+    int bk;\r
+    Backup(int ii) { bk = ii; }\r
+    public String toString() {\r
+        return "(?" + (bk < 0 ? ">" + (-bk) : "<" + bk) + ")" + nextString();\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(pos < bk) return -1;\r
+        return nextMatch(pos-bk,pt);\r
+    }\r
+    public patInt minChars() { return new patInt(-bk); }\r
+    public patInt maxChars() { return new patInt(-bk); }\r
+    public Pattern clone1(Hashtable h) { return new Backup(bk); }\r
+};\r
diff --git a/src/com/stevesoft/pat/BasicStringBufferLike.java b/src/com/stevesoft/pat/BasicStringBufferLike.java
new file mode 100755 (executable)
index 0000000..6e7b26c
--- /dev/null
@@ -0,0 +1,18 @@
+package//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+com.stevesoft.pat;\r
+\r
+/** An abstraction of the StringBuffer which only\r
+    implements a subset of StringBuffer's methods.\r
+    */\r
+public interface BasicStringBufferLike {\r
+  public void append(char c);\r
+  public void append(String s);\r
+  public StringLike toStringLike();\r
+  public Object unwrap();\r
+}\r
diff --git a/src/com/stevesoft/pat/Bits.java b/src/com/stevesoft/pat/Bits.java
new file mode 100755 (executable)
index 0000000..244889f
--- /dev/null
@@ -0,0 +1,3072 @@
+package//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+com.stevesoft.pat;\r
+\r
+import java.io.*;\r
+\r
+public class Bits {\r
+  char[] carray;\r
+  Bits(char[] carray) {\r
+    this.carray = carray;\r
+  }\r
+  public boolean get(int i) {\r
+    return ((carray[i>>4]) & (1<<(i&15))) != 0;\r
+  }\r
+  public void set(int i,boolean b) {\r
+    if(b) {\r
+      carray[i>>4] |= (char) 1<<(i&15);\r
+    } else {\r
+      carray[i>>4] &= (char)~(1<<(i&15));\r
+    }\r
+  }\r
+\r
+  /*\r
+  public static String n4(char c) {\r
+    String s = Integer.toHexString(c);\r
+    while(s.length()<4)\r
+      s = "0"+s;\r
+    return s;\r
+  }\r
+  static abstract class Tester {\r
+    abstract boolean test(char c);\r
+  }\r
+  public static void main(String[] args) throws Exception {\r
+    //pw_s.println("  static {");\r
+    FileWriter fw = new FileWriter("x.out");\r
+    fw.close();\r
+    test("upper",new Tester() {\r
+      boolean test(char c) {\r
+        return Character.isUpperCase(c);\r
+      }\r
+    });\r
+    test("lower",new Tester() {\r
+      boolean test(char c) {\r
+        return Character.isLowerCase(c);\r
+      }\r
+    });\r
+    test("title",new Tester() {\r
+      boolean test(char c) {\r
+        return Character.isLowerCase(c);\r
+      }\r
+    });\r
+    test("currency",new Tester() {\r
+      boolean test(char c) {\r
+        return Character.getType(c)==Character.CURRENCY_SYMBOL;\r
+      }\r
+    });\r
+    test("decimal_digit",new Tester() {\r
+      boolean test(char c) {\r
+        return Character.getType(c)==Character.DECIMAL_DIGIT_NUMBER;\r
+      }\r
+    });\r
+    test("math",new Tester() {\r
+      boolean test(char c) {\r
+        return Character.getType(c)==Character.MATH_SYMBOL;\r
+      }\r
+    });\r
+    test("letter",new Tester() {\r
+      boolean test(char c) {\r
+        return Character.isLetter(c);\r
+      }\r
+    });\r
+    test("white",new Tester() {\r
+      boolean test(char c) {\r
+        return Character.isWhitespace(c);\r
+      }\r
+    });\r
+    test("punct",new Tester() {\r
+      boolean test(char c) {\r
+       boolean r = false;\r
+        switch(Character.getType(c)) {\r
+        case Character.DASH_PUNCTUATION:\r
+        case Character.START_PUNCTUATION:\r
+        case Character.END_PUNCTUATION:\r
+        case Character.CONNECTOR_PUNCTUATION:\r
+        case Character.OTHER_PUNCTUATION:\r
+         r = true;\r
+         break;\r
+       default:\r
+         r = false;\r
+         break;\r
+       }\r
+       return r;\r
+      }\r
+    });\r
+    //pw_s.println("  }");\r
+    fw = new FileWriter("x.out",true);\r
+    fw.write(sw.toString());\r
+    fw.close();\r
+  }\r
+  static StringWriter sw = new StringWriter();\r
+  static PrintWriter pw_s = new PrintWriter(sw,true);\r
+  public static void test(String var,Tester t) throws Exception {\r
+\r
+    char[] ca = new char[(66536 >> 4)+1];\r
+    Bits b = new Bits(ca);\r
+    FileWriter fw = new FileWriter("x.out",true);\r
+    PrintWriter pw = new PrintWriter(fw);\r
+\r
+    //pw_s.println("    "+var+"_f();");\r
+    pw.println("  public static Bits "+var+";");\r
+    pw.println("  static void "+var+"_f() {");\r
+    pw.println("    char[] data = new char["+ca.length+"];");\r
+    pw.println("    "+var+" = new Bits(data);");\r
+    for(int i=0;i<66536;i++) {\r
+      char c = (char)i;\r
+      //b.set(i,Character.getType(c)==Character.CURRENCY_SYMBOL);\r
+      b.set(i,t.test(c));\r
+    }\r
+    for(int i=0;i<ca.length;i++) {\r
+      if(ca[i] != 0) {\r
+        pw.println("    data["+i+"]=(char)0x"+n4(ca[i])+";");\r
+      }\r
+    }\r
+    pw.println();\r
+    pw.println("  }");\r
+\r
+    pw.close();\r
+  }\r
+  */\r
+  public static Bits upper;\r
+  static void upper_f() {\r
+    char[] data = new char[4159];\r
+    upper = new Bits(data);\r
+    data[4]=(char)0xfffe;\r
+    data[5]=(char)0x07ff;\r
+    data[12]=(char)0xffff;\r
+    data[13]=(char)0x7f7f;\r
+    data[16]=(char)0x5555;\r
+    data[17]=(char)0x5555;\r
+    data[18]=(char)0x5555;\r
+    data[19]=(char)0xaa55;\r
+    data[20]=(char)0x54aa;\r
+    data[21]=(char)0x5555;\r
+    data[22]=(char)0x5555;\r
+    data[23]=(char)0x2b55;\r
+    data[24]=(char)0xced6;\r
+    data[25]=(char)0xb1db;\r
+    data[26]=(char)0xd2d5;\r
+    data[27]=(char)0x11ae;\r
+    data[28]=(char)0xa490;\r
+    data[29]=(char)0x4aaa;\r
+    data[30]=(char)0x5555;\r
+    data[31]=(char)0x5412;\r
+    data[32]=(char)0x5555;\r
+    data[33]=(char)0x0055;\r
+    data[56]=(char)0xd740;\r
+    data[57]=(char)0xfffe;\r
+    data[58]=(char)0x0ffb;\r
+    data[61]=(char)0x541c;\r
+    data[62]=(char)0x5555;\r
+    data[64]=(char)0xdffe;\r
+    data[65]=(char)0xffff;\r
+    data[66]=(char)0xffff;\r
+    data[70]=(char)0x5555;\r
+    data[71]=(char)0x5555;\r
+    data[72]=(char)0x0001;\r
+    data[73]=(char)0x5555;\r
+    data[74]=(char)0x5555;\r
+    data[75]=(char)0x5555;\r
+    data[76]=(char)0x088a;\r
+    data[77]=(char)0x5555;\r
+    data[78]=(char)0x4555;\r
+    data[79]=(char)0x0115;\r
+    data[83]=(char)0xfffe;\r
+    data[84]=(char)0xffff;\r
+    data[85]=(char)0x007f;\r
+    data[266]=(char)0xffff;\r
+    data[267]=(char)0xffff;\r
+    data[268]=(char)0x003f;\r
+    data[480]=(char)0x5555;\r
+    data[481]=(char)0x5555;\r
+    data[482]=(char)0x5555;\r
+    data[483]=(char)0x5555;\r
+    data[484]=(char)0x5555;\r
+    data[485]=(char)0x5555;\r
+    data[486]=(char)0x5555;\r
+    data[487]=(char)0x5555;\r
+    data[488]=(char)0x5555;\r
+    data[489]=(char)0x0015;\r
+    data[490]=(char)0x5555;\r
+    data[491]=(char)0x5555;\r
+    data[492]=(char)0x5555;\r
+    data[493]=(char)0x5555;\r
+    data[494]=(char)0x5555;\r
+    data[495]=(char)0x0155;\r
+    data[496]=(char)0xff00;\r
+    data[497]=(char)0x3f00;\r
+    data[498]=(char)0xff00;\r
+    data[499]=(char)0xff00;\r
+    data[500]=(char)0x3f00;\r
+    data[501]=(char)0xaa00;\r
+    data[502]=(char)0xff00;\r
+    data[504]=(char)0xff00;\r
+    data[505]=(char)0xff00;\r
+    data[506]=(char)0xff00;\r
+    data[507]=(char)0x5f00;\r
+    data[508]=(char)0x1f00;\r
+    data[509]=(char)0x0f00;\r
+    data[510]=(char)0x1f00;\r
+    data[511]=(char)0x1f00;\r
+    data[528]=(char)0x3884;\r
+    data[529]=(char)0x3f27;\r
+    data[530]=(char)0x3d50;\r
+    data[531]=(char)0x000b;\r
+    data[4082]=(char)0xfffe;\r
+    data[4083]=(char)0x07ff;\r
+    data[4100]=(char)0xfffe;\r
+    data[4101]=(char)0x07ff;\r
+    data[4108]=(char)0xffff;\r
+    data[4109]=(char)0x7f7f;\r
+    data[4112]=(char)0x5555;\r
+    data[4113]=(char)0x5555;\r
+    data[4114]=(char)0x5555;\r
+    data[4115]=(char)0xaa55;\r
+    data[4116]=(char)0x54aa;\r
+    data[4117]=(char)0x5555;\r
+    data[4118]=(char)0x5555;\r
+    data[4119]=(char)0x2b55;\r
+    data[4120]=(char)0xced6;\r
+    data[4121]=(char)0xb1db;\r
+    data[4122]=(char)0xd2d5;\r
+    data[4123]=(char)0x11ae;\r
+    data[4124]=(char)0xa490;\r
+    data[4125]=(char)0x4aaa;\r
+    data[4126]=(char)0x5555;\r
+    data[4127]=(char)0x5412;\r
+    data[4128]=(char)0x5555;\r
+    data[4129]=(char)0x0055;\r
+    data[4152]=(char)0xd740;\r
+    data[4153]=(char)0xfffe;\r
+    data[4154]=(char)0x0ffb;\r
+    data[4157]=(char)0x541c;\r
+    data[4158]=(char)0x0055;\r
+\r
+  }\r
+  public static Bits lower;\r
+  static void lower_f() {\r
+    char[] data = new char[4159];\r
+    lower = new Bits(data);\r
+    data[6]=(char)0xfffe;\r
+    data[7]=(char)0x07ff;\r
+    data[10]=(char)0x0400;\r
+    data[11]=(char)0x0420;\r
+    data[13]=(char)0x8000;\r
+    data[14]=(char)0xffff;\r
+    data[15]=(char)0xff7f;\r
+    data[16]=(char)0xaaaa;\r
+    data[17]=(char)0xaaaa;\r
+    data[18]=(char)0xaaaa;\r
+    data[19]=(char)0x55aa;\r
+    data[20]=(char)0xab55;\r
+    data[21]=(char)0xaaaa;\r
+    data[22]=(char)0xaaaa;\r
+    data[23]=(char)0xd4aa;\r
+    data[24]=(char)0x3129;\r
+    data[25]=(char)0x4e24;\r
+    data[26]=(char)0x292a;\r
+    data[27]=(char)0x2651;\r
+    data[28]=(char)0x5240;\r
+    data[29]=(char)0xb555;\r
+    data[30]=(char)0xaaaa;\r
+    data[31]=(char)0xa829;\r
+    data[32]=(char)0xaaaa;\r
+    data[33]=(char)0x00aa;\r
+    data[37]=(char)0xffff;\r
+    data[38]=(char)0xffff;\r
+    data[39]=(char)0xffff;\r
+    data[40]=(char)0xffff;\r
+    data[41]=(char)0xffff;\r
+    data[42]=(char)0x01ff;\r
+    data[57]=(char)0x0001;\r
+    data[58]=(char)0xf000;\r
+    data[59]=(char)0xffff;\r
+    data[60]=(char)0x7fff;\r
+    data[61]=(char)0x0063;\r
+    data[62]=(char)0xaaa8;\r
+    data[63]=(char)0x0007;\r
+    data[67]=(char)0xffff;\r
+    data[68]=(char)0xffff;\r
+    data[69]=(char)0xdffe;\r
+    data[70]=(char)0xaaaa;\r
+    data[71]=(char)0xaaaa;\r
+    data[72]=(char)0x0002;\r
+    data[73]=(char)0xaaaa;\r
+    data[74]=(char)0xaaaa;\r
+    data[75]=(char)0xaaaa;\r
+    data[76]=(char)0x1114;\r
+    data[77]=(char)0xaaaa;\r
+    data[78]=(char)0x8aaa;\r
+    data[79]=(char)0x022a;\r
+    data[86]=(char)0xfffe;\r
+    data[87]=(char)0xffff;\r
+    data[88]=(char)0x00ff;\r
+    data[269]=(char)0xffff;\r
+    data[270]=(char)0xffff;\r
+    data[271]=(char)0x007f;\r
+    data[480]=(char)0xaaaa;\r
+    data[481]=(char)0xaaaa;\r
+    data[482]=(char)0xaaaa;\r
+    data[483]=(char)0xaaaa;\r
+    data[484]=(char)0xaaaa;\r
+    data[485]=(char)0xaaaa;\r
+    data[486]=(char)0xaaaa;\r
+    data[487]=(char)0xaaaa;\r
+    data[488]=(char)0xaaaa;\r
+    data[489]=(char)0x0fea;\r
+    data[490]=(char)0xaaaa;\r
+    data[491]=(char)0xaaaa;\r
+    data[492]=(char)0xaaaa;\r
+    data[493]=(char)0xaaaa;\r
+    data[494]=(char)0xaaaa;\r
+    data[495]=(char)0x02aa;\r
+    data[496]=(char)0x00ff;\r
+    data[497]=(char)0x003f;\r
+    data[498]=(char)0x00ff;\r
+    data[499]=(char)0x00ff;\r
+    data[500]=(char)0x003f;\r
+    data[501]=(char)0x00ff;\r
+    data[502]=(char)0x00ff;\r
+    data[503]=(char)0x3fff;\r
+    data[504]=(char)0x00ff;\r
+    data[505]=(char)0x00ff;\r
+    data[506]=(char)0x00ff;\r
+    data[507]=(char)0x00df;\r
+    data[508]=(char)0x00dc;\r
+    data[509]=(char)0x00cf;\r
+    data[510]=(char)0x00ff;\r
+    data[511]=(char)0x00dc;\r
+    data[519]=(char)0x8000;\r
+    data[528]=(char)0xc400;\r
+    data[529]=(char)0x0008;\r
+    data[530]=(char)0xc000;\r
+    data[531]=(char)0x0010;\r
+    data[4016]=(char)0x007f;\r
+    data[4017]=(char)0x00f8;\r
+    data[4084]=(char)0xfffe;\r
+    data[4085]=(char)0x07ff;\r
+    data[4102]=(char)0xfffe;\r
+    data[4103]=(char)0x07ff;\r
+    data[4106]=(char)0x0400;\r
+    data[4107]=(char)0x0420;\r
+    data[4109]=(char)0x8000;\r
+    data[4110]=(char)0xffff;\r
+    data[4111]=(char)0xff7f;\r
+    data[4112]=(char)0xaaaa;\r
+    data[4113]=(char)0xaaaa;\r
+    data[4114]=(char)0xaaaa;\r
+    data[4115]=(char)0x55aa;\r
+    data[4116]=(char)0xab55;\r
+    data[4117]=(char)0xaaaa;\r
+    data[4118]=(char)0xaaaa;\r
+    data[4119]=(char)0xd4aa;\r
+    data[4120]=(char)0x3129;\r
+    data[4121]=(char)0x4e24;\r
+    data[4122]=(char)0x292a;\r
+    data[4123]=(char)0x2651;\r
+    data[4124]=(char)0x5240;\r
+    data[4125]=(char)0xb555;\r
+    data[4126]=(char)0xaaaa;\r
+    data[4127]=(char)0xa829;\r
+    data[4128]=(char)0xaaaa;\r
+    data[4129]=(char)0x00aa;\r
+    data[4133]=(char)0xffff;\r
+    data[4134]=(char)0xffff;\r
+    data[4135]=(char)0xffff;\r
+    data[4136]=(char)0xffff;\r
+    data[4137]=(char)0xffff;\r
+    data[4138]=(char)0x01ff;\r
+    data[4153]=(char)0x0001;\r
+    data[4154]=(char)0xf000;\r
+    data[4155]=(char)0xffff;\r
+    data[4156]=(char)0x7fff;\r
+    data[4157]=(char)0x0063;\r
+    data[4158]=(char)0x00a8;\r
+\r
+  }\r
+  public static Bits title;\r
+  static void title_f() {\r
+    char[] data = new char[4159];\r
+    title = new Bits(data);\r
+    data[6]=(char)0xfffe;\r
+    data[7]=(char)0x07ff;\r
+    data[10]=(char)0x0400;\r
+    data[11]=(char)0x0420;\r
+    data[13]=(char)0x8000;\r
+    data[14]=(char)0xffff;\r
+    data[15]=(char)0xff7f;\r
+    data[16]=(char)0xaaaa;\r
+    data[17]=(char)0xaaaa;\r
+    data[18]=(char)0xaaaa;\r
+    data[19]=(char)0x55aa;\r
+    data[20]=(char)0xab55;\r
+    data[21]=(char)0xaaaa;\r
+    data[22]=(char)0xaaaa;\r
+    data[23]=(char)0xd4aa;\r
+    data[24]=(char)0x3129;\r
+    data[25]=(char)0x4e24;\r
+    data[26]=(char)0x292a;\r
+    data[27]=(char)0x2651;\r
+    data[28]=(char)0x5240;\r
+    data[29]=(char)0xb555;\r
+    data[30]=(char)0xaaaa;\r
+    data[31]=(char)0xa829;\r
+    data[32]=(char)0xaaaa;\r
+    data[33]=(char)0x00aa;\r
+    data[37]=(char)0xffff;\r
+    data[38]=(char)0xffff;\r
+    data[39]=(char)0xffff;\r
+    data[40]=(char)0xffff;\r
+    data[41]=(char)0xffff;\r
+    data[42]=(char)0x01ff;\r
+    data[57]=(char)0x0001;\r
+    data[58]=(char)0xf000;\r
+    data[59]=(char)0xffff;\r
+    data[60]=(char)0x7fff;\r
+    data[61]=(char)0x0063;\r
+    data[62]=(char)0xaaa8;\r
+    data[63]=(char)0x0007;\r
+    data[67]=(char)0xffff;\r
+    data[68]=(char)0xffff;\r
+    data[69]=(char)0xdffe;\r
+    data[70]=(char)0xaaaa;\r
+    data[71]=(char)0xaaaa;\r
+    data[72]=(char)0x0002;\r
+    data[73]=(char)0xaaaa;\r
+    data[74]=(char)0xaaaa;\r
+    data[75]=(char)0xaaaa;\r
+    data[76]=(char)0x1114;\r
+    data[77]=(char)0xaaaa;\r
+    data[78]=(char)0x8aaa;\r
+    data[79]=(char)0x022a;\r
+    data[86]=(char)0xfffe;\r
+    data[87]=(char)0xffff;\r
+    data[88]=(char)0x00ff;\r
+    data[269]=(char)0xffff;\r
+    data[270]=(char)0xffff;\r
+    data[271]=(char)0x007f;\r
+    data[480]=(char)0xaaaa;\r
+    data[481]=(char)0xaaaa;\r
+    data[482]=(char)0xaaaa;\r
+    data[483]=(char)0xaaaa;\r
+    data[484]=(char)0xaaaa;\r
+    data[485]=(char)0xaaaa;\r
+    data[486]=(char)0xaaaa;\r
+    data[487]=(char)0xaaaa;\r
+    data[488]=(char)0xaaaa;\r
+    data[489]=(char)0x0fea;\r
+    data[490]=(char)0xaaaa;\r
+    data[491]=(char)0xaaaa;\r
+    data[492]=(char)0xaaaa;\r
+    data[493]=(char)0xaaaa;\r
+    data[494]=(char)0xaaaa;\r
+    data[495]=(char)0x02aa;\r
+    data[496]=(char)0x00ff;\r
+    data[497]=(char)0x003f;\r
+    data[498]=(char)0x00ff;\r
+    data[499]=(char)0x00ff;\r
+    data[500]=(char)0x003f;\r
+    data[501]=(char)0x00ff;\r
+    data[502]=(char)0x00ff;\r
+    data[503]=(char)0x3fff;\r
+    data[504]=(char)0x00ff;\r
+    data[505]=(char)0x00ff;\r
+    data[506]=(char)0x00ff;\r
+    data[507]=(char)0x00df;\r
+    data[508]=(char)0x00dc;\r
+    data[509]=(char)0x00cf;\r
+    data[510]=(char)0x00ff;\r
+    data[511]=(char)0x00dc;\r
+    data[519]=(char)0x8000;\r
+    data[528]=(char)0xc400;\r
+    data[529]=(char)0x0008;\r
+    data[530]=(char)0xc000;\r
+    data[531]=(char)0x0010;\r
+    data[4016]=(char)0x007f;\r
+    data[4017]=(char)0x00f8;\r
+    data[4084]=(char)0xfffe;\r
+    data[4085]=(char)0x07ff;\r
+    data[4102]=(char)0xfffe;\r
+    data[4103]=(char)0x07ff;\r
+    data[4106]=(char)0x0400;\r
+    data[4107]=(char)0x0420;\r
+    data[4109]=(char)0x8000;\r
+    data[4110]=(char)0xffff;\r
+    data[4111]=(char)0xff7f;\r
+    data[4112]=(char)0xaaaa;\r
+    data[4113]=(char)0xaaaa;\r
+    data[4114]=(char)0xaaaa;\r
+    data[4115]=(char)0x55aa;\r
+    data[4116]=(char)0xab55;\r
+    data[4117]=(char)0xaaaa;\r
+    data[4118]=(char)0xaaaa;\r
+    data[4119]=(char)0xd4aa;\r
+    data[4120]=(char)0x3129;\r
+    data[4121]=(char)0x4e24;\r
+    data[4122]=(char)0x292a;\r
+    data[4123]=(char)0x2651;\r
+    data[4124]=(char)0x5240;\r
+    data[4125]=(char)0xb555;\r
+    data[4126]=(char)0xaaaa;\r
+    data[4127]=(char)0xa829;\r
+    data[4128]=(char)0xaaaa;\r
+    data[4129]=(char)0x00aa;\r
+    data[4133]=(char)0xffff;\r
+    data[4134]=(char)0xffff;\r
+    data[4135]=(char)0xffff;\r
+    data[4136]=(char)0xffff;\r
+    data[4137]=(char)0xffff;\r
+    data[4138]=(char)0x01ff;\r
+    data[4153]=(char)0x0001;\r
+    data[4154]=(char)0xf000;\r
+    data[4155]=(char)0xffff;\r
+    data[4156]=(char)0x7fff;\r
+    data[4157]=(char)0x0063;\r
+    data[4158]=(char)0x00a8;\r
+\r
+  }\r
+  public static Bits currency;\r
+  static void currency_f() {\r
+    char[] data = new char[4159];\r
+    currency = new Bits(data);\r
+    data[2]=(char)0x0010;\r
+    data[10]=(char)0x003c;\r
+    data[159]=(char)0x000c;\r
+    data[227]=(char)0x8000;\r
+    data[522]=(char)0x1fff;\r
+    data[4070]=(char)0x0200;\r
+    data[4080]=(char)0x0010;\r
+    data[4094]=(char)0x0063;\r
+    data[4098]=(char)0x0010;\r
+    data[4106]=(char)0x003c;\r
+\r
+  }\r
+  public static Bits decimal_digit;\r
+  static void decimal_digit_f() {\r
+    char[] data = new char[4159];\r
+    decimal_digit = new Bits(data);\r
+    data[3]=(char)0x03ff;\r
+    data[102]=(char)0x03ff;\r
+    data[111]=(char)0x03ff;\r
+    data[150]=(char)0xffc0;\r
+    data[158]=(char)0xffc0;\r
+    data[166]=(char)0xffc0;\r
+    data[174]=(char)0xffc0;\r
+    data[182]=(char)0xffc0;\r
+    data[190]=(char)0xff80;\r
+    data[198]=(char)0xffc0;\r
+    data[206]=(char)0xffc0;\r
+    data[214]=(char)0xffc0;\r
+    data[229]=(char)0x03ff;\r
+    data[237]=(char)0x03ff;\r
+    data[242]=(char)0x03ff;\r
+    data[4081]=(char)0x03ff;\r
+    data[4099]=(char)0x03ff;\r
+\r
+  }\r
+  public static Bits math;\r
+  static void math_f() {\r
+    char[] data = new char[4159];\r
+    math = new Bits(data);\r
+    data[2]=(char)0x0800;\r
+    data[3]=(char)0x7000;\r
+    data[7]=(char)0x5000;\r
+    data[10]=(char)0x1000;\r
+    data[11]=(char)0x0002;\r
+    data[13]=(char)0x0080;\r
+    data[15]=(char)0x0080;\r
+    data[516]=(char)0x0010;\r
+    data[519]=(char)0x1c00;\r
+    data[520]=(char)0x1c00;\r
+    data[537]=(char)0x001f;\r
+    data[541]=(char)0x0014;\r
+    data[544]=(char)0xffff;\r
+    data[545]=(char)0xffff;\r
+    data[546]=(char)0xffff;\r
+    data[547]=(char)0xffff;\r
+    data[548]=(char)0xffff;\r
+    data[549]=(char)0xffff;\r
+    data[550]=(char)0xffff;\r
+    data[551]=(char)0xffff;\r
+    data[552]=(char)0xffff;\r
+    data[553]=(char)0xffff;\r
+    data[554]=(char)0xffff;\r
+    data[555]=(char)0xffff;\r
+    data[556]=(char)0xffff;\r
+    data[557]=(char)0xffff;\r
+    data[558]=(char)0xffff;\r
+    data[559]=(char)0x0003;\r
+    data[560]=(char)0x0f00;\r
+    data[562]=(char)0x0003;\r
+    data[4018]=(char)0x0200;\r
+    data[4070]=(char)0x0074;\r
+    data[4080]=(char)0x0800;\r
+    data[4081]=(char)0x7000;\r
+    data[4085]=(char)0x5000;\r
+    data[4094]=(char)0x1f04;\r
+    data[4098]=(char)0x0800;\r
+    data[4099]=(char)0x7000;\r
+    data[4103]=(char)0x5000;\r
+    data[4106]=(char)0x1000;\r
+    data[4107]=(char)0x0002;\r
+    data[4109]=(char)0x0080;\r
+    data[4111]=(char)0x0080;\r
+\r
+  }\r
+  public static Bits letter;\r
+  static void letter_f() {\r
+    char[] data = new char[4159];\r
+    letter = new Bits(data);\r
+    data[4]=(char)0xfffe;\r
+    data[5]=(char)0x07ff;\r
+    data[6]=(char)0xfffe;\r
+    data[7]=(char)0x07ff;\r
+    data[10]=(char)0x0400;\r
+    data[11]=(char)0x0420;\r
+    data[12]=(char)0xffff;\r
+    data[13]=(char)0xff7f;\r
+    data[14]=(char)0xffff;\r
+    data[15]=(char)0xff7f;\r
+    data[16]=(char)0xffff;\r
+    data[17]=(char)0xffff;\r
+    data[18]=(char)0xffff;\r
+    data[19]=(char)0xffff;\r
+    data[20]=(char)0xffff;\r
+    data[21]=(char)0xffff;\r
+    data[22]=(char)0xffff;\r
+    data[23]=(char)0xffff;\r
+    data[24]=(char)0xffff;\r
+    data[25]=(char)0xffff;\r
+    data[26]=(char)0xffff;\r
+    data[27]=(char)0xffff;\r
+    data[28]=(char)0xffff;\r
+    data[29]=(char)0xffff;\r
+    data[30]=(char)0xffff;\r
+    data[31]=(char)0xfc3f;\r
+    data[32]=(char)0xffff;\r
+    data[33]=(char)0x00ff;\r
+    data[37]=(char)0xffff;\r
+    data[38]=(char)0xffff;\r
+    data[39]=(char)0xffff;\r
+    data[40]=(char)0xffff;\r
+    data[41]=(char)0xffff;\r
+    data[42]=(char)0x01ff;\r
+    data[43]=(char)0xf9ff;\r
+    data[44]=(char)0x0003;\r
+    data[45]=(char)0x0003;\r
+    data[46]=(char)0x001f;\r
+    data[55]=(char)0x0400;\r
+    data[56]=(char)0xd740;\r
+    data[57]=(char)0xffff;\r
+    data[58]=(char)0xfffb;\r
+    data[59]=(char)0xffff;\r
+    data[60]=(char)0x7fff;\r
+    data[61]=(char)0x547f;\r
+    data[62]=(char)0xfffd;\r
+    data[63]=(char)0x000f;\r
+    data[64]=(char)0xdffe;\r
+    data[65]=(char)0xffff;\r
+    data[66]=(char)0xffff;\r
+    data[67]=(char)0xffff;\r
+    data[68]=(char)0xffff;\r
+    data[69]=(char)0xdffe;\r
+    data[70]=(char)0xffff;\r
+    data[71]=(char)0xffff;\r
+    data[72]=(char)0x0003;\r
+    data[73]=(char)0xffff;\r
+    data[74]=(char)0xffff;\r
+    data[75]=(char)0xffff;\r
+    data[76]=(char)0x199f;\r
+    data[77]=(char)0xffff;\r
+    data[78]=(char)0xcfff;\r
+    data[79]=(char)0x033f;\r
+    data[83]=(char)0xfffe;\r
+    data[84]=(char)0xffff;\r
+    data[85]=(char)0x027f;\r
+    data[86]=(char)0xfffe;\r
+    data[87]=(char)0xffff;\r
+    data[88]=(char)0x00ff;\r
+    data[93]=(char)0xffff;\r
+    data[94]=(char)0x07ff;\r
+    data[95]=(char)0x0007;\r
+    data[98]=(char)0xfffe;\r
+    data[99]=(char)0x07ff;\r
+    data[100]=(char)0x07ff;\r
+    data[103]=(char)0xfffe;\r
+    data[104]=(char)0xffff;\r
+    data[105]=(char)0xffff;\r
+    data[106]=(char)0xffff;\r
+    data[107]=(char)0x7cff;\r
+    data[108]=(char)0x7fff;\r
+    data[109]=(char)0x002f;\r
+    data[110]=(char)0x0060;\r
+    data[144]=(char)0xffe0;\r
+    data[145]=(char)0xffff;\r
+    data[146]=(char)0xffff;\r
+    data[147]=(char)0x23ff;\r
+    data[149]=(char)0xff00;\r
+    data[150]=(char)0x0003;\r
+    data[152]=(char)0x9fe0;\r
+    data[153]=(char)0xfff9;\r
+    data[154]=(char)0xfdff;\r
+    data[155]=(char)0x03c5;\r
+    data[157]=(char)0xb000;\r
+    data[158]=(char)0x0003;\r
+    data[159]=(char)0x0003;\r
+    data[160]=(char)0x87e0;\r
+    data[161]=(char)0xfff9;\r
+    data[162]=(char)0xfdff;\r
+    data[163]=(char)0x036d;\r
+    data[165]=(char)0x5e00;\r
+    data[167]=(char)0x001c;\r
+    data[168]=(char)0xafe0;\r
+    data[169]=(char)0xfffb;\r
+    data[170]=(char)0xfdff;\r
+    data[171]=(char)0x23ed;\r
+    data[174]=(char)0x0001;\r
+    data[176]=(char)0x9fe0;\r
+    data[177]=(char)0xfff9;\r
+    data[178]=(char)0xfdff;\r
+    data[179]=(char)0x23cd;\r
+    data[181]=(char)0xb000;\r
+    data[182]=(char)0x0003;\r
+    data[184]=(char)0xc7e0;\r
+    data[185]=(char)0xd63d;\r
+    data[186]=(char)0xc718;\r
+    data[187]=(char)0x03bf;\r
+    data[192]=(char)0xdfe0;\r
+    data[193]=(char)0xfffd;\r
+    data[194]=(char)0xfdff;\r
+    data[195]=(char)0x03ef;\r
+    data[198]=(char)0x0003;\r
+    data[200]=(char)0xdfe0;\r
+    data[201]=(char)0xfffd;\r
+    data[202]=(char)0xfdff;\r
+    data[203]=(char)0x03ef;\r
+    data[205]=(char)0x4000;\r
+    data[206]=(char)0x0003;\r
+    data[208]=(char)0xdfe0;\r
+    data[209]=(char)0xfffd;\r
+    data[210]=(char)0xfdff;\r
+    data[211]=(char)0x03ff;\r
+    data[214]=(char)0x0003;\r
+    data[224]=(char)0xfffe;\r
+    data[225]=(char)0xffff;\r
+    data[226]=(char)0x7fff;\r
+    data[227]=(char)0x000d;\r
+    data[228]=(char)0x007f;\r
+    data[232]=(char)0x2596;\r
+    data[233]=(char)0xfef0;\r
+    data[234]=(char)0x6cae;\r
+    data[235]=(char)0x200d;\r
+    data[236]=(char)0x005f;\r
+    data[237]=(char)0x3000;\r
+    data[244]=(char)0xfeff;\r
+    data[245]=(char)0xffff;\r
+    data[246]=(char)0x03ff;\r
+    data[266]=(char)0xffff;\r
+    data[267]=(char)0xffff;\r
+    data[268]=(char)0x003f;\r
+    data[269]=(char)0xffff;\r
+    data[270]=(char)0xffff;\r
+    data[271]=(char)0x007f;\r
+    data[272]=(char)0xffff;\r
+    data[273]=(char)0xffff;\r
+    data[274]=(char)0xffff;\r
+    data[275]=(char)0xffff;\r
+    data[276]=(char)0xffff;\r
+    data[277]=(char)0x83ff;\r
+    data[278]=(char)0xffff;\r
+    data[279]=(char)0xffff;\r
+    data[280]=(char)0xffff;\r
+    data[281]=(char)0xffff;\r
+    data[282]=(char)0xff07;\r
+    data[283]=(char)0xffff;\r
+    data[284]=(char)0xffff;\r
+    data[285]=(char)0xffff;\r
+    data[286]=(char)0xffff;\r
+    data[287]=(char)0x03ff;\r
+    data[480]=(char)0xffff;\r
+    data[481]=(char)0xffff;\r
+    data[482]=(char)0xffff;\r
+    data[483]=(char)0xffff;\r
+    data[484]=(char)0xffff;\r
+    data[485]=(char)0xffff;\r
+    data[486]=(char)0xffff;\r
+    data[487]=(char)0xffff;\r
+    data[488]=(char)0xffff;\r
+    data[489]=(char)0x0fff;\r
+    data[490]=(char)0xffff;\r
+    data[491]=(char)0xffff;\r
+    data[492]=(char)0xffff;\r
+    data[493]=(char)0xffff;\r
+    data[494]=(char)0xffff;\r
+    data[495]=(char)0x03ff;\r
+    data[496]=(char)0xffff;\r
+    data[497]=(char)0x3f3f;\r
+    data[498]=(char)0xffff;\r
+    data[499]=(char)0xffff;\r
+    data[500]=(char)0x3f3f;\r
+    data[501]=(char)0xaaff;\r
+    data[502]=(char)0xffff;\r
+    data[503]=(char)0x3fff;\r
+    data[504]=(char)0xffff;\r
+    data[505]=(char)0xffff;\r
+    data[506]=(char)0xffff;\r
+    data[507]=(char)0x5fdf;\r
+    data[508]=(char)0x1fdc;\r
+    data[509]=(char)0x0fcf;\r
+    data[510]=(char)0x1fff;\r
+    data[511]=(char)0x1fdc;\r
+    data[519]=(char)0x8000;\r
+    data[528]=(char)0xfc84;\r
+    data[529]=(char)0x3f2f;\r
+    data[530]=(char)0xfd50;\r
+    data[531]=(char)0x01fb;\r
+    data[768]=(char)0x0020;\r
+    data[771]=(char)0x003e;\r
+    data[772]=(char)0xfffe;\r
+    data[773]=(char)0xffff;\r
+    data[774]=(char)0xffff;\r
+    data[775]=(char)0xffff;\r
+    data[776]=(char)0xffff;\r
+    data[777]=(char)0x781f;\r
+    data[778]=(char)0xfffe;\r
+    data[779]=(char)0xffff;\r
+    data[780]=(char)0xffff;\r
+    data[781]=(char)0xffff;\r
+    data[782]=(char)0xffff;\r
+    data[783]=(char)0x77ff;\r
+    data[784]=(char)0xffe0;\r
+    data[785]=(char)0xffff;\r
+    data[786]=(char)0x1fff;\r
+    data[787]=(char)0xfffe;\r
+    data[788]=(char)0xffff;\r
+    data[789]=(char)0xffff;\r
+    data[790]=(char)0xffff;\r
+    data[791]=(char)0xffff;\r
+    data[792]=(char)0x7fff;\r
+    data[1248]=(char)0xffff;\r
+    data[1249]=(char)0xffff;\r
+    data[1250]=(char)0xffff;\r
+    data[1251]=(char)0xffff;\r
+    data[1252]=(char)0xffff;\r
+    data[1253]=(char)0xffff;\r
+    data[1254]=(char)0xffff;\r
+    data[1255]=(char)0xffff;\r
+    data[1256]=(char)0xffff;\r
+    data[1257]=(char)0xffff;\r
+    data[1258]=(char)0xffff;\r
+    data[1259]=(char)0xffff;\r
+    data[1260]=(char)0xffff;\r
+    data[1261]=(char)0xffff;\r
+    data[1262]=(char)0xffff;\r
+    data[1263]=(char)0xffff;\r
+    data[1264]=(char)0xffff;\r
+    data[1265]=(char)0xffff;\r
+    data[1266]=(char)0xffff;\r
+    data[1267]=(char)0xffff;\r
+    data[1268]=(char)0xffff;\r
+    data[1269]=(char)0xffff;\r
+    data[1270]=(char)0xffff;\r
+    data[1271]=(char)0xffff;\r
+    data[1272]=(char)0xffff;\r
+    data[1273]=(char)0xffff;\r
+    data[1274]=(char)0xffff;\r
+    data[1275]=(char)0xffff;\r
+    data[1276]=(char)0xffff;\r
+    data[1277]=(char)0xffff;\r
+    data[1278]=(char)0xffff;\r
+    data[1279]=(char)0xffff;\r
+    data[1280]=(char)0xffff;\r
+    data[1281]=(char)0xffff;\r
+    data[1282]=(char)0xffff;\r
+    data[1283]=(char)0xffff;\r
+    data[1284]=(char)0xffff;\r
+    data[1285]=(char)0xffff;\r
+    data[1286]=(char)0xffff;\r
+    data[1287]=(char)0xffff;\r
+    data[1288]=(char)0xffff;\r
+    data[1289]=(char)0xffff;\r
+    data[1290]=(char)0xffff;\r
+    data[1291]=(char)0xffff;\r
+    data[1292]=(char)0xffff;\r
+    data[1293]=(char)0xffff;\r
+    data[1294]=(char)0xffff;\r
+    data[1295]=(char)0xffff;\r
+    data[1296]=(char)0xffff;\r
+    data[1297]=(char)0xffff;\r
+    data[1298]=(char)0xffff;\r
+    data[1299]=(char)0xffff;\r
+    data[1300]=(char)0xffff;\r
+    data[1301]=(char)0xffff;\r
+    data[1302]=(char)0xffff;\r
+    data[1303]=(char)0xffff;\r
+    data[1304]=(char)0xffff;\r
+    data[1305]=(char)0xffff;\r
+    data[1306]=(char)0xffff;\r
+    data[1307]=(char)0xffff;\r
+    data[1308]=(char)0xffff;\r
+    data[1309]=(char)0xffff;\r
+    data[1310]=(char)0xffff;\r
+    data[1311]=(char)0xffff;\r
+    data[1312]=(char)0xffff;\r
+    data[1313]=(char)0xffff;\r
+    data[1314]=(char)0xffff;\r
+    data[1315]=(char)0xffff;\r
+    data[1316]=(char)0xffff;\r
+    data[1317]=(char)0xffff;\r
+    data[1318]=(char)0xffff;\r
+    data[1319]=(char)0xffff;\r
+    data[1320]=(char)0xffff;\r
+    data[1321]=(char)0xffff;\r
+    data[1322]=(char)0xffff;\r
+    data[1323]=(char)0xffff;\r
+    data[1324]=(char)0xffff;\r
+    data[1325]=(char)0xffff;\r
+    data[1326]=(char)0xffff;\r
+    data[1327]=(char)0xffff;\r
+    data[1328]=(char)0xffff;\r
+    data[1329]=(char)0xffff;\r
+    data[1330]=(char)0xffff;\r
+    data[1331]=(char)0xffff;\r
+    data[1332]=(char)0xffff;\r
+    data[1333]=(char)0xffff;\r
+    data[1334]=(char)0xffff;\r
+    data[1335]=(char)0xffff;\r
+    data[1336]=(char)0xffff;\r
+    data[1337]=(char)0xffff;\r
+    data[1338]=(char)0xffff;\r
+    data[1339]=(char)0xffff;\r
+    data[1340]=(char)0xffff;\r
+    data[1341]=(char)0xffff;\r
+    data[1342]=(char)0xffff;\r
+    data[1343]=(char)0xffff;\r
+    data[1344]=(char)0xffff;\r
+    data[1345]=(char)0xffff;\r
+    data[1346]=(char)0xffff;\r
+    data[1347]=(char)0xffff;\r
+    data[1348]=(char)0xffff;\r
+    data[1349]=(char)0xffff;\r
+    data[1350]=(char)0xffff;\r
+    data[1351]=(char)0xffff;\r
+    data[1352]=(char)0xffff;\r
+    data[1353]=(char)0xffff;\r
+    data[1354]=(char)0xffff;\r
+    data[1355]=(char)0xffff;\r
+    data[1356]=(char)0xffff;\r
+    data[1357]=(char)0xffff;\r
+    data[1358]=(char)0xffff;\r
+    data[1359]=(char)0xffff;\r
+    data[1360]=(char)0xffff;\r
+    data[1361]=(char)0xffff;\r
+    data[1362]=(char)0xffff;\r
+    data[1363]=(char)0xffff;\r
+    data[1364]=(char)0xffff;\r
+    data[1365]=(char)0xffff;\r
+    data[1366]=(char)0xffff;\r
+    data[1367]=(char)0xffff;\r
+    data[1368]=(char)0xffff;\r
+    data[1369]=(char)0xffff;\r
+    data[1370]=(char)0xffff;\r
+    data[1371]=(char)0xffff;\r
+    data[1372]=(char)0xffff;\r
+    data[1373]=(char)0xffff;\r
+    data[1374]=(char)0xffff;\r
+    data[1375]=(char)0xffff;\r
+    data[1376]=(char)0xffff;\r
+    data[1377]=(char)0xffff;\r
+    data[1378]=(char)0xffff;\r
+    data[1379]=(char)0xffff;\r
+    data[1380]=(char)0xffff;\r
+    data[1381]=(char)0xffff;\r
+    data[1382]=(char)0xffff;\r
+    data[1383]=(char)0xffff;\r
+    data[1384]=(char)0xffff;\r
+    data[1385]=(char)0xffff;\r
+    data[1386]=(char)0xffff;\r
+    data[1387]=(char)0xffff;\r
+    data[1388]=(char)0xffff;\r
+    data[1389]=(char)0xffff;\r
+    data[1390]=(char)0xffff;\r
+    data[1391]=(char)0xffff;\r
+    data[1392]=(char)0xffff;\r
+    data[1393]=(char)0xffff;\r
+    data[1394]=(char)0xffff;\r
+    data[1395]=(char)0xffff;\r
+    data[1396]=(char)0xffff;\r
+    data[1397]=(char)0xffff;\r
+    data[1398]=(char)0xffff;\r
+    data[1399]=(char)0xffff;\r
+    data[1400]=(char)0xffff;\r
+    data[1401]=(char)0xffff;\r
+    data[1402]=(char)0xffff;\r
+    data[1403]=(char)0xffff;\r
+    data[1404]=(char)0xffff;\r
+    data[1405]=(char)0xffff;\r
+    data[1406]=(char)0xffff;\r
+    data[1407]=(char)0xffff;\r
+    data[1408]=(char)0xffff;\r
+    data[1409]=(char)0xffff;\r
+    data[1410]=(char)0xffff;\r
+    data[1411]=(char)0xffff;\r
+    data[1412]=(char)0xffff;\r
+    data[1413]=(char)0xffff;\r
+    data[1414]=(char)0xffff;\r
+    data[1415]=(char)0xffff;\r
+    data[1416]=(char)0xffff;\r
+    data[1417]=(char)0xffff;\r
+    data[1418]=(char)0xffff;\r
+    data[1419]=(char)0xffff;\r
+    data[1420]=(char)0xffff;\r
+    data[1421]=(char)0xffff;\r
+    data[1422]=(char)0xffff;\r
+    data[1423]=(char)0xffff;\r
+    data[1424]=(char)0xffff;\r
+    data[1425]=(char)0xffff;\r
+    data[1426]=(char)0xffff;\r
+    data[1427]=(char)0xffff;\r
+    data[1428]=(char)0xffff;\r
+    data[1429]=(char)0xffff;\r
+    data[1430]=(char)0xffff;\r
+    data[1431]=(char)0xffff;\r
+    data[1432]=(char)0xffff;\r
+    data[1433]=(char)0xffff;\r
+    data[1434]=(char)0xffff;\r
+    data[1435]=(char)0xffff;\r
+    data[1436]=(char)0xffff;\r
+    data[1437]=(char)0xffff;\r
+    data[1438]=(char)0xffff;\r
+    data[1439]=(char)0xffff;\r
+    data[1440]=(char)0xffff;\r
+    data[1441]=(char)0xffff;\r
+    data[1442]=(char)0xffff;\r
+    data[1443]=(char)0xffff;\r
+    data[1444]=(char)0xffff;\r
+    data[1445]=(char)0xffff;\r
+    data[1446]=(char)0xffff;\r
+    data[1447]=(char)0xffff;\r
+    data[1448]=(char)0xffff;\r
+    data[1449]=(char)0xffff;\r
+    data[1450]=(char)0xffff;\r
+    data[1451]=(char)0xffff;\r
+    data[1452]=(char)0xffff;\r
+    data[1453]=(char)0xffff;\r
+    data[1454]=(char)0xffff;\r
+    data[1455]=(char)0xffff;\r
+    data[1456]=(char)0xffff;\r
+    data[1457]=(char)0xffff;\r
+    data[1458]=(char)0xffff;\r
+    data[1459]=(char)0xffff;\r
+    data[1460]=(char)0xffff;\r
+    data[1461]=(char)0xffff;\r
+    data[1462]=(char)0xffff;\r
+    data[1463]=(char)0xffff;\r
+    data[1464]=(char)0xffff;\r
+    data[1465]=(char)0xffff;\r
+    data[1466]=(char)0xffff;\r
+    data[1467]=(char)0xffff;\r
+    data[1468]=(char)0xffff;\r
+    data[1469]=(char)0xffff;\r
+    data[1470]=(char)0xffff;\r
+    data[1471]=(char)0xffff;\r
+    data[1472]=(char)0xffff;\r
+    data[1473]=(char)0xffff;\r
+    data[1474]=(char)0xffff;\r
+    data[1475]=(char)0xffff;\r
+    data[1476]=(char)0xffff;\r
+    data[1477]=(char)0xffff;\r
+    data[1478]=(char)0xffff;\r
+    data[1479]=(char)0xffff;\r
+    data[1480]=(char)0xffff;\r
+    data[1481]=(char)0xffff;\r
+    data[1482]=(char)0xffff;\r
+    data[1483]=(char)0xffff;\r
+    data[1484]=(char)0xffff;\r
+    data[1485]=(char)0xffff;\r
+    data[1486]=(char)0xffff;\r
+    data[1487]=(char)0xffff;\r
+    data[1488]=(char)0xffff;\r
+    data[1489]=(char)0xffff;\r
+    data[1490]=(char)0xffff;\r
+    data[1491]=(char)0xffff;\r
+    data[1492]=(char)0xffff;\r
+    data[1493]=(char)0xffff;\r
+    data[1494]=(char)0xffff;\r
+    data[1495]=(char)0xffff;\r
+    data[1496]=(char)0xffff;\r
+    data[1497]=(char)0xffff;\r
+    data[1498]=(char)0xffff;\r
+    data[1499]=(char)0xffff;\r
+    data[1500]=(char)0xffff;\r
+    data[1501]=(char)0xffff;\r
+    data[1502]=(char)0xffff;\r
+    data[1503]=(char)0xffff;\r
+    data[1504]=(char)0xffff;\r
+    data[1505]=(char)0xffff;\r
+    data[1506]=(char)0xffff;\r
+    data[1507]=(char)0xffff;\r
+    data[1508]=(char)0xffff;\r
+    data[1509]=(char)0xffff;\r
+    data[1510]=(char)0xffff;\r
+    data[1511]=(char)0xffff;\r
+    data[1512]=(char)0xffff;\r
+    data[1513]=(char)0xffff;\r
+    data[1514]=(char)0xffff;\r
+    data[1515]=(char)0xffff;\r
+    data[1516]=(char)0xffff;\r
+    data[1517]=(char)0xffff;\r
+    data[1518]=(char)0xffff;\r
+    data[1519]=(char)0xffff;\r
+    data[1520]=(char)0xffff;\r
+    data[1521]=(char)0xffff;\r
+    data[1522]=(char)0xffff;\r
+    data[1523]=(char)0xffff;\r
+    data[1524]=(char)0xffff;\r
+    data[1525]=(char)0xffff;\r
+    data[1526]=(char)0xffff;\r
+    data[1527]=(char)0xffff;\r
+    data[1528]=(char)0xffff;\r
+    data[1529]=(char)0xffff;\r
+    data[1530]=(char)0xffff;\r
+    data[1531]=(char)0xffff;\r
+    data[1532]=(char)0xffff;\r
+    data[1533]=(char)0xffff;\r
+    data[1534]=(char)0xffff;\r
+    data[1535]=(char)0xffff;\r
+    data[1536]=(char)0xffff;\r
+    data[1537]=(char)0xffff;\r
+    data[1538]=(char)0xffff;\r
+    data[1539]=(char)0xffff;\r
+    data[1540]=(char)0xffff;\r
+    data[1541]=(char)0xffff;\r
+    data[1542]=(char)0xffff;\r
+    data[1543]=(char)0xffff;\r
+    data[1544]=(char)0xffff;\r
+    data[1545]=(char)0xffff;\r
+    data[1546]=(char)0xffff;\r
+    data[1547]=(char)0xffff;\r
+    data[1548]=(char)0xffff;\r
+    data[1549]=(char)0xffff;\r
+    data[1550]=(char)0xffff;\r
+    data[1551]=(char)0xffff;\r
+    data[1552]=(char)0xffff;\r
+    data[1553]=(char)0xffff;\r
+    data[1554]=(char)0xffff;\r
+    data[1555]=(char)0xffff;\r
+    data[1556]=(char)0xffff;\r
+    data[1557]=(char)0xffff;\r
+    data[1558]=(char)0xffff;\r
+    data[1559]=(char)0xffff;\r
+    data[1560]=(char)0xffff;\r
+    data[1561]=(char)0xffff;\r
+    data[1562]=(char)0xffff;\r
+    data[1563]=(char)0xffff;\r
+    data[1564]=(char)0xffff;\r
+    data[1565]=(char)0xffff;\r
+    data[1566]=(char)0xffff;\r
+    data[1567]=(char)0xffff;\r
+    data[1568]=(char)0xffff;\r
+    data[1569]=(char)0xffff;\r
+    data[1570]=(char)0xffff;\r
+    data[1571]=(char)0xffff;\r
+    data[1572]=(char)0xffff;\r
+    data[1573]=(char)0xffff;\r
+    data[1574]=(char)0xffff;\r
+    data[1575]=(char)0xffff;\r
+    data[1576]=(char)0xffff;\r
+    data[1577]=(char)0xffff;\r
+    data[1578]=(char)0xffff;\r
+    data[1579]=(char)0xffff;\r
+    data[1580]=(char)0xffff;\r
+    data[1581]=(char)0xffff;\r
+    data[1582]=(char)0xffff;\r
+    data[1583]=(char)0xffff;\r
+    data[1584]=(char)0xffff;\r
+    data[1585]=(char)0xffff;\r
+    data[1586]=(char)0xffff;\r
+    data[1587]=(char)0xffff;\r
+    data[1588]=(char)0xffff;\r
+    data[1589]=(char)0xffff;\r
+    data[1590]=(char)0xffff;\r
+    data[1591]=(char)0xffff;\r
+    data[1592]=(char)0xffff;\r
+    data[1593]=(char)0xffff;\r
+    data[1594]=(char)0xffff;\r
+    data[1595]=(char)0xffff;\r
+    data[1596]=(char)0xffff;\r
+    data[1597]=(char)0xffff;\r
+    data[1598]=(char)0xffff;\r
+    data[1599]=(char)0xffff;\r
+    data[1600]=(char)0xffff;\r
+    data[1601]=(char)0xffff;\r
+    data[1602]=(char)0xffff;\r
+    data[1603]=(char)0xffff;\r
+    data[1604]=(char)0xffff;\r
+    data[1605]=(char)0xffff;\r
+    data[1606]=(char)0xffff;\r
+    data[1607]=(char)0xffff;\r
+    data[1608]=(char)0xffff;\r
+    data[1609]=(char)0xffff;\r
+    data[1610]=(char)0xffff;\r
+    data[1611]=(char)0xffff;\r
+    data[1612]=(char)0xffff;\r
+    data[1613]=(char)0xffff;\r
+    data[1614]=(char)0xffff;\r
+    data[1615]=(char)0xffff;\r
+    data[1616]=(char)0xffff;\r
+    data[1617]=(char)0xffff;\r
+    data[1618]=(char)0xffff;\r
+    data[1619]=(char)0xffff;\r
+    data[1620]=(char)0xffff;\r
+    data[1621]=(char)0xffff;\r
+    data[1622]=(char)0xffff;\r
+    data[1623]=(char)0xffff;\r
+    data[1624]=(char)0xffff;\r
+    data[1625]=(char)0xffff;\r
+    data[1626]=(char)0xffff;\r
+    data[1627]=(char)0xffff;\r
+    data[1628]=(char)0xffff;\r
+    data[1629]=(char)0xffff;\r
+    data[1630]=(char)0xffff;\r
+    data[1631]=(char)0xffff;\r
+    data[1632]=(char)0xffff;\r
+    data[1633]=(char)0xffff;\r
+    data[1634]=(char)0xffff;\r
+    data[1635]=(char)0xffff;\r
+    data[1636]=(char)0xffff;\r
+    data[1637]=(char)0xffff;\r
+    data[1638]=(char)0xffff;\r
+    data[1639]=(char)0xffff;\r
+    data[1640]=(char)0xffff;\r
+    data[1641]=(char)0xffff;\r
+    data[1642]=(char)0xffff;\r
+    data[1643]=(char)0xffff;\r
+    data[1644]=(char)0xffff;\r
+    data[1645]=(char)0xffff;\r
+    data[1646]=(char)0xffff;\r
+    data[1647]=(char)0xffff;\r
+    data[1648]=(char)0xffff;\r
+    data[1649]=(char)0xffff;\r
+    data[1650]=(char)0xffff;\r
+    data[1651]=(char)0xffff;\r
+    data[1652]=(char)0xffff;\r
+    data[1653]=(char)0xffff;\r
+    data[1654]=(char)0xffff;\r
+    data[1655]=(char)0xffff;\r
+    data[1656]=(char)0xffff;\r
+    data[1657]=(char)0xffff;\r
+    data[1658]=(char)0xffff;\r
+    data[1659]=(char)0xffff;\r
+    data[1660]=(char)0xffff;\r
+    data[1661]=(char)0xffff;\r
+    data[1662]=(char)0xffff;\r
+    data[1663]=(char)0xffff;\r
+    data[1664]=(char)0xffff;\r
+    data[1665]=(char)0xffff;\r
+    data[1666]=(char)0xffff;\r
+    data[1667]=(char)0xffff;\r
+    data[1668]=(char)0xffff;\r
+    data[1669]=(char)0xffff;\r
+    data[1670]=(char)0xffff;\r
+    data[1671]=(char)0xffff;\r
+    data[1672]=(char)0xffff;\r
+    data[1673]=(char)0xffff;\r
+    data[1674]=(char)0xffff;\r
+    data[1675]=(char)0xffff;\r
+    data[1676]=(char)0xffff;\r
+    data[1677]=(char)0xffff;\r
+    data[1678]=(char)0xffff;\r
+    data[1679]=(char)0xffff;\r
+    data[1680]=(char)0xffff;\r
+    data[1681]=(char)0xffff;\r
+    data[1682]=(char)0xffff;\r
+    data[1683]=(char)0xffff;\r
+    data[1684]=(char)0xffff;\r
+    data[1685]=(char)0xffff;\r
+    data[1686]=(char)0xffff;\r
+    data[1687]=(char)0xffff;\r
+    data[1688]=(char)0xffff;\r
+    data[1689]=(char)0xffff;\r
+    data[1690]=(char)0xffff;\r
+    data[1691]=(char)0xffff;\r
+    data[1692]=(char)0xffff;\r
+    data[1693]=(char)0xffff;\r
+    data[1694]=(char)0xffff;\r
+    data[1695]=(char)0xffff;\r
+    data[1696]=(char)0xffff;\r
+    data[1697]=(char)0xffff;\r
+    data[1698]=(char)0xffff;\r
+    data[1699]=(char)0xffff;\r
+    data[1700]=(char)0xffff;\r
+    data[1701]=(char)0xffff;\r
+    data[1702]=(char)0xffff;\r
+    data[1703]=(char)0xffff;\r
+    data[1704]=(char)0xffff;\r
+    data[1705]=(char)0xffff;\r
+    data[1706]=(char)0xffff;\r
+    data[1707]=(char)0xffff;\r
+    data[1708]=(char)0xffff;\r
+    data[1709]=(char)0xffff;\r
+    data[1710]=(char)0xffff;\r
+    data[1711]=(char)0xffff;\r
+    data[1712]=(char)0xffff;\r
+    data[1713]=(char)0xffff;\r
+    data[1714]=(char)0xffff;\r
+    data[1715]=(char)0xffff;\r
+    data[1716]=(char)0xffff;\r
+    data[1717]=(char)0xffff;\r
+    data[1718]=(char)0xffff;\r
+    data[1719]=(char)0xffff;\r
+    data[1720]=(char)0xffff;\r
+    data[1721]=(char)0xffff;\r
+    data[1722]=(char)0xffff;\r
+    data[1723]=(char)0xffff;\r
+    data[1724]=(char)0xffff;\r
+    data[1725]=(char)0xffff;\r
+    data[1726]=(char)0xffff;\r
+    data[1727]=(char)0xffff;\r
+    data[1728]=(char)0xffff;\r
+    data[1729]=(char)0xffff;\r
+    data[1730]=(char)0xffff;\r
+    data[1731]=(char)0xffff;\r
+    data[1732]=(char)0xffff;\r
+    data[1733]=(char)0xffff;\r
+    data[1734]=(char)0xffff;\r
+    data[1735]=(char)0xffff;\r
+    data[1736]=(char)0xffff;\r
+    data[1737]=(char)0xffff;\r
+    data[1738]=(char)0xffff;\r
+    data[1739]=(char)0xffff;\r
+    data[1740]=(char)0xffff;\r
+    data[1741]=(char)0xffff;\r
+    data[1742]=(char)0xffff;\r
+    data[1743]=(char)0xffff;\r
+    data[1744]=(char)0xffff;\r
+    data[1745]=(char)0xffff;\r
+    data[1746]=(char)0xffff;\r
+    data[1747]=(char)0xffff;\r
+    data[1748]=(char)0xffff;\r
+    data[1749]=(char)0xffff;\r
+    data[1750]=(char)0xffff;\r
+    data[1751]=(char)0xffff;\r
+    data[1752]=(char)0xffff;\r
+    data[1753]=(char)0xffff;\r
+    data[1754]=(char)0xffff;\r
+    data[1755]=(char)0xffff;\r
+    data[1756]=(char)0xffff;\r
+    data[1757]=(char)0xffff;\r
+    data[1758]=(char)0xffff;\r
+    data[1759]=(char)0xffff;\r
+    data[1760]=(char)0xffff;\r
+    data[1761]=(char)0xffff;\r
+    data[1762]=(char)0xffff;\r
+    data[1763]=(char)0xffff;\r
+    data[1764]=(char)0xffff;\r
+    data[1765]=(char)0xffff;\r
+    data[1766]=(char)0xffff;\r
+    data[1767]=(char)0xffff;\r
+    data[1768]=(char)0xffff;\r
+    data[1769]=(char)0xffff;\r
+    data[1770]=(char)0xffff;\r
+    data[1771]=(char)0xffff;\r
+    data[1772]=(char)0xffff;\r
+    data[1773]=(char)0xffff;\r
+    data[1774]=(char)0xffff;\r
+    data[1775]=(char)0xffff;\r
+    data[1776]=(char)0xffff;\r
+    data[1777]=(char)0xffff;\r
+    data[1778]=(char)0xffff;\r
+    data[1779]=(char)0xffff;\r
+    data[1780]=(char)0xffff;\r
+    data[1781]=(char)0xffff;\r
+    data[1782]=(char)0xffff;\r
+    data[1783]=(char)0xffff;\r
+    data[1784]=(char)0xffff;\r
+    data[1785]=(char)0xffff;\r
+    data[1786]=(char)0xffff;\r
+    data[1787]=(char)0xffff;\r
+    data[1788]=(char)0xffff;\r
+    data[1789]=(char)0xffff;\r
+    data[1790]=(char)0xffff;\r
+    data[1791]=(char)0xffff;\r
+    data[1792]=(char)0xffff;\r
+    data[1793]=(char)0xffff;\r
+    data[1794]=(char)0xffff;\r
+    data[1795]=(char)0xffff;\r
+    data[1796]=(char)0xffff;\r
+    data[1797]=(char)0xffff;\r
+    data[1798]=(char)0xffff;\r
+    data[1799]=(char)0xffff;\r
+    data[1800]=(char)0xffff;\r
+    data[1801]=(char)0xffff;\r
+    data[1802]=(char)0xffff;\r
+    data[1803]=(char)0xffff;\r
+    data[1804]=(char)0xffff;\r
+    data[1805]=(char)0xffff;\r
+    data[1806]=(char)0xffff;\r
+    data[1807]=(char)0xffff;\r
+    data[1808]=(char)0xffff;\r
+    data[1809]=(char)0xffff;\r
+    data[1810]=(char)0xffff;\r
+    data[1811]=(char)0xffff;\r
+    data[1812]=(char)0xffff;\r
+    data[1813]=(char)0xffff;\r
+    data[1814]=(char)0xffff;\r
+    data[1815]=(char)0xffff;\r
+    data[1816]=(char)0xffff;\r
+    data[1817]=(char)0xffff;\r
+    data[1818]=(char)0xffff;\r
+    data[1819]=(char)0xffff;\r
+    data[1820]=(char)0xffff;\r
+    data[1821]=(char)0xffff;\r
+    data[1822]=(char)0xffff;\r
+    data[1823]=(char)0xffff;\r
+    data[1824]=(char)0xffff;\r
+    data[1825]=(char)0xffff;\r
+    data[1826]=(char)0xffff;\r
+    data[1827]=(char)0xffff;\r
+    data[1828]=(char)0xffff;\r
+    data[1829]=(char)0xffff;\r
+    data[1830]=(char)0xffff;\r
+    data[1831]=(char)0xffff;\r
+    data[1832]=(char)0xffff;\r
+    data[1833]=(char)0xffff;\r
+    data[1834]=(char)0xffff;\r
+    data[1835]=(char)0xffff;\r
+    data[1836]=(char)0xffff;\r
+    data[1837]=(char)0xffff;\r
+    data[1838]=(char)0xffff;\r
+    data[1839]=(char)0xffff;\r
+    data[1840]=(char)0xffff;\r
+    data[1841]=(char)0xffff;\r
+    data[1842]=(char)0xffff;\r
+    data[1843]=(char)0xffff;\r
+    data[1844]=(char)0xffff;\r
+    data[1845]=(char)0xffff;\r
+    data[1846]=(char)0xffff;\r
+    data[1847]=(char)0xffff;\r
+    data[1848]=(char)0xffff;\r
+    data[1849]=(char)0xffff;\r
+    data[1850]=(char)0xffff;\r
+    data[1851]=(char)0xffff;\r
+    data[1852]=(char)0xffff;\r
+    data[1853]=(char)0xffff;\r
+    data[1854]=(char)0xffff;\r
+    data[1855]=(char)0xffff;\r
+    data[1856]=(char)0xffff;\r
+    data[1857]=(char)0xffff;\r
+    data[1858]=(char)0xffff;\r
+    data[1859]=(char)0xffff;\r
+    data[1860]=(char)0xffff;\r
+    data[1861]=(char)0xffff;\r
+    data[1862]=(char)0xffff;\r
+    data[1863]=(char)0xffff;\r
+    data[1864]=(char)0xffff;\r
+    data[1865]=(char)0xffff;\r
+    data[1866]=(char)0xffff;\r
+    data[1867]=(char)0xffff;\r
+    data[1868]=(char)0xffff;\r
+    data[1869]=(char)0xffff;\r
+    data[1870]=(char)0xffff;\r
+    data[1871]=(char)0xffff;\r
+    data[1872]=(char)0xffff;\r
+    data[1873]=(char)0xffff;\r
+    data[1874]=(char)0xffff;\r
+    data[1875]=(char)0xffff;\r
+    data[1876]=(char)0xffff;\r
+    data[1877]=(char)0xffff;\r
+    data[1878]=(char)0xffff;\r
+    data[1879]=(char)0xffff;\r
+    data[1880]=(char)0xffff;\r
+    data[1881]=(char)0xffff;\r
+    data[1882]=(char)0xffff;\r
+    data[1883]=(char)0xffff;\r
+    data[1884]=(char)0xffff;\r
+    data[1885]=(char)0xffff;\r
+    data[1886]=(char)0xffff;\r
+    data[1887]=(char)0xffff;\r
+    data[1888]=(char)0xffff;\r
+    data[1889]=(char)0xffff;\r
+    data[1890]=(char)0xffff;\r
+    data[1891]=(char)0xffff;\r
+    data[1892]=(char)0xffff;\r
+    data[1893]=(char)0xffff;\r
+    data[1894]=(char)0xffff;\r
+    data[1895]=(char)0xffff;\r
+    data[1896]=(char)0xffff;\r
+    data[1897]=(char)0xffff;\r
+    data[1898]=(char)0xffff;\r
+    data[1899]=(char)0xffff;\r
+    data[1900]=(char)0xffff;\r
+    data[1901]=(char)0xffff;\r
+    data[1902]=(char)0xffff;\r
+    data[1903]=(char)0xffff;\r
+    data[1904]=(char)0xffff;\r
+    data[1905]=(char)0xffff;\r
+    data[1906]=(char)0xffff;\r
+    data[1907]=(char)0xffff;\r
+    data[1908]=(char)0xffff;\r
+    data[1909]=(char)0xffff;\r
+    data[1910]=(char)0xffff;\r
+    data[1911]=(char)0xffff;\r
+    data[1912]=(char)0xffff;\r
+    data[1913]=(char)0xffff;\r
+    data[1914]=(char)0xffff;\r
+    data[1915]=(char)0xffff;\r
+    data[1916]=(char)0xffff;\r
+    data[1917]=(char)0xffff;\r
+    data[1918]=(char)0xffff;\r
+    data[1919]=(char)0xffff;\r
+    data[1920]=(char)0xffff;\r
+    data[1921]=(char)0xffff;\r
+    data[1922]=(char)0xffff;\r
+    data[1923]=(char)0xffff;\r
+    data[1924]=(char)0xffff;\r
+    data[1925]=(char)0xffff;\r
+    data[1926]=(char)0xffff;\r
+    data[1927]=(char)0xffff;\r
+    data[1928]=(char)0xffff;\r
+    data[1929]=(char)0xffff;\r
+    data[1930]=(char)0xffff;\r
+    data[1931]=(char)0xffff;\r
+    data[1932]=(char)0xffff;\r
+    data[1933]=(char)0xffff;\r
+    data[1934]=(char)0xffff;\r
+    data[1935]=(char)0xffff;\r
+    data[1936]=(char)0xffff;\r
+    data[1937]=(char)0xffff;\r
+    data[1938]=(char)0xffff;\r
+    data[1939]=(char)0xffff;\r
+    data[1940]=(char)0xffff;\r
+    data[1941]=(char)0xffff;\r
+    data[1942]=(char)0xffff;\r
+    data[1943]=(char)0xffff;\r
+    data[1944]=(char)0xffff;\r
+    data[1945]=(char)0xffff;\r
+    data[1946]=(char)0xffff;\r
+    data[1947]=(char)0xffff;\r
+    data[1948]=(char)0xffff;\r
+    data[1949]=(char)0xffff;\r
+    data[1950]=(char)0xffff;\r
+    data[1951]=(char)0xffff;\r
+    data[1952]=(char)0xffff;\r
+    data[1953]=(char)0xffff;\r
+    data[1954]=(char)0xffff;\r
+    data[1955]=(char)0xffff;\r
+    data[1956]=(char)0xffff;\r
+    data[1957]=(char)0xffff;\r
+    data[1958]=(char)0xffff;\r
+    data[1959]=(char)0xffff;\r
+    data[1960]=(char)0xffff;\r
+    data[1961]=(char)0xffff;\r
+    data[1962]=(char)0xffff;\r
+    data[1963]=(char)0xffff;\r
+    data[1964]=(char)0xffff;\r
+    data[1965]=(char)0xffff;\r
+    data[1966]=(char)0xffff;\r
+    data[1967]=(char)0xffff;\r
+    data[1968]=(char)0xffff;\r
+    data[1969]=(char)0xffff;\r
+    data[1970]=(char)0xffff;\r
+    data[1971]=(char)0xffff;\r
+    data[1972]=(char)0xffff;\r
+    data[1973]=(char)0xffff;\r
+    data[1974]=(char)0xffff;\r
+    data[1975]=(char)0xffff;\r
+    data[1976]=(char)0xffff;\r
+    data[1977]=(char)0xffff;\r
+    data[1978]=(char)0xffff;\r
+    data[1979]=(char)0xffff;\r
+    data[1980]=(char)0xffff;\r
+    data[1981]=(char)0xffff;\r
+    data[1982]=(char)0xffff;\r
+    data[1983]=(char)0xffff;\r
+    data[1984]=(char)0xffff;\r
+    data[1985]=(char)0xffff;\r
+    data[1986]=(char)0xffff;\r
+    data[1987]=(char)0xffff;\r
+    data[1988]=(char)0xffff;\r
+    data[1989]=(char)0xffff;\r
+    data[1990]=(char)0xffff;\r
+    data[1991]=(char)0xffff;\r
+    data[1992]=(char)0xffff;\r
+    data[1993]=(char)0xffff;\r
+    data[1994]=(char)0xffff;\r
+    data[1995]=(char)0xffff;\r
+    data[1996]=(char)0xffff;\r
+    data[1997]=(char)0xffff;\r
+    data[1998]=(char)0xffff;\r
+    data[1999]=(char)0xffff;\r
+    data[2000]=(char)0xffff;\r
+    data[2001]=(char)0xffff;\r
+    data[2002]=(char)0xffff;\r
+    data[2003]=(char)0xffff;\r
+    data[2004]=(char)0xffff;\r
+    data[2005]=(char)0xffff;\r
+    data[2006]=(char)0xffff;\r
+    data[2007]=(char)0xffff;\r
+    data[2008]=(char)0xffff;\r
+    data[2009]=(char)0xffff;\r
+    data[2010]=(char)0xffff;\r
+    data[2011]=(char)0xffff;\r
+    data[2012]=(char)0xffff;\r
+    data[2013]=(char)0xffff;\r
+    data[2014]=(char)0xffff;\r
+    data[2015]=(char)0xffff;\r
+    data[2016]=(char)0xffff;\r
+    data[2017]=(char)0xffff;\r
+    data[2018]=(char)0xffff;\r
+    data[2019]=(char)0xffff;\r
+    data[2020]=(char)0xffff;\r
+    data[2021]=(char)0xffff;\r
+    data[2022]=(char)0xffff;\r
+    data[2023]=(char)0xffff;\r
+    data[2024]=(char)0xffff;\r
+    data[2025]=(char)0xffff;\r
+    data[2026]=(char)0xffff;\r
+    data[2027]=(char)0xffff;\r
+    data[2028]=(char)0xffff;\r
+    data[2029]=(char)0xffff;\r
+    data[2030]=(char)0xffff;\r
+    data[2031]=(char)0xffff;\r
+    data[2032]=(char)0xffff;\r
+    data[2033]=(char)0xffff;\r
+    data[2034]=(char)0xffff;\r
+    data[2035]=(char)0xffff;\r
+    data[2036]=(char)0xffff;\r
+    data[2037]=(char)0xffff;\r
+    data[2038]=(char)0xffff;\r
+    data[2039]=(char)0xffff;\r
+    data[2040]=(char)0xffff;\r
+    data[2041]=(char)0xffff;\r
+    data[2042]=(char)0xffff;\r
+    data[2043]=(char)0xffff;\r
+    data[2044]=(char)0xffff;\r
+    data[2045]=(char)0xffff;\r
+    data[2046]=(char)0xffff;\r
+    data[2047]=(char)0xffff;\r
+    data[2048]=(char)0xffff;\r
+    data[2049]=(char)0xffff;\r
+    data[2050]=(char)0xffff;\r
+    data[2051]=(char)0xffff;\r
+    data[2052]=(char)0xffff;\r
+    data[2053]=(char)0xffff;\r
+    data[2054]=(char)0xffff;\r
+    data[2055]=(char)0xffff;\r
+    data[2056]=(char)0xffff;\r
+    data[2057]=(char)0xffff;\r
+    data[2058]=(char)0xffff;\r
+    data[2059]=(char)0xffff;\r
+    data[2060]=(char)0xffff;\r
+    data[2061]=(char)0xffff;\r
+    data[2062]=(char)0xffff;\r
+    data[2063]=(char)0xffff;\r
+    data[2064]=(char)0xffff;\r
+    data[2065]=(char)0xffff;\r
+    data[2066]=(char)0xffff;\r
+    data[2067]=(char)0xffff;\r
+    data[2068]=(char)0xffff;\r
+    data[2069]=(char)0xffff;\r
+    data[2070]=(char)0xffff;\r
+    data[2071]=(char)0xffff;\r
+    data[2072]=(char)0xffff;\r
+    data[2073]=(char)0xffff;\r
+    data[2074]=(char)0xffff;\r
+    data[2075]=(char)0xffff;\r
+    data[2076]=(char)0xffff;\r
+    data[2077]=(char)0xffff;\r
+    data[2078]=(char)0xffff;\r
+    data[2079]=(char)0xffff;\r
+    data[2080]=(char)0xffff;\r
+    data[2081]=(char)0xffff;\r
+    data[2082]=(char)0xffff;\r
+    data[2083]=(char)0xffff;\r
+    data[2084]=(char)0xffff;\r
+    data[2085]=(char)0xffff;\r
+    data[2086]=(char)0xffff;\r
+    data[2087]=(char)0xffff;\r
+    data[2088]=(char)0xffff;\r
+    data[2089]=(char)0xffff;\r
+    data[2090]=(char)0xffff;\r
+    data[2091]=(char)0xffff;\r
+    data[2092]=(char)0xffff;\r
+    data[2093]=(char)0xffff;\r
+    data[2094]=(char)0xffff;\r
+    data[2095]=(char)0xffff;\r
+    data[2096]=(char)0xffff;\r
+    data[2097]=(char)0xffff;\r
+    data[2098]=(char)0xffff;\r
+    data[2099]=(char)0xffff;\r
+    data[2100]=(char)0xffff;\r
+    data[2101]=(char)0xffff;\r
+    data[2102]=(char)0xffff;\r
+    data[2103]=(char)0xffff;\r
+    data[2104]=(char)0xffff;\r
+    data[2105]=(char)0xffff;\r
+    data[2106]=(char)0xffff;\r
+    data[2107]=(char)0xffff;\r
+    data[2108]=(char)0xffff;\r
+    data[2109]=(char)0xffff;\r
+    data[2110]=(char)0xffff;\r
+    data[2111]=(char)0xffff;\r
+    data[2112]=(char)0xffff;\r
+    data[2113]=(char)0xffff;\r
+    data[2114]=(char)0xffff;\r
+    data[2115]=(char)0xffff;\r
+    data[2116]=(char)0xffff;\r
+    data[2117]=(char)0xffff;\r
+    data[2118]=(char)0xffff;\r
+    data[2119]=(char)0xffff;\r
+    data[2120]=(char)0xffff;\r
+    data[2121]=(char)0xffff;\r
+    data[2122]=(char)0xffff;\r
+    data[2123]=(char)0xffff;\r
+    data[2124]=(char)0xffff;\r
+    data[2125]=(char)0xffff;\r
+    data[2126]=(char)0xffff;\r
+    data[2127]=(char)0xffff;\r
+    data[2128]=(char)0xffff;\r
+    data[2129]=(char)0xffff;\r
+    data[2130]=(char)0xffff;\r
+    data[2131]=(char)0xffff;\r
+    data[2132]=(char)0xffff;\r
+    data[2133]=(char)0xffff;\r
+    data[2134]=(char)0xffff;\r
+    data[2135]=(char)0xffff;\r
+    data[2136]=(char)0xffff;\r
+    data[2137]=(char)0xffff;\r
+    data[2138]=(char)0xffff;\r
+    data[2139]=(char)0xffff;\r
+    data[2140]=(char)0xffff;\r
+    data[2141]=(char)0xffff;\r
+    data[2142]=(char)0xffff;\r
+    data[2143]=(char)0xffff;\r
+    data[2144]=(char)0xffff;\r
+    data[2145]=(char)0xffff;\r
+    data[2146]=(char)0xffff;\r
+    data[2147]=(char)0xffff;\r
+    data[2148]=(char)0xffff;\r
+    data[2149]=(char)0xffff;\r
+    data[2150]=(char)0xffff;\r
+    data[2151]=(char)0xffff;\r
+    data[2152]=(char)0xffff;\r
+    data[2153]=(char)0xffff;\r
+    data[2154]=(char)0xffff;\r
+    data[2155]=(char)0xffff;\r
+    data[2156]=(char)0xffff;\r
+    data[2157]=(char)0xffff;\r
+    data[2158]=(char)0xffff;\r
+    data[2159]=(char)0xffff;\r
+    data[2160]=(char)0xffff;\r
+    data[2161]=(char)0xffff;\r
+    data[2162]=(char)0xffff;\r
+    data[2163]=(char)0xffff;\r
+    data[2164]=(char)0xffff;\r
+    data[2165]=(char)0xffff;\r
+    data[2166]=(char)0xffff;\r
+    data[2167]=(char)0xffff;\r
+    data[2168]=(char)0xffff;\r
+    data[2169]=(char)0xffff;\r
+    data[2170]=(char)0xffff;\r
+    data[2171]=(char)0xffff;\r
+    data[2172]=(char)0xffff;\r
+    data[2173]=(char)0xffff;\r
+    data[2174]=(char)0xffff;\r
+    data[2175]=(char)0xffff;\r
+    data[2176]=(char)0xffff;\r
+    data[2177]=(char)0xffff;\r
+    data[2178]=(char)0xffff;\r
+    data[2179]=(char)0xffff;\r
+    data[2180]=(char)0xffff;\r
+    data[2181]=(char)0xffff;\r
+    data[2182]=(char)0xffff;\r
+    data[2183]=(char)0xffff;\r
+    data[2184]=(char)0xffff;\r
+    data[2185]=(char)0xffff;\r
+    data[2186]=(char)0xffff;\r
+    data[2187]=(char)0xffff;\r
+    data[2188]=(char)0xffff;\r
+    data[2189]=(char)0xffff;\r
+    data[2190]=(char)0xffff;\r
+    data[2191]=(char)0xffff;\r
+    data[2192]=(char)0xffff;\r
+    data[2193]=(char)0xffff;\r
+    data[2194]=(char)0xffff;\r
+    data[2195]=(char)0xffff;\r
+    data[2196]=(char)0xffff;\r
+    data[2197]=(char)0xffff;\r
+    data[2198]=(char)0xffff;\r
+    data[2199]=(char)0xffff;\r
+    data[2200]=(char)0xffff;\r
+    data[2201]=(char)0xffff;\r
+    data[2202]=(char)0xffff;\r
+    data[2203]=(char)0xffff;\r
+    data[2204]=(char)0xffff;\r
+    data[2205]=(char)0xffff;\r
+    data[2206]=(char)0xffff;\r
+    data[2207]=(char)0xffff;\r
+    data[2208]=(char)0xffff;\r
+    data[2209]=(char)0xffff;\r
+    data[2210]=(char)0xffff;\r
+    data[2211]=(char)0xffff;\r
+    data[2212]=(char)0xffff;\r
+    data[2213]=(char)0xffff;\r
+    data[2214]=(char)0xffff;\r
+    data[2215]=(char)0xffff;\r
+    data[2216]=(char)0xffff;\r
+    data[2217]=(char)0xffff;\r
+    data[2218]=(char)0xffff;\r
+    data[2219]=(char)0xffff;\r
+    data[2220]=(char)0xffff;\r
+    data[2221]=(char)0xffff;\r
+    data[2222]=(char)0xffff;\r
+    data[2223]=(char)0xffff;\r
+    data[2224]=(char)0xffff;\r
+    data[2225]=(char)0xffff;\r
+    data[2226]=(char)0xffff;\r
+    data[2227]=(char)0xffff;\r
+    data[2228]=(char)0xffff;\r
+    data[2229]=(char)0xffff;\r
+    data[2230]=(char)0xffff;\r
+    data[2231]=(char)0xffff;\r
+    data[2232]=(char)0xffff;\r
+    data[2233]=(char)0xffff;\r
+    data[2234]=(char)0xffff;\r
+    data[2235]=(char)0xffff;\r
+    data[2236]=(char)0xffff;\r
+    data[2237]=(char)0xffff;\r
+    data[2238]=(char)0xffff;\r
+    data[2239]=(char)0xffff;\r
+    data[2240]=(char)0xffff;\r
+    data[2241]=(char)0xffff;\r
+    data[2242]=(char)0xffff;\r
+    data[2243]=(char)0xffff;\r
+    data[2244]=(char)0xffff;\r
+    data[2245]=(char)0xffff;\r
+    data[2246]=(char)0xffff;\r
+    data[2247]=(char)0xffff;\r
+    data[2248]=(char)0xffff;\r
+    data[2249]=(char)0xffff;\r
+    data[2250]=(char)0xffff;\r
+    data[2251]=(char)0xffff;\r
+    data[2252]=(char)0xffff;\r
+    data[2253]=(char)0xffff;\r
+    data[2254]=(char)0xffff;\r
+    data[2255]=(char)0xffff;\r
+    data[2256]=(char)0xffff;\r
+    data[2257]=(char)0xffff;\r
+    data[2258]=(char)0xffff;\r
+    data[2259]=(char)0xffff;\r
+    data[2260]=(char)0xffff;\r
+    data[2261]=(char)0xffff;\r
+    data[2262]=(char)0xffff;\r
+    data[2263]=(char)0xffff;\r
+    data[2264]=(char)0xffff;\r
+    data[2265]=(char)0xffff;\r
+    data[2266]=(char)0xffff;\r
+    data[2267]=(char)0xffff;\r
+    data[2268]=(char)0xffff;\r
+    data[2269]=(char)0xffff;\r
+    data[2270]=(char)0xffff;\r
+    data[2271]=(char)0xffff;\r
+    data[2272]=(char)0xffff;\r
+    data[2273]=(char)0xffff;\r
+    data[2274]=(char)0xffff;\r
+    data[2275]=(char)0xffff;\r
+    data[2276]=(char)0xffff;\r
+    data[2277]=(char)0xffff;\r
+    data[2278]=(char)0xffff;\r
+    data[2279]=(char)0xffff;\r
+    data[2280]=(char)0xffff;\r
+    data[2281]=(char)0xffff;\r
+    data[2282]=(char)0xffff;\r
+    data[2283]=(char)0xffff;\r
+    data[2284]=(char)0xffff;\r
+    data[2285]=(char)0xffff;\r
+    data[2286]=(char)0xffff;\r
+    data[2287]=(char)0xffff;\r
+    data[2288]=(char)0xffff;\r
+    data[2289]=(char)0xffff;\r
+    data[2290]=(char)0xffff;\r
+    data[2291]=(char)0xffff;\r
+    data[2292]=(char)0xffff;\r
+    data[2293]=(char)0xffff;\r
+    data[2294]=(char)0xffff;\r
+    data[2295]=(char)0xffff;\r
+    data[2296]=(char)0xffff;\r
+    data[2297]=(char)0xffff;\r
+    data[2298]=(char)0xffff;\r
+    data[2299]=(char)0xffff;\r
+    data[2300]=(char)0xffff;\r
+    data[2301]=(char)0xffff;\r
+    data[2302]=(char)0xffff;\r
+    data[2303]=(char)0xffff;\r
+    data[2304]=(char)0xffff;\r
+    data[2305]=(char)0xffff;\r
+    data[2306]=(char)0xffff;\r
+    data[2307]=(char)0xffff;\r
+    data[2308]=(char)0xffff;\r
+    data[2309]=(char)0xffff;\r
+    data[2310]=(char)0xffff;\r
+    data[2311]=(char)0xffff;\r
+    data[2312]=(char)0xffff;\r
+    data[2313]=(char)0xffff;\r
+    data[2314]=(char)0xffff;\r
+    data[2315]=(char)0xffff;\r
+    data[2316]=(char)0xffff;\r
+    data[2317]=(char)0xffff;\r
+    data[2318]=(char)0xffff;\r
+    data[2319]=(char)0xffff;\r
+    data[2320]=(char)0xffff;\r
+    data[2321]=(char)0xffff;\r
+    data[2322]=(char)0xffff;\r
+    data[2323]=(char)0xffff;\r
+    data[2324]=(char)0xffff;\r
+    data[2325]=(char)0xffff;\r
+    data[2326]=(char)0xffff;\r
+    data[2327]=(char)0xffff;\r
+    data[2328]=(char)0xffff;\r
+    data[2329]=(char)0xffff;\r
+    data[2330]=(char)0xffff;\r
+    data[2331]=(char)0xffff;\r
+    data[2332]=(char)0xffff;\r
+    data[2333]=(char)0xffff;\r
+    data[2334]=(char)0xffff;\r
+    data[2335]=(char)0xffff;\r
+    data[2336]=(char)0xffff;\r
+    data[2337]=(char)0xffff;\r
+    data[2338]=(char)0xffff;\r
+    data[2339]=(char)0xffff;\r
+    data[2340]=(char)0xffff;\r
+    data[2341]=(char)0xffff;\r
+    data[2342]=(char)0xffff;\r
+    data[2343]=(char)0xffff;\r
+    data[2344]=(char)0xffff;\r
+    data[2345]=(char)0xffff;\r
+    data[2346]=(char)0xffff;\r
+    data[2347]=(char)0xffff;\r
+    data[2348]=(char)0xffff;\r
+    data[2349]=(char)0xffff;\r
+    data[2350]=(char)0xffff;\r
+    data[2351]=(char)0xffff;\r
+    data[2352]=(char)0xffff;\r
+    data[2353]=(char)0xffff;\r
+    data[2354]=(char)0xffff;\r
+    data[2355]=(char)0xffff;\r
+    data[2356]=(char)0xffff;\r
+    data[2357]=(char)0xffff;\r
+    data[2358]=(char)0xffff;\r
+    data[2359]=(char)0xffff;\r
+    data[2360]=(char)0xffff;\r
+    data[2361]=(char)0xffff;\r
+    data[2362]=(char)0xffff;\r
+    data[2363]=(char)0xffff;\r
+    data[2364]=(char)0xffff;\r
+    data[2365]=(char)0xffff;\r
+    data[2366]=(char)0xffff;\r
+    data[2367]=(char)0xffff;\r
+    data[2368]=(char)0xffff;\r
+    data[2369]=(char)0xffff;\r
+    data[2370]=(char)0xffff;\r
+    data[2371]=(char)0xffff;\r
+    data[2372]=(char)0xffff;\r
+    data[2373]=(char)0xffff;\r
+    data[2374]=(char)0xffff;\r
+    data[2375]=(char)0xffff;\r
+    data[2376]=(char)0xffff;\r
+    data[2377]=(char)0xffff;\r
+    data[2378]=(char)0xffff;\r
+    data[2379]=(char)0xffff;\r
+    data[2380]=(char)0xffff;\r
+    data[2381]=(char)0xffff;\r
+    data[2382]=(char)0xffff;\r
+    data[2383]=(char)0xffff;\r
+    data[2384]=(char)0xffff;\r
+    data[2385]=(char)0xffff;\r
+    data[2386]=(char)0xffff;\r
+    data[2387]=(char)0xffff;\r
+    data[2388]=(char)0xffff;\r
+    data[2389]=(char)0xffff;\r
+    data[2390]=(char)0xffff;\r
+    data[2391]=(char)0xffff;\r
+    data[2392]=(char)0xffff;\r
+    data[2393]=(char)0xffff;\r
+    data[2394]=(char)0xffff;\r
+    data[2395]=(char)0xffff;\r
+    data[2396]=(char)0xffff;\r
+    data[2397]=(char)0xffff;\r
+    data[2398]=(char)0xffff;\r
+    data[2399]=(char)0xffff;\r
+    data[2400]=(char)0xffff;\r
+    data[2401]=(char)0xffff;\r
+    data[2402]=(char)0xffff;\r
+    data[2403]=(char)0xffff;\r
+    data[2404]=(char)0xffff;\r
+    data[2405]=(char)0xffff;\r
+    data[2406]=(char)0xffff;\r
+    data[2407]=(char)0xffff;\r
+    data[2408]=(char)0xffff;\r
+    data[2409]=(char)0xffff;\r
+    data[2410]=(char)0xffff;\r
+    data[2411]=(char)0xffff;\r
+    data[2412]=(char)0xffff;\r
+    data[2413]=(char)0xffff;\r
+    data[2414]=(char)0xffff;\r
+    data[2415]=(char)0xffff;\r
+    data[2416]=(char)0xffff;\r
+    data[2417]=(char)0xffff;\r
+    data[2418]=(char)0xffff;\r
+    data[2419]=(char)0xffff;\r
+    data[2420]=(char)0xffff;\r
+    data[2421]=(char)0xffff;\r
+    data[2422]=(char)0xffff;\r
+    data[2423]=(char)0xffff;\r
+    data[2424]=(char)0xffff;\r
+    data[2425]=(char)0xffff;\r
+    data[2426]=(char)0xffff;\r
+    data[2427]=(char)0xffff;\r
+    data[2428]=(char)0xffff;\r
+    data[2429]=(char)0xffff;\r
+    data[2430]=(char)0xffff;\r
+    data[2431]=(char)0xffff;\r
+    data[2432]=(char)0xffff;\r
+    data[2433]=(char)0xffff;\r
+    data[2434]=(char)0xffff;\r
+    data[2435]=(char)0xffff;\r
+    data[2436]=(char)0xffff;\r
+    data[2437]=(char)0xffff;\r
+    data[2438]=(char)0xffff;\r
+    data[2439]=(char)0xffff;\r
+    data[2440]=(char)0xffff;\r
+    data[2441]=(char)0xffff;\r
+    data[2442]=(char)0xffff;\r
+    data[2443]=(char)0xffff;\r
+    data[2444]=(char)0xffff;\r
+    data[2445]=(char)0xffff;\r
+    data[2446]=(char)0xffff;\r
+    data[2447]=(char)0xffff;\r
+    data[2448]=(char)0xffff;\r
+    data[2449]=(char)0xffff;\r
+    data[2450]=(char)0xffff;\r
+    data[2451]=(char)0xffff;\r
+    data[2452]=(char)0xffff;\r
+    data[2453]=(char)0xffff;\r
+    data[2454]=(char)0xffff;\r
+    data[2455]=(char)0xffff;\r
+    data[2456]=(char)0xffff;\r
+    data[2457]=(char)0xffff;\r
+    data[2458]=(char)0xffff;\r
+    data[2459]=(char)0xffff;\r
+    data[2460]=(char)0xffff;\r
+    data[2461]=(char)0xffff;\r
+    data[2462]=(char)0xffff;\r
+    data[2463]=(char)0xffff;\r
+    data[2464]=(char)0xffff;\r
+    data[2465]=(char)0xffff;\r
+    data[2466]=(char)0xffff;\r
+    data[2467]=(char)0xffff;\r
+    data[2468]=(char)0xffff;\r
+    data[2469]=(char)0xffff;\r
+    data[2470]=(char)0xffff;\r
+    data[2471]=(char)0xffff;\r
+    data[2472]=(char)0xffff;\r
+    data[2473]=(char)0xffff;\r
+    data[2474]=(char)0xffff;\r
+    data[2475]=(char)0xffff;\r
+    data[2476]=(char)0xffff;\r
+    data[2477]=(char)0xffff;\r
+    data[2478]=(char)0xffff;\r
+    data[2479]=(char)0xffff;\r
+    data[2480]=(char)0xffff;\r
+    data[2481]=(char)0xffff;\r
+    data[2482]=(char)0xffff;\r
+    data[2483]=(char)0xffff;\r
+    data[2484]=(char)0xffff;\r
+    data[2485]=(char)0xffff;\r
+    data[2486]=(char)0xffff;\r
+    data[2487]=(char)0xffff;\r
+    data[2488]=(char)0xffff;\r
+    data[2489]=(char)0xffff;\r
+    data[2490]=(char)0xffff;\r
+    data[2491]=(char)0xffff;\r
+    data[2492]=(char)0xffff;\r
+    data[2493]=(char)0xffff;\r
+    data[2494]=(char)0xffff;\r
+    data[2495]=(char)0xffff;\r
+    data[2496]=(char)0xffff;\r
+    data[2497]=(char)0xffff;\r
+    data[2498]=(char)0xffff;\r
+    data[2499]=(char)0xffff;\r
+    data[2500]=(char)0xffff;\r
+    data[2501]=(char)0xffff;\r
+    data[2502]=(char)0xffff;\r
+    data[2503]=(char)0xffff;\r
+    data[2504]=(char)0xffff;\r
+    data[2505]=(char)0xffff;\r
+    data[2506]=(char)0xffff;\r
+    data[2507]=(char)0xffff;\r
+    data[2508]=(char)0xffff;\r
+    data[2509]=(char)0xffff;\r
+    data[2510]=(char)0xffff;\r
+    data[2511]=(char)0xffff;\r
+    data[2512]=(char)0xffff;\r
+    data[2513]=(char)0xffff;\r
+    data[2514]=(char)0xffff;\r
+    data[2515]=(char)0xffff;\r
+    data[2516]=(char)0xffff;\r
+    data[2517]=(char)0xffff;\r
+    data[2518]=(char)0xffff;\r
+    data[2519]=(char)0xffff;\r
+    data[2520]=(char)0xffff;\r
+    data[2521]=(char)0xffff;\r
+    data[2522]=(char)0xffff;\r
+    data[2523]=(char)0xffff;\r
+    data[2524]=(char)0xffff;\r
+    data[2525]=(char)0xffff;\r
+    data[2526]=(char)0xffff;\r
+    data[2527]=(char)0xffff;\r
+    data[2528]=(char)0xffff;\r
+    data[2529]=(char)0xffff;\r
+    data[2530]=(char)0xffff;\r
+    data[2531]=(char)0xffff;\r
+    data[2532]=(char)0xffff;\r
+    data[2533]=(char)0xffff;\r
+    data[2534]=(char)0xffff;\r
+    data[2535]=(char)0xffff;\r
+    data[2536]=(char)0xffff;\r
+    data[2537]=(char)0xffff;\r
+    data[2538]=(char)0xffff;\r
+    data[2539]=(char)0xffff;\r
+    data[2540]=(char)0xffff;\r
+    data[2541]=(char)0xffff;\r
+    data[2542]=(char)0xffff;\r
+    data[2543]=(char)0xffff;\r
+    data[2544]=(char)0xffff;\r
+    data[2545]=(char)0xffff;\r
+    data[2546]=(char)0xffff;\r
+    data[2547]=(char)0xffff;\r
+    data[2548]=(char)0xffff;\r
+    data[2549]=(char)0xffff;\r
+    data[2550]=(char)0xffff;\r
+    data[2551]=(char)0xffff;\r
+    data[2552]=(char)0xffff;\r
+    data[2553]=(char)0xffff;\r
+    data[2554]=(char)0x003f;\r
+    data[2752]=(char)0xffff;\r
+    data[2753]=(char)0xffff;\r
+    data[2754]=(char)0xffff;\r
+    data[2755]=(char)0xffff;\r
+    data[2756]=(char)0xffff;\r
+    data[2757]=(char)0xffff;\r
+    data[2758]=(char)0xffff;\r
+    data[2759]=(char)0xffff;\r
+    data[2760]=(char)0xffff;\r
+    data[2761]=(char)0xffff;\r
+    data[2762]=(char)0xffff;\r
+    data[2763]=(char)0xffff;\r
+    data[2764]=(char)0xffff;\r
+    data[2765]=(char)0xffff;\r
+    data[2766]=(char)0xffff;\r
+    data[2767]=(char)0xffff;\r
+    data[2768]=(char)0xffff;\r
+    data[2769]=(char)0xffff;\r
+    data[2770]=(char)0xffff;\r
+    data[2771]=(char)0xffff;\r
+    data[2772]=(char)0xffff;\r
+    data[2773]=(char)0xffff;\r
+    data[2774]=(char)0xffff;\r
+    data[2775]=(char)0xffff;\r
+    data[2776]=(char)0xffff;\r
+    data[2777]=(char)0xffff;\r
+    data[2778]=(char)0xffff;\r
+    data[2779]=(char)0xffff;\r
+    data[2780]=(char)0xffff;\r
+    data[2781]=(char)0xffff;\r
+    data[2782]=(char)0xffff;\r
+    data[2783]=(char)0xffff;\r
+    data[2784]=(char)0xffff;\r
+    data[2785]=(char)0xffff;\r
+    data[2786]=(char)0xffff;\r
+    data[2787]=(char)0xffff;\r
+    data[2788]=(char)0xffff;\r
+    data[2789]=(char)0xffff;\r
+    data[2790]=(char)0xffff;\r
+    data[2791]=(char)0xffff;\r
+    data[2792]=(char)0xffff;\r
+    data[2793]=(char)0xffff;\r
+    data[2794]=(char)0xffff;\r
+    data[2795]=(char)0xffff;\r
+    data[2796]=(char)0xffff;\r
+    data[2797]=(char)0xffff;\r
+    data[2798]=(char)0xffff;\r
+    data[2799]=(char)0xffff;\r
+    data[2800]=(char)0xffff;\r
+    data[2801]=(char)0xffff;\r
+    data[2802]=(char)0xffff;\r
+    data[2803]=(char)0xffff;\r
+    data[2804]=(char)0xffff;\r
+    data[2805]=(char)0xffff;\r
+    data[2806]=(char)0xffff;\r
+    data[2807]=(char)0xffff;\r
+    data[2808]=(char)0xffff;\r
+    data[2809]=(char)0xffff;\r
+    data[2810]=(char)0xffff;\r
+    data[2811]=(char)0xffff;\r
+    data[2812]=(char)0xffff;\r
+    data[2813]=(char)0xffff;\r
+    data[2814]=(char)0xffff;\r
+    data[2815]=(char)0xffff;\r
+    data[2816]=(char)0xffff;\r
+    data[2817]=(char)0xffff;\r
+    data[2818]=(char)0xffff;\r
+    data[2819]=(char)0xffff;\r
+    data[2820]=(char)0xffff;\r
+    data[2821]=(char)0xffff;\r
+    data[2822]=(char)0xffff;\r
+    data[2823]=(char)0xffff;\r
+    data[2824]=(char)0xffff;\r
+    data[2825]=(char)0xffff;\r
+    data[2826]=(char)0xffff;\r
+    data[2827]=(char)0xffff;\r
+    data[2828]=(char)0xffff;\r
+    data[2829]=(char)0xffff;\r
+    data[2830]=(char)0xffff;\r
+    data[2831]=(char)0xffff;\r
+    data[2832]=(char)0xffff;\r
+    data[2833]=(char)0xffff;\r
+    data[2834]=(char)0xffff;\r
+    data[2835]=(char)0xffff;\r
+    data[2836]=(char)0xffff;\r
+    data[2837]=(char)0xffff;\r
+    data[2838]=(char)0xffff;\r
+    data[2839]=(char)0xffff;\r
+    data[2840]=(char)0xffff;\r
+    data[2841]=(char)0xffff;\r
+    data[2842]=(char)0xffff;\r
+    data[2843]=(char)0xffff;\r
+    data[2844]=(char)0xffff;\r
+    data[2845]=(char)0xffff;\r
+    data[2846]=(char)0xffff;\r
+    data[2847]=(char)0xffff;\r
+    data[2848]=(char)0xffff;\r
+    data[2849]=(char)0xffff;\r
+    data[2850]=(char)0xffff;\r
+    data[2851]=(char)0xffff;\r
+    data[2852]=(char)0xffff;\r
+    data[2853]=(char)0xffff;\r
+    data[2854]=(char)0xffff;\r
+    data[2855]=(char)0xffff;\r
+    data[2856]=(char)0xffff;\r
+    data[2857]=(char)0xffff;\r
+    data[2858]=(char)0xffff;\r
+    data[2859]=(char)0xffff;\r
+    data[2860]=(char)0xffff;\r
+    data[2861]=(char)0xffff;\r
+    data[2862]=(char)0xffff;\r
+    data[2863]=(char)0xffff;\r
+    data[2864]=(char)0xffff;\r
+    data[2865]=(char)0xffff;\r
+    data[2866]=(char)0xffff;\r
+    data[2867]=(char)0xffff;\r
+    data[2868]=(char)0xffff;\r
+    data[2869]=(char)0xffff;\r
+    data[2870]=(char)0xffff;\r
+    data[2871]=(char)0xffff;\r
+    data[2872]=(char)0xffff;\r
+    data[2873]=(char)0xffff;\r
+    data[2874]=(char)0xffff;\r
+    data[2875]=(char)0xffff;\r
+    data[2876]=(char)0xffff;\r
+    data[2877]=(char)0xffff;\r
+    data[2878]=(char)0xffff;\r
+    data[2879]=(char)0xffff;\r
+    data[2880]=(char)0xffff;\r
+    data[2881]=(char)0xffff;\r
+    data[2882]=(char)0xffff;\r
+    data[2883]=(char)0xffff;\r
+    data[2884]=(char)0xffff;\r
+    data[2885]=(char)0xffff;\r
+    data[2886]=(char)0xffff;\r
+    data[2887]=(char)0xffff;\r
+    data[2888]=(char)0xffff;\r
+    data[2889]=(char)0xffff;\r
+    data[2890]=(char)0xffff;\r
+    data[2891]=(char)0xffff;\r
+    data[2892]=(char)0xffff;\r
+    data[2893]=(char)0xffff;\r
+    data[2894]=(char)0xffff;\r
+    data[2895]=(char)0xffff;\r
+    data[2896]=(char)0xffff;\r
+    data[2897]=(char)0xffff;\r
+    data[2898]=(char)0xffff;\r
+    data[2899]=(char)0xffff;\r
+    data[2900]=(char)0xffff;\r
+    data[2901]=(char)0xffff;\r
+    data[2902]=(char)0xffff;\r
+    data[2903]=(char)0xffff;\r
+    data[2904]=(char)0xffff;\r
+    data[2905]=(char)0xffff;\r
+    data[2906]=(char)0xffff;\r
+    data[2907]=(char)0xffff;\r
+    data[2908]=(char)0xffff;\r
+    data[2909]=(char)0xffff;\r
+    data[2910]=(char)0xffff;\r
+    data[2911]=(char)0xffff;\r
+    data[2912]=(char)0xffff;\r
+    data[2913]=(char)0xffff;\r
+    data[2914]=(char)0xffff;\r
+    data[2915]=(char)0xffff;\r
+    data[2916]=(char)0xffff;\r
+    data[2917]=(char)0xffff;\r
+    data[2918]=(char)0xffff;\r
+    data[2919]=(char)0xffff;\r
+    data[2920]=(char)0xffff;\r
+    data[2921]=(char)0xffff;\r
+    data[2922]=(char)0xffff;\r
+    data[2923]=(char)0xffff;\r
+    data[2924]=(char)0xffff;\r
+    data[2925]=(char)0xffff;\r
+    data[2926]=(char)0xffff;\r
+    data[2927]=(char)0xffff;\r
+    data[2928]=(char)0xffff;\r
+    data[2929]=(char)0xffff;\r
+    data[2930]=(char)0xffff;\r
+    data[2931]=(char)0xffff;\r
+    data[2932]=(char)0xffff;\r
+    data[2933]=(char)0xffff;\r
+    data[2934]=(char)0xffff;\r
+    data[2935]=(char)0xffff;\r
+    data[2936]=(char)0xffff;\r
+    data[2937]=(char)0xffff;\r
+    data[2938]=(char)0xffff;\r
+    data[2939]=(char)0xffff;\r
+    data[2940]=(char)0xffff;\r
+    data[2941]=(char)0xffff;\r
+    data[2942]=(char)0xffff;\r
+    data[2943]=(char)0xffff;\r
+    data[2944]=(char)0xffff;\r
+    data[2945]=(char)0xffff;\r
+    data[2946]=(char)0xffff;\r
+    data[2947]=(char)0xffff;\r
+    data[2948]=(char)0xffff;\r
+    data[2949]=(char)0xffff;\r
+    data[2950]=(char)0xffff;\r
+    data[2951]=(char)0xffff;\r
+    data[2952]=(char)0xffff;\r
+    data[2953]=(char)0xffff;\r
+    data[2954]=(char)0xffff;\r
+    data[2955]=(char)0xffff;\r
+    data[2956]=(char)0xffff;\r
+    data[2957]=(char)0xffff;\r
+    data[2958]=(char)0xffff;\r
+    data[2959]=(char)0xffff;\r
+    data[2960]=(char)0xffff;\r
+    data[2961]=(char)0xffff;\r
+    data[2962]=(char)0xffff;\r
+    data[2963]=(char)0xffff;\r
+    data[2964]=(char)0xffff;\r
+    data[2965]=(char)0xffff;\r
+    data[2966]=(char)0xffff;\r
+    data[2967]=(char)0xffff;\r
+    data[2968]=(char)0xffff;\r
+    data[2969]=(char)0xffff;\r
+    data[2970]=(char)0xffff;\r
+    data[2971]=(char)0xffff;\r
+    data[2972]=(char)0xffff;\r
+    data[2973]=(char)0xffff;\r
+    data[2974]=(char)0xffff;\r
+    data[2975]=(char)0xffff;\r
+    data[2976]=(char)0xffff;\r
+    data[2977]=(char)0xffff;\r
+    data[2978]=(char)0xffff;\r
+    data[2979]=(char)0xffff;\r
+    data[2980]=(char)0xffff;\r
+    data[2981]=(char)0xffff;\r
+    data[2982]=(char)0xffff;\r
+    data[2983]=(char)0xffff;\r
+    data[2984]=(char)0xffff;\r
+    data[2985]=(char)0xffff;\r
+    data[2986]=(char)0xffff;\r
+    data[2987]=(char)0xffff;\r
+    data[2988]=(char)0xffff;\r
+    data[2989]=(char)0xffff;\r
+    data[2990]=(char)0xffff;\r
+    data[2991]=(char)0xffff;\r
+    data[2992]=(char)0xffff;\r
+    data[2993]=(char)0xffff;\r
+    data[2994]=(char)0xffff;\r
+    data[2995]=(char)0xffff;\r
+    data[2996]=(char)0xffff;\r
+    data[2997]=(char)0xffff;\r
+    data[2998]=(char)0xffff;\r
+    data[2999]=(char)0xffff;\r
+    data[3000]=(char)0xffff;\r
+    data[3001]=(char)0xffff;\r
+    data[3002]=(char)0xffff;\r
+    data[3003]=(char)0xffff;\r
+    data[3004]=(char)0xffff;\r
+    data[3005]=(char)0xffff;\r
+    data[3006]=(char)0xffff;\r
+    data[3007]=(char)0xffff;\r
+    data[3008]=(char)0xffff;\r
+    data[3009]=(char)0xffff;\r
+    data[3010]=(char)0xffff;\r
+    data[3011]=(char)0xffff;\r
+    data[3012]=(char)0xffff;\r
+    data[3013]=(char)0xffff;\r
+    data[3014]=(char)0xffff;\r
+    data[3015]=(char)0xffff;\r
+    data[3016]=(char)0xffff;\r
+    data[3017]=(char)0xffff;\r
+    data[3018]=(char)0xffff;\r
+    data[3019]=(char)0xffff;\r
+    data[3020]=(char)0xffff;\r
+    data[3021]=(char)0xffff;\r
+    data[3022]=(char)0xffff;\r
+    data[3023]=(char)0xffff;\r
+    data[3024]=(char)0xffff;\r
+    data[3025]=(char)0xffff;\r
+    data[3026]=(char)0xffff;\r
+    data[3027]=(char)0xffff;\r
+    data[3028]=(char)0xffff;\r
+    data[3029]=(char)0xffff;\r
+    data[3030]=(char)0xffff;\r
+    data[3031]=(char)0xffff;\r
+    data[3032]=(char)0xffff;\r
+    data[3033]=(char)0xffff;\r
+    data[3034]=(char)0xffff;\r
+    data[3035]=(char)0xffff;\r
+    data[3036]=(char)0xffff;\r
+    data[3037]=(char)0xffff;\r
+    data[3038]=(char)0xffff;\r
+    data[3039]=(char)0xffff;\r
+    data[3040]=(char)0xffff;\r
+    data[3041]=(char)0xffff;\r
+    data[3042]=(char)0xffff;\r
+    data[3043]=(char)0xffff;\r
+    data[3044]=(char)0xffff;\r
+    data[3045]=(char)0xffff;\r
+    data[3046]=(char)0xffff;\r
+    data[3047]=(char)0xffff;\r
+    data[3048]=(char)0xffff;\r
+    data[3049]=(char)0xffff;\r
+    data[3050]=(char)0xffff;\r
+    data[3051]=(char)0xffff;\r
+    data[3052]=(char)0xffff;\r
+    data[3053]=(char)0xffff;\r
+    data[3054]=(char)0xffff;\r
+    data[3055]=(char)0xffff;\r
+    data[3056]=(char)0xffff;\r
+    data[3057]=(char)0xffff;\r
+    data[3058]=(char)0xffff;\r
+    data[3059]=(char)0xffff;\r
+    data[3060]=(char)0xffff;\r
+    data[3061]=(char)0xffff;\r
+    data[3062]=(char)0xffff;\r
+    data[3063]=(char)0xffff;\r
+    data[3064]=(char)0xffff;\r
+    data[3065]=(char)0xffff;\r
+    data[3066]=(char)0xffff;\r
+    data[3067]=(char)0xffff;\r
+    data[3068]=(char)0xffff;\r
+    data[3069]=(char)0xffff;\r
+    data[3070]=(char)0xffff;\r
+    data[3071]=(char)0xffff;\r
+    data[3072]=(char)0xffff;\r
+    data[3073]=(char)0xffff;\r
+    data[3074]=(char)0xffff;\r
+    data[3075]=(char)0xffff;\r
+    data[3076]=(char)0xffff;\r
+    data[3077]=(char)0xffff;\r
+    data[3078]=(char)0xffff;\r
+    data[3079]=(char)0xffff;\r
+    data[3080]=(char)0xffff;\r
+    data[3081]=(char)0xffff;\r
+    data[3082]=(char)0xffff;\r
+    data[3083]=(char)0xffff;\r
+    data[3084]=(char)0xffff;\r
+    data[3085]=(char)0xffff;\r
+    data[3086]=(char)0xffff;\r
+    data[3087]=(char)0xffff;\r
+    data[3088]=(char)0xffff;\r
+    data[3089]=(char)0xffff;\r
+    data[3090]=(char)0xffff;\r
+    data[3091]=(char)0xffff;\r
+    data[3092]=(char)0xffff;\r
+    data[3093]=(char)0xffff;\r
+    data[3094]=(char)0xffff;\r
+    data[3095]=(char)0xffff;\r
+    data[3096]=(char)0xffff;\r
+    data[3097]=(char)0xffff;\r
+    data[3098]=(char)0xffff;\r
+    data[3099]=(char)0xffff;\r
+    data[3100]=(char)0xffff;\r
+    data[3101]=(char)0xffff;\r
+    data[3102]=(char)0xffff;\r
+    data[3103]=(char)0xffff;\r
+    data[3104]=(char)0xffff;\r
+    data[3105]=(char)0xffff;\r
+    data[3106]=(char)0xffff;\r
+    data[3107]=(char)0xffff;\r
+    data[3108]=(char)0xffff;\r
+    data[3109]=(char)0xffff;\r
+    data[3110]=(char)0xffff;\r
+    data[3111]=(char)0xffff;\r
+    data[3112]=(char)0xffff;\r
+    data[3113]=(char)0xffff;\r
+    data[3114]=(char)0xffff;\r
+    data[3115]=(char)0xffff;\r
+    data[3116]=(char)0xffff;\r
+    data[3117]=(char)0xffff;\r
+    data[3118]=(char)0xffff;\r
+    data[3119]=(char)0xffff;\r
+    data[3120]=(char)0xffff;\r
+    data[3121]=(char)0xffff;\r
+    data[3122]=(char)0xffff;\r
+    data[3123]=(char)0xffff;\r
+    data[3124]=(char)0xffff;\r
+    data[3125]=(char)0xffff;\r
+    data[3126]=(char)0xffff;\r
+    data[3127]=(char)0xffff;\r
+    data[3128]=(char)0xffff;\r
+    data[3129]=(char)0xffff;\r
+    data[3130]=(char)0xffff;\r
+    data[3131]=(char)0xffff;\r
+    data[3132]=(char)0xffff;\r
+    data[3133]=(char)0xffff;\r
+    data[3134]=(char)0xffff;\r
+    data[3135]=(char)0xffff;\r
+    data[3136]=(char)0xffff;\r
+    data[3137]=(char)0xffff;\r
+    data[3138]=(char)0xffff;\r
+    data[3139]=(char)0xffff;\r
+    data[3140]=(char)0xffff;\r
+    data[3141]=(char)0xffff;\r
+    data[3142]=(char)0xffff;\r
+    data[3143]=(char)0xffff;\r
+    data[3144]=(char)0xffff;\r
+    data[3145]=(char)0xffff;\r
+    data[3146]=(char)0xffff;\r
+    data[3147]=(char)0xffff;\r
+    data[3148]=(char)0xffff;\r
+    data[3149]=(char)0xffff;\r
+    data[3150]=(char)0xffff;\r
+    data[3151]=(char)0xffff;\r
+    data[3152]=(char)0xffff;\r
+    data[3153]=(char)0xffff;\r
+    data[3154]=(char)0xffff;\r
+    data[3155]=(char)0xffff;\r
+    data[3156]=(char)0xffff;\r
+    data[3157]=(char)0xffff;\r
+    data[3158]=(char)0xffff;\r
+    data[3159]=(char)0xffff;\r
+    data[3160]=(char)0xffff;\r
+    data[3161]=(char)0xffff;\r
+    data[3162]=(char)0xffff;\r
+    data[3163]=(char)0xffff;\r
+    data[3164]=(char)0xffff;\r
+    data[3165]=(char)0xffff;\r
+    data[3166]=(char)0xffff;\r
+    data[3167]=(char)0xffff;\r
+    data[3168]=(char)0xffff;\r
+    data[3169]=(char)0xffff;\r
+    data[3170]=(char)0xffff;\r
+    data[3171]=(char)0xffff;\r
+    data[3172]=(char)0xffff;\r
+    data[3173]=(char)0xffff;\r
+    data[3174]=(char)0xffff;\r
+    data[3175]=(char)0xffff;\r
+    data[3176]=(char)0xffff;\r
+    data[3177]=(char)0xffff;\r
+    data[3178]=(char)0xffff;\r
+    data[3179]=(char)0xffff;\r
+    data[3180]=(char)0xffff;\r
+    data[3181]=(char)0xffff;\r
+    data[3182]=(char)0xffff;\r
+    data[3183]=(char)0xffff;\r
+    data[3184]=(char)0xffff;\r
+    data[3185]=(char)0xffff;\r
+    data[3186]=(char)0xffff;\r
+    data[3187]=(char)0xffff;\r
+    data[3188]=(char)0xffff;\r
+    data[3189]=(char)0xffff;\r
+    data[3190]=(char)0xffff;\r
+    data[3191]=(char)0xffff;\r
+    data[3192]=(char)0xffff;\r
+    data[3193]=(char)0xffff;\r
+    data[3194]=(char)0xffff;\r
+    data[3195]=(char)0xffff;\r
+    data[3196]=(char)0xffff;\r
+    data[3197]=(char)0xffff;\r
+    data[3198]=(char)0xffff;\r
+    data[3199]=(char)0xffff;\r
+    data[3200]=(char)0xffff;\r
+    data[3201]=(char)0xffff;\r
+    data[3202]=(char)0xffff;\r
+    data[3203]=(char)0xffff;\r
+    data[3204]=(char)0xffff;\r
+    data[3205]=(char)0xffff;\r
+    data[3206]=(char)0xffff;\r
+    data[3207]=(char)0xffff;\r
+    data[3208]=(char)0xffff;\r
+    data[3209]=(char)0xffff;\r
+    data[3210]=(char)0xffff;\r
+    data[3211]=(char)0xffff;\r
+    data[3212]=(char)0xffff;\r
+    data[3213]=(char)0xffff;\r
+    data[3214]=(char)0xffff;\r
+    data[3215]=(char)0xffff;\r
+    data[3216]=(char)0xffff;\r
+    data[3217]=(char)0xffff;\r
+    data[3218]=(char)0xffff;\r
+    data[3219]=(char)0xffff;\r
+    data[3220]=(char)0xffff;\r
+    data[3221]=(char)0xffff;\r
+    data[3222]=(char)0xffff;\r
+    data[3223]=(char)0xffff;\r
+    data[3224]=(char)0xffff;\r
+    data[3225]=(char)0xffff;\r
+    data[3226]=(char)0xffff;\r
+    data[3227]=(char)0xffff;\r
+    data[3228]=(char)0xffff;\r
+    data[3229]=(char)0xffff;\r
+    data[3230]=(char)0xffff;\r
+    data[3231]=(char)0xffff;\r
+    data[3232]=(char)0xffff;\r
+    data[3233]=(char)0xffff;\r
+    data[3234]=(char)0xffff;\r
+    data[3235]=(char)0xffff;\r
+    data[3236]=(char)0xffff;\r
+    data[3237]=(char)0xffff;\r
+    data[3238]=(char)0xffff;\r
+    data[3239]=(char)0xffff;\r
+    data[3240]=(char)0xffff;\r
+    data[3241]=(char)0xffff;\r
+    data[3242]=(char)0xffff;\r
+    data[3243]=(char)0xffff;\r
+    data[3244]=(char)0xffff;\r
+    data[3245]=(char)0xffff;\r
+    data[3246]=(char)0xffff;\r
+    data[3247]=(char)0xffff;\r
+    data[3248]=(char)0xffff;\r
+    data[3249]=(char)0xffff;\r
+    data[3250]=(char)0xffff;\r
+    data[3251]=(char)0xffff;\r
+    data[3252]=(char)0xffff;\r
+    data[3253]=(char)0xffff;\r
+    data[3254]=(char)0xffff;\r
+    data[3255]=(char)0xffff;\r
+    data[3256]=(char)0xffff;\r
+    data[3257]=(char)0xffff;\r
+    data[3258]=(char)0xffff;\r
+    data[3259]=(char)0xffff;\r
+    data[3260]=(char)0xffff;\r
+    data[3261]=(char)0xffff;\r
+    data[3262]=(char)0xffff;\r
+    data[3263]=(char)0xffff;\r
+    data[3264]=(char)0xffff;\r
+    data[3265]=(char)0xffff;\r
+    data[3266]=(char)0xffff;\r
+    data[3267]=(char)0xffff;\r
+    data[3268]=(char)0xffff;\r
+    data[3269]=(char)0xffff;\r
+    data[3270]=(char)0xffff;\r
+    data[3271]=(char)0xffff;\r
+    data[3272]=(char)0xffff;\r
+    data[3273]=(char)0xffff;\r
+    data[3274]=(char)0xffff;\r
+    data[3275]=(char)0xffff;\r
+    data[3276]=(char)0xffff;\r
+    data[3277]=(char)0xffff;\r
+    data[3278]=(char)0xffff;\r
+    data[3279]=(char)0xffff;\r
+    data[3280]=(char)0xffff;\r
+    data[3281]=(char)0xffff;\r
+    data[3282]=(char)0xffff;\r
+    data[3283]=(char)0xffff;\r
+    data[3284]=(char)0xffff;\r
+    data[3285]=(char)0xffff;\r
+    data[3286]=(char)0xffff;\r
+    data[3287]=(char)0xffff;\r
+    data[3288]=(char)0xffff;\r
+    data[3289]=(char)0xffff;\r
+    data[3290]=(char)0xffff;\r
+    data[3291]=(char)0xffff;\r
+    data[3292]=(char)0xffff;\r
+    data[3293]=(char)0xffff;\r
+    data[3294]=(char)0xffff;\r
+    data[3295]=(char)0xffff;\r
+    data[3296]=(char)0xffff;\r
+    data[3297]=(char)0xffff;\r
+    data[3298]=(char)0xffff;\r
+    data[3299]=(char)0xffff;\r
+    data[3300]=(char)0xffff;\r
+    data[3301]=(char)0xffff;\r
+    data[3302]=(char)0xffff;\r
+    data[3303]=(char)0xffff;\r
+    data[3304]=(char)0xffff;\r
+    data[3305]=(char)0xffff;\r
+    data[3306]=(char)0xffff;\r
+    data[3307]=(char)0xffff;\r
+    data[3308]=(char)0xffff;\r
+    data[3309]=(char)0xffff;\r
+    data[3310]=(char)0xffff;\r
+    data[3311]=(char)0xffff;\r
+    data[3312]=(char)0xffff;\r
+    data[3313]=(char)0xffff;\r
+    data[3314]=(char)0xffff;\r
+    data[3315]=(char)0xffff;\r
+    data[3316]=(char)0xffff;\r
+    data[3317]=(char)0xffff;\r
+    data[3318]=(char)0xffff;\r
+    data[3319]=(char)0xffff;\r
+    data[3320]=(char)0xffff;\r
+    data[3321]=(char)0xffff;\r
+    data[3322]=(char)0xffff;\r
+    data[3323]=(char)0xffff;\r
+    data[3324]=(char)0xffff;\r
+    data[3325]=(char)0xffff;\r
+    data[3326]=(char)0xffff;\r
+    data[3327]=(char)0xffff;\r
+    data[3328]=(char)0xffff;\r
+    data[3329]=(char)0xffff;\r
+    data[3330]=(char)0xffff;\r
+    data[3331]=(char)0xffff;\r
+    data[3332]=(char)0xffff;\r
+    data[3333]=(char)0xffff;\r
+    data[3334]=(char)0xffff;\r
+    data[3335]=(char)0xffff;\r
+    data[3336]=(char)0xffff;\r
+    data[3337]=(char)0xffff;\r
+    data[3338]=(char)0xffff;\r
+    data[3339]=(char)0xffff;\r
+    data[3340]=(char)0xffff;\r
+    data[3341]=(char)0xffff;\r
+    data[3342]=(char)0xffff;\r
+    data[3343]=(char)0xffff;\r
+    data[3344]=(char)0xffff;\r
+    data[3345]=(char)0xffff;\r
+    data[3346]=(char)0xffff;\r
+    data[3347]=(char)0xffff;\r
+    data[3348]=(char)0xffff;\r
+    data[3349]=(char)0xffff;\r
+    data[3350]=(char)0xffff;\r
+    data[3351]=(char)0xffff;\r
+    data[3352]=(char)0xffff;\r
+    data[3353]=(char)0xffff;\r
+    data[3354]=(char)0xffff;\r
+    data[3355]=(char)0xffff;\r
+    data[3356]=(char)0xffff;\r
+    data[3357]=(char)0xffff;\r
+    data[3358]=(char)0xffff;\r
+    data[3359]=(char)0xffff;\r
+    data[3360]=(char)0xffff;\r
+    data[3361]=(char)0xffff;\r
+    data[3362]=(char)0xffff;\r
+    data[3363]=(char)0xffff;\r
+    data[3364]=(char)0xffff;\r
+    data[3365]=(char)0xffff;\r
+    data[3366]=(char)0xffff;\r
+    data[3367]=(char)0xffff;\r
+    data[3368]=(char)0xffff;\r
+    data[3369]=(char)0xffff;\r
+    data[3370]=(char)0xffff;\r
+    data[3371]=(char)0xffff;\r
+    data[3372]=(char)0xffff;\r
+    data[3373]=(char)0xffff;\r
+    data[3374]=(char)0xffff;\r
+    data[3375]=(char)0xffff;\r
+    data[3376]=(char)0xffff;\r
+    data[3377]=(char)0xffff;\r
+    data[3378]=(char)0xffff;\r
+    data[3379]=(char)0xffff;\r
+    data[3380]=(char)0xffff;\r
+    data[3381]=(char)0xffff;\r
+    data[3382]=(char)0xffff;\r
+    data[3383]=(char)0xffff;\r
+    data[3384]=(char)0xffff;\r
+    data[3385]=(char)0xffff;\r
+    data[3386]=(char)0xffff;\r
+    data[3387]=(char)0xffff;\r
+    data[3388]=(char)0xffff;\r
+    data[3389]=(char)0xffff;\r
+    data[3390]=(char)0xffff;\r
+    data[3391]=(char)0xffff;\r
+    data[3392]=(char)0xffff;\r
+    data[3393]=(char)0xffff;\r
+    data[3394]=(char)0xffff;\r
+    data[3395]=(char)0xffff;\r
+    data[3396]=(char)0xffff;\r
+    data[3397]=(char)0xffff;\r
+    data[3398]=(char)0xffff;\r
+    data[3399]=(char)0xffff;\r
+    data[3400]=(char)0xffff;\r
+    data[3401]=(char)0xffff;\r
+    data[3402]=(char)0xffff;\r
+    data[3403]=(char)0xffff;\r
+    data[3404]=(char)0xffff;\r
+    data[3405]=(char)0xffff;\r
+    data[3406]=(char)0xffff;\r
+    data[3407]=(char)0xffff;\r
+    data[3408]=(char)0xffff;\r
+    data[3409]=(char)0xffff;\r
+    data[3410]=(char)0xffff;\r
+    data[3411]=(char)0xffff;\r
+    data[3412]=(char)0xffff;\r
+    data[3413]=(char)0xffff;\r
+    data[3414]=(char)0xffff;\r
+    data[3415]=(char)0xffff;\r
+    data[3416]=(char)0xffff;\r
+    data[3417]=(char)0xffff;\r
+    data[3418]=(char)0xffff;\r
+    data[3419]=(char)0xffff;\r
+    data[3420]=(char)0xffff;\r
+    data[3421]=(char)0xffff;\r
+    data[3422]=(char)0xffff;\r
+    data[3423]=(char)0xffff;\r
+    data[3424]=(char)0xffff;\r
+    data[3425]=(char)0xffff;\r
+    data[3426]=(char)0xffff;\r
+    data[3427]=(char)0xffff;\r
+    data[3428]=(char)0xffff;\r
+    data[3429]=(char)0xffff;\r
+    data[3430]=(char)0xffff;\r
+    data[3431]=(char)0xffff;\r
+    data[3432]=(char)0xffff;\r
+    data[3433]=(char)0xffff;\r
+    data[3434]=(char)0xffff;\r
+    data[3435]=(char)0xffff;\r
+    data[3436]=(char)0xffff;\r
+    data[3437]=(char)0xffff;\r
+    data[3438]=(char)0xffff;\r
+    data[3439]=(char)0xffff;\r
+    data[3440]=(char)0xffff;\r
+    data[3441]=(char)0xffff;\r
+    data[3442]=(char)0xffff;\r
+    data[3443]=(char)0xffff;\r
+    data[3444]=(char)0xffff;\r
+    data[3445]=(char)0xffff;\r
+    data[3446]=(char)0xffff;\r
+    data[3447]=(char)0xffff;\r
+    data[3448]=(char)0xffff;\r
+    data[3449]=(char)0xffff;\r
+    data[3450]=(char)0x000f;\r
+    data[3984]=(char)0xffff;\r
+    data[3985]=(char)0xffff;\r
+    data[3986]=(char)0xffff;\r
+    data[3987]=(char)0xffff;\r
+    data[3988]=(char)0xffff;\r
+    data[3989]=(char)0xffff;\r
+    data[3990]=(char)0xffff;\r
+    data[3991]=(char)0xffff;\r
+    data[3992]=(char)0xffff;\r
+    data[3993]=(char)0xffff;\r
+    data[3994]=(char)0xffff;\r
+    data[3995]=(char)0xffff;\r
+    data[3996]=(char)0xffff;\r
+    data[3997]=(char)0xffff;\r
+    data[3998]=(char)0xffff;\r
+    data[3999]=(char)0xffff;\r
+    data[4000]=(char)0xffff;\r
+    data[4001]=(char)0xffff;\r
+    data[4002]=(char)0x3fff;\r
+    data[4016]=(char)0x007f;\r
+    data[4017]=(char)0x80f8;\r
+    data[4018]=(char)0xfdff;\r
+    data[4019]=(char)0x5f7f;\r
+    data[4020]=(char)0xffdb;\r
+    data[4021]=(char)0xffff;\r
+    data[4022]=(char)0xffff;\r
+    data[4023]=(char)0xffff;\r
+    data[4024]=(char)0xffff;\r
+    data[4025]=(char)0xffff;\r
+    data[4026]=(char)0xffff;\r
+    data[4027]=(char)0x0003;\r
+    data[4029]=(char)0xfff8;\r
+    data[4030]=(char)0xffff;\r
+    data[4031]=(char)0xffff;\r
+    data[4032]=(char)0xffff;\r
+    data[4033]=(char)0xffff;\r
+    data[4034]=(char)0xffff;\r
+    data[4035]=(char)0xffff;\r
+    data[4036]=(char)0xffff;\r
+    data[4037]=(char)0xffff;\r
+    data[4038]=(char)0xffff;\r
+    data[4039]=(char)0xffff;\r
+    data[4040]=(char)0xffff;\r
+    data[4041]=(char)0xffff;\r
+    data[4042]=(char)0xffff;\r
+    data[4043]=(char)0xffff;\r
+    data[4044]=(char)0xffff;\r
+    data[4045]=(char)0xffff;\r
+    data[4046]=(char)0xffff;\r
+    data[4047]=(char)0xffff;\r
+    data[4048]=(char)0xffff;\r
+    data[4049]=(char)0xffff;\r
+    data[4050]=(char)0xffff;\r
+    data[4051]=(char)0x3fff;\r
+    data[4053]=(char)0xffff;\r
+    data[4054]=(char)0xffff;\r
+    data[4055]=(char)0xffff;\r
+    data[4056]=(char)0xffff;\r
+    data[4057]=(char)0xfffc;\r
+    data[4058]=(char)0xffff;\r
+    data[4059]=(char)0xffff;\r
+    data[4060]=(char)0x00ff;\r
+    data[4063]=(char)0x0fff;\r
+    data[4071]=(char)0xffd7;\r
+    data[4072]=(char)0xffff;\r
+    data[4073]=(char)0xffff;\r
+    data[4074]=(char)0xffff;\r
+    data[4075]=(char)0xffff;\r
+    data[4076]=(char)0xffff;\r
+    data[4077]=(char)0xffff;\r
+    data[4078]=(char)0xffff;\r
+    data[4079]=(char)0x1fff;\r
+    data[4082]=(char)0xfffe;\r
+    data[4083]=(char)0x07ff;\r
+    data[4084]=(char)0xfffe;\r
+    data[4085]=(char)0x07ff;\r
+    data[4086]=(char)0xffc0;\r
+    data[4087]=(char)0xffff;\r
+    data[4088]=(char)0xffff;\r
+    data[4089]=(char)0xffff;\r
+    data[4090]=(char)0xffff;\r
+    data[4091]=(char)0x7fff;\r
+    data[4092]=(char)0xfcfc;\r
+    data[4093]=(char)0x1cfc;\r
+    data[4100]=(char)0xfffe;\r
+    data[4101]=(char)0x07ff;\r
+    data[4102]=(char)0xfffe;\r
+    data[4103]=(char)0x07ff;\r
+    data[4106]=(char)0x0400;\r
+    data[4107]=(char)0x0420;\r
+    data[4108]=(char)0xffff;\r
+    data[4109]=(char)0xff7f;\r
+    data[4110]=(char)0xffff;\r
+    data[4111]=(char)0xff7f;\r
+    data[4112]=(char)0xffff;\r
+    data[4113]=(char)0xffff;\r
+    data[4114]=(char)0xffff;\r
+    data[4115]=(char)0xffff;\r
+    data[4116]=(char)0xffff;\r
+    data[4117]=(char)0xffff;\r
+    data[4118]=(char)0xffff;\r
+    data[4119]=(char)0xffff;\r
+    data[4120]=(char)0xffff;\r
+    data[4121]=(char)0xffff;\r
+    data[4122]=(char)0xffff;\r
+    data[4123]=(char)0xffff;\r
+    data[4124]=(char)0xffff;\r
+    data[4125]=(char)0xffff;\r
+    data[4126]=(char)0xffff;\r
+    data[4127]=(char)0xfc3f;\r
+    data[4128]=(char)0xffff;\r
+    data[4129]=(char)0x00ff;\r
+    data[4133]=(char)0xffff;\r
+    data[4134]=(char)0xffff;\r
+    data[4135]=(char)0xffff;\r
+    data[4136]=(char)0xffff;\r
+    data[4137]=(char)0xffff;\r
+    data[4138]=(char)0x01ff;\r
+    data[4139]=(char)0xf9ff;\r
+    data[4140]=(char)0x0003;\r
+    data[4141]=(char)0x0003;\r
+    data[4142]=(char)0x001f;\r
+    data[4151]=(char)0x0400;\r
+    data[4152]=(char)0xd740;\r
+    data[4153]=(char)0xffff;\r
+    data[4154]=(char)0xfffb;\r
+    data[4155]=(char)0xffff;\r
+    data[4156]=(char)0x7fff;\r
+    data[4157]=(char)0x547f;\r
+    data[4158]=(char)0x00fd;\r
+\r
+  }\r
+  public static Bits white;\r
+  static void white_f() {\r
+    char[] data = new char[4159];\r
+    white = new Bits(data);\r
+    data[0]=(char)0x3e00;\r
+    data[1]=(char)0xf000;\r
+    data[2]=(char)0x0001;\r
+    data[512]=(char)0x0fff;\r
+    data[514]=(char)0x0300;\r
+    data[768]=(char)0x0001;\r
+    data[4096]=(char)0x3e00;\r
+    data[4097]=(char)0xf000;\r
+    data[4098]=(char)0x0001;\r
+\r
+  }\r
+  public static Bits punct;\r
+  static void punct_f() {\r
+    char[] data = new char[4159];\r
+    punct = new Bits(data);\r
+    data[2]=(char)0xf7ee;\r
+    data[3]=(char)0x8c00;\r
+    data[4]=(char)0x0001;\r
+    data[5]=(char)0xb800;\r
+    data[7]=(char)0x2800;\r
+    data[10]=(char)0x2802;\r
+    data[11]=(char)0x8880;\r
+    data[55]=(char)0x4030;\r
+    data[56]=(char)0x0080;\r
+    data[85]=(char)0xfc00;\r
+    data[88]=(char)0x0200;\r
+    data[91]=(char)0x4000;\r
+    data[92]=(char)0x0009;\r
+    data[95]=(char)0x0018;\r
+    data[96]=(char)0x1000;\r
+    data[97]=(char)0x8800;\r
+    data[102]=(char)0x3c00;\r
+    data[109]=(char)0x0010;\r
+    data[150]=(char)0x0030;\r
+    data[151]=(char)0x0001;\r
+    data[226]=(char)0x8000;\r
+    data[229]=(char)0x0c00;\r
+    data[234]=(char)0x8000;\r
+    data[240]=(char)0xfff0;\r
+    data[241]=(char)0x0007;\r
+    data[243]=(char)0x3c00;\r
+    data[248]=(char)0x0020;\r
+    data[271]=(char)0x0800;\r
+    data[513]=(char)0xffff;\r
+    data[514]=(char)0x00ff;\r
+    data[515]=(char)0xffff;\r
+    data[516]=(char)0x006f;\r
+    data[519]=(char)0x6000;\r
+    data[520]=(char)0x6000;\r
+    data[562]=(char)0x0600;\r
+    data[768]=(char)0xff4e;\r
+    data[769]=(char)0xfff3;\r
+    data[771]=(char)0x0001;\r
+    data[783]=(char)0x0800;\r
+    data[4051]=(char)0xc000;\r
+    data[4067]=(char)0xffff;\r
+    data[4068]=(char)0xfe1f;\r
+    data[4069]=(char)0xfff7;\r
+    data[4070]=(char)0x0d0b;\r
+    data[4080]=(char)0xf7ee;\r
+    data[4081]=(char)0x8c00;\r
+    data[4082]=(char)0x0001;\r
+    data[4083]=(char)0xb800;\r
+    data[4085]=(char)0x2800;\r
+    data[4086]=(char)0x003e;\r
+    data[4098]=(char)0xf7ee;\r
+    data[4099]=(char)0x8c00;\r
+    data[4100]=(char)0x0001;\r
+    data[4101]=(char)0xb800;\r
+    data[4103]=(char)0x2800;\r
+    data[4106]=(char)0x2802;\r
+    data[4107]=(char)0x8880;\r
+    data[4151]=(char)0x4030;\r
+    data[4152]=(char)0x0080;\r
+\r
+  }\r
+}\r
diff --git a/src/com/stevesoft/pat/Boundary.java b/src/com/stevesoft/pat/Boundary.java
new file mode 100755 (executable)
index 0000000..959bb04
--- /dev/null
@@ -0,0 +1,51 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** This class implements the word boundary pattern element: \b. */\r
+class Boundary extends Pattern {\r
+    public String toString() {\r
+        return "\\b"+nextString();\r
+    }\r
+    boolean isAChar(char c) {\r
+        if(c >= 'a' && c <= 'z')\r
+            return true;\r
+        if(c >= 'A' && c <= 'Z')\r
+            return true;\r
+        if(c >= '0' && c <= '9')\r
+            return true;\r
+        if(c == '_')\r
+            return true;\r
+        return false;\r
+    }\r
+    boolean matchLeft(int pos,Pthings pt) {\r
+        if(pos <= 0)\r
+            return true;\r
+        if(isAChar(pt.src.charAt(pos))\r
+                && isAChar(pt.src.charAt(pos-1)))\r
+            return false;\r
+        return true;\r
+    }\r
+    boolean matchRight(int pos,Pthings pt) {\r
+        if(pos < 0) return false;\r
+        if(pos+1 >= pt.src.length())\r
+            return true;\r
+        if(isAChar(pt.src.charAt(pos))\r
+                && isAChar(pt.src.charAt(pos+1)))\r
+            return false;\r
+        return true;\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(matchRight(pos-1,pt) || matchLeft(pos,pt))\r
+            return nextMatch(pos,pt);\r
+        return -1;\r
+    }\r
+    public patInt maxChars() { return new patInt(0); }\r
+    public Pattern clone1(Hashtable h) { return new Boundary(); }\r
+};\r
diff --git a/src/com/stevesoft/pat/Bracket.java b/src/com/stevesoft/pat/Bracket.java
new file mode 100755 (executable)
index 0000000..9f60179
--- /dev/null
@@ -0,0 +1,48 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Vector;\r
+import java.util.Hashtable;\r
+\r
+/** The Bracket is a form of the Or class,\r
+ implements the pattern element [  ]. */\r
+class Bracket extends Or {\r
+    boolean neg;\r
+    Bracket(boolean n) { neg = n; }\r
+    String leftForm() {\r
+        if(neg)\r
+            return "[^";\r
+        else\r
+            return "[";\r
+    }\r
+    String rightForm() { return "]"; }\r
+    String sepForm() { return ""; }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(pos >= pt.src.length()) return -1;\r
+        int r = super.matchInternal(pos,pt);\r
+        if((neg && r<0)||(!neg && r>=0))\r
+            return nextMatch(pos+1,pt);\r
+        return -1;\r
+    }\r
+    public patInt minChars() { return new patInt(1); }\r
+    public patInt maxChars() { return new patInt(1); }\r
+\r
+    public Or addOr(Pattern p) {\r
+        pv = null;\r
+        v.addElement(p);\r
+        p.setParent(null);\r
+        return this;\r
+    }\r
+    public Pattern clone1(Hashtable h) {\r
+        Bracket b = new Bracket(neg);\r
+        b.v = new Vector();\r
+        for(int i=0;i<v.size();i++)\r
+            b.v.addElement( ((Pattern)v.elementAt(i)).clone1(h) );\r
+        return b;\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/CaseMgr.java b/src/com/stevesoft/pat/CaseMgr.java
new file mode 100755 (executable)
index 0000000..2de70d4
--- /dev/null
@@ -0,0 +1,1537 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** Encapsulates the Unicode definitions of Upper,\r
+    Lower, and Title case as defined by <a href="http://www.unicode.org">\r
+    unicode.org</a>.\r
+    <p>\r
+    The performance of the methods found in String\r
+    and Character is better, but these methods work\r
+    both in java 1.0 and 1.1.  If it is desirable,\r
+    either to gain a slight performance increase or\r
+    to accomodate application specific modifications\r
+    to the definitions of upper, lower, and title case\r
+    then it should be a straightforward task to substitute\r
+    your own methods for these.\r
+    */\r
+final public class CaseMgr {\r
+    final static boolean java_1_0 = false;\r
+    /** Convert a character to upper case .*/\r
+    public static char toUpperCase(char c) {\r
+      if(java_1_0) {\r
+        int ret = (int)c;\r
+        switch(c) {\r
+        case 97: ret=65; break;\r
+        case 98: ret=66; break;\r
+        case 99: ret=67; break;\r
+        case 100: ret=68; break;\r
+        case 101: ret=69; break;\r
+        case 102: ret=70; break;\r
+        case 103: ret=71; break;\r
+        case 104: ret=72; break;\r
+        case 105: ret=73; break;\r
+        case 106: ret=74; break;\r
+        case 107: ret=75; break;\r
+        case 108: ret=76; break;\r
+        case 109: ret=77; break;\r
+        case 110: ret=78; break;\r
+        case 111: ret=79; break;\r
+        case 112: ret=80; break;\r
+        case 113: ret=81; break;\r
+        case 114: ret=82; break;\r
+        case 115: ret=83; break;\r
+        case 116: ret=84; break;\r
+        case 117: ret=85; break;\r
+        case 118: ret=86; break;\r
+        case 119: ret=87; break;\r
+        case 120: ret=88; break;\r
+        case 121: ret=89; break;\r
+        case 122: ret=90; break;\r
+        case 224: ret=192; break;\r
+        case 225: ret=193; break;\r
+        case 226: ret=194; break;\r
+        case 227: ret=195; break;\r
+        case 228: ret=196; break;\r
+        case 229: ret=197; break;\r
+        case 230: ret=198; break;\r
+        case 231: ret=199; break;\r
+        case 232: ret=200; break;\r
+        case 233: ret=201; break;\r
+        case 234: ret=202; break;\r
+        case 235: ret=203; break;\r
+        case 236: ret=204; break;\r
+        case 237: ret=205; break;\r
+        case 238: ret=206; break;\r
+        case 239: ret=207; break;\r
+        case 240: ret=208; break;\r
+        case 241: ret=209; break;\r
+        case 242: ret=210; break;\r
+        case 243: ret=211; break;\r
+        case 244: ret=212; break;\r
+        case 245: ret=213; break;\r
+        case 246: ret=214; break;\r
+        case 248: ret=216; break;\r
+        case 249: ret=217; break;\r
+        case 250: ret=218; break;\r
+        case 251: ret=219; break;\r
+        case 252: ret=220; break;\r
+        case 253: ret=221; break;\r
+        case 254: ret=222; break;\r
+        case 255: ret=376; break;\r
+        case 257: ret=256; break;\r
+        case 259: ret=258; break;\r
+        case 261: ret=260; break;\r
+        case 263: ret=262; break;\r
+        case 265: ret=264; break;\r
+        case 267: ret=266; break;\r
+        case 269: ret=268; break;\r
+        case 271: ret=270; break;\r
+        case 273: ret=272; break;\r
+        case 275: ret=274; break;\r
+        case 277: ret=276; break;\r
+        case 279: ret=278; break;\r
+        case 281: ret=280; break;\r
+        case 283: ret=282; break;\r
+        case 285: ret=284; break;\r
+        case 287: ret=286; break;\r
+        case 289: ret=288; break;\r
+        case 291: ret=290; break;\r
+        case 293: ret=292; break;\r
+        case 295: ret=294; break;\r
+        case 297: ret=296; break;\r
+        case 299: ret=298; break;\r
+        case 301: ret=300; break;\r
+        case 303: ret=302; break;\r
+        case 305: ret=73; break;\r
+        case 307: ret=306; break;\r
+        case 309: ret=308; break;\r
+        case 311: ret=310; break;\r
+        case 314: ret=313; break;\r
+        case 316: ret=315; break;\r
+        case 318: ret=317; break;\r
+        case 320: ret=319; break;\r
+        case 322: ret=321; break;\r
+        case 324: ret=323; break;\r
+        case 326: ret=325; break;\r
+        case 328: ret=327; break;\r
+        case 331: ret=330; break;\r
+        case 333: ret=332; break;\r
+        case 335: ret=334; break;\r
+        case 337: ret=336; break;\r
+        case 339: ret=338; break;\r
+        case 341: ret=340; break;\r
+        case 343: ret=342; break;\r
+        case 345: ret=344; break;\r
+        case 347: ret=346; break;\r
+        case 349: ret=348; break;\r
+        case 351: ret=350; break;\r
+        case 353: ret=352; break;\r
+        case 355: ret=354; break;\r
+        case 357: ret=356; break;\r
+        case 359: ret=358; break;\r
+        case 361: ret=360; break;\r
+        case 363: ret=362; break;\r
+        case 365: ret=364; break;\r
+        case 367: ret=366; break;\r
+        case 369: ret=368; break;\r
+        case 371: ret=370; break;\r
+        case 373: ret=372; break;\r
+        case 375: ret=374; break;\r
+        case 378: ret=377; break;\r
+        case 380: ret=379; break;\r
+        case 382: ret=381; break;\r
+        case 383: ret=83; break;\r
+        case 387: ret=386; break;\r
+        case 389: ret=388; break;\r
+        case 392: ret=391; break;\r
+        case 396: ret=395; break;\r
+        case 402: ret=401; break;\r
+        case 409: ret=408; break;\r
+        case 417: ret=416; break;\r
+        case 419: ret=418; break;\r
+        case 421: ret=420; break;\r
+        case 424: ret=423; break;\r
+        case 429: ret=428; break;\r
+        case 432: ret=431; break;\r
+        case 436: ret=435; break;\r
+        case 438: ret=437; break;\r
+        case 441: ret=440; break;\r
+        case 445: ret=444; break;\r
+        case 453: ret=452; break;\r
+        case 454: ret=452; break;\r
+        case 456: ret=455; break;\r
+        case 457: ret=455; break;\r
+        case 459: ret=458; break;\r
+        case 460: ret=458; break;\r
+        case 462: ret=461; break;\r
+        case 464: ret=463; break;\r
+        case 466: ret=465; break;\r
+        case 468: ret=467; break;\r
+        case 470: ret=469; break;\r
+        case 472: ret=471; break;\r
+        case 474: ret=473; break;\r
+        case 476: ret=475; break;\r
+        case 479: ret=478; break;\r
+        case 481: ret=480; break;\r
+        case 483: ret=482; break;\r
+        case 485: ret=484; break;\r
+        case 487: ret=486; break;\r
+        case 489: ret=488; break;\r
+        case 491: ret=490; break;\r
+        case 493: ret=492; break;\r
+        case 495: ret=494; break;\r
+        case 498: ret=497; break;\r
+        case 499: ret=497; break;\r
+        case 501: ret=500; break;\r
+        case 507: ret=506; break;\r
+        case 509: ret=508; break;\r
+        case 511: ret=510; break;\r
+        case 513: ret=512; break;\r
+        case 515: ret=514; break;\r
+        case 517: ret=516; break;\r
+        case 519: ret=518; break;\r
+        case 521: ret=520; break;\r
+        case 523: ret=522; break;\r
+        case 525: ret=524; break;\r
+        case 527: ret=526; break;\r
+        case 529: ret=528; break;\r
+        case 531: ret=530; break;\r
+        case 533: ret=532; break;\r
+        case 535: ret=534; break;\r
+        case 595: ret=385; break;\r
+        case 596: ret=390; break;\r
+        case 598: ret=393; break;\r
+        case 599: ret=394; break;\r
+        case 600: ret=398; break;\r
+        case 601: ret=399; break;\r
+        case 603: ret=400; break;\r
+        case 608: ret=403; break;\r
+        case 611: ret=404; break;\r
+        case 616: ret=407; break;\r
+        case 617: ret=406; break;\r
+        case 623: ret=412; break;\r
+        case 626: ret=413; break;\r
+        case 643: ret=425; break;\r
+        case 648: ret=430; break;\r
+        case 650: ret=433; break;\r
+        case 651: ret=434; break;\r
+        case 658: ret=439; break;\r
+        case 940: ret=902; break;\r
+        case 941: ret=904; break;\r
+        case 942: ret=905; break;\r
+        case 943: ret=906; break;\r
+        case 945: ret=913; break;\r
+        case 946: ret=914; break;\r
+        case 947: ret=915; break;\r
+        case 948: ret=916; break;\r
+        case 949: ret=917; break;\r
+        case 950: ret=918; break;\r
+        case 951: ret=919; break;\r
+        case 952: ret=920; break;\r
+        case 953: ret=921; break;\r
+        case 954: ret=922; break;\r
+        case 955: ret=923; break;\r
+        case 956: ret=924; break;\r
+        case 957: ret=925; break;\r
+        case 958: ret=926; break;\r
+        case 959: ret=927; break;\r
+        case 960: ret=928; break;\r
+        case 961: ret=929; break;\r
+        case 963: ret=931; break;\r
+        case 964: ret=932; break;\r
+        case 965: ret=933; break;\r
+        case 966: ret=934; break;\r
+        case 967: ret=935; break;\r
+        case 968: ret=936; break;\r
+        case 969: ret=937; break;\r
+        case 970: ret=938; break;\r
+        case 971: ret=939; break;\r
+        case 972: ret=908; break;\r
+        case 973: ret=910; break;\r
+        case 974: ret=911; break;\r
+        case 976: ret=914; break;\r
+        case 977: ret=920; break;\r
+        case 981: ret=934; break;\r
+        case 982: ret=928; break;\r
+        case 995: ret=994; break;\r
+        case 997: ret=996; break;\r
+        case 999: ret=998; break;\r
+        case 1001: ret=1000; break;\r
+        case 1003: ret=1002; break;\r
+        case 1005: ret=1004; break;\r
+        case 1007: ret=1006; break;\r
+        case 1008: ret=922; break;\r
+        case 1009: ret=929; break;\r
+        case 1072: ret=1040; break;\r
+        case 1073: ret=1041; break;\r
+        case 1074: ret=1042; break;\r
+        case 1075: ret=1043; break;\r
+        case 1076: ret=1044; break;\r
+        case 1077: ret=1045; break;\r
+        case 1078: ret=1046; break;\r
+        case 1079: ret=1047; break;\r
+        case 1080: ret=1048; break;\r
+        case 1081: ret=1049; break;\r
+        case 1082: ret=1050; break;\r
+        case 1083: ret=1051; break;\r
+        case 1084: ret=1052; break;\r
+        case 1085: ret=1053; break;\r
+        case 1086: ret=1054; break;\r
+        case 1087: ret=1055; break;\r
+        case 1088: ret=1056; break;\r
+        case 1089: ret=1057; break;\r
+        case 1090: ret=1058; break;\r
+        case 1091: ret=1059; break;\r
+        case 1092: ret=1060; break;\r
+        case 1093: ret=1061; break;\r
+        case 1094: ret=1062; break;\r
+        case 1095: ret=1063; break;\r
+        case 1096: ret=1064; break;\r
+        case 1097: ret=1065; break;\r
+        case 1098: ret=1066; break;\r
+        case 1099: ret=1067; break;\r
+        case 1100: ret=1068; break;\r
+        case 1101: ret=1069; break;\r
+        case 1102: ret=1070; break;\r
+        case 1103: ret=1071; break;\r
+        case 1105: ret=1025; break;\r
+        case 1106: ret=1026; break;\r
+        case 1107: ret=1027; break;\r
+        case 1108: ret=1028; break;\r
+        case 1109: ret=1029; break;\r
+        case 1110: ret=1030; break;\r
+        case 1111: ret=1031; break;\r
+        case 1112: ret=1032; break;\r
+        case 1113: ret=1033; break;\r
+        case 1114: ret=1034; break;\r
+        case 1115: ret=1035; break;\r
+        case 1116: ret=1036; break;\r
+        case 1118: ret=1038; break;\r
+        case 1119: ret=1039; break;\r
+        case 1121: ret=1120; break;\r
+        case 1123: ret=1122; break;\r
+        case 1125: ret=1124; break;\r
+        case 1127: ret=1126; break;\r
+        case 1129: ret=1128; break;\r
+        case 1131: ret=1130; break;\r
+        case 1133: ret=1132; break;\r
+        case 1135: ret=1134; break;\r
+        case 1137: ret=1136; break;\r
+        case 1139: ret=1138; break;\r
+        case 1141: ret=1140; break;\r
+        case 1143: ret=1142; break;\r
+        case 1145: ret=1144; break;\r
+        case 1147: ret=1146; break;\r
+        case 1149: ret=1148; break;\r
+        case 1151: ret=1150; break;\r
+        case 1153: ret=1152; break;\r
+        case 1169: ret=1168; break;\r
+        case 1171: ret=1170; break;\r
+        case 1173: ret=1172; break;\r
+        case 1175: ret=1174; break;\r
+        case 1177: ret=1176; break;\r
+        case 1179: ret=1178; break;\r
+        case 1181: ret=1180; break;\r
+        case 1183: ret=1182; break;\r
+        case 1185: ret=1184; break;\r
+        case 1187: ret=1186; break;\r
+        case 1189: ret=1188; break;\r
+        case 1191: ret=1190; break;\r
+        case 1193: ret=1192; break;\r
+        case 1195: ret=1194; break;\r
+        case 1197: ret=1196; break;\r
+        case 1199: ret=1198; break;\r
+        case 1201: ret=1200; break;\r
+        case 1203: ret=1202; break;\r
+        case 1205: ret=1204; break;\r
+        case 1207: ret=1206; break;\r
+        case 1209: ret=1208; break;\r
+        case 1211: ret=1210; break;\r
+        case 1213: ret=1212; break;\r
+        case 1215: ret=1214; break;\r
+        case 1218: ret=1217; break;\r
+        case 1220: ret=1219; break;\r
+        case 1224: ret=1223; break;\r
+        case 1228: ret=1227; break;\r
+        case 1233: ret=1232; break;\r
+        case 1235: ret=1234; break;\r
+        case 1237: ret=1236; break;\r
+        case 1239: ret=1238; break;\r
+        case 1241: ret=1240; break;\r
+        case 1243: ret=1242; break;\r
+        case 1245: ret=1244; break;\r
+        case 1247: ret=1246; break;\r
+        case 1249: ret=1248; break;\r
+        case 1251: ret=1250; break;\r
+        case 1253: ret=1252; break;\r
+        case 1255: ret=1254; break;\r
+        case 1257: ret=1256; break;\r
+        case 1259: ret=1258; break;\r
+        case 1263: ret=1262; break;\r
+        case 1265: ret=1264; break;\r
+        case 1267: ret=1266; break;\r
+        case 1269: ret=1268; break;\r
+        case 1273: ret=1272; break;\r
+        case 1377: ret=1329; break;\r
+        case 1378: ret=1330; break;\r
+        case 1379: ret=1331; break;\r
+        case 1380: ret=1332; break;\r
+        case 1381: ret=1333; break;\r
+        case 1382: ret=1334; break;\r
+        case 1383: ret=1335; break;\r
+        case 1384: ret=1336; break;\r
+        case 1385: ret=1337; break;\r
+        case 1386: ret=1338; break;\r
+        case 1387: ret=1339; break;\r
+        case 1388: ret=1340; break;\r
+        case 1389: ret=1341; break;\r
+        case 1390: ret=1342; break;\r
+        case 1391: ret=1343; break;\r
+        case 1392: ret=1344; break;\r
+        case 1393: ret=1345; break;\r
+        case 1394: ret=1346; break;\r
+        case 1395: ret=1347; break;\r
+        case 1396: ret=1348; break;\r
+        case 1397: ret=1349; break;\r
+        case 1398: ret=1350; break;\r
+        case 1399: ret=1351; break;\r
+        case 1400: ret=1352; break;\r
+        case 1401: ret=1353; break;\r
+        case 1402: ret=1354; break;\r
+        case 1403: ret=1355; break;\r
+        case 1404: ret=1356; break;\r
+        case 1405: ret=1357; break;\r
+        case 1406: ret=1358; break;\r
+        case 1407: ret=1359; break;\r
+        case 1408: ret=1360; break;\r
+        case 1409: ret=1361; break;\r
+        case 1410: ret=1362; break;\r
+        case 1411: ret=1363; break;\r
+        case 1412: ret=1364; break;\r
+        case 1413: ret=1365; break;\r
+        case 1414: ret=1366; break;\r
+        case 7681: ret=7680; break;\r
+        case 7683: ret=7682; break;\r
+        case 7685: ret=7684; break;\r
+        case 7687: ret=7686; break;\r
+        case 7689: ret=7688; break;\r
+        case 7691: ret=7690; break;\r
+        case 7693: ret=7692; break;\r
+        case 7695: ret=7694; break;\r
+        case 7697: ret=7696; break;\r
+        case 7699: ret=7698; break;\r
+        case 7701: ret=7700; break;\r
+        case 7703: ret=7702; break;\r
+        case 7705: ret=7704; break;\r
+        case 7707: ret=7706; break;\r
+        case 7709: ret=7708; break;\r
+        case 7711: ret=7710; break;\r
+        case 7713: ret=7712; break;\r
+        case 7715: ret=7714; break;\r
+        case 7717: ret=7716; break;\r
+        case 7719: ret=7718; break;\r
+        case 7721: ret=7720; break;\r
+        case 7723: ret=7722; break;\r
+        case 7725: ret=7724; break;\r
+        case 7727: ret=7726; break;\r
+        case 7729: ret=7728; break;\r
+        case 7731: ret=7730; break;\r
+        case 7733: ret=7732; break;\r
+        case 7735: ret=7734; break;\r
+        case 7737: ret=7736; break;\r
+        case 7739: ret=7738; break;\r
+        case 7741: ret=7740; break;\r
+        case 7743: ret=7742; break;\r
+        case 7745: ret=7744; break;\r
+        case 7747: ret=7746; break;\r
+        case 7749: ret=7748; break;\r
+        case 7751: ret=7750; break;\r
+        case 7753: ret=7752; break;\r
+        case 7755: ret=7754; break;\r
+        case 7757: ret=7756; break;\r
+        case 7759: ret=7758; break;\r
+        case 7761: ret=7760; break;\r
+        case 7763: ret=7762; break;\r
+        case 7765: ret=7764; break;\r
+        case 7767: ret=7766; break;\r
+        case 7769: ret=7768; break;\r
+        case 7771: ret=7770; break;\r
+        case 7773: ret=7772; break;\r
+        case 7775: ret=7774; break;\r
+        case 7777: ret=7776; break;\r
+        case 7779: ret=7778; break;\r
+        case 7781: ret=7780; break;\r
+        case 7783: ret=7782; break;\r
+        case 7785: ret=7784; break;\r
+        case 7787: ret=7786; break;\r
+        case 7789: ret=7788; break;\r
+        case 7791: ret=7790; break;\r
+        case 7793: ret=7792; break;\r
+        case 7795: ret=7794; break;\r
+        case 7797: ret=7796; break;\r
+        case 7799: ret=7798; break;\r
+        case 7801: ret=7800; break;\r
+        case 7803: ret=7802; break;\r
+        case 7805: ret=7804; break;\r
+        case 7807: ret=7806; break;\r
+        case 7809: ret=7808; break;\r
+        case 7811: ret=7810; break;\r
+        case 7813: ret=7812; break;\r
+        case 7815: ret=7814; break;\r
+        case 7817: ret=7816; break;\r
+        case 7819: ret=7818; break;\r
+        case 7821: ret=7820; break;\r
+        case 7823: ret=7822; break;\r
+        case 7825: ret=7824; break;\r
+        case 7827: ret=7826; break;\r
+        case 7829: ret=7828; break;\r
+        case 7841: ret=7840; break;\r
+        case 7843: ret=7842; break;\r
+        case 7845: ret=7844; break;\r
+        case 7847: ret=7846; break;\r
+        case 7849: ret=7848; break;\r
+        case 7851: ret=7850; break;\r
+        case 7853: ret=7852; break;\r
+        case 7855: ret=7854; break;\r
+        case 7857: ret=7856; break;\r
+        case 7859: ret=7858; break;\r
+        case 7861: ret=7860; break;\r
+        case 7863: ret=7862; break;\r
+        case 7865: ret=7864; break;\r
+        case 7867: ret=7866; break;\r
+        case 7869: ret=7868; break;\r
+        case 7871: ret=7870; break;\r
+        case 7873: ret=7872; break;\r
+        case 7875: ret=7874; break;\r
+        case 7877: ret=7876; break;\r
+        case 7879: ret=7878; break;\r
+        case 7881: ret=7880; break;\r
+        case 7883: ret=7882; break;\r
+        case 7885: ret=7884; break;\r
+        case 7887: ret=7886; break;\r
+        case 7889: ret=7888; break;\r
+        case 7891: ret=7890; break;\r
+        case 7893: ret=7892; break;\r
+        case 7895: ret=7894; break;\r
+        case 7897: ret=7896; break;\r
+        case 7899: ret=7898; break;\r
+        case 7901: ret=7900; break;\r
+        case 7903: ret=7902; break;\r
+        case 7905: ret=7904; break;\r
+        case 7907: ret=7906; break;\r
+        case 7909: ret=7908; break;\r
+        case 7911: ret=7910; break;\r
+        case 7913: ret=7912; break;\r
+        case 7915: ret=7914; break;\r
+        case 7917: ret=7916; break;\r
+        case 7919: ret=7918; break;\r
+        case 7921: ret=7920; break;\r
+        case 7923: ret=7922; break;\r
+        case 7925: ret=7924; break;\r
+        case 7927: ret=7926; break;\r
+        case 7929: ret=7928; break;\r
+        case 7936: ret=7944; break;\r
+        case 7937: ret=7945; break;\r
+        case 7938: ret=7946; break;\r
+        case 7939: ret=7947; break;\r
+        case 7940: ret=7948; break;\r
+        case 7941: ret=7949; break;\r
+        case 7942: ret=7950; break;\r
+        case 7943: ret=7951; break;\r
+        case 7952: ret=7960; break;\r
+        case 7953: ret=7961; break;\r
+        case 7954: ret=7962; break;\r
+        case 7955: ret=7963; break;\r
+        case 7956: ret=7964; break;\r
+        case 7957: ret=7965; break;\r
+        case 7968: ret=7976; break;\r
+        case 7969: ret=7977; break;\r
+        case 7970: ret=7978; break;\r
+        case 7971: ret=7979; break;\r
+        case 7972: ret=7980; break;\r
+        case 7973: ret=7981; break;\r
+        case 7974: ret=7982; break;\r
+        case 7975: ret=7983; break;\r
+        case 7984: ret=7992; break;\r
+        case 7985: ret=7993; break;\r
+        case 7986: ret=7994; break;\r
+        case 7987: ret=7995; break;\r
+        case 7988: ret=7996; break;\r
+        case 7989: ret=7997; break;\r
+        case 7990: ret=7998; break;\r
+        case 7991: ret=7999; break;\r
+        case 8000: ret=8008; break;\r
+        case 8001: ret=8009; break;\r
+        case 8002: ret=8010; break;\r
+        case 8003: ret=8011; break;\r
+        case 8004: ret=8012; break;\r
+        case 8005: ret=8013; break;\r
+        case 8017: ret=8025; break;\r
+        case 8019: ret=8027; break;\r
+        case 8021: ret=8029; break;\r
+        case 8023: ret=8031; break;\r
+        case 8032: ret=8040; break;\r
+        case 8033: ret=8041; break;\r
+        case 8034: ret=8042; break;\r
+        case 8035: ret=8043; break;\r
+        case 8036: ret=8044; break;\r
+        case 8037: ret=8045; break;\r
+        case 8038: ret=8046; break;\r
+        case 8039: ret=8047; break;\r
+        case 8048: ret=8122; break;\r
+        case 8049: ret=8123; break;\r
+        case 8050: ret=8136; break;\r
+        case 8051: ret=8137; break;\r
+        case 8052: ret=8138; break;\r
+        case 8053: ret=8139; break;\r
+        case 8054: ret=8154; break;\r
+        case 8055: ret=8155; break;\r
+        case 8056: ret=8184; break;\r
+        case 8057: ret=8185; break;\r
+        case 8058: ret=8170; break;\r
+        case 8059: ret=8171; break;\r
+        case 8060: ret=8186; break;\r
+        case 8061: ret=8187; break;\r
+        case 8064: ret=8072; break;\r
+        case 8065: ret=8073; break;\r
+        case 8066: ret=8074; break;\r
+        case 8067: ret=8075; break;\r
+        case 8068: ret=8076; break;\r
+        case 8069: ret=8077; break;\r
+        case 8070: ret=8078; break;\r
+        case 8071: ret=8079; break;\r
+        case 8080: ret=8088; break;\r
+        case 8081: ret=8089; break;\r
+        case 8082: ret=8090; break;\r
+        case 8083: ret=8091; break;\r
+        case 8084: ret=8092; break;\r
+        case 8085: ret=8093; break;\r
+        case 8086: ret=8094; break;\r
+        case 8087: ret=8095; break;\r
+        case 8096: ret=8104; break;\r
+        case 8097: ret=8105; break;\r
+        case 8098: ret=8106; break;\r
+        case 8099: ret=8107; break;\r
+        case 8100: ret=8108; break;\r
+        case 8101: ret=8109; break;\r
+        case 8102: ret=8110; break;\r
+        case 8103: ret=8111; break;\r
+        case 8112: ret=8120; break;\r
+        case 8113: ret=8121; break;\r
+        case 8115: ret=8124; break;\r
+        case 8131: ret=8140; break;\r
+        case 8144: ret=8152; break;\r
+        case 8145: ret=8153; break;\r
+        case 8160: ret=8168; break;\r
+        case 8161: ret=8169; break;\r
+        case 8165: ret=8172; break;\r
+        case 8179: ret=8188; break;\r
+        case 8560: ret=8544; break;\r
+        case 8561: ret=8545; break;\r
+        case 8562: ret=8546; break;\r
+        case 8563: ret=8547; break;\r
+        case 8564: ret=8548; break;\r
+        case 8565: ret=8549; break;\r
+        case 8566: ret=8550; break;\r
+        case 8567: ret=8551; break;\r
+        case 8568: ret=8552; break;\r
+        case 8569: ret=8553; break;\r
+        case 8570: ret=8554; break;\r
+        case 8571: ret=8555; break;\r
+        case 8572: ret=8556; break;\r
+        case 8573: ret=8557; break;\r
+        case 8574: ret=8558; break;\r
+        case 8575: ret=8559; break;\r
+        case 9424: ret=9398; break;\r
+        case 9425: ret=9399; break;\r
+        case 9426: ret=9400; break;\r
+        case 9427: ret=9401; break;\r
+        case 9428: ret=9402; break;\r
+        case 9429: ret=9403; break;\r
+        case 9430: ret=9404; break;\r
+        case 9431: ret=9405; break;\r
+        case 9432: ret=9406; break;\r
+        case 9433: ret=9407; break;\r
+        case 9434: ret=9408; break;\r
+        case 9435: ret=9409; break;\r
+        case 9436: ret=9410; break;\r
+        case 9437: ret=9411; break;\r
+        case 9438: ret=9412; break;\r
+        case 9439: ret=9413; break;\r
+        case 9440: ret=9414; break;\r
+        case 9441: ret=9415; break;\r
+        case 9442: ret=9416; break;\r
+        case 9443: ret=9417; break;\r
+        case 9444: ret=9418; break;\r
+        case 9445: ret=9419; break;\r
+        case 9446: ret=9420; break;\r
+        case 9447: ret=9421; break;\r
+        case 9448: ret=9422; break;\r
+        case 9449: ret=9423; break;\r
+        case 65345: ret=65313; break;\r
+        case 65346: ret=65314; break;\r
+        case 65347: ret=65315; break;\r
+        case 65348: ret=65316; break;\r
+        case 65349: ret=65317; break;\r
+        case 65350: ret=65318; break;\r
+        case 65351: ret=65319; break;\r
+        case 65352: ret=65320; break;\r
+        case 65353: ret=65321; break;\r
+        case 65354: ret=65322; break;\r
+        case 65355: ret=65323; break;\r
+        case 65356: ret=65324; break;\r
+        case 65357: ret=65325; break;\r
+        case 65358: ret=65326; break;\r
+        case 65359: ret=65327; break;\r
+        case 65360: ret=65328; break;\r
+        case 65361: ret=65329; break;\r
+        case 65362: ret=65330; break;\r
+        case 65363: ret=65331; break;\r
+        case 65364: ret=65332; break;\r
+        case 65365: ret=65333; break;\r
+        case 65366: ret=65334; break;\r
+        case 65367: ret=65335; break;\r
+        case 65368: ret=65336; break;\r
+        case 65369: ret=65337; break;\r
+        case 65370: ret=65338; break;\r
+        }\r
+        return (char)ret;\r
+      }\r
+      return Character.toUpperCase(c);\r
+    }\r
+    /** Convert a character to lower case. */\r
+    public static char toLowerCase(char c) {\r
+      if(java_1_0) {\r
+        int ret = (int)c;\r
+        switch(c) {\r
+        case 65: ret=97; break;\r
+        case 66: ret=98; break;\r
+        case 67: ret=99; break;\r
+        case 68: ret=100; break;\r
+        case 69: ret=101; break;\r
+        case 70: ret=102; break;\r
+        case 71: ret=103; break;\r
+        case 72: ret=104; break;\r
+        case 73: ret=105; break;\r
+        case 74: ret=106; break;\r
+        case 75: ret=107; break;\r
+        case 76: ret=108; break;\r
+        case 77: ret=109; break;\r
+        case 78: ret=110; break;\r
+        case 79: ret=111; break;\r
+        case 80: ret=112; break;\r
+        case 81: ret=113; break;\r
+        case 82: ret=114; break;\r
+        case 83: ret=115; break;\r
+        case 84: ret=116; break;\r
+        case 85: ret=117; break;\r
+        case 86: ret=118; break;\r
+        case 87: ret=119; break;\r
+        case 88: ret=120; break;\r
+        case 89: ret=121; break;\r
+        case 90: ret=122; break;\r
+        case 192: ret=224; break;\r
+        case 193: ret=225; break;\r
+        case 194: ret=226; break;\r
+        case 195: ret=227; break;\r
+        case 196: ret=228; break;\r
+        case 197: ret=229; break;\r
+        case 198: ret=230; break;\r
+        case 199: ret=231; break;\r
+        case 200: ret=232; break;\r
+        case 201: ret=233; break;\r
+        case 202: ret=234; break;\r
+        case 203: ret=235; break;\r
+        case 204: ret=236; break;\r
+        case 205: ret=237; break;\r
+        case 206: ret=238; break;\r
+        case 207: ret=239; break;\r
+        case 208: ret=240; break;\r
+        case 209: ret=241; break;\r
+        case 210: ret=242; break;\r
+        case 211: ret=243; break;\r
+        case 212: ret=244; break;\r
+        case 213: ret=245; break;\r
+        case 214: ret=246; break;\r
+        case 216: ret=248; break;\r
+        case 217: ret=249; break;\r
+        case 218: ret=250; break;\r
+        case 219: ret=251; break;\r
+        case 220: ret=252; break;\r
+        case 221: ret=253; break;\r
+        case 222: ret=254; break;\r
+        case 256: ret=257; break;\r
+        case 258: ret=259; break;\r
+        case 260: ret=261; break;\r
+        case 262: ret=263; break;\r
+        case 264: ret=265; break;\r
+        case 266: ret=267; break;\r
+        case 268: ret=269; break;\r
+        case 270: ret=271; break;\r
+        case 272: ret=273; break;\r
+        case 274: ret=275; break;\r
+        case 276: ret=277; break;\r
+        case 278: ret=279; break;\r
+        case 280: ret=281; break;\r
+        case 282: ret=283; break;\r
+        case 284: ret=285; break;\r
+        case 286: ret=287; break;\r
+        case 288: ret=289; break;\r
+        case 290: ret=291; break;\r
+        case 292: ret=293; break;\r
+        case 294: ret=295; break;\r
+        case 296: ret=297; break;\r
+        case 298: ret=299; break;\r
+        case 300: ret=301; break;\r
+        case 302: ret=303; break;\r
+        case 304: ret=105; break;\r
+        case 306: ret=307; break;\r
+        case 308: ret=309; break;\r
+        case 310: ret=311; break;\r
+        case 313: ret=314; break;\r
+        case 315: ret=316; break;\r
+        case 317: ret=318; break;\r
+        case 319: ret=320; break;\r
+        case 321: ret=322; break;\r
+        case 323: ret=324; break;\r
+        case 325: ret=326; break;\r
+        case 327: ret=328; break;\r
+        case 330: ret=331; break;\r
+        case 332: ret=333; break;\r
+        case 334: ret=335; break;\r
+        case 336: ret=337; break;\r
+        case 338: ret=339; break;\r
+        case 340: ret=341; break;\r
+        case 342: ret=343; break;\r
+        case 344: ret=345; break;\r
+        case 346: ret=347; break;\r
+        case 348: ret=349; break;\r
+        case 350: ret=351; break;\r
+        case 352: ret=353; break;\r
+        case 354: ret=355; break;\r
+        case 356: ret=357; break;\r
+        case 358: ret=359; break;\r
+        case 360: ret=361; break;\r
+        case 362: ret=363; break;\r
+        case 364: ret=365; break;\r
+        case 366: ret=367; break;\r
+        case 368: ret=369; break;\r
+        case 370: ret=371; break;\r
+        case 372: ret=373; break;\r
+        case 374: ret=375; break;\r
+        case 376: ret=255; break;\r
+        case 377: ret=378; break;\r
+        case 379: ret=380; break;\r
+        case 381: ret=382; break;\r
+        case 385: ret=595; break;\r
+        case 386: ret=387; break;\r
+        case 388: ret=389; break;\r
+        case 390: ret=596; break;\r
+        case 391: ret=392; break;\r
+        case 393: ret=598; break;\r
+        case 394: ret=599; break;\r
+        case 395: ret=396; break;\r
+        case 398: ret=600; break;\r
+        case 399: ret=601; break;\r
+        case 400: ret=603; break;\r
+        case 401: ret=402; break;\r
+        case 403: ret=608; break;\r
+        case 404: ret=611; break;\r
+        case 406: ret=617; break;\r
+        case 407: ret=616; break;\r
+        case 408: ret=409; break;\r
+        case 412: ret=623; break;\r
+        case 413: ret=626; break;\r
+        case 416: ret=417; break;\r
+        case 418: ret=419; break;\r
+        case 420: ret=421; break;\r
+        case 423: ret=424; break;\r
+        case 425: ret=643; break;\r
+        case 428: ret=429; break;\r
+        case 430: ret=648; break;\r
+        case 431: ret=432; break;\r
+        case 433: ret=650; break;\r
+        case 434: ret=651; break;\r
+        case 435: ret=436; break;\r
+        case 437: ret=438; break;\r
+        case 439: ret=658; break;\r
+        case 440: ret=441; break;\r
+        case 444: ret=445; break;\r
+        case 452: ret=454; break;\r
+        case 453: ret=454; break;\r
+        case 455: ret=457; break;\r
+        case 456: ret=457; break;\r
+        case 458: ret=460; break;\r
+        case 459: ret=460; break;\r
+        case 461: ret=462; break;\r
+        case 463: ret=464; break;\r
+        case 465: ret=466; break;\r
+        case 467: ret=468; break;\r
+        case 469: ret=470; break;\r
+        case 471: ret=472; break;\r
+        case 473: ret=474; break;\r
+        case 475: ret=476; break;\r
+        case 478: ret=479; break;\r
+        case 480: ret=481; break;\r
+        case 482: ret=483; break;\r
+        case 484: ret=485; break;\r
+        case 486: ret=487; break;\r
+        case 488: ret=489; break;\r
+        case 490: ret=491; break;\r
+        case 492: ret=493; break;\r
+        case 494: ret=495; break;\r
+        case 497: ret=499; break;\r
+        case 498: ret=499; break;\r
+        case 500: ret=501; break;\r
+        case 506: ret=507; break;\r
+        case 508: ret=509; break;\r
+        case 510: ret=511; break;\r
+        case 512: ret=513; break;\r
+        case 514: ret=515; break;\r
+        case 516: ret=517; break;\r
+        case 518: ret=519; break;\r
+        case 520: ret=521; break;\r
+        case 522: ret=523; break;\r
+        case 524: ret=525; break;\r
+        case 526: ret=527; break;\r
+        case 528: ret=529; break;\r
+        case 530: ret=531; break;\r
+        case 532: ret=533; break;\r
+        case 534: ret=535; break;\r
+        case 902: ret=940; break;\r
+        case 904: ret=941; break;\r
+        case 905: ret=942; break;\r
+        case 906: ret=943; break;\r
+        case 908: ret=972; break;\r
+        case 910: ret=973; break;\r
+        case 911: ret=974; break;\r
+        case 913: ret=945; break;\r
+        case 914: ret=946; break;\r
+        case 915: ret=947; break;\r
+        case 916: ret=948; break;\r
+        case 917: ret=949; break;\r
+        case 918: ret=950; break;\r
+        case 919: ret=951; break;\r
+        case 920: ret=952; break;\r
+        case 921: ret=953; break;\r
+        case 922: ret=954; break;\r
+        case 923: ret=955; break;\r
+        case 924: ret=956; break;\r
+        case 925: ret=957; break;\r
+        case 926: ret=958; break;\r
+        case 927: ret=959; break;\r
+        case 928: ret=960; break;\r
+        case 929: ret=961; break;\r
+        case 931: ret=963; break;\r
+        case 932: ret=964; break;\r
+        case 933: ret=965; break;\r
+        case 934: ret=966; break;\r
+        case 935: ret=967; break;\r
+        case 936: ret=968; break;\r
+        case 937: ret=969; break;\r
+        case 938: ret=970; break;\r
+        case 939: ret=971; break;\r
+        case 994: ret=995; break;\r
+        case 996: ret=997; break;\r
+        case 998: ret=999; break;\r
+        case 1000: ret=1001; break;\r
+        case 1002: ret=1003; break;\r
+        case 1004: ret=1005; break;\r
+        case 1006: ret=1007; break;\r
+        case 1025: ret=1105; break;\r
+        case 1026: ret=1106; break;\r
+        case 1027: ret=1107; break;\r
+        case 1028: ret=1108; break;\r
+        case 1029: ret=1109; break;\r
+        case 1030: ret=1110; break;\r
+        case 1031: ret=1111; break;\r
+        case 1032: ret=1112; break;\r
+        case 1033: ret=1113; break;\r
+        case 1034: ret=1114; break;\r
+        case 1035: ret=1115; break;\r
+        case 1036: ret=1116; break;\r
+        case 1038: ret=1118; break;\r
+        case 1039: ret=1119; break;\r
+        case 1040: ret=1072; break;\r
+        case 1041: ret=1073; break;\r
+        case 1042: ret=1074; break;\r
+        case 1043: ret=1075; break;\r
+        case 1044: ret=1076; break;\r
+        case 1045: ret=1077; break;\r
+        case 1046: ret=1078; break;\r
+        case 1047: ret=1079; break;\r
+        case 1048: ret=1080; break;\r
+        case 1049: ret=1081; break;\r
+        case 1050: ret=1082; break;\r
+        case 1051: ret=1083; break;\r
+        case 1052: ret=1084; break;\r
+        case 1053: ret=1085; break;\r
+        case 1054: ret=1086; break;\r
+        case 1055: ret=1087; break;\r
+        case 1056: ret=1088; break;\r
+        case 1057: ret=1089; break;\r
+        case 1058: ret=1090; break;\r
+        case 1059: ret=1091; break;\r
+        case 1060: ret=1092; break;\r
+        case 1061: ret=1093; break;\r
+        case 1062: ret=1094; break;\r
+        case 1063: ret=1095; break;\r
+        case 1064: ret=1096; break;\r
+        case 1065: ret=1097; break;\r
+        case 1066: ret=1098; break;\r
+        case 1067: ret=1099; break;\r
+        case 1068: ret=1100; break;\r
+        case 1069: ret=1101; break;\r
+        case 1070: ret=1102; break;\r
+        case 1071: ret=1103; break;\r
+        case 1120: ret=1121; break;\r
+        case 1122: ret=1123; break;\r
+        case 1124: ret=1125; break;\r
+        case 1126: ret=1127; break;\r
+        case 1128: ret=1129; break;\r
+        case 1130: ret=1131; break;\r
+        case 1132: ret=1133; break;\r
+        case 1134: ret=1135; break;\r
+        case 1136: ret=1137; break;\r
+        case 1138: ret=1139; break;\r
+        case 1140: ret=1141; break;\r
+        case 1142: ret=1143; break;\r
+        case 1144: ret=1145; break;\r
+        case 1146: ret=1147; break;\r
+        case 1148: ret=1149; break;\r
+        case 1150: ret=1151; break;\r
+        case 1152: ret=1153; break;\r
+        case 1168: ret=1169; break;\r
+        case 1170: ret=1171; break;\r
+        case 1172: ret=1173; break;\r
+        case 1174: ret=1175; break;\r
+        case 1176: ret=1177; break;\r
+        case 1178: ret=1179; break;\r
+        case 1180: ret=1181; break;\r
+        case 1182: ret=1183; break;\r
+        case 1184: ret=1185; break;\r
+        case 1186: ret=1187; break;\r
+        case 1188: ret=1189; break;\r
+        case 1190: ret=1191; break;\r
+        case 1192: ret=1193; break;\r
+        case 1194: ret=1195; break;\r
+        case 1196: ret=1197; break;\r
+        case 1198: ret=1199; break;\r
+        case 1200: ret=1201; break;\r
+        case 1202: ret=1203; break;\r
+        case 1204: ret=1205; break;\r
+        case 1206: ret=1207; break;\r
+        case 1208: ret=1209; break;\r
+        case 1210: ret=1211; break;\r
+        case 1212: ret=1213; break;\r
+        case 1214: ret=1215; break;\r
+        case 1217: ret=1218; break;\r
+        case 1219: ret=1220; break;\r
+        case 1223: ret=1224; break;\r
+        case 1227: ret=1228; break;\r
+        case 1232: ret=1233; break;\r
+        case 1234: ret=1235; break;\r
+        case 1236: ret=1237; break;\r
+        case 1238: ret=1239; break;\r
+        case 1240: ret=1241; break;\r
+        case 1242: ret=1243; break;\r
+        case 1244: ret=1245; break;\r
+        case 1246: ret=1247; break;\r
+        case 1248: ret=1249; break;\r
+        case 1250: ret=1251; break;\r
+        case 1252: ret=1253; break;\r
+        case 1254: ret=1255; break;\r
+        case 1256: ret=1257; break;\r
+        case 1258: ret=1259; break;\r
+        case 1262: ret=1263; break;\r
+        case 1264: ret=1265; break;\r
+        case 1266: ret=1267; break;\r
+        case 1268: ret=1269; break;\r
+        case 1272: ret=1273; break;\r
+        case 1329: ret=1377; break;\r
+        case 1330: ret=1378; break;\r
+        case 1331: ret=1379; break;\r
+        case 1332: ret=1380; break;\r
+        case 1333: ret=1381; break;\r
+        case 1334: ret=1382; break;\r
+        case 1335: ret=1383; break;\r
+        case 1336: ret=1384; break;\r
+        case 1337: ret=1385; break;\r
+        case 1338: ret=1386; break;\r
+        case 1339: ret=1387; break;\r
+        case 1340: ret=1388; break;\r
+        case 1341: ret=1389; break;\r
+        case 1342: ret=1390; break;\r
+        case 1343: ret=1391; break;\r
+        case 1344: ret=1392; break;\r
+        case 1345: ret=1393; break;\r
+        case 1346: ret=1394; break;\r
+        case 1347: ret=1395; break;\r
+        case 1348: ret=1396; break;\r
+        case 1349: ret=1397; break;\r
+        case 1350: ret=1398; break;\r
+        case 1351: ret=1399; break;\r
+        case 1352: ret=1400; break;\r
+        case 1353: ret=1401; break;\r
+        case 1354: ret=1402; break;\r
+        case 1355: ret=1403; break;\r
+        case 1356: ret=1404; break;\r
+        case 1357: ret=1405; break;\r
+        case 1358: ret=1406; break;\r
+        case 1359: ret=1407; break;\r
+        case 1360: ret=1408; break;\r
+        case 1361: ret=1409; break;\r
+        case 1362: ret=1410; break;\r
+        case 1363: ret=1411; break;\r
+        case 1364: ret=1412; break;\r
+        case 1365: ret=1413; break;\r
+        case 1366: ret=1414; break;\r
+        case 4256: ret=4304; break;\r
+        case 4257: ret=4305; break;\r
+        case 4258: ret=4306; break;\r
+        case 4259: ret=4307; break;\r
+        case 4260: ret=4308; break;\r
+        case 4261: ret=4309; break;\r
+        case 4262: ret=4310; break;\r
+        case 4263: ret=4311; break;\r
+        case 4264: ret=4312; break;\r
+        case 4265: ret=4313; break;\r
+        case 4266: ret=4314; break;\r
+        case 4267: ret=4315; break;\r
+        case 4268: ret=4316; break;\r
+        case 4269: ret=4317; break;\r
+        case 4270: ret=4318; break;\r
+        case 4271: ret=4319; break;\r
+        case 4272: ret=4320; break;\r
+        case 4273: ret=4321; break;\r
+        case 4274: ret=4322; break;\r
+        case 4275: ret=4323; break;\r
+        case 4276: ret=4324; break;\r
+        case 4277: ret=4325; break;\r
+        case 4278: ret=4326; break;\r
+        case 4279: ret=4327; break;\r
+        case 4280: ret=4328; break;\r
+        case 4281: ret=4329; break;\r
+        case 4282: ret=4330; break;\r
+        case 4283: ret=4331; break;\r
+        case 4284: ret=4332; break;\r
+        case 4285: ret=4333; break;\r
+        case 4286: ret=4334; break;\r
+        case 4287: ret=4335; break;\r
+        case 4288: ret=4336; break;\r
+        case 4289: ret=4337; break;\r
+        case 4290: ret=4338; break;\r
+        case 4291: ret=4339; break;\r
+        case 4292: ret=4340; break;\r
+        case 4293: ret=4341; break;\r
+        case 7680: ret=7681; break;\r
+        case 7682: ret=7683; break;\r
+        case 7684: ret=7685; break;\r
+        case 7686: ret=7687; break;\r
+        case 7688: ret=7689; break;\r
+        case 7690: ret=7691; break;\r
+        case 7692: ret=7693; break;\r
+        case 7694: ret=7695; break;\r
+        case 7696: ret=7697; break;\r
+        case 7698: ret=7699; break;\r
+        case 7700: ret=7701; break;\r
+        case 7702: ret=7703; break;\r
+        case 7704: ret=7705; break;\r
+        case 7706: ret=7707; break;\r
+        case 7708: ret=7709; break;\r
+        case 7710: ret=7711; break;\r
+        case 7712: ret=7713; break;\r
+        case 7714: ret=7715; break;\r
+        case 7716: ret=7717; break;\r
+        case 7718: ret=7719; break;\r
+        case 7720: ret=7721; break;\r
+        case 7722: ret=7723; break;\r
+        case 7724: ret=7725; break;\r
+        case 7726: ret=7727; break;\r
+        case 7728: ret=7729; break;\r
+        case 7730: ret=7731; break;\r
+        case 7732: ret=7733; break;\r
+        case 7734: ret=7735; break;\r
+        case 7736: ret=7737; break;\r
+        case 7738: ret=7739; break;\r
+        case 7740: ret=7741; break;\r
+        case 7742: ret=7743; break;\r
+        case 7744: ret=7745; break;\r
+        case 7746: ret=7747; break;\r
+        case 7748: ret=7749; break;\r
+        case 7750: ret=7751; break;\r
+        case 7752: ret=7753; break;\r
+        case 7754: ret=7755; break;\r
+        case 7756: ret=7757; break;\r
+        case 7758: ret=7759; break;\r
+        case 7760: ret=7761; break;\r
+        case 7762: ret=7763; break;\r
+        case 7764: ret=7765; break;\r
+        case 7766: ret=7767; break;\r
+        case 7768: ret=7769; break;\r
+        case 7770: ret=7771; break;\r
+        case 7772: ret=7773; break;\r
+        case 7774: ret=7775; break;\r
+        case 7776: ret=7777; break;\r
+        case 7778: ret=7779; break;\r
+        case 7780: ret=7781; break;\r
+        case 7782: ret=7783; break;\r
+        case 7784: ret=7785; break;\r
+        case 7786: ret=7787; break;\r
+        case 7788: ret=7789; break;\r
+        case 7790: ret=7791; break;\r
+        case 7792: ret=7793; break;\r
+        case 7794: ret=7795; break;\r
+        case 7796: ret=7797; break;\r
+        case 7798: ret=7799; break;\r
+        case 7800: ret=7801; break;\r
+        case 7802: ret=7803; break;\r
+        case 7804: ret=7805; break;\r
+        case 7806: ret=7807; break;\r
+        case 7808: ret=7809; break;\r
+        case 7810: ret=7811; break;\r
+        case 7812: ret=7813; break;\r
+        case 7814: ret=7815; break;\r
+        case 7816: ret=7817; break;\r
+        case 7818: ret=7819; break;\r
+        case 7820: ret=7821; break;\r
+        case 7822: ret=7823; break;\r
+        case 7824: ret=7825; break;\r
+        case 7826: ret=7827; break;\r
+        case 7828: ret=7829; break;\r
+        case 7840: ret=7841; break;\r
+        case 7842: ret=7843; break;\r
+        case 7844: ret=7845; break;\r
+        case 7846: ret=7847; break;\r
+        case 7848: ret=7849; break;\r
+        case 7850: ret=7851; break;\r
+        case 7852: ret=7853; break;\r
+        case 7854: ret=7855; break;\r
+        case 7856: ret=7857; break;\r
+        case 7858: ret=7859; break;\r
+        case 7860: ret=7861; break;\r
+        case 7862: ret=7863; break;\r
+        case 7864: ret=7865; break;\r
+        case 7866: ret=7867; break;\r
+        case 7868: ret=7869; break;\r
+        case 7870: ret=7871; break;\r
+        case 7872: ret=7873; break;\r
+        case 7874: ret=7875; break;\r
+        case 7876: ret=7877; break;\r
+        case 7878: ret=7879; break;\r
+        case 7880: ret=7881; break;\r
+        case 7882: ret=7883; break;\r
+        case 7884: ret=7885; break;\r
+        case 7886: ret=7887; break;\r
+        case 7888: ret=7889; break;\r
+        case 7890: ret=7891; break;\r
+        case 7892: ret=7893; break;\r
+        case 7894: ret=7895; break;\r
+        case 7896: ret=7897; break;\r
+        case 7898: ret=7899; break;\r
+        case 7900: ret=7901; break;\r
+        case 7902: ret=7903; break;\r
+        case 7904: ret=7905; break;\r
+        case 7906: ret=7907; break;\r
+        case 7908: ret=7909; break;\r
+        case 7910: ret=7911; break;\r
+        case 7912: ret=7913; break;\r
+        case 7914: ret=7915; break;\r
+        case 7916: ret=7917; break;\r
+        case 7918: ret=7919; break;\r
+        case 7920: ret=7921; break;\r
+        case 7922: ret=7923; break;\r
+        case 7924: ret=7925; break;\r
+        case 7926: ret=7927; break;\r
+        case 7928: ret=7929; break;\r
+        case 7944: ret=7936; break;\r
+        case 7945: ret=7937; break;\r
+        case 7946: ret=7938; break;\r
+        case 7947: ret=7939; break;\r
+        case 7948: ret=7940; break;\r
+        case 7949: ret=7941; break;\r
+        case 7950: ret=7942; break;\r
+        case 7951: ret=7943; break;\r
+        case 7960: ret=7952; break;\r
+        case 7961: ret=7953; break;\r
+        case 7962: ret=7954; break;\r
+        case 7963: ret=7955; break;\r
+        case 7964: ret=7956; break;\r
+        case 7965: ret=7957; break;\r
+        case 7976: ret=7968; break;\r
+        case 7977: ret=7969; break;\r
+        case 7978: ret=7970; break;\r
+        case 7979: ret=7971; break;\r
+        case 7980: ret=7972; break;\r
+        case 7981: ret=7973; break;\r
+        case 7982: ret=7974; break;\r
+        case 7983: ret=7975; break;\r
+        case 7992: ret=7984; break;\r
+        case 7993: ret=7985; break;\r
+        case 7994: ret=7986; break;\r
+        case 7995: ret=7987; break;\r
+        case 7996: ret=7988; break;\r
+        case 7997: ret=7989; break;\r
+        case 7998: ret=7990; break;\r
+        case 7999: ret=7991; break;\r
+        case 8008: ret=8000; break;\r
+        case 8009: ret=8001; break;\r
+        case 8010: ret=8002; break;\r
+        case 8011: ret=8003; break;\r
+        case 8012: ret=8004; break;\r
+        case 8013: ret=8005; break;\r
+        case 8025: ret=8017; break;\r
+        case 8027: ret=8019; break;\r
+        case 8029: ret=8021; break;\r
+        case 8031: ret=8023; break;\r
+        case 8040: ret=8032; break;\r
+        case 8041: ret=8033; break;\r
+        case 8042: ret=8034; break;\r
+        case 8043: ret=8035; break;\r
+        case 8044: ret=8036; break;\r
+        case 8045: ret=8037; break;\r
+        case 8046: ret=8038; break;\r
+        case 8047: ret=8039; break;\r
+        case 8072: ret=8064; break;\r
+        case 8073: ret=8065; break;\r
+        case 8074: ret=8066; break;\r
+        case 8075: ret=8067; break;\r
+        case 8076: ret=8068; break;\r
+        case 8077: ret=8069; break;\r
+        case 8078: ret=8070; break;\r
+        case 8079: ret=8071; break;\r
+        case 8088: ret=8080; break;\r
+        case 8089: ret=8081; break;\r
+        case 8090: ret=8082; break;\r
+        case 8091: ret=8083; break;\r
+        case 8092: ret=8084; break;\r
+        case 8093: ret=8085; break;\r
+        case 8094: ret=8086; break;\r
+        case 8095: ret=8087; break;\r
+        case 8104: ret=8096; break;\r
+        case 8105: ret=8097; break;\r
+        case 8106: ret=8098; break;\r
+        case 8107: ret=8099; break;\r
+        case 8108: ret=8100; break;\r
+        case 8109: ret=8101; break;\r
+        case 8110: ret=8102; break;\r
+        case 8111: ret=8103; break;\r
+        case 8120: ret=8112; break;\r
+        case 8121: ret=8113; break;\r
+        case 8122: ret=8048; break;\r
+        case 8123: ret=8049; break;\r
+        case 8124: ret=8115; break;\r
+        case 8136: ret=8050; break;\r
+        case 8137: ret=8051; break;\r
+        case 8138: ret=8052; break;\r
+        case 8139: ret=8053; break;\r
+        case 8140: ret=8131; break;\r
+        case 8152: ret=8144; break;\r
+        case 8153: ret=8145; break;\r
+        case 8154: ret=8054; break;\r
+        case 8155: ret=8055; break;\r
+        case 8168: ret=8160; break;\r
+        case 8169: ret=8161; break;\r
+        case 8170: ret=8058; break;\r
+        case 8171: ret=8059; break;\r
+        case 8172: ret=8165; break;\r
+        case 8184: ret=8056; break;\r
+        case 8185: ret=8057; break;\r
+        case 8186: ret=8060; break;\r
+        case 8187: ret=8061; break;\r
+        case 8188: ret=8179; break;\r
+        case 8544: ret=8560; break;\r
+        case 8545: ret=8561; break;\r
+        case 8546: ret=8562; break;\r
+        case 8547: ret=8563; break;\r
+        case 8548: ret=8564; break;\r
+        case 8549: ret=8565; break;\r
+        case 8550: ret=8566; break;\r
+        case 8551: ret=8567; break;\r
+        case 8552: ret=8568; break;\r
+        case 8553: ret=8569; break;\r
+        case 8554: ret=8570; break;\r
+        case 8555: ret=8571; break;\r
+        case 8556: ret=8572; break;\r
+        case 8557: ret=8573; break;\r
+        case 8558: ret=8574; break;\r
+        case 8559: ret=8575; break;\r
+        case 9398: ret=9424; break;\r
+        case 9399: ret=9425; break;\r
+        case 9400: ret=9426; break;\r
+        case 9401: ret=9427; break;\r
+        case 9402: ret=9428; break;\r
+        case 9403: ret=9429; break;\r
+        case 9404: ret=9430; break;\r
+        case 9405: ret=9431; break;\r
+        case 9406: ret=9432; break;\r
+        case 9407: ret=9433; break;\r
+        case 9408: ret=9434; break;\r
+        case 9409: ret=9435; break;\r
+        case 9410: ret=9436; break;\r
+        case 9411: ret=9437; break;\r
+        case 9412: ret=9438; break;\r
+        case 9413: ret=9439; break;\r
+        case 9414: ret=9440; break;\r
+        case 9415: ret=9441; break;\r
+        case 9416: ret=9442; break;\r
+        case 9417: ret=9443; break;\r
+        case 9418: ret=9444; break;\r
+        case 9419: ret=9445; break;\r
+        case 9420: ret=9446; break;\r
+        case 9421: ret=9447; break;\r
+        case 9422: ret=9448; break;\r
+        case 9423: ret=9449; break;\r
+        case 65313: ret=65345; break;\r
+        case 65314: ret=65346; break;\r
+        case 65315: ret=65347; break;\r
+        case 65316: ret=65348; break;\r
+        case 65317: ret=65349; break;\r
+        case 65318: ret=65350; break;\r
+        case 65319: ret=65351; break;\r
+        case 65320: ret=65352; break;\r
+        case 65321: ret=65353; break;\r
+        case 65322: ret=65354; break;\r
+        case 65323: ret=65355; break;\r
+        case 65324: ret=65356; break;\r
+        case 65325: ret=65357; break;\r
+        case 65326: ret=65358; break;\r
+        case 65327: ret=65359; break;\r
+        case 65328: ret=65360; break;\r
+        case 65329: ret=65361; break;\r
+        case 65330: ret=65362; break;\r
+        case 65331: ret=65363; break;\r
+        case 65332: ret=65364; break;\r
+        case 65333: ret=65365; break;\r
+        case 65334: ret=65366; break;\r
+        case 65335: ret=65367; break;\r
+        case 65336: ret=65368; break;\r
+        case 65337: ret=65369; break;\r
+        case 65338: ret=65370; break;\r
+        }\r
+        return (char)ret;\r
+      }\r
+      return Character.toLowerCase(c);\r
+    }\r
+    /** Convert a String to title case. */\r
+    public static String toTitleCase(String s) {\r
+        StringBuffer sb = new StringBuffer();\r
+        for(int i=0;i<s.length();i++)\r
+            sb.append(CaseMgr.toTitleCase(s.charAt(i)));\r
+        return sb.toString();\r
+    }\r
+    /** Convert a String to upper case. */\r
+    public static String toUpperCase(String s) {\r
+        StringBuffer sb = new StringBuffer();\r
+        for(int i=0;i<s.length();i++)\r
+            sb.append(CaseMgr.toUpperCase(s.charAt(i)));\r
+        return sb.toString();\r
+    }\r
+    /** Convert a String to lower case. */\r
+    public static String toLowerCase(String s) {\r
+        StringBuffer sb = new StringBuffer();\r
+        for(int i=0;i<s.length();i++)\r
+            sb.append(CaseMgr.toLowerCase(s.charAt(i)));\r
+        return sb.toString();\r
+    }\r
+    /** Convert a character to title case.*/\r
+    public static char toTitleCase(char c) {\r
+      if(java_1_0) {\r
+        int ret = (int)toUpperCase(c);\r
+        switch(c) {\r
+        case 452: ret=453; break;\r
+        case 453: ret=453; break;\r
+        case 454: ret=453; break;\r
+        case 455: ret=456; break;\r
+        case 456: ret=456; break;\r
+        case 457: ret=456; break;\r
+        case 458: ret=459; break;\r
+        case 459: ret=459; break;\r
+        case 460: ret=459; break;\r
+        case 497: ret=498; break;\r
+        case 498: ret=498; break;\r
+        case 499: ret=498; break;\r
+        }\r
+        return (char)ret;\r
+      }\r
+      return Character.toTitleCase(c);\r
+    }\r
+    /** Duplicates the regionMatches routine of String -- but\r
+        makes use of the definitions of upper, lower, and title\r
+        case in this class when ignoreCase is set. */\r
+    public static boolean regionMatches( StringLike s1,\r
+        boolean ign,int i1,StringLike s2,int i2,int i3) {\r
+        int itot=i2+i3;\r
+        if(itot>s2.length()||i1+i3>s1.length()) return false;\r
+        if(!ign) {\r
+            for(int i=i2;i<itot;i++)\r
+                if(s2.charAt(i) != s1.charAt(i1++))\r
+                    return false;\r
+        } else {\r
+            for(int i=i2;i<itot;i++)\r
+                if(toLowerCase(s2.charAt(i)) != toLowerCase(s1.charAt(i1++)))\r
+                    return false;\r
+        }\r
+        return true;\r
+    }\r
+    /** Duplicates the regionMatches routine of String -- but\r
+        makes use of the definitions of upper, lower, and title\r
+        case in this class when ignoreCase is set. */\r
+    public static boolean regionMatches( String s1,\r
+        boolean ign,int i1,StringLike s2,int i2,int i3) {\r
+        int itot=i2+i3;\r
+        if(itot>s2.length()||i1+i3>s1.length()) return false;\r
+        if(!ign) {\r
+            for(int i=i2;i<itot;i++)\r
+                if(s2.charAt(i) != s1.charAt(i1++))\r
+                    return false;\r
+        } else {\r
+            for(int i=i2;i<itot;i++)\r
+                if(toLowerCase(s2.charAt(i)) != toLowerCase(s1.charAt(i1++)))\r
+                    return false;\r
+        }\r
+        return true;\r
+    }\r
+    /** Duplicates the regionMatches routine of String -- but\r
+        makes use of the definitions of upper, lower, and title\r
+        case in this class when ignoreCase is set. */\r
+    public static boolean regionMatches( StringLike s1,\r
+        boolean ign,int i1,String s2,int i2,int i3) {\r
+        int itot=i2+i3;\r
+        if(itot>s2.length()||i1+i3>s1.length()) return false;\r
+        if(!ign) {\r
+            for(int i=i2;i<itot;i++)\r
+                if(s2.charAt(i) != s1.charAt(i1++))\r
+                    return false;\r
+        } else {\r
+            for(int i=i2;i<itot;i++)\r
+                if(toLowerCase(s2.charAt(i)) != toLowerCase(s1.charAt(i1++)))\r
+                    return false;\r
+        }\r
+        return true;\r
+    }\r
+    /** Duplicates the regionMatches routine of String -- but\r
+        makes use of the definitions of upper, lower, and title\r
+        case in this class when ignoreCase is set. */\r
+    public static boolean regionMatches( String s1,\r
+        boolean ign,int i1,String s2,int i2,int i3) {\r
+        int itot=i2+i3;\r
+        if(itot>s2.length()||i1+i3>s1.length()) return false;\r
+        if(!ign) {\r
+            for(int i=i2;i<itot;i++)\r
+                if(s2.charAt(i) != s1.charAt(i1++))\r
+                    return false;\r
+        } else {\r
+            for(int i=i2;i<itot;i++)\r
+                if(toLowerCase(s2.charAt(i)) != toLowerCase(s1.charAt(i1++)))\r
+                    return false;\r
+        }\r
+        return true;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/ChangeRule.java b/src/com/stevesoft/pat/ChangeRule.java
new file mode 100755 (executable)
index 0000000..d9ea870
--- /dev/null
@@ -0,0 +1,22 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This class implements user defined special replacement rules\r
+  * of the form ${=name}. See <a href="http://javaregex.com/code/trans2.java.html">trans2.java</a>\r
+  * and <a href="http://javaregex.com/code/trans2a.java.html">trans2a.java</a>.\r
+  */\r
+public class ChangeRule extends SpecialRule {\r
+    Regex NewRule;\r
+    public ChangeRule(ChangeRule c) { NewRule=c.NewRule; }\r
+    public ChangeRule(String nm,Regex rr) { name=nm; NewRule = rr; }\r
+    public ChangeRule(String nm,Transformer tr) { name=nm; NewRule = tr.rp; }\r
+    public Object clone1() { return new ChangeRule(this); }\r
+    public String toString1() { return "${="+name+"}"; }\r
+    public void apply(StringBufferLike sb,RegRes rr) {}\r
+}\r
diff --git a/src/com/stevesoft/pat/CodeRule.java b/src/com/stevesoft/pat/CodeRule.java
new file mode 100755 (executable)
index 0000000..31c779f
--- /dev/null
@@ -0,0 +1,21 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** Implements the rules for \U, \L, \E, \Q in substitutions. */\r
+public final class CodeRule extends SpecialRule {\r
+    char c = 'E';\r
+    public CodeRule() {}\r
+    public CodeRule(char c) {\r
+        this.c = c;\r
+    }\r
+    public void apply(StringBufferLike sb,RegRes res) {\r
+      sb.setMode(c);\r
+    }\r
+    public String toString1() { return "\\"+c; }\r
+}\r
diff --git a/src/com/stevesoft/pat/Ctrl.java b/src/com/stevesoft/pat/Ctrl.java
new file mode 100755 (executable)
index 0000000..ba7fc20
--- /dev/null
@@ -0,0 +1,269 @@
+package//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+com.stevesoft.pat;\r
+\r
+public class Ctrl {\r
+  public final static char[] cmap = {\r
+    (char)64,\r
+    (char)65,\r
+    (char)66,\r
+    (char)67,\r
+    (char)68,\r
+    (char)69,\r
+    (char)70,\r
+    (char)71,\r
+    (char)72,\r
+    (char)73,\r
+    (char)74,\r
+    (char)75,\r
+    (char)76,\r
+    (char)77,\r
+    (char)78,\r
+    (char)79,\r
+    (char)80,\r
+    (char)81,\r
+    (char)82,\r
+    (char)83,\r
+    (char)84,\r
+    (char)85,\r
+    (char)86,\r
+    (char)87,\r
+    (char)88,\r
+    (char)89,\r
+    (char)90,\r
+    (char)91,\r
+    (char)92,\r
+    (char)93,\r
+    (char)94,\r
+    (char)95,\r
+    (char)96,\r
+    (char)97,\r
+    (char)97,\r
+    (char)99,\r
+    (char)100,\r
+    (char)101,\r
+    (char)102,\r
+    (char)103,\r
+    (char)104,\r
+    (char)105,\r
+    (char)106,\r
+    (char)107,\r
+    (char)108,\r
+    (char)109,\r
+    (char)110,\r
+    (char)111,\r
+    (char)112,\r
+    (char)113,\r
+    (char)114,\r
+    (char)115,\r
+    (char)116,\r
+    (char)117,\r
+    (char)118,\r
+    (char)119,\r
+    (char)120,\r
+    (char)121,\r
+    (char)122,\r
+    (char)123,\r
+    (char)124,\r
+    (char)125,\r
+    (char)126,\r
+    (char)127,\r
+    (char)0,\r
+    (char)1,\r
+    (char)2,\r
+    (char)3,\r
+    (char)4,\r
+    (char)5,\r
+    (char)6,\r
+    (char)7,\r
+    (char)8,\r
+    (char)9,\r
+    (char)10,\r
+    (char)11,\r
+    (char)12,\r
+    (char)13,\r
+    (char)14,\r
+    (char)15,\r
+    (char)16,\r
+    (char)17,\r
+    (char)18,\r
+    (char)19,\r
+    (char)20,\r
+    (char)21,\r
+    (char)22,\r
+    (char)23,\r
+    (char)24,\r
+    (char)25,\r
+    (char)26,\r
+    (char)27,\r
+    (char)27,\r
+    (char)29,\r
+    (char)30,\r
+    (char)31,\r
+    (char)32,\r
+    (char)1,\r
+    (char)2,\r
+    (char)3,\r
+    (char)4,\r
+    (char)5,\r
+    (char)6,\r
+    (char)7,\r
+    (char)8,\r
+    (char)9,\r
+    (char)10,\r
+    (char)11,\r
+    (char)12,\r
+    (char)13,\r
+    (char)14,\r
+    (char)15,\r
+    (char)16,\r
+    (char)17,\r
+    (char)18,\r
+    (char)19,\r
+    (char)20,\r
+    (char)21,\r
+    (char)22,\r
+    (char)23,\r
+    (char)24,\r
+    (char)25,\r
+    (char)26,\r
+    (char)59,\r
+    (char)60,\r
+    (char)61,\r
+    (char)62,\r
+    (char)63,\r
+    (char)192,\r
+    (char)193,\r
+    (char)194,\r
+    (char)195,\r
+    (char)196,\r
+    (char)197,\r
+    (char)198,\r
+    (char)199,\r
+    (char)200,\r
+    (char)201,\r
+    (char)202,\r
+    (char)203,\r
+    (char)204,\r
+    (char)205,\r
+    (char)206,\r
+    (char)207,\r
+    (char)208,\r
+    (char)209,\r
+    (char)210,\r
+    (char)211,\r
+    (char)212,\r
+    (char)213,\r
+    (char)214,\r
+    (char)215,\r
+    (char)216,\r
+    (char)217,\r
+    (char)218,\r
+    (char)219,\r
+    (char)220,\r
+    (char)221,\r
+    (char)222,\r
+    (char)223,\r
+    (char)224,\r
+    (char)225,\r
+    (char)226,\r
+    (char)227,\r
+    (char)228,\r
+    (char)229,\r
+    (char)230,\r
+    (char)231,\r
+    (char)232,\r
+    (char)233,\r
+    (char)234,\r
+    (char)235,\r
+    (char)236,\r
+    (char)237,\r
+    (char)238,\r
+    (char)239,\r
+    (char)240,\r
+    (char)241,\r
+    (char)242,\r
+    (char)243,\r
+    (char)244,\r
+    (char)245,\r
+    (char)246,\r
+    (char)247,\r
+    (char)248,\r
+    (char)249,\r
+    (char)250,\r
+    (char)251,\r
+    (char)252,\r
+    (char)253,\r
+    (char)254,\r
+    (char)255,\r
+    (char)128,\r
+    (char)129,\r
+    (char)130,\r
+    (char)131,\r
+    (char)132,\r
+    (char)133,\r
+    (char)134,\r
+    (char)135,\r
+    (char)136,\r
+    (char)137,\r
+    (char)138,\r
+    (char)139,\r
+    (char)140,\r
+    (char)141,\r
+    (char)142,\r
+    (char)143,\r
+    (char)144,\r
+    (char)145,\r
+    (char)146,\r
+    (char)147,\r
+    (char)148,\r
+    (char)149,\r
+    (char)150,\r
+    (char)151,\r
+    (char)152,\r
+    (char)153,\r
+    (char)154,\r
+    (char)155,\r
+    (char)156,\r
+    (char)157,\r
+    (char)158,\r
+    (char)159,\r
+    (char)160,\r
+    (char)161,\r
+    (char)162,\r
+    (char)163,\r
+    (char)164,\r
+    (char)165,\r
+    (char)166,\r
+    (char)167,\r
+    (char)168,\r
+    (char)169,\r
+    (char)170,\r
+    (char)171,\r
+    (char)172,\r
+    (char)173,\r
+    (char)174,\r
+    (char)175,\r
+    (char)176,\r
+    (char)177,\r
+    (char)178,\r
+    (char)179,\r
+    (char)180,\r
+    (char)181,\r
+    (char)182,\r
+    (char)183,\r
+    (char)184,\r
+    (char)185,\r
+    (char)186,\r
+    (char)187,\r
+    (char)188,\r
+    (char)189,\r
+    (char)190,\r
+    (char)191\r
+  };\r
+}\r
diff --git a/src/com/stevesoft/pat/Custom.java b/src/com/stevesoft/pat/Custom.java
new file mode 100755 (executable)
index 0000000..e7621a1
--- /dev/null
@@ -0,0 +1,42 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** Simple custom patterns.  See\r
+    <a href="http://javaregex.com/code/deriv2.java.html">deriv2.java</a>\r
+    and <a href="http://javaregex.com/code/deriv3.java.html">deriv3.java</a>\r
+    in the test directory.\r
+    @see com.stevesoft.pat.CustomEndpoint\r
+ */\r
+class Custom extends PatternSub {\r
+    String select;\r
+    Validator v;\r
+    int start;\r
+    Custom(String s) {\r
+        select = s;\r
+        v = (Validator)Regex.validators.get(s);\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        start = pos;\r
+        return sub.matchInternal(pos,pt);\r
+    }\r
+    public String toString() {\r
+        String a = v.argsave == null ? "" : ":"+v.argsave;\r
+        return "(??"+select+a+")"+nextString();\r
+    }\r
+    public patInt minChars() { return v.minChars(); }\r
+    public patInt maxChars() { return v.maxChars(); }\r
+    Pattern clone1(Hashtable h) {\r
+        Custom c = new Custom(select);\r
+        h.put(c,c);\r
+        h.put(this,c);\r
+        c.sub = sub.clone(h);\r
+        return c;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/CustomEndpoint.java b/src/com/stevesoft/pat/CustomEndpoint.java
new file mode 100755 (executable)
index 0000000..b8fc704
--- /dev/null
@@ -0,0 +1,27 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** This class is needed internally to make backtracking work\r
+  * correctly in user-defined patterns.\r
+  */\r
+class CustomEndpoint extends Pattern {\r
+    Custom c;\r
+    CustomEndpoint(Custom cm) { c = cm; }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        int npos = c.v.validate(pt.src,c.start,pos);\r
+        if(npos >= 0) \r
+            return nextMatch(npos,pt);\r
+        return -1;\r
+    }\r
+    public String toString() { return ""; }\r
+    Pattern clone1(Hashtable h) {\r
+        return new CustomEndpoint((Custom)c.clone(h));\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/DirFileRegex.java b/src/com/stevesoft/pat/DirFileRegex.java
new file mode 100755 (executable)
index 0000000..731457c
--- /dev/null
@@ -0,0 +1,19 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.io.File;\r
+\r
+/** This class is just like FileRegex, except that its accept method\r
+ only returns true if the file matching the pattern is a directory.*/\r
+public class DirFileRegex extends FileRegex {\r
+    public DirFileRegex() { dirflag = DIR; }\r
+    public DirFileRegex(String fp) { super(fp); dirflag = DIR; }\r
+    public static String[] list(String f) {\r
+        return list(f,DIR);\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/DotMulti.java b/src/com/stevesoft/pat/DotMulti.java
new file mode 100755 (executable)
index 0000000..514c161
--- /dev/null
@@ -0,0 +1,125 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** A special optimization of multi that is used when the\r
+  * common subpattern ".*" is encountered.\r
+  */\r
+class DotMulti extends PatternSub {\r
+    patInt fewestMatches,mostMatches;\r
+    public patInt minChars() {\r
+        return fewestMatches;\r
+    }\r
+    public patInt maxChars() {\r
+        return mostMatches;\r
+    }\r
+    public boolean matchFewest = false;\r
+\r
+    StringLike src=null;\r
+    int srclength=0;\r
+    boolean dotDoesntMatchCR=true;\r
+    DotMulti(patInt a,patInt b) {\r
+        fewestMatches = a;\r
+        mostMatches = b;\r
+    }\r
+    public String toString() {\r
+        return ".{"\r
+            +fewestMatches+","+mostMatches+"}"+\r
+            (matchFewest ? "?" : "")+"(?# <= dot multi)"+\r
+            nextString();\r
+    }\r
+    final int submatchInternal(int pos,Pthings pt) {\r
+        if(pos < srclength) {\r
+            if(dotDoesntMatchCR) {\r
+                if(src.charAt(pos) != '\n')\r
+                    return 1+pos;\r
+            } else return 1+pos;\r
+        }\r
+        return -1;\r
+    }\r
+    final static int step = 1;\r
+    static int idcount = 1;\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        int m=-1;\r
+        int i=pos;\r
+        src = pt.src;\r
+        srclength = src.length();\r
+        dotDoesntMatchCR = pt.dotDoesntMatchCR;\r
+        if(matchFewest) {\r
+            int nMatches = 0;\r
+            while(fewestMatches.intValue() > nMatches) {\r
+                i=submatchInternal(i,pt);\r
+                if(i<0) return -1;\r
+                nMatches++;\r
+            }\r
+            if(i<0) return -1;\r
+            int ii = nextMatch(i,pt);\r
+            if(ii >= 0) return ii;\r
+            if(!mostMatches.finite()) {\r
+                while(i >= 0) {\r
+                    i = submatchInternal(i,pt);\r
+                    if(i < 0) return -1;\r
+                    ii = nextMatch(i,pt);\r
+                    if(ii >= 0) return ii;\r
+                }\r
+            } else {\r
+                while(i > 0) {\r
+                    i = submatchInternal(i,pt);\r
+                    if(i < 0) return -1;\r
+                    nMatches++;\r
+                    if(nMatches > mostMatches.intValue())\r
+                        return -1;\r
+                    ii = nextMatch(i,pt);\r
+                    if(ii >= 0) return ii;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+        int nMatches = 0;\r
+        while(fewestMatches.intValue() > nMatches) {\r
+            i=submatchInternal(i,pt);\r
+            if(i >= 0)\r
+                nMatches++;\r
+            else\r
+                return -1;\r
+        }\r
+        m=i;\r
+        if(mostMatches.finite()) {\r
+            while(nMatches < mostMatches.intValue()) {\r
+                i = submatchInternal(i,pt);\r
+                if(i>=0) {\r
+                    m=i;\r
+                    nMatches++;\r
+                } else break;\r
+            }\r
+        } else {\r
+            while(true) {\r
+                i = submatchInternal(i,pt);\r
+                if(i>=0) {\r
+                    m=i;\r
+                    nMatches++;\r
+                } else break;\r
+            }\r
+        }\r
+        while(m >= pos) {\r
+            int r=nextMatch(m,pt);\r
+            if(r >= 0) return r;\r
+            m -= step;\r
+            nMatches--;\r
+            if(nMatches < fewestMatches.intValue())\r
+                return -1;\r
+        }\r
+        return -1;\r
+    }\r
+    Pattern clone1(Hashtable h) {\r
+        DotMulti dm = new DotMulti(fewestMatches,mostMatches);\r
+        dm.matchFewest = matchFewest;\r
+        return dm;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/End.java b/src/com/stevesoft/pat/End.java
new file mode 100755 (executable)
index 0000000..75e5acf
--- /dev/null
@@ -0,0 +1,42 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+//class AddToEnd extends RegSyntax {};\r
+\r
+/** Compiles the '$' or the '\Z' Pattern.  It is\r
+ an error to have further Pattern elements after\r
+ '\Z'.  It is the end of the String. */\r
+class End extends Pattern {\r
+    boolean retIsEnd;\r
+    End(boolean b) { retIsEnd = b; }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(retIsEnd && pt.mFlag && pos < pt.src.length()) {\r
+            if(pt.src.charAt(pos)=='\n') {\r
+                return nextMatch(pos,pt);\r
+           }\r
+       }\r
+        if(pt.src.length() == pos)\r
+            return nextMatch(pos,pt);\r
+       else if(pos<pt.src.length())\r
+           // Access the next character...\r
+           // this is crucial to making \r
+           // RegexReader work.\r
+           pt.src.charAt(pos);\r
+        return -1;\r
+    }\r
+    public String toString() {\r
+        if(retIsEnd)\r
+            return "$";\r
+        else\r
+            return "\\Z";\r
+    }\r
+    public patInt maxChars() { return new patInt(1); }\r
+    public Pattern clone1(Hashtable h) { return new End(retIsEnd); }\r
+};\r
diff --git a/src/com/stevesoft/pat/FastBracket.java b/src/com/stevesoft/pat/FastBracket.java
new file mode 100755 (executable)
index 0000000..2720cc4
--- /dev/null
@@ -0,0 +1,191 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.util.*;\r
+\r
+/** Uses table lookup to match [] type constructs, but\r
+    only if it can use a lookup table 256 bits in size.\r
+    It is impractical to make a table if it is too large.\r
+    */\r
+public class FastBracket extends Bracket {\r
+    int min, max;\r
+    BitSet bs;\r
+    FastBracket(boolean n) { super(n); }\r
+    // This routine can optimize a bracket, possibly\r
+    // it will replace it with a FastBracket.\r
+    static Bracket process(Bracket b,boolean ignc) {\r
+        Vector v = b.v;\r
+        b.pv = null;\r
+        try {\r
+\r
+            // Expand out the vector to make separate\r
+            // entries for other cases if ignoreCase is\r
+            // turned on.\r
+            Vector nv = v;\r
+            if(ignc) {\r
+                nv = new Vector();\r
+                for(int i=0;i<v.size();i++) {\r
+                    Pattern p = (Pattern)v.elementAt(i);\r
+                    nv.addElement(p);\r
+                    if(p instanceof oneChar) {\r
+                        oneChar oc = (oneChar)p;\r
+                        nv.addElement(new oneChar(oc.altc));\r
+                    } else if(p instanceof Range) {\r
+                        Range ra = (Range)p;\r
+                        nv.addElement(new Range(ra.altlo,ra.althi));\r
+                    }\r
+                }\r
+            }\r
+            v = nv;\r
+\r
+            // Bubble sort, make sure elements\r
+            // are in order.  This will allow us\r
+            // to merge them.\r
+            for(int i=0;i<v.size()-1;i++) {\r
+                for(int j=0;j<v.size()-1;j++) {\r
+                    char c1 = getl(v.elementAt(j));\r
+                    char c2 = getl(v.elementAt(j+1));\r
+                    if(c2 < c1) {\r
+                        Object o = v.elementAt(j);\r
+                        v.setElementAt(v.elementAt(j+1),j);\r
+                        v.setElementAt(o,j+1);\r
+                    }\r
+                }\r
+            }\r
+\r
+            nv = new Vector();\r
+            // merge -- remove overlaps\r
+            Pattern p = (Pattern)v.elementAt(0);\r
+            nv.addElement(p);\r
+            for(int i=1;i<v.size();i++) {\r
+                if(geth(p)+1 >= getl(v.elementAt(i))) {\r
+                    Pattern p2 = (Pattern)v.elementAt(i);\r
+                    char lo = min(getl(p),getl(p2));\r
+                    char hi = max(geth(p),geth(p2));\r
+                    nv.setElementAt(p=mkelem(lo,hi),nv.size()-1);\r
+                } else {\r
+                    p = (Pattern)v.elementAt(i);\r
+                    nv.addElement(p);\r
+                }\r
+            }\r
+\r
+            b.v = v = nv;\r
+        } catch(RegSyntax e) {\r
+            e.printStackTrace();\r
+        }\r
+\r
+        // We don't want these things to be empty.\r
+        Vector negv = neg(v);\r
+        if(v.size()==1) return b;\r
+        if(negv.size()==1) {\r
+            b.v = negv;\r
+            b.neg = !b.neg;\r
+            return b;\r
+        }\r
+\r
+        // Now consider if we can make a FastBracket.\r
+        // Uses a BitSet to do a lookup.\r
+        FastBracket fb = newbrack(v,b.neg);\r
+        if(fb == null)\r
+            fb = newbrack(negv,!b.neg);\r
+        if(fb != null) {\r
+            fb.parent = b.parent;\r
+            fb.next = b.next;\r
+            return fb;\r
+        }\r
+\r
+        // return the normal Bracket.\r
+        return b;\r
+    }\r
+\r
+    // Build a FastBracket and set bits.  If this can't\r
+    // be done, return null.\r
+    final static FastBracket newbrack(Vector v,boolean neg) {\r
+        FastBracket fb = new FastBracket(neg);\r
+        fb.v = v;\r
+        if(v.size()==0) return null;\r
+        fb.min = getl(v.elementAt(0));\r
+        fb.max = geth(v.elementAt(v.size()-1));\r
+        if(fb.max-fb.min <= 256) {\r
+            fb.bs = new BitSet(fb.max-fb.min+1);\r
+            for(int i=0;i<v.size();i++) {\r
+                Object o = v.elementAt(i);\r
+                int min0 = getl(o)-fb.min;\r
+                int max0 = geth(o)-fb.min;\r
+                for(int j=min0;j<=max0;j++)\r
+                    fb.bs.set(j);\r
+            }\r
+            return fb;\r
+        }\r
+        return null;\r
+    }\r
+\r
+    // Negate a sorted Vector.  Applying this\r
+    // operation twice should yield the same Vector\r
+    // back.\r
+    final static Vector neg(Vector v) {\r
+        try {\r
+            Vector nv = new Vector();\r
+            if(v.size()==0) {\r
+                nv.addElement(new Range((char)0,(char)65535));\r
+                return nv;\r
+            }\r
+            int p0 = getl(v.elementAt(0));\r
+            if(p0!=0)\r
+                nv.addElement(mkelem((char)0,(char)(p0-1) ));\r
+            for(int i=0;i<v.size()-1;i++) {\r
+                int hi = getl(v.elementAt(i+1))-1;\r
+                int lo = geth(v.elementAt(i))+1;\r
+                nv.addElement(mkelem((char)lo,(char)hi));\r
+            }\r
+            int pN = geth(v.lastElement());\r
+            if(pN != 65535)\r
+                nv.addElement(mkelem((char)(pN+1),(char)65535));\r
+            return nv;\r
+        } catch(RegSyntax rs) {\r
+            return null;\r
+        }\r
+    }\r
+    // Make either a Range or oneChar Object, depending on which\r
+    // is appropriate.\r
+    final static Pattern mkelem(char lo,char hi) throws RegSyntax {\r
+        return lo==hi ? (Pattern)(new oneChar(lo)) : (Pattern)(new Range(lo,hi));\r
+    }\r
+    static final char min(char a,char b) {\r
+        return a<b ? a : b;\r
+    }\r
+    static final char max(char a,char b) {\r
+        return a>b ? a : b;\r
+    }\r
+\r
+    // getl -- get lower value of Range object,\r
+    // or get value of oneChar object.\r
+    final static char getl(Object o) {\r
+        Pattern p = (Pattern)o;\r
+        if(p instanceof Range)\r
+            return ((Range)p).lo;\r
+        return ((oneChar)p).c;\r
+    }\r
+    // geth -- get higher value of Range object,\r
+    // or get value of oneChar object.\r
+    final static char geth(Object o) {\r
+        Pattern p = (Pattern)o;\r
+        if(p instanceof Range)\r
+            return ((Range)p).hi;\r
+        return ((oneChar)p).c;\r
+    }\r
+\r
+    // This is the easy part!\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(pos >= pt.src.length() || Masked(pos,pt)) return -1;\r
+        char c = pt.src.charAt(pos);\r
+        return (neg ^ (c >= min && c <= max && bs.get(c-min)) ) ?\r
+            nextMatch(pos+1,pt) : -1;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/FastMulti.java b/src/com/stevesoft/pat/FastMulti.java
new file mode 100755 (executable)
index 0000000..2a38281
--- /dev/null
@@ -0,0 +1,111 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** A special case of Multi, implemented when minChars().equals(maxChars()),\r
+  * and some other conditions spelled out in RegOpt.safe4fm "Safe for\r
+  * FastMulti."  It avoids stack growth problems as well as being slightly\r
+  * faster.\r
+  */\r
+class FastMulti extends PatternSub {\r
+    patInt fewestMatches,mostMatches;\r
+    public patInt minChars() {\r
+        return sub.countMinChars().mul(fewestMatches);\r
+    }\r
+    public patInt maxChars() {\r
+        return sub.countMaxChars().mul(mostMatches);\r
+    }\r
+    public boolean matchFewest = false;\r
+\r
+    FastMulti(patInt a,patInt b,Pattern p) throws RegSyntax {\r
+        if(p == null) RegSyntaxError.endItAll("Null length pattern "+\r
+                "followed by *, +, or other Multi.");\r
+        fewestMatches = a;\r
+        mostMatches = b;\r
+        sub = p;\r
+        step = p.countMinChars().intValue();\r
+        sub.setParent(null);\r
+    }\r
+    public String toString() {\r
+        return sub.toString()+"{"\r
+            +fewestMatches+","+mostMatches+"}"+\r
+            (matchFewest ? "?" : "")+"(?# <= fast multi)"+\r
+            nextString();\r
+    }\r
+    int step = -1;\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        int m=-1;\r
+        int i=pos;\r
+        int endstr = pt.src.length()-step;\r
+        patInt matches = new patInt(0);\r
+        if(matchFewest) {\r
+            if(fewestMatches.lessEq(matches)) {\r
+                int ii = nextMatch(i,pt);\r
+                if(ii >= 0) return ii;\r
+            }\r
+            while(i >= 0 && i <= endstr) {\r
+                i=sub.matchInternal(i,pt);\r
+                if(i >= 0) {\r
+                    matches.inc();\r
+                    if(fewestMatches.lessEq(matches)) {\r
+                        int ii = nextMatch(i,pt);\r
+                        if(ii >= 0) return ii;\r
+                    }\r
+                    if(matches.equals(mostMatches))\r
+                        return -1;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+        int nMatches = 0;\r
+        while(fewestMatches.intValue() > nMatches) {\r
+            i=sub.matchInternal(i,pt);\r
+            if(i >= 0)\r
+                nMatches++;\r
+            else\r
+                return -1;\r
+        }\r
+        m=i;\r
+        if(mostMatches.finite()) {\r
+            while(nMatches < mostMatches.intValue()) {\r
+                i = sub.matchInternal(i,pt);\r
+                if(i>=0) {\r
+                    m=i;\r
+                    nMatches++;\r
+                } else break;\r
+            }\r
+        } else {\r
+            while(true) {\r
+                i = sub.matchInternal(i,pt);\r
+                if(i>=0) {\r
+                    m=i;\r
+                    nMatches++;\r
+                } else break;\r
+            }\r
+        }\r
+        while(m >= pos) {\r
+            int r=nextMatch(m,pt);\r
+            if(r >= 0) return r;\r
+            m -= step;\r
+            nMatches--;\r
+            if(nMatches < fewestMatches.intValue())\r
+                return -1;\r
+        }\r
+        return -1;\r
+    }\r
+    public Pattern clone1(Hashtable h) {\r
+        try {\r
+            FastMulti fm = new FastMulti(fewestMatches,mostMatches,sub.clone(h));\r
+            fm.matchFewest = matchFewest;\r
+            return fm;\r
+        } catch(RegSyntax rs) {\r
+            return null;\r
+        }\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/FileRegex.java b/src/com/stevesoft/pat/FileRegex.java
new file mode 100755 (executable)
index 0000000..f5ac448
--- /dev/null
@@ -0,0 +1,215 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+/** This class is a different form of Regex designed to work more\r
+ like the file matching utility of a Unix shell.  It is implemented\r
+ by some simple string transformations:\r
+ <center>\r
+ <table border=1>\r
+ <tr> <td> FileRegex </td> <td> Regex </td>\r
+ <tr> <td> * </td><td> .* </td>\r
+ <tr> <td> . </td><td> \. </td>\r
+ <tr> <td> { </td><td> (?: </td>\r
+ <tr> <td> {?! </td><td> (?! </td>\r
+ <tr> <td> {?= </td><td> (?= </td>\r
+ <tr> <td> {?? </td><td> (?? </td>\r
+ <tr> <td> } </td><td> ) </td>\r
+ <tr> <td> ? </td><td> . </td>\r
+ <tr> <td> {,} </td><td> (|) </td>\r
+ </table>\r
+ </center>\r
+ Note that a FileRegex pattern always ends with the Regex\r
+ pattern element "$".  If you like to experiment, try making\r
+ FileRegex's and then printing them out.  The toString() method\r
+ does a decompile of the pattern to a standard Regex.  Here are\r
+ some more complete examples:\r
+ <center>\r
+ <table border=3>\r
+ <tr> <td> FileRegex </td><td> Regex </td>\r
+ <tr> <td>*.java </td><td> .*\.java$ </td>\r
+ <tr> <td>*.{java,html} </td><td> .*\.(java|html)$ </td>\r
+ <tr> <td> foo.[chC] </td><td> foo.[chC]$ </td>\r
+ </table>\r
+ </center>\r
+ */\r
+public class FileRegex extends Regex {\r
+    /** Build an unitialized FileRegex. */\r
+    public FileRegex() { dirflag=EITHER; }\r
+    /** Build a FileRegex form String s. */\r
+    public FileRegex(String s) {\r
+        super(s);\r
+        dirflag = EITHER;\r
+    }\r
+    /** Compile a new pattern.\r
+        Throws @exception com.stevesoft.pat.RegSyntax for\r
+        nonsensical patterns like "[9-0]+" just as Regex does.\r
+        @see com.stevesoft.pat#compile(java.lang.String)\r
+        */\r
+    public void compile(String s) throws RegSyntax {\r
+       String npat = toFileRegex(s);\r
+        super.compile(npat);\r
+        if(File.separatorChar == '\\') // MS-DOS\r
+            ignoreCase = true;\r
+    }\r
+    /** This is the method required by FileNameFilter.\r
+       To get a listing of files in the current directory\r
+         ending in .java, do this:\r
+        <pre>\r
+        File dot = new File(".");\r
+        FileRegex java_files = new FileRegex("*.java");\r
+        String[] file_list = dot.list(java_files);\r
+        </pre>\r
+        */\r
+    public boolean accept(File dir,String s) {\r
+        if(dirflag != EITHER) {\r
+            File f = new File(s);\r
+            if(f.isDirectory() && dirflag == NONDIR)\r
+                return false;\r
+            if(!f.isDirectory() && dirflag == DIR)\r
+                return false;\r
+        }\r
+        return matchAt(s,0);\r
+    }\r
+    int dirflag = 0;\r
+    final static int EITHER=0,DIR=1,NONDIR=2;\r
+\r
+    /** Provides an alternative to File.list -- this\r
+        separates its argument according to File.pathSeparator.\r
+        To each path, it splits off a directory -- all characters\r
+        up to and including the first instance of File.separator --\r
+        and a file pattern -- the part that comes after the directory.\r
+        It then produces a list of all the pattern matches on all\r
+        the paths.  Thus "*.java:../*.java" would produce a list of\r
+        all the java files in this directory and in the ".." directory\r
+        on a Unix machine.  "*.java;..\\*.java" would do the same thing\r
+        on a Dos machine. */\r
+    public static String[] list(String f) {\r
+        return list(f,EITHER);\r
+    }\r
+    static String[] list(String f,int df) {\r
+        //return list_(f,new FileRegex());\r
+        StringTokenizer st = new StringTokenizer(f,File.pathSeparator);\r
+        Vector v = new Vector();\r
+        while(st.hasMoreTokens()) {\r
+            String path = st.nextToken();\r
+            list1(path,v,df,true);\r
+        }\r
+        String[] sa = new String[v.size()];\r
+        v.copyInto(sa);\r
+        return sa;\r
+    }\r
+    final static Regex root=new Regex(File.separatorChar=='/' ?\r
+        "/$" : "(?:.:|)\\\\$");\r
+    static void list1(String path,Vector v,int df,boolean rec) {\r
+       // if path looks like a/b/c/ or d:\ then add .\r
+        if(root.matchAt(path,0)) {\r
+            v.addElement(path+".");\r
+            return;\r
+        }\r
+        File f = new File(path);\r
+        if(f.getParent() != null && rec) {\r
+            Vector v2 = new Vector();\r
+            list1(f.getParent(),v2,DIR,true);\r
+            for(int i=0;i<v2.size();i++) {\r
+                String path2 = ((String)v2.elementAt(i))+\r
+                    File.separator+f.getName();\r
+                list1(path2,v,df,false);\r
+            }\r
+        } else {\r
+            File base = new File(path);\r
+\r
+            String dir_s = base.getParent();\r
+            if(dir_s==null) dir_s=".";\r
+            File dir = new File(dir_s);\r
+\r
+            FileRegex fr = new FileRegex(base.getName());\r
+            if(fr.isLiteral()) {\r
+                v.addElement(dir_s+File.separator+base.getName());\r
+                return;\r
+            }\r
+            fr.dirflag = df;\r
+            String[] sa = dir.list(fr);\r
+            if(sa == null) return;\r
+            for(int i=0;i<sa.length;i++) {\r
+                v.addElement(dir_s+File.separator+sa[i]);\r
+            }\r
+        }\r
+    }\r
+\r
+    /** This method takes a file regular expression, and translates it\r
+            into the type of pattern used by a normal Regex. */\r
+    public static String toFileRegex(String s) {\r
+        StrPos sp = new StrPos(s,0);\r
+        StringBuffer sb = new StringBuffer();\r
+        if(sp.incMatch("{?e=")) {\r
+            char e = sp.thisChar();\r
+            sp.inc();\r
+            if(sp.incMatch("}")) {\r
+                sb.append("(?e="+e+")^");\r
+            } else {\r
+                sb.append("^(?e=");\r
+            }\r
+            sp.esc = e;\r
+        }\r
+        int ParenLvl = 0;\r
+        while(!sp.eos()) {\r
+           if(File.separatorChar == '\\') {\r
+             if(sp.escaped())\r
+               sb.append("\\\\");\r
+             sp.dontMatch = false;\r
+           }\r
+            if(sp.incMatch("?"))\r
+                sb.append(".");\r
+            else if(sp.incMatch(".")) {\r
+                sb.append(sp.esc);\r
+                sb.append('.');\r
+            } else if(sp.incMatch("{??")) {\r
+                sb.append("(??");\r
+                ParenLvl++;\r
+                // allow negative lookahead to work\r
+            } else if(sp.incMatch("{?!")) {\r
+                sb.append("(?!");\r
+                ParenLvl++;\r
+                // allow positive lookahead to work\r
+            } else if(sp.incMatch("{?=")) {\r
+                sb.append("(?=");\r
+                ParenLvl++;\r
+            } else if(sp.incMatch("{")) {\r
+                sb.append("(?:");\r
+                ParenLvl++;\r
+            } else if(sp.incMatch("}")) {\r
+                sb.append(')');\r
+                ParenLvl--;\r
+            } else if(ParenLvl != 0 && sp.incMatch(","))\r
+                sb.append('|');\r
+            else if(sp.incMatch("*"))\r
+                sb.append(".*");\r
+            else {\r
+                sb.append(sp.thisChar());\r
+                sp.inc();\r
+            }\r
+        }\r
+        sb.append("$");\r
+        return sb.toString();\r
+    }\r
+    public boolean isLiteral() {\r
+        Pattern x = thePattern;\r
+        while(x != null && !(x instanceof End)) {\r
+            if(x instanceof oneChar)\r
+                ;\r
+            else if(x instanceof Skipped)\r
+                ;\r
+            else return false;\r
+            x = x.next;\r
+        }\r
+        return true;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/Group.java b/src/com/stevesoft/pat/Group.java
new file mode 100755 (executable)
index 0000000..4f73114
--- /dev/null
@@ -0,0 +1,42 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** This class implements the (?@<>) syntax that matches\r
+ a balanced parenthesis.  Not in perl 5. */\r
+class Group extends Pattern {\r
+    char op,cl;\r
+    Group(char opi,char cli) {\r
+        op = opi;\r
+        cl = cli;\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        int i,count=1;\r
+        if(pos < pt.src.length())\r
+            if(!Masked(pos,pt) && pt.src.charAt(pos) != op)\r
+                return -1;\r
+        for(i=pos+1;i<pt.src.length();i++) {\r
+            char c = pt.src.charAt(i);\r
+            boolean b = !Masked(i,pt);\r
+            if(b && c == ESC) {\r
+                i++;\r
+            } else {\r
+                if(b && c == cl) count--;\r
+                if(count == 0) return nextMatch(i+1,pt);\r
+                if(b && c == op) count++;\r
+            }\r
+        }\r
+        return -1;\r
+    }\r
+    public String toString() {\r
+        return "(?@"+op+cl+")"+nextString();\r
+    }\r
+    public patInt minChars() { return new patInt(2); }\r
+    Pattern clone1(Hashtable h) { return new Group(op,cl); }\r
+};\r
diff --git a/src/com/stevesoft/pat/LeftRule.java b/src/com/stevesoft/pat/LeftRule.java
new file mode 100755 (executable)
index 0000000..1737abd
--- /dev/null
@@ -0,0 +1,21 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** The apply(StringBufferLike sb,RegRes res) method of this derivation\r
+    of ReplaceRule appends the contents of res.left() to the StringBuffer\r
+    sb.\r
+    @see com.stevesoft.pat.ReplaceRule\r
+    */\r
+public class LeftRule extends ReplaceRule {\r
+    public LeftRule() {}\r
+    public void apply(StringBufferLike sb,RegRes res) {\r
+        sb.append(res.left());\r
+    }\r
+    public String toString1() { return "$`"; }\r
+}\r
diff --git a/src/com/stevesoft/pat/Multi.java b/src/com/stevesoft/pat/Multi.java
new file mode 100755 (executable)
index 0000000..2960b75
--- /dev/null
@@ -0,0 +1,60 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** Matches any number of instances of sub Pattern\r
+ this was the hardest method to write.  It implements\r
+ '+', '*', '?', "{0,10}", "{5,}", "{5}", etc.\r
+ @see pat.Multi_stage2\r
+ @see pat.MultiMin\r
+ */\r
+class Multi extends PatternSub {\r
+    patInt a,b;\r
+    public patInt minChars() { return a.mul(p.countMinChars()); }\r
+    public patInt maxChars() { return b.mul(p.countMaxChars()); }\r
+    Pattern p;\r
+    Multi_stage2 st2;\r
+    public boolean matchFewest = false;\r
+    /**\r
+        @param a The fewest number of times the sub pattern can match.\r
+        @param b The maximum number of times the sub pattern can match.\r
+        @param p The sub pattern.\r
+        @see Multi_stage2\r
+        @see MultiMin\r
+        */\r
+    public Multi(patInt a,patInt b,Pattern p) throws RegSyntax {\r
+        this.a = a;\r
+        this.b = b;\r
+        this.p = p;\r
+        st2 = new Multi_stage2(a,b,p);\r
+        st2.parent = this;\r
+        sub = st2.sub;\r
+    }\r
+    public String toString() {\r
+        st2.matchFewest = matchFewest;\r
+        return st2.toString();\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        try {\r
+            st2 = new Multi_stage2(a,b,p);\r
+        } catch(RegSyntax r__) {}\r
+        st2.matchFewest = matchFewest;\r
+        st2.parent = this;\r
+        return st2.matchInternal(pos,pt);\r
+    }\r
+    public Pattern clone1(Hashtable h) {\r
+        try {\r
+            Multi m = new Multi(a,b,((Pattern)p).clone(h));\r
+            m.matchFewest = matchFewest;\r
+            return m;\r
+        } catch(RegSyntax rs) {\r
+            return null;\r
+        }\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/MultiMin.java b/src/com/stevesoft/pat/MultiMin.java
new file mode 100755 (executable)
index 0000000..f6d2fd8
--- /dev/null
@@ -0,0 +1,18 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This extension of multi is the version of multi\r
+ which wants to match the fewest number of characters.\r
+ It implements the *? type of syntax. */\r
+class MultiMin extends Multi {\r
+    MultiMin(patInt i1,patInt i2,Pattern p) throws RegSyntax {\r
+        super(i1,i2,p);\r
+        matchFewest = true;\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/Multi_stage2.java b/src/com/stevesoft/pat/Multi_stage2.java
new file mode 100755 (executable)
index 0000000..41afa39
--- /dev/null
@@ -0,0 +1,103 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** If Multi were not split into a second stage, then\r
+ a nested Multi would try to re-use the same count\r
+ variable and the whole thing would break. */\r
+class Multi_stage2 extends PatternSub {\r
+    Pattern nextRet;\r
+    patInt count;\r
+    patInt matchMin,matchMax;\r
+    public boolean matchFewest = false;\r
+    public String toString() {\r
+        String ret = "";\r
+        ret += sub.toString();\r
+        ret += "{"+matchMin+","+matchMax+"}";\r
+        if(matchFewest) ret += "?";\r
+        ret += parent.nextString();\r
+        return ret;\r
+    }\r
+    Multi_stage2(patInt a,patInt b,Pattern p) throws RegSyntax {\r
+        if(p == null) RegSyntaxError.endItAll(\r
+                "Multiple match of Null pattern requested.");\r
+        sub = p;\r
+        nextRet = this;\r
+        sub.setParent(this);\r
+        matchMin = a;\r
+        matchMax = b;\r
+        count = new patInt(0);\r
+        // we must have b > a > -1 for this\r
+        // to make sense.\r
+        if(!a.lessEq(b))\r
+            //throw new BadMultiArgs();\r
+            RegSyntaxError.endItAll("Bad Multi Args: "+a+">"+b);\r
+        patInt i = new patInt(-1);\r
+        if(a.lessEq(i))\r
+            //throw new BadMultiArgs();\r
+            RegSyntaxError.endItAll("Bad Multi Args: "+a+"< 0");\r
+    }\r
+    public Pattern getNext() {\r
+        return nextRet;\r
+    }\r
+    int pos_old = -1;\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        sub.setParent(this);\r
+\r
+        int canUse = -1;\r
+\r
+        // check for some forms of infinite recursion...\r
+        if(pos_old >= 0 && pos == pos_old) {\r
+            return -1;\r
+        }\r
+        pos_old = pos;\r
+\r
+        if(matchMin.lessEq(count))\r
+            canUse = pos;\r
+        if(!count.lessEq(matchMax) || pos > pt.src.length())\r
+            return -1;\r
+\r
+        if((matchFewest||count.equals(matchMax)) && canUse >= 0) {\r
+            Pattern n = super.getNext();\r
+            if(n == null)\r
+                return canUse;\r
+            int ret = testMatch(n,pos,pt);\r
+            if(ret >= 0) {\r
+               return ret;\r
+            }\r
+            else canUse = -1;\r
+        }\r
+\r
+        count.inc();\r
+        try {\r
+            if(count.lessEq(matchMax)) {\r
+                int r = testMatch(sub,pos,pt);\r
+                if(r >= 0)\r
+                    return r;\r
+            }\r
+        } finally { count.dec(); }\r
+\r
+        if(!matchFewest && canUse >= 0) {\r
+            Pattern n = super.getNext();\r
+            if(n == null)\r
+                return canUse;\r
+            int ret = testMatch(n,pos,pt);\r
+            return ret;\r
+        } else return canUse;\r
+    }\r
+    public Pattern clone1(Hashtable h) {\r
+        try {\r
+            Multi_stage2 m = new Multi_stage2(matchMin,matchMax,sub.clone(h));\r
+            m.matchFewest = matchFewest;\r
+            return m;\r
+        } catch(RegSyntax rs) {\r
+            return null;\r
+        }\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/NoPattern.java b/src/com/stevesoft/pat/NoPattern.java
new file mode 100755 (executable)
index 0000000..3bac329
--- /dev/null
@@ -0,0 +1,19 @@
+package//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+com.stevesoft.pat;\r
+import java.util.*;\r
+\r
+/** The idea behind this class is simply to eliminate the need for\r
+  * testing to see if Regex.thePattern is null.  Every instruction\r
+  * we can eliminate from _search will help.\r
+  */\r
+public class NoPattern extends Pattern {\r
+    public String toString() { return "(?e=#)[^#d#D]"; }\r
+    public int matchInternal(int i,Pthings p) { return -1; }\r
+    Pattern clone1(Hashtable h) { return new NoPattern(); }\r
+}\r
diff --git a/src/com/stevesoft/pat/NonDirFileRegex.java b/src/com/stevesoft/pat/NonDirFileRegex.java
new file mode 100755 (executable)
index 0000000..92f54a3
--- /dev/null
@@ -0,0 +1,19 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.io.File;\r
+\r
+/** This class is just like FileRegex, except that its accept method\r
+ only returns true if the file matching the pattern is not a directory.*/\r
+public class NonDirFileRegex extends FileRegex {\r
+    public NonDirFileRegex() { dirflag = NONDIR; }\r
+    public NonDirFileRegex(String fp) { super(fp); dirflag = NONDIR; }\r
+    public static String[] list(String f) {\r
+        return list(f,NONDIR);\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/NotImplementedError.java b/src/com/stevesoft/pat/NotImplementedError.java
new file mode 100755 (executable)
index 0000000..f8835f2
--- /dev/null
@@ -0,0 +1,14 @@
+package//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+com.stevesoft.pat;\r
+\r
+public class NotImplementedError extends Error {\r
+  public NotImplementedError(String s) {\r
+    super(s);\r
+  }\r
+}\r
diff --git a/src/com/stevesoft/pat/NullPattern.java b/src/com/stevesoft/pat/NullPattern.java
new file mode 100755 (executable)
index 0000000..082b0f3
--- /dev/null
@@ -0,0 +1,21 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** This pattern matches nothing -- it is found in patterns\r
+  * like (hello|world|) where a zero-length subelement occurs.\r
+  */\r
+class NullPattern extends Pattern {\r
+    public String toString() { return nextString(); }\r
+    public int matchInternal(int p,Pthings pt) {\r
+        return nextMatch(p,pt);\r
+    }\r
+    public patInt maxChars() { return new patInt(0); }\r
+    Pattern clone1(Hashtable h) { return new NullPattern(); }\r
+}\r
diff --git a/src/com/stevesoft/pat/NullRule.java b/src/com/stevesoft/pat/NullRule.java
new file mode 100755 (executable)
index 0000000..454c81e
--- /dev/null
@@ -0,0 +1,19 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** The apply(StringBufferLike sb,RegRes res) method of this derivation\r
+    of ReplaceRule appends nothing to the contents of the StringBuffer sb.\r
+    @see com.stevesoft.pat.ReplaceRule\r
+    */\r
+public class NullRule extends ReplaceRule {\r
+    public NullRule() {}\r
+    public void apply(StringBufferLike sb,RegRes res) {\r
+    }\r
+    public String toString1() { return ""; }\r
+}\r
diff --git a/src/com/stevesoft/pat/Or.java b/src/com/stevesoft/pat/Or.java
new file mode 100755 (executable)
index 0000000..9791c74
--- /dev/null
@@ -0,0 +1,81 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.util.*;\r
+\r
+/** This class implements the (?: ... ) extended Pattern.\r
+ It provides a base class from which we derive the\r
+ [ ... ], ( ... ), (?! ... ), and (?= ... ) patterns. */\r
+class Or extends Pattern {\r
+    Vector v;\r
+    Pattern[] pv = null;\r
+    Or() { v = new Vector(); }\r
+    String leftForm() { return "(?:"; }\r
+    String rightForm() { return ")"; }\r
+    String sepForm() { return "|"; }\r
+    public Or addOr(Pattern p) {\r
+        pv = null;\r
+        v.addElement(p);\r
+        p.setParent(this);\r
+        return this;\r
+    }\r
+    public String toString() {\r
+        int i;\r
+        StringBuffer sb = new StringBuffer();\r
+        sb.append(leftForm());\r
+        if(v.size()>0)\r
+            sb.append( ((Pattern)v.elementAt(0)).toString() );\r
+        for(i=1;i<v.size();i++) {\r
+            sb.append(sepForm());\r
+            sb.append( ((Pattern)v.elementAt(i)).toString() );\r
+        }\r
+        sb.append(rightForm());\r
+        sb.append(nextString());\r
+        return sb.toString();\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(pv == null) {\r
+            pv = new Pattern[v.size()];\r
+            v.copyInto(pv);\r
+        }\r
+        for(int i=0;i<v.size();i++) {\r
+            Pattern p = pv[i];//(Pattern)v.elementAt(i);\r
+            int r = p.matchInternal(pos,pt);\r
+            if(r >= 0)\r
+                return r;\r
+        }\r
+        return -1;\r
+    }\r
+    public patInt minChars() {\r
+        if(v.size()==0) return new patInt(0);\r
+        patInt m = ((Pattern)v.elementAt(0)).countMinChars();\r
+        for(int i=1;i<v.size();i++) {\r
+            Pattern p = (Pattern)v.elementAt(i);\r
+            m.mineq(p.countMinChars());\r
+        }\r
+        return m;\r
+    }\r
+    public patInt maxChars() {\r
+        if(v.size()==0) return new patInt(0);\r
+        patInt m = ((Pattern)v.elementAt(0)).countMaxChars();\r
+        for(int i=1;i<v.size();i++) {\r
+            Pattern p = (Pattern)v.elementAt(i);\r
+            m.maxeq(p.countMaxChars());\r
+        }\r
+        return m;\r
+    }\r
+    Pattern clone1(Hashtable h) {\r
+        Or o=new Or();\r
+        h.put(this,o);\r
+        h.put(o,o);\r
+        for(int i=0;i<v.size();i++)\r
+            o.v.addElement( ((Pattern)v.elementAt(i)).clone(h) );\r
+        return o;\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/OrMark.java b/src/com/stevesoft/pat/OrMark.java
new file mode 100755 (executable)
index 0000000..e9bf0ca
--- /dev/null
@@ -0,0 +1,51 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+/** Implements the parenthesis pattern subelement.*/\r
+class OrMark extends Or {\r
+    SubMark sm = new SubMark();\r
+    int id;\r
+    OrMark(int i) {\r
+        sm.om = this;\r
+        id = i;\r
+    }\r
+    String leftForm() { return "("; }\r
+    public Pattern getNext() {\r
+        return sm;\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        sm.next = super.getNext();\r
+        if(pt.marks == null) {\r
+            int n2 = 2 * pt.nMarks+2;\r
+            pt.marks = new int[n2];\r
+            for(int i=0;i<n2;i++)\r
+                pt.marks[i] = -1;\r
+        }\r
+        pt.marks[id] = pos;\r
+        int ret = super.matchInternal(pos,pt);\r
+        if(ret < 0)\r
+            pt.marks[id] = -1;\r
+        else if(pt.marks[id] > pt.marks[id+pt.nMarks]) {\r
+            int swap = pt.marks[id];\r
+            pt.marks[id] = pt.marks[id+pt.nMarks]+1;\r
+            pt.marks[id+pt.nMarks] = swap+1;\r
+        }\r
+        return ret;\r
+    }\r
+    public Pattern clone1(Hashtable h) {\r
+        OrMark om = new OrMark(id);\r
+        h.put(om,om);\r
+        h.put(this,om);\r
+        for(int i=0;i<v.size();i++)\r
+            om.v.addElement( ((Pattern)v.elementAt(i)).clone(h) );\r
+        return om;\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/PartialBuffer.java b/src/com/stevesoft/pat/PartialBuffer.java
new file mode 100755 (executable)
index 0000000..2239545
--- /dev/null
@@ -0,0 +1,84 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.io.*;\r
+\r
+/** This class allows you to match on a partial string.\r
+    If the allowOverRun flag is true, then the\r
+    length() method returns a number 1 larger than\r
+    is actually contained by the class.\r
+    <p>\r
+    If one attempts to access the last character as\r
+    follows:\r
+    <pre>\r
+    StringBuffer sb = ...;\r
+    ...\r
+    PartialBuffer pb = new PartialBuffer(sb);\r
+    char c = pb.charAt(pb.length()-1);\r
+    </pre>\r
+    then two things happen.  First, a zero is returned\r
+    into the variable c.  Second, the overRun flag is\r
+    set to "true."  Accessing data beyond the end of\r
+    the buffer is considered an "overRun" of the data.\r
+    <p>\r
+    This can be helpful in determining whether more\r
+    characters are required for a match to occur, as\r
+    the pseudo-code below illustrates.\r
+    <pre>\r
+    int i = ...;\r
+    Regex r = new Regex("some pattern");\r
+    pb.allowOverRun = true;\r
+    pb.overRun = true;\r
+    boolean result = r.matchAt(pb,i);\r
+    if(pb.overRun) {\r
+      // The result of the match is not relevant, regardless\r
+      // of whether result is true or false.  We need to\r
+      // append more data to the buffer and try again.\r
+      ....\r
+      sb.append(more data);\r
+    }\r
+    </pre>\r
+    */\r
+class PartialBuffer implements StringLike {\r
+  int off;\r
+  public boolean allowOverRun = true;\r
+  public boolean overRun = false;\r
+  StringBuffer sb;\r
+  PartialBuffer(StringBuffer sb) {\r
+    this.sb = sb;\r
+  }\r
+  public char charAt(int n) {\r
+    n += off;\r
+    if(n == sb.length()) {\r
+      overRun = true;\r
+      return 0;\r
+    }\r
+    return sb.charAt(n);\r
+  }\r
+  public int length() {\r
+    return allowOverRun ? sb.length()+1 : sb.length();\r
+  }\r
+  public int indexOf(char c) {\r
+    for(int i=0;i<sb.length();i++)\r
+      if(sb.charAt(i)==c)\r
+        return i;\r
+    return -1;\r
+  }\r
+  public Object unwrap() { return sb; }\r
+  public String substring(int i1,int i2) {\r
+    StringBuffer sb = new StringBuffer(i2-i1);\r
+    for(int i=i1;i<i2;i++)\r
+      sb.append(charAt(i));\r
+    return sb.toString();\r
+  }\r
+  /** Just returns null. */\r
+  public BasicStringBufferLike newStringBufferLike() {\r
+    return null;\r
+  }\r
+}\r
diff --git a/src/com/stevesoft/pat/Pattern.java b/src/com/stevesoft/pat/Pattern.java
new file mode 100755 (executable)
index 0000000..404991c
--- /dev/null
@@ -0,0 +1,193 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.*;\r
+/**\r
+        Shareware: package pat\r
+   <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>\r
+*/ /**\r
+Class Pattern is the base class on which all the other pattern\r
+elements are built. */\r
+\r
+public abstract class Pattern {\r
+    /** The ESC character, the user can provide his own value\r
+            for the escape character through regex.esc */\r
+    public final static char ESC = '\\';\r
+    final static String PROTECT_THESE = "[]{}(),$,-\"^.";\r
+\r
+    /** The interal match function, it must be provided by any\r
+        class which wishes to extend Pattern. */\r
+    public abstract int matchInternal(int i,Pthings p);\r
+    public abstract String toString();\r
+\r
+    // Class Pattern is a singly linked list\r
+    // chained together by member next.  The member\r
+    // parent is used so that sub patterns can access\r
+    // the chain they are branching from.\r
+    Pattern next=null,parent=null;\r
+\r
+    /** This gets the next element of a Pattern that\r
+            we wish to match.  If we are at the end of a\r
+            subchain of patterns, it will return us to the\r
+            parent chain. */\r
+    public Pattern getNext() {\r
+        return next != null ? next :\r
+        (parent == null ? null : parent.getNext());\r
+    }\r
+    /** Call this method if you have a pattern element that\r
+            takes a sub pattern (such as Or), and\r
+            after you have added a sub pattern to the current\r
+            pattern element. */\r
+    public void setParent(Pattern p) {\r
+        if(next != null) next.setParent(p);\r
+        else parent = p;\r
+    }\r
+    /** This determines if the remainder of a Pattern\r
+            matches.  Type "return nextMatch" from within\r
+            matchInternal if the current\r
+            Pattern matches.  Otherwise, return a -1.*/\r
+    public int nextMatch(int i,Pthings pt) {\r
+        Pattern p = getNext();\r
+        /*if(p == null) return i;\r
+                return p.matchInternal(i,pt);*/\r
+        return p==null ? i : p.matchInternal(i,pt);\r
+    }\r
+    /** This is a toString() for the remainder\r
+            of the Pattern elements after this one.\r
+            use this when overriding toString(). Called from\r
+            within toString(). */\r
+    public String nextString() {\r
+        if(next == null) return "";\r
+        return next.toString();\r
+    }\r
+\r
+    /** a method to detect whether char c is in String s */\r
+    final static boolean inString(char c,String s) {\r
+        int i;\r
+        for(i=0;i<s.length();i++)\r
+            if(s.charAt(i)==c)\r
+                return true;\r
+        return false;\r
+    }\r
+\r
+    /** A method to create a string that protects the characters\r
+            listed in PROTECT_THESE by prepending the esc character.\r
+            The esc character itself is automatically protected. */\r
+    final static\r
+        String protect(String s,String PROTECT_THESE,char esc) {\r
+        int i;\r
+        StringBuffer sb = new StringBuffer();\r
+        String p = PROTECT_THESE+esc;\r
+        for(i=0;i<s.length();i++) {\r
+            char c = s.charAt(i);\r
+            if(inString(c,p))\r
+                sb.append(esc);\r
+            sb.append(c);\r
+        }\r
+        return sb.toString();\r
+    }\r
+\r
+    /** This can be used to perform a match test from\r
+            within class Pattern. */\r
+    public int match(StringLike s,Pthings pt) {\r
+        return matchAt(s,0,pt);\r
+    }\r
+    /** This can be used to perform a match test from\r
+            within class Pattern. */\r
+    public int matchAt(StringLike s,int i,Pthings pt) {\r
+        pt.src = s;\r
+        int r = matchInternal(i,pt);\r
+        if(r < 0) return -1;\r
+        mfrom = r<i ? r+1 : i;\r
+        return r<i ? i-r-1 : r-i;\r
+    }\r
+    int mfrom=0;\r
+\r
+    // Detect masked characters\r
+    final boolean Masked(int i,Pthings pt) {\r
+        return pt.cbits == null ? false : pt.cbits.get(i);\r
+    }\r
+\r
+    /** add a Pattern to the singly-linked Pattern chain. */\r
+    public Pattern add(Pattern p) {\r
+        if(next == null) {\r
+            if(p==null) return this;\r
+            next = p;\r
+            p.parent = parent;\r
+            parent = null;\r
+        } else next.add(p);\r
+        return this;\r
+    }\r
+    /** The minimum number of characters which\r
+        this pattern element can match. */\r
+    public patInt minChars() { return new patInt(0); }\r
+    /** The maximum number of characters which\r
+        this pattern element can match. */\r
+    public patInt maxChars() { return new patInf(); }\r
+    /** return minimum number of characters in pattern */\r
+    public final patInt countMinChars() {\r
+        Pattern p = this;\r
+        patInt sum = new patInt(0);\r
+        while(p != null) {\r
+            sum.pluseq(p.minChars());\r
+            p = p.next;\r
+        }\r
+        return sum;\r
+    }\r
+    /** return maximum number of characters in pattern */\r
+    public final patInt countMaxChars() {\r
+        Pattern p = this;\r
+        patInt sum = new patInt(0);\r
+        while(p != null) {\r
+            sum.pluseq(p.maxChars());\r
+            p = p.next;\r
+        }\r
+        return sum;\r
+    }\r
+\r
+    // This method is only needed by Multi_stage2 so far...\r
+    // the reason is that it may try something else after a\r
+    // match succeeds.  OrMark will only record the last thing\r
+    // tried in marks, so we need to backup the result of the\r
+    // last successful match and restore it if the next one\r
+    // does not succeed.\r
+    final int testMatch(Pattern p,int pos,Pthings pt) {\r
+        int[] tab = null;\r
+        if(pt.marks != null) try {\r
+                tab = new int[pt.marks.length];\r
+                for(int i=0;i<tab.length;i++)\r
+                    tab[i] = pt.marks[i];\r
+            } catch(Throwable t) {}\r
+        int ret = p.matchInternal(pos,pt);\r
+        if(ret < 0) pt.marks = tab;\r
+        return ret;\r
+    }\r
+\r
+    /** Clones this pattern elements without cloning others in the\r
+        linked list. */\r
+    Pattern clone1(Hashtable h) {\r
+        throw new Error("No such method as clone1 for "+getClass().getName());\r
+    }\r
+    Pattern clone(Hashtable h) {\r
+        Pattern p = (Pattern)h.get(this);\r
+        if(p != null) {\r
+            return p;\r
+        }\r
+        p=clone1(h);\r
+        if(p==null)throw new Error("Null from clone1!");\r
+        h.put(this,p);\r
+        h.put(p,p);\r
+        if(next != null) p.next = next.clone(h);\r
+        if(parent != null) p.parent = parent.clone(h);\r
+        return p;\r
+    }\r
+    public boolean equals(Object o) {\r
+        return o == this;\r
+    }\r
+};\r
+\r
diff --git a/src/com/stevesoft/pat/PatternSub.java b/src/com/stevesoft/pat/PatternSub.java
new file mode 100755 (executable)
index 0000000..d88296b
--- /dev/null
@@ -0,0 +1,15 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This is simply a subclass of pattern that\r
+  * contains a sub pattern.\r
+  */\r
+abstract class PatternSub extends Pattern {\r
+    Pattern sub;\r
+}\r
diff --git a/src/com/stevesoft/pat/PopRule.java b/src/com/stevesoft/pat/PopRule.java
new file mode 100755 (executable)
index 0000000..1428edb
--- /dev/null
@@ -0,0 +1,16 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** Implements substitution rule $POP. See the example\r
+  * file <a href="http://javaregex.com/code/trans3.java.html">trans3.html</a>.\r
+  */\r
+public class PopRule extends SpecialRule {\r
+    public PopRule() {}\r
+    public String toString1() { return "${POP}"; }\r
+}\r
diff --git a/src/com/stevesoft/pat/Prop.java b/src/com/stevesoft/pat/Prop.java
new file mode 100755 (executable)
index 0000000..9319db5
--- /dev/null
@@ -0,0 +1,52 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** Get Unicode properties for a character.  See\r
+<a href="http://unicode.org">http://unicode.org</a>. */\r
+public class Prop {\r
+    /** Is this a "Decimal Digit" according to Unicode? */\r
+    public final static boolean isDecimalDigit(char c) {\r
+      if(Bits.decimal_digit == null)\r
+        Bits.decimal_digit_f();\r
+      return Bits.decimal_digit.get(c);\r
+    }\r
+    /** Is this a "Alphabetic" according to Unicode? */\r
+    public final static boolean isAlphabetic(char c) {\r
+      if(Bits.letter == null)\r
+        Bits.letter_f();\r
+      return Bits.letter.get(c);\r
+    }\r
+    /** Is this a "Math" according to Unicode? */\r
+    public final static boolean isMath(char c) {\r
+      if(Bits.math == null)\r
+        Bits.math_f();\r
+      return Bits.math.get(c);\r
+    }\r
+\r
+    /** Is this a "Currency" according to Unicode? */\r
+    public final static boolean isCurrency(char c) {\r
+      if(Bits.currency == null)\r
+        Bits.currency_f();\r
+      return Bits.currency.get(c);\r
+    }\r
+\r
+    /** Is c a white space character according to Unicode? */\r
+    public final static boolean isWhite(char c) {\r
+      if(Bits.white == null)\r
+        Bits.white_f();\r
+      return Bits.white.get(c);\r
+    }\r
+\r
+    /** Is c a punctuation character according to Unicode? */\r
+    public final static boolean isPunct(char c) {\r
+      if(Bits.punct == null)\r
+        Bits.punct_f();\r
+      return Bits.punct.get(c);\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/Pthings.java b/src/com/stevesoft/pat/Pthings.java
new file mode 100755 (executable)
index 0000000..0a465ce
--- /dev/null
@@ -0,0 +1,33 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.*;\r
+\r
+/** \r
+Things that need to be kept track of during a\r
+ match.  Passed along with Pattern.matchInternal. */\r
+public class Pthings {\r
+    /** The current text we are attempting to match. */\r
+    public StringLike src;\r
+    /** Whether we should ignore the case of letters in\r
+        this match. */\r
+    public boolean ignoreCase;\r
+    public boolean mFlag;\r
+    /** The mask to use when dontMatchInQuotes is set. */\r
+    public BitSet cbits;\r
+    /** Used to keep track of backreferences. */\r
+    //public Hashtable marks;\r
+    public int[] marks;\r
+    public int nMarks;\r
+    /** Used to set the behavior of "."  By default, it\r
+        now fails to match the '\n' character. */\r
+    public boolean dotDoesntMatchCR;\r
+    /** Determine if Skipped strings need to be checked. */\r
+    public boolean no_check;\r
+    int lastPos;\r
+}\r
diff --git a/src/com/stevesoft/pat/PushRule.java b/src/com/stevesoft/pat/PushRule.java
new file mode 100755 (executable)
index 0000000..cdc33f9
--- /dev/null
@@ -0,0 +1,22 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** See the example file\r
+    <a href="http://javaregex.com/code/trans3.java.html">trans3.java</a> for\r
+    further examples of how this is used.  You will probably not\r
+    want to call it directly. */\r
+public class PushRule extends SpecialRule {\r
+    Regex NewRule;\r
+    public PushRule(PushRule p) { NewRule = p.NewRule; }\r
+    public PushRule(String nm,Regex rr) { name=nm; NewRule = rr; }\r
+    public PushRule(String nm,Transformer tr) { name = nm; NewRule = tr.rp; }\r
+    public Object clone1() { return new PushRule(this); }\r
+    public String String1() { return "${+"+name+"}"; }\r
+    public void apply(StringBufferLike sbl,RegRes rr) {}\r
+}\r
diff --git a/src/com/stevesoft/pat/RBuffer.java b/src/com/stevesoft/pat/RBuffer.java
new file mode 100755 (executable)
index 0000000..08fb920
--- /dev/null
@@ -0,0 +1,36 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.io.*;\r
+import com.stevesoft.pat.wrap.*;\r
+\r
+/** This class is used internally by RegexReader to\r
+    store blocks of data. */\r
+class RBuffer {\r
+  boolean done = false;\r
+  StringBuffer sb;\r
+  int pos,epos;\r
+  RBuffer next;\r
+  RBuffer() {}\r
+  RBuffer(StringBuffer sb) { this.sb = sb; }\r
+  public String toString() {\r
+    return "sb="+sb.toString().replace('\n',' ')+\r
+      " pos="+pos+" epos="+epos+\r
+      " sb.length()="+sb.length()+\r
+      "\n"+sp(pos+3)+"^"+sp(epos-pos-1)+"^";\r
+  }\r
+  String sp(int n) {\r
+    if(n<=0)\r
+      return "";\r
+    StringBuffer sb = new StringBuffer(n);\r
+    for(int i=0;i<n;i++)\r
+      sb.append(' ');\r
+    return sb.toString();\r
+  }\r
+}\r
diff --git a/src/com/stevesoft/pat/Range.java b/src/com/stevesoft/pat/Range.java
new file mode 100755 (executable)
index 0000000..5d5f9a1
--- /dev/null
@@ -0,0 +1,61 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** Thrown when one encounters things like [z-a] */\r
+class BadRangeArgs extends RegSyntax {};\r
+\r
+/** Implments a subelement (ranges) of the [] pattern element.\r
+For example, [a-z023] is implemented using a range and tree oneChar\r
+classes.\r
+@see Bracket\r
+@see oneChar\r
+*/\r
+class Range extends Pattern {\r
+    char lo,hi,altlo,althi;\r
+    boolean printBrackets = false;\r
+    public String toString() {\r
+        String s=protect(""+lo,PROTECT_THESE,ESC)+"-"\r
+            +protect(""+hi,PROTECT_THESE,ESC);\r
+        if(!printBrackets)\r
+            return s;\r
+        return "["+s+"]";\r
+    }\r
+    Range(char loi,char hii) throws RegSyntax {\r
+        lo = loi; hi = hii;\r
+        oneChar o = null;\r
+        if(lo >= hi)\r
+            //throw new BadRangeArgs();\r
+            RegSyntaxError.endItAll("Badly formed []'s : "+lo+" >= "+hi);\r
+        o = new oneChar(lo);\r
+        altlo = o.altc;\r
+        o = new oneChar(hi);\r
+        althi = o.altc;\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(pos >= pt.src.length()) return -1;\r
+        if(Masked(pos,pt)) return -1;\r
+        char c = pt.src.charAt(pos);\r
+        if(lo <= c && c <= hi ||\r
+                (pt.ignoreCase && (altlo <= c && c <= althi)))\r
+            return nextMatch(pos+1,pt);\r
+        return -1;\r
+    }\r
+    public patInt minChars() { return new patInt(1); }\r
+    public patInt maxChars() { return new patInt(1); }\r
+    public Pattern clone1(Hashtable h) {\r
+        try {\r
+            Range r = new Range(lo,hi);\r
+            r.printBrackets = printBrackets;\r
+            return r;\r
+        } catch(RegSyntax rs) {\r
+            return null;\r
+        }\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/RegOpt.java b/src/com/stevesoft/pat/RegOpt.java
new file mode 100755 (executable)
index 0000000..1033500
--- /dev/null
@@ -0,0 +1,336 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.*;\r
+import java.io.*;\r
+\r
+/** This class is just like oneChar, but doesn't worry about case. */\r
+class FastChar extends oneChar {\r
+    FastChar(char c) { super(c); }\r
+    public int matchInternal(int p,Pthings pt) {\r
+        return (p < pt.src.length()\r
+            && pt.src.charAt(p)==c) ?\r
+            nextMatch(p+1,pt) : -1;\r
+    }\r
+    Pattern clone1(Hashtable h) {\r
+        return new FastChar(c);\r
+    }\r
+}\r
+\r
+/** This class is a hashtable keyed by Character\r
+  * Objects.  It is used to match things of the\r
+  * form (?:a..|b..|c..|..) match with greater efficiency --\r
+  * by using a Hashtable that indexes into the group\r
+  * of patterns.\r
+  */\r
+class Branch extends Pattern {\r
+    Hashtable h = new Hashtable();\r
+    // We need to keep track of the order\r
+    // of the keys -- if we don't then\r
+    // recompiling the output of toString\r
+    // may produce errors by re-ordering\r
+    // ()'s and changing the id number of\r
+    // the backreference associated with\r
+    // a subpattern.\r
+    Vector keys = new Vector();\r
+    Branch() {}\r
+    Pattern clone1(Hashtable x) {\r
+        Branch b = new Branch();\r
+        b.keys = (Vector)keys.clone();\r
+        x.put(this,b);\r
+        x.put(b,b);\r
+\r
+        for(int i=0;i<keys.size();i++) {\r
+            Pattern p = (Pattern)h.get(keys.elementAt(i));\r
+            b.h.put(keys.elementAt(i),p.clone(x));\r
+        }\r
+        return b;\r
+    }\r
+\r
+    // this function eliminates Branches with 0 or 1 elements.\r
+    final Pattern reduce(boolean ignoreCase,boolean dontMinQ) {\r
+        if(h.size()==1) {\r
+            Enumeration e = h.keys();\r
+            Character c = (Character)e.nextElement();\r
+            Pattern oc;\r
+            if(ignoreCase||dontMinQ)\r
+                oc=new oneChar(c.charValue());\r
+            else oc=new FastChar(c.charValue());\r
+            oc.next = (Pattern)h.get(c);\r
+            oc.add(next);\r
+            return oc;\r
+        } else if(h.size()==0) return null;\r
+        return this;\r
+    }\r
+    public patInt maxChars() {\r
+        Enumeration e = h.keys();\r
+        patInt count = new patInt(0);\r
+        while(e.hasMoreElements()) {\r
+            Object key = e.nextElement();\r
+            Pattern pa = (Pattern)h.get(key);\r
+            patInt pi = pa.maxChars();\r
+            pi.inc();\r
+            count.maxeq(pi);\r
+        }\r
+        return count;\r
+    }\r
+    public patInt minChars() {\r
+        Enumeration e = h.keys();\r
+        patInt count = new patInt(0);\r
+        while(e.hasMoreElements()) {\r
+            Object key = e.nextElement();\r
+            Pattern pa = (Pattern)h.get(key);\r
+            patInt pi = pa.minChars();\r
+            pi.inc();\r
+            count.mineq(pi);\r
+        }\r
+        return count;\r
+    }\r
+\r
+    // adds a oneChar object to this Branch\r
+    void addc(oneChar o,boolean ignoreCase,boolean dontMinQ) {\r
+        Pattern n = o.next;\r
+        if(n == null)\r
+            n = new NullPattern();\r
+        else\r
+            n = RegOpt.opt(n,ignoreCase,dontMinQ);\r
+        n.setParent(this);\r
+        set(new Character(o.c),n,ignoreCase,dontMinQ);\r
+        if(ignoreCase) {\r
+            if(o.c != o.altc)\r
+                set(new Character(o.altc),n,ignoreCase,dontMinQ);\r
+            if(o.c != o.altc2 && o.altc != o.altc2)\r
+                set(new Character(o.altc2),n,ignoreCase,dontMinQ);\r
+        }\r
+    }\r
+    void set(Character c,Pattern n,boolean igc,boolean dontMinQ) {\r
+        Pattern p = (Pattern)h.get(c);\r
+        next = null;\r
+        // This letter is not yet used in the Branch object.\r
+        // We need to add it.\r
+        if(p==null) {\r
+            if(n instanceof Or) {\r
+                // A NullPattern is prepended to an Or\r
+                // to prevent confusing this object.\r
+                // For example: (boo|bug) => (b(?:oo|ug))\r
+                // during this process.  However, we\r
+                // want (b(?:oo|ell)|bug)\r
+                NullPattern np = new NullPattern();\r
+                np.add(n);\r
+                h.put(c,np);\r
+            } else {\r
+                h.put(c,n);\r
+            }\r
+            // Make sure we remember the order things were\r
+            // added into the Branch object so that we can\r
+            // properly convert it to a String.\r
+            keys.addElement(c);\r
+        } else if(p instanceof Or) {\r
+            ((Or)p).addOr(n);\r
+        } else if(p instanceof oneChar && n instanceof oneChar\r
+                && ((oneChar)p).c != ((oneChar)n).c) {\r
+            Branch b = new Branch();\r
+            b.addc((oneChar)p,igc,dontMinQ);\r
+            b.addc((oneChar)n,igc,dontMinQ);\r
+            h.put(c,b);\r
+            b.setParent(this);\r
+        } else if(p instanceof Branch && n instanceof oneChar) {\r
+            ((Branch)p).addc((oneChar)n,igc,dontMinQ);\r
+            n.setParent(p);\r
+        } else {\r
+            // Create an Or object to receive the variety\r
+            // of branches in the pattern if the current letter\r
+            // is matched.  We do not attempt to make these\r
+            // sub-branches into a Branch object yet.\r
+            Or o = new Or();\r
+            o.setParent(this);\r
+\r
+            // Remove NullPattern from p -- it's no longer needed.\r
+            if(p instanceof NullPattern\r
+                    && p.parent == null && p.next != null) {\r
+                o.addOr(p.next);\r
+            } else {\r
+                o.addOr(p);\r
+            }\r
+            o.addOr(n);\r
+\r
+            Pattern optpat = RegOpt.opt(o,igc,dontMinQ);\r
+            h.put(c,optpat);\r
+            optpat.setParent(this);\r
+        }\r
+    }\r
+    public String toString() {\r
+        StringBuffer sb = new StringBuffer();\r
+        // should protect this...\r
+        sb.append("(?:(?#branch)");// Hashtable)");\r
+        for(int i=0;i<keys.size();i++) {\r
+            Character c = (Character)keys.elementAt(i);\r
+            sb.append(c);\r
+            sb.append(h.get(c));\r
+            if(i+1<keys.size())\r
+                sb.append("|");\r
+        }\r
+        sb.append(")");\r
+        sb.append(nextString());\r
+        return sb.toString();\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(pos >= pt.src.length()) return -1;\r
+        Pattern n = (Pattern)h.get(new Character(pt.src.charAt(pos)));\r
+        if(n == null) return -1;\r
+        if(pt.cbits != null && pt.cbits.get(pos)) return -1;\r
+        return n.matchInternal(pos+1,pt);\r
+    }\r
+}\r
+\r
+/** This is just a place to put the optimizing function.\r
+    It is never instantiated as an Object.  It just sorts\r
+    through the RegOpt looking for things it can change\r
+    and make faster. */\r
+public class RegOpt {\r
+    static Pattern opt(Pattern p,boolean ignoreCase,\r
+        boolean dontMinQ) {\r
+        if(p == null) return p;\r
+        if(p instanceof Bracket) {\r
+            Bracket b = (Bracket)p;\r
+            // FastBracket is the only special\r
+            // optimized class to have its own\r
+            // source file.\r
+            p = FastBracket.process(b,ignoreCase);\r
+            //if(!(p instanceof FastBracket)\r
+            //p = Switch.process(b,ignoreCase);\r
+            p.next = b.next;\r
+            p.parent = b.parent;\r
+        } else if(p instanceof oneChar && !ignoreCase\r
+                && !dontMinQ) {\r
+            oneChar o = (oneChar)p;\r
+            p = new FastChar(o.c);\r
+            p.next = o.next;\r
+            p.parent = o.parent;\r
+        } else if(p instanceof Or\r
+                && ((Or)p).leftForm().equals("(?:")\r
+                && ((Or)p).v.size()==1) { // Eliminate this Or Object.\r
+            Or o = (Or)p;\r
+            p = (Pattern)o.v.elementAt(0);\r
+            p.setParent(null);\r
+            p = RegOpt.opt(p,ignoreCase,dontMinQ);\r
+            p.add(o.next);\r
+        } else if(p instanceof Or) {\r
+            Or o = (Or)p;\r
+            o.pv = null;\r
+            Vector v = o.v;\r
+            o.v = new Vector();\r
+            Branch b = new Branch();\r
+            b.parent = o.parent;\r
+            for(int i=0;i<v.size();i++) {\r
+                Pattern pp = (Pattern)v.elementAt(i);\r
+                // We want to have at least two oneChar's in\r
+                // the Or Object to consider making a Branch.\r
+                if(pp instanceof oneChar && (b.h.size()>=1 ||\r
+                        (i+1<v.size() && v.elementAt(i+1) instanceof oneChar)))\r
+                    b.addc((oneChar)pp,ignoreCase,dontMinQ);\r
+                else {\r
+                    if(b.keys.size() > 0) {\r
+                        Pattern p2 = (Pattern)b.reduce(ignoreCase,dontMinQ);\r
+                        if(p2 != null) {\r
+                            o.addOr(p2);\r
+                            b = new Branch();\r
+                            b.parent = o.parent;\r
+                        }\r
+                    }\r
+                    o.addOr(opt(pp,ignoreCase,dontMinQ));\r
+                }\r
+            }\r
+            if(b.keys.size()>0) {\r
+                Pattern p2=(Pattern)b.reduce(ignoreCase,dontMinQ);\r
+                if(p2 != null)\r
+                    o.addOr(p2);\r
+            }\r
+            if(o.v.size()==1\r
+                    && o.leftForm().equals("(?:")) { // Eliminate Or Object\r
+                p = (Pattern)o.v.elementAt(0);\r
+                p.setParent(null);\r
+                p = RegOpt.opt(p,ignoreCase,dontMinQ);\r
+                p.add(o.next);\r
+            }\r
+        } else if(p instanceof FastMulti) {\r
+            PatternSub ps = (PatternSub)p;\r
+            ps.sub = RegOpt.opt(ps.sub,ignoreCase,dontMinQ);\r
+        } else if(p instanceof Multi && safe4fm( ((PatternSub)p).sub )) {\r
+            Multi m = (Multi)p;\r
+            FastMulti fm = null;\r
+            try {\r
+                fm = new FastMulti(m.a,m.b,\r
+                    opt(m.sub,ignoreCase,dontMinQ));\r
+            } catch(RegSyntax rs) {}\r
+            fm.parent = m.parent;\r
+            fm.matchFewest = m.matchFewest;\r
+            fm.next = m.next;\r
+            p = fm;\r
+        }\r
+        if(p.next != null)\r
+            p.next = opt(p.next,ignoreCase,dontMinQ);\r
+        return p;\r
+    }\r
+    final static boolean safe4fm(Pattern x) {\r
+        while(x != null) {\r
+            if(x instanceof Bracket)\r
+                ;\r
+            else if(x instanceof Range)\r
+                ;\r
+            else if(x instanceof oneChar)\r
+                ;\r
+            else if(x instanceof Any)\r
+                ;\r
+            else if(x instanceof Custom\r
+                    && ((Custom)x).v instanceof UniValidator)\r
+                ;\r
+            else if(x instanceof Or) {\r
+                Or o = (Or)x;\r
+                if(!o.leftForm().equals("(?:"))\r
+                    return false;\r
+                patInt lo = o.countMinChars();\r
+                patInt hi = o.countMaxChars();\r
+                if(!lo.equals(hi))\r
+                    return false;\r
+                for(int i=0;i<o.v.size();i++)\r
+                    if(!safe4fm((Pattern)o.v.elementAt(i)) )\r
+                        return false;\r
+            } else return false;\r
+            x = x.next;\r
+        }\r
+        return true;\r
+    }\r
+    /*\r
+    public static void setParents(Regex r) {\r
+      setParents(r.thePattern,null);\r
+    }\r
+    static void setParents(Pattern p,Pattern x) {\r
+      if(p instanceof PatternSub && !(p instanceof FastMulti)\r
+      && !(p instanceof DotMulti))\r
+        RegOpt.setParents( ((PatternSub)p).sub, p);\r
+      else if(p instanceof Or && !(p instanceof Bracket)) {\r
+        Or o = (Or)p;\r
+        for(int i=0;i<o.v.size();i++)\r
+          RegOpt.setParents((Pattern)o.v.elementAt(i),o);\r
+      } else if(p instanceof Branch) {\r
+        Branch b = (Branch)p;\r
+        Enumeration e = b.h.keys();\r
+        while(e.hasMoreElements()) {\r
+          Object o = e.nextElement();\r
+          RegOpt.setParents( (Pattern)b.h.get(o), b);\r
+        }\r
+      }\r
+      if(p.next == null)\r
+        p.parent = x;\r
+      else {\r
+        p.parent = null;\r
+        RegOpt.setParents(p.next,x);\r
+      }\r
+    }*/\r
+}\r
diff --git a/src/com/stevesoft/pat/RegRes.java b/src/com/stevesoft/pat/RegRes.java
new file mode 100755 (executable)
index 0000000..f181564
--- /dev/null
@@ -0,0 +1,166 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.*;\r
+\r
+/** \r
+        Shareware: package pat\r
+   <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>\r
+*/ /**\r
+This class is used to store a result from Regex */\r
+public class RegRes implements Cloneable {\r
+    protected int[] marks = null;\r
+    protected boolean didMatch_ = false;\r
+    protected StringLike src=null;\r
+\r
+    /** Obtain the text String that was matched against. */\r
+    public String getString() { return src.toString(); }\r
+    /** Obtain the source StringLike object. */\r
+    public StringLike getStringLike() { return src; }\r
+    protected int charsMatched_=0,matchFrom_=0,numSubs_=0;\r
+    public String toString() {\r
+        StringBuffer sb = new StringBuffer();\r
+        sb.append("match="+matchedFrom()+":"+charsMatched());\r
+        if(!didMatch()) return sb.toString();\r
+        for(int i=0;i<numSubs();i++) {\r
+            int n = i + 1;\r
+            sb.append(" sub("+n+")="+matchedFrom(n)+\r
+                ":"+charsMatched(n));\r
+        }\r
+        return sb.toString();\r
+    }\r
+    public RegRes() {}\r
+    public RegRes(RegRes r) {\r
+      copyOutOf(r);\r
+    }\r
+    public void copyOutOf(RegRes r) {\r
+        if(r.marks == null)\r
+            marks = null;\r
+        else try {\r
+                //marks = (Hashtable)r.marks.clone();\r
+                marks = new int[r.marks.length];\r
+                for(int i=0;i<marks.length;i++)\r
+                    marks[i]=r.marks[i];\r
+                //marks = (int[])r.marks.clone();\r
+            } catch (Throwable t) {}\r
+        didMatch_ = r.didMatch_;\r
+        src = r.src;\r
+        charsMatched_ = r.charsMatched_;\r
+        matchFrom_ = r.matchFrom_;\r
+        numSubs_ = r.numSubs_;\r
+    }\r
+    public Object clone() { return new RegRes(this); }\r
+    public boolean equals(RegRes r) {\r
+        if(charsMatched_!=r.charsMatched_\r
+                || matchFrom_   !=r.matchFrom_\r
+                || didMatch_    !=r.didMatch_\r
+                || numSubs_     !=r.numSubs_\r
+                || !src.unwrap().equals(r.src.unwrap()))\r
+            return false;\r
+        if(marks==null && r.marks!=null)\r
+            return false;\r
+        if(marks!=null && r.marks==null)\r
+            return false;\r
+        for(int i=1;i<=numSubs_;i++) {\r
+            if(matchedFrom(i) != r.matchedFrom(i))\r
+                return false;\r
+            else if(charsMatched(i) != r.charsMatched(i))\r
+                return false;\r
+        }\r
+        return true;\r
+    }\r
+    /** Obtains the match if successful, null otherwise.*/\r
+    public String stringMatched() {\r
+        int mf=matchedFrom(), cm = charsMatched();\r
+        return !didMatch_ || mf<0 || cm<0 ? null :\r
+        src.substring(mf,mf+cm);\r
+    }\r
+    /** Obtains the position backreference number i begins to match, or\r
+         -1 if backreference i was not matched. */\r
+    public int matchedFrom(int i) {\r
+        if(marks==null||i>numSubs_) return -1;\r
+        //Integer in=(Integer)marks.get("left"+i);\r
+        //return in == null ? -1 : in.intValue();\r
+        return marks[i];\r
+    }\r
+    /** Obtains the number of characters matched by backreference i, or\r
+         -1 if backreference i was not matched. */\r
+    public int charsMatched(int i) {\r
+        if(marks==null||i>numSubs_||!didMatch_) return -1;\r
+        //Integer in = (Integer)marks.get("right"+i);\r
+        //int i2 = in==null ? -1 : in.intValue();\r
+        int mf = matchedFrom(i);\r
+        return mf < 0 ? -1 : marks[i+numSubs_]-matchedFrom(i);\r
+    }\r
+    /** This is either equal to matchedFrom(i)+charsMatched(i) if the match\r
+        was successful, or -1 if it was not. */\r
+    public int matchedTo(int i) {\r
+        if(marks==null||i>numSubs_||!didMatch_) return -1;\r
+        return marks[i+numSubs_];\r
+    }\r
+    /** Obtains a substring matching the nth set\r
+                of parenthesis from the pattern. See\r
+                numSubs(void), or null if the nth backrefence did\r
+                not match. */\r
+    public String stringMatched(int i) {\r
+        int mf = matchedFrom(i), cm = charsMatched(i);\r
+        return !didMatch_ || mf<0 || cm<0 ? null :\r
+        src.substring(mf,mf+cm);\r
+    }\r
+    /** This returns the part of the string that preceeds the match,\r
+         or null if the match failed.*/\r
+    public String left() {\r
+        int mf = matchedFrom();\r
+        return !didMatch_ || (mf<0) ? null : src.substring(0,mf);\r
+    }\r
+    /** This returns the part of the string that follows the ith\r
+                backreference, or null if the backreference did not match. */\r
+    public String left(int i) {\r
+        int mf = matchedFrom(i);\r
+        return !didMatch_ || (mf<0) ? null : src.substring(0,mf);\r
+    }\r
+    /** This returns the part of the string that follows the match,\r
+         or null if the backreference did not match.*/\r
+    public String right() {\r
+        int mf = matchedFrom(), cm = charsMatched();\r
+        return !didMatch_ || mf<0 || cm<0 ? null : src.substring(mf+\r
+            cm,src.length());\r
+    }\r
+    /** This returns the string to the right of the ith backreference,\r
+         or null if the backreference did not match. */\r
+    public String right(int i) {\r
+        int mf = matchedFrom(i), cm = charsMatched(i);\r
+        return !didMatch_ || mf<0 || cm<0 ? null :\r
+        src.substring(mf+cm,src.length());\r
+    }\r
+    /** After a successful match, this returns the location of\r
+                the first matching character, or -1 if the match failed.*/\r
+    public int matchedFrom() { return !didMatch_ ? -1 : matchFrom_; }\r
+    /** After a successful match, this returns the number of\r
+                characters in the match, or -1 if the match failed. */\r
+    public int charsMatched() { return !didMatch_||matchFrom_<0 ? -1 : charsMatched_; }\r
+    /** This is matchedFrom()+charsMatched() after a successful match,\r
+        or -1 otherwise. */\r
+    public int matchedTo() { return !didMatch_ ? -1 : matchFrom_+charsMatched_;}\r
+    /** This returns the number of\r
+                backreferences (parenthesis) in the pattern,\r
+                i.e. the pattern "(ab)" has\r
+                one, the pattern "(a)(b)" has two, etc. */\r
+    public int numSubs() { return numSubs_; }\r
+    /** Contains true if the last match was successful. */\r
+    public boolean didMatch() { return didMatch_; }\r
+\r
+    /** An older name for matchedFrom. */\r
+    public int matchFrom() { return matchedFrom(); }\r
+    /** An older name for stringMatched(). */\r
+    public String substring() { return stringMatched(); }\r
+    /** An older name for matchedFrom. */\r
+    public int matchFrom(int i) { return matchedFrom(i); }\r
+    /** An older name for stringMatched. */\r
+    public String substring(int i) { return stringMatched(i); }\r
+}\r
diff --git a/src/com/stevesoft/pat/RegSyntax.java b/src/com/stevesoft/pat/RegSyntax.java
new file mode 100755 (executable)
index 0000000..1a51d9e
--- /dev/null
@@ -0,0 +1,24 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/*\r
+        Shareware: package pat\r
+   <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>\r
+*/\r
+/**\r
+This type of syntax error is thrown whenever a syntax error\r
+ is encountered in the pattern. It may not be caught directly, as\r
+ it is not in the throws clause of any method.  To detect it, catch\r
+ Throwable, and use instanceof to see if it is a RegSyntax. */\r
+public class RegSyntax extends Exception {\r
+    RegSyntax() {}\r
+    RegSyntax(String msg) {\r
+        super(msg);\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/RegSyntaxError.java b/src/com/stevesoft/pat/RegSyntaxError.java
new file mode 100755 (executable)
index 0000000..c403412
--- /dev/null
@@ -0,0 +1,29 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** When enabled, this class is thrown instead of\r
+    the normal RegSyntax.  Thus, enabling of this\r
+    class will make your debugging easier -- but\r
+    if you leave it on and forget to catch RegSyntaxError\r
+    a user-supplied pattern could generate a\r
+    RegSyntaxError that will kill your application.\r
+\r
+    I strongly recommend turning this flag on, however,\r
+    as I think it is more likely to help than to hurt\r
+    your programming efforts.\r
+    */\r
+public class RegSyntaxError extends Error {\r
+    public static boolean RegSyntaxErrorEnabled = false;\r
+    public RegSyntaxError() {}\r
+    public RegSyntaxError(String s) { super(s); }\r
+    final static void endItAll(String s) throws RegSyntax {\r
+        if(RegSyntaxErrorEnabled) throw new RegSyntaxError(s);\r
+        throw new RegSyntax(s);\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/Regex.java b/src/com/stevesoft/pat/Regex.java
new file mode 100755 (executable)
index 0000000..c7379de
--- /dev/null
@@ -0,0 +1,1429 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.*;\r
+import java.io.*;\r
+import com.stevesoft.pat.wrap.StringWrap;\r
+\r
+\r
+/** Matches a Unicode punctuation character. */\r
+class UnicodePunct extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && Prop.isPunct(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a Unicode white space character. */\r
+class UnicodeWhite extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && Prop.isWhite(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a character that is not a Unicode punctuation\r
+  * character.\r
+  */\r
+class NUnicodePunct extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && !Prop.isPunct(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a character that is not a\r
+  * Unicode white space character.\r
+  */\r
+class NUnicodeWhite extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && !Prop.isWhite(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a Unicode word character: an alphanumeric or underscore. */\r
+class UnicodeW extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        if(from >= s.length()) return -1;\r
+        char c = s.charAt(from);\r
+        return (Prop.isAlphabetic(c)||Prop.isDecimalDigit(c)||c=='_') ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a character that is not a Unicode alphanumeric or underscore. */\r
+class NUnicodeW extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        if(from >= s.length()) return -1;\r
+        char c = s.charAt(from);\r
+        return !(Prop.isAlphabetic(c)||Prop.isDecimalDigit(c)||c=='_') ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a Unicode decimal digit. */\r
+class UnicodeDigit extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && Prop.isDecimalDigit(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+/** Matches a character that is not a Unicode digit.*/\r
+class NUnicodeDigit extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && !Prop.isDecimalDigit(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a Unicode math character. */\r
+class UnicodeMath extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && Prop.isMath(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+/** Matches a non-math Unicode character. */\r
+class NUnicodeMath extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && !Prop.isMath(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a Unicode currency symbol. */\r
+class UnicodeCurrency extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && Prop.isCurrency(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+/** Matches a non-currency symbol Unicode character. */\r
+class NUnicodeCurrency extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && !Prop.isCurrency(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a Unicode alphabetic character. */\r
+class UnicodeAlpha extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && Prop.isAlphabetic(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches a non-alphabetic Unicode character. */\r
+class NUnicodeAlpha extends UniValidator {\r
+    public int validate(StringLike s,int from,int to) {\r
+        return from<s.length() && !Prop.isAlphabetic(s.charAt(from)) ? to : -1;\r
+    }\r
+}\r
+\r
+/** Matches an upper case Unicode character. */\r
+class UnicodeUpper extends UniValidator {\r
+  public int validate(StringLike s,int from,int to) {\r
+    return from<s.length() && isUpper(s.charAt(from)) ? to : -1;\r
+  }\r
+  final boolean isUpper(char c) {\r
+    return c == CaseMgr.toUpperCase(c) && c != CaseMgr.toLowerCase(c);\r
+  }\r
+}\r
+\r
+/** Matches an upper case Unicode character. */\r
+class UnicodeLower extends UniValidator {\r
+  public int validate(StringLike s,int from,int to) {\r
+    return from<s.length() && isLower(s.charAt(from)) ? to : -1;\r
+  }\r
+  final boolean isLower(char c) {\r
+    return c != CaseMgr.toUpperCase(c) && c == CaseMgr.toLowerCase(c);\r
+  }\r
+}\r
+\r
+/**\r
+Regex provides the parser which constructs the linked list of\r
+Pattern classes from a String.\r
+<p>\r
+For the purpose of this documentation, the fact that java interprets the\r
+backslash will be ignored.  In practice, however, you will need a\r
+double backslash to obtain a string that contains a single backslash\r
+character.  Thus, the example pattern "\b" should really be typed\r
+as "\\b" inside java code.\r
+<p>\r
+Note that Regex is part of package "com.stevesoft.pat".\r
+To use it, simply import\r
+com.stevesoft.pat.Regex at the top of your file.\r
+<p>\r
+Regex is made with a constructor that takes a String that defines\r
+the regular expression.  Thus, for example\r
+<pre>\r
+      Regex r = new Regex("[a-c]*");\r
+</pre>\r
+matches any number of characters so long as the are 'a', 'b', or 'c').\r
+<p>\r
+To attempt to match the Pattern to a given string, you can use either\r
+the search(String) member function, or the matchAt(String,int position)\r
+member function.  These functions return a boolean which tells you\r
+whether or not the thing worked, and sets the methods "charsMatched()"\r
+and "matchedFrom()" in the Regex object appropriately.\r
+<p>\r
+The portion of the string before the match can be obtained by the\r
+left() member, and the portion after the match can be obtained\r
+by the right() member.\r
+<p>\r
+Essentially, this package implements a syntax that is very much\r
+like the perl 5 regular expression syntax.\r
+\r
+Longer example:\r
+<pre>\r
+        Regex r = new Regex("x(a|b)y");\r
+        r.matchAt("xay",0);\r
+        System.out.println("sub = "+r.stringMatched(1));\r
+</pre>\r
+The above would print "sub = a".\r
+<pre>\r
+        r.left() // would return "x"\r
+        r.right() // would return "y"\r
+</pre>\r
+<p>\r
+Differences between this package and perl5:<br>\r
+The extended Pattern for setting flags, is now supported,\r
+but the flags are different.  "(?i)" tells the pattern to\r
+ignore case, "(?Q)" sets the "dontMatchInQuotes" flag, and\r
+"(?iQ)" sets them both.  You can change the escape character.\r
+The pattern <pre>(?e=#)#d+</pre> is the same as <pre>\d+</pre>,\r
+but note that the sequence <pre>(?e=#)</pre> <b>must</b> occur\r
+at the very beginning of the pattern.  There may be other small\r
+differences as well.  I will either make my package conform\r
+or note them as I become aware of them.\r
+<p>\r
+This package supports additional patterns not in perl5:\r
+<center>\r
+<table border=1>\r
+<tr><td>(?@())</td><td>Group</td><td>This matches all characters between\r
+the '(' character and the balancing ')' character.  Thus, it will\r
+match "()" as well as "(())".  The balancing characters are\r
+arbitrary, thus (?@{}) matches on "{}" and "{{}}".</td>\r
+<tr><td>(?&lt1)</td><td>Backup</td><td>Moves the pointer backwards within the text.\r
+This allows you to make a "look behind."  It fails if it\r
+attempts to move to a position before the beginning of the string.\r
+"x(?&lt1)" is equivalent to "(?=x)".  The number, 1 in this example,\r
+is the number of characters to move backwards.</td>\r
+</table>\r
+</center>\r
+</dl>\r
+@author Steven R. Brandt\r
+@version package com.stevesoft.pat, release 1.5.3\r
+@see Pattern\r
+*/\r
+public class Regex extends RegRes implements FilenameFilter {\r
+    /** BackRefOffset gives the identity number of the first\r
+        pattern.  Version 1.0 used zero, version 1.1 uses 1 to be\r
+        more compatible with perl. */\r
+    static int BackRefOffset = 1;\r
+    private static Pattern none = new NoPattern();\r
+    Pattern thePattern = none;\r
+    patInt minMatch = new patInt(0);\r
+\r
+    static Hashtable validators = new Hashtable();\r
+    static {\r
+        define("p","(?>1)",new UnicodePunct());\r
+        define("P","(?>1)",new NUnicodePunct());\r
+        define("s","(?>1)",new UnicodeWhite());\r
+        define("S","(?>1)",new NUnicodeWhite());\r
+        define("w","(?>1)",new UnicodeW());\r
+        define("W","(?>1)",new NUnicodeW());\r
+        define("d","(?>1)",new UnicodeDigit());\r
+        define("D","(?>1)",new NUnicodeDigit());\r
+        define("m","(?>1)",new UnicodeMath());\r
+        define("M","(?>1)",new NUnicodeMath());\r
+        define("c","(?>1)",new UnicodeCurrency());\r
+        define("C","(?>1)",new NUnicodeCurrency());\r
+        define("a","(?>1)",new UnicodeAlpha());\r
+        define("A","(?>1)",new NUnicodeAlpha());\r
+        define("uc","(?>1)",new UnicodeUpper());\r
+        define("lc","(?>1)",new UnicodeLower());\r
+    }\r
+\r
+    /** Set the dontMatch in quotes flag. */\r
+    public void setDontMatchInQuotes(boolean b) {\r
+      dontMatchInQuotes = b;\r
+    }\r
+    /** Find out if the dontMatchInQuotes flag is enabled. */\r
+    public boolean getDontMatchInQuotes() {\r
+      return dontMatchInQuotes;\r
+    }\r
+    boolean dontMatchInQuotes = false;\r
+\r
+    /** Set the state of the ignoreCase flag.  If set to true, then\r
+        the pattern matcher will ignore case when searching for a\r
+        match. */\r
+    public void setIgnoreCase(boolean b) {\r
+        ignoreCase = b;\r
+    }\r
+    /** Get the state of the ignoreCase flag.  Returns true if we\r
+        are ignoring the case of the pattern, false otherwise. */\r
+    public boolean getIgnoreCase() {\r
+        return ignoreCase;\r
+    }\r
+    boolean ignoreCase = false;\r
+    \r
+    static boolean defaultMFlag = false;\r
+    /** Set the default value of the m flag.  If it\r
+        is set to true, then the MFlag will be on\r
+       for any regex search executed. */\r
+    public static void setDefaultMFlag(boolean mFlag) {\r
+      defaultMFlag = mFlag;\r
+    }\r
+    /** Get the default value of the m flag.  If it\r
+        is set to true, then the MFlag will be on\r
+       for any regex search executed. */\r
+    public static boolean getDefaultMFlag() {\r
+      return defaultMFlag;\r
+    }\r
+\r
+    /** Initializes the object without a Pattern. To supply a Pattern\r
+        use compile(String s).\r
+         @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
+                 */\r
+    public Regex() {}\r
+    /** Create and compile a Regex, but do not throw any exceptions.\r
+        If you wish to have exceptions thrown for syntax errors,\r
+        you must use the Regex(void) constructor to create the\r
+        Regex object, and then call the compile method.  Therefore, you\r
+        should only call this method when you know your pattern is right.\r
+        I will probably become more like\r
+         @see com.stevesoft.pat.Regex#search(java.lang.String)\r
+         @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
+         */\r
+    public Regex(String s) {\r
+        try {\r
+            compile(s);\r
+        } catch(RegSyntax rs) {}\r
+    }\r
+\r
+    ReplaceRule rep = null;\r
+    /** Create and compile both a Regex and a ReplaceRule.\r
+        @see com.stevesoft.pat.ReplaceRule\r
+       @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
+        */\r
+    public Regex(String s,String rp) {\r
+        this(s);\r
+        rep = ReplaceRule.perlCode(rp);\r
+    }\r
+    /** Create and compile a Regex, but give it the ReplaceRule\r
+        specified.  This allows the user finer control of the\r
+        Replacement process, if that is desired.\r
+        @see com.stevesoft.pat.ReplaceRule\r
+       @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
+        */\r
+    public Regex(String s,ReplaceRule rp) {\r
+        this(s);\r
+        rep = rp;\r
+    }\r
+\r
+    /** Change the ReplaceRule of this Regex by compiling\r
+        a new one using String rp. */\r
+    public void setReplaceRule(String rp) {\r
+        rep = ReplaceRule.perlCode(rp);\r
+        repr = null; // Clear Replacer history\r
+    }\r
+\r
+    /** Change the ReplaceRule of this Regex to rp. */\r
+    public void setReplaceRule(ReplaceRule rp) {\r
+        rep = rp;\r
+    }\r
+    /** Test to see if a custom defined rule exists.\r
+        @see com.stevesoft.pat#define(java.lang.String,java.lang.String,Validator)\r
+        */\r
+    public static boolean isDefined(String nm) {\r
+        return validators.get(nm) != null;\r
+    }\r
+    /** Removes a custom defined rule.\r
+        @see com.stevesoft.pat#define(java.lang.String,java.lang.String,Validator)\r
+        */\r
+    public static void undefine(String nm) {\r
+        validators.remove(nm);\r
+    }\r
+    /** Defines a method to create a new rule.  See test/deriv2.java\r
+        and test/deriv3.java for examples of how to use it. */\r
+    public static void define(String nm,String pat,Validator v) {\r
+        v.pattern = pat;\r
+        validators.put(nm,v);\r
+    }\r
+    /** Defines a shorthand for a pattern.  The pattern will be\r
+        invoked by a string that has the form "(??"+nm+")".\r
+        */\r
+    public static void define(String nm,String pat) {\r
+        validators.put(nm,pat);\r
+    }\r
+\r
+    /** Get the current ReplaceRule. */\r
+    public ReplaceRule getReplaceRule() { return rep; }\r
+\r
+    Replacer repr = null;\r
+    final Replacer _getReplacer() {\r
+        return repr==null ? repr=new Replacer() : repr;\r
+    }\r
+    public Replacer getReplacer() {\r
+        if(repr == null)\r
+            repr = new Replacer();\r
+        repr.rh.me = this;\r
+        repr.rh.prev = null;\r
+        return repr;\r
+    }\r
+    /** Replace the first occurence of this pattern in String s\r
+        according to the ReplaceRule.\r
+        @see com.stevesoft.pat.ReplaceRule\r
+        @see com.stevesoft.pat.Regex#getReplaceRule()\r
+        */\r
+    public String replaceFirst(String s) {\r
+        return _getReplacer().replaceFirstRegion(s,this,0,s.length()).toString();\r
+    }\r
+    /** Replace the first occurence of this pattern in String s\r
+        beginning with position pos according to the ReplaceRule.\r
+        @see com.stevesoft.pat.ReplaceRule\r
+        @see com.stevesoft.pat.Regex#getReplaceRule()\r
+        */\r
+    public String replaceFirstFrom(String s,int pos) {\r
+        return _getReplacer().replaceFirstRegion(s,this,pos,s.length()).toString();\r
+    }\r
+    /** Replace the first occurence of this pattern in String s\r
+        beginning with position start and ending with end\r
+        according to the ReplaceRule.\r
+        @see com.stevesoft.pat.ReplaceRule\r
+        @see com.stevesoft.pat.Regex#getReplaceRule()\r
+        */\r
+    public String replaceFirstRegion(String s,int start,int end) {\r
+        return _getReplacer().replaceFirstRegion(s,this,start,end).toString();\r
+    }\r
+\r
+    /** Replace all occurences of this pattern in String s\r
+        according to the ReplaceRule.\r
+        @see com.stevesoft.pat.ReplaceRule\r
+        @see com.stevesoft.pat.Regex#getReplaceRule()\r
+        */\r
+    public String replaceAll(String s) {\r
+        return _getReplacer().replaceAllRegion(s,this,0,s.length()).toString();\r
+    }\r
+    public StringLike replaceAll(StringLike s) {\r
+        return _getReplacer().replaceAllRegion(s,this,0,s.length());\r
+    }\r
+    /** Replace all occurences of this pattern in String s\r
+        beginning with position pos according to the ReplaceRule.\r
+        @see com.stevesoft.pat.ReplaceRule\r
+        @see com.stevesoft.pat.Regex#getReplaceRule()\r
+        */\r
+    public String replaceAllFrom(String s,int pos) {\r
+        return _getReplacer().replaceAllRegion(s,this,pos,s.length()).toString();\r
+    }\r
+    /** Replace all occurences of this pattern in String s\r
+        beginning with position start and ending with end\r
+        according to the ReplaceRule.\r
+        @see com.stevesoft.pat.ReplaceRule\r
+        @see com.stevesoft.pat.Regex#getReplaceRule()\r
+        */\r
+    public String replaceAllRegion(String s,int start,int end) {\r
+        return _getReplacer().replaceAllRegion(s,this,start,end).toString();\r
+    }\r
+\r
+\r
+    /** Essentially clones the Regex object */\r
+    public Regex(Regex r) {\r
+        super((RegRes)r);\r
+        dontMatchInQuotes = r.dontMatchInQuotes;\r
+        esc = r.esc;\r
+        ignoreCase = r.ignoreCase;\r
+        gFlag = r.gFlag;\r
+        if(r.rep==null)\r
+            rep = null;\r
+        else\r
+            rep = (ReplaceRule)r.rep.clone();\r
+        /* try {\r
+            compile(r.toString());\r
+        } catch(RegSyntax r_) {} */\r
+        thePattern = r.thePattern.clone(new Hashtable());\r
+        minMatch = r.minMatch;\r
+        skipper = r.skipper;\r
+    }\r
+\r
+    /** By default,\r
+                the escape character is the backslash, but you can\r
+                make it anything you want by setting this variable. */\r
+    public char esc = Pattern.ESC;\r
+    /** This method compiles a regular expression, making it\r
+         possible to call the search or matchAt methods.\r
+                @exception com.stevesoft.pat.RegSyntax\r
+                is thrown if a syntax error is encountered\r
+               in the pattern.\r
+                 For example, "x{3,1}" or "*a" are not valid\r
+                patterns.\r
+                @see com.stevesoft.pat.Regex#search\r
+                @see com.stevesoft.pat.Regex#matchAt\r
+                */\r
+    public void compile(String prepat) throws RegSyntax {\r
+        String postpat = parsePerl.codify(prepat,true);\r
+        String pat = postpat==null ? prepat : postpat;\r
+        minMatch = null;\r
+        ignoreCase = false;\r
+        dontMatchInQuotes = false;\r
+        Rthings mk = new Rthings(this);\r
+        int offset = mk.val;\r
+        String newpat = pat;\r
+        thePattern = none;\r
+        p = null;\r
+        or = null;\r
+        minMatch = new patInt(0);\r
+        StrPos sp = new StrPos(pat,0);\r
+        if(sp.incMatch("(?e=")) {\r
+            char newEsc = sp.c;\r
+            sp.inc();\r
+            if(sp.match(')'))\r
+                newpat = reEscape(pat.substring(6),\r
+                    newEsc,Pattern.ESC);\r
+        } else if(esc != Pattern.ESC)\r
+            newpat = reEscape(pat,esc,Pattern.ESC);\r
+        thePattern = _compile(newpat,mk);\r
+        numSubs_ = mk.val-offset;\r
+        mk.set(this);\r
+    }\r
+\r
+    /*  If a Regex is compared against a Regex, a check is\r
+        done to see that the patterns are equal as well as\r
+        the most recent match.  If a Regex is compare with\r
+        a RegRes, only the result of the most recent match\r
+        is compared. */\r
+    public boolean equals(Object o) {\r
+        if(o instanceof Regex) {\r
+            if(toString().equals(o.toString()))\r
+                return super.equals(o);\r
+            else\r
+                return false;\r
+        } else return super.equals(o);\r
+    }\r
+\r
+    /** A clone by any other name would smell as sweet. */\r
+    public Object clone() {\r
+        return new Regex(this);\r
+    }\r
+    /** Return a clone of the underlying RegRes object. */\r
+    public RegRes result() {\r
+      return (RegRes)super.clone();\r
+    }\r
+\r
+    // prep sets global variables of class\r
+    // Pattern so that it can access them\r
+    // during an attempt at a match\r
+    Pthings pt = new Pthings();\r
+    final Pthings prep(StringLike s) {\r
+       //if(gFlag)\r
+          pt.lastPos = matchedTo();\r
+        if(pt.lastPos < 0) pt.lastPos = 0;\r
+        if( (s==null ? null : s.unwrap()) != (src==null ? null : s.unwrap()) )\r
+          pt.lastPos = 0;\r
+        src = s;\r
+        pt.dotDoesntMatchCR=dotDoesntMatchCR && (!sFlag);\r
+       pt.mFlag = (mFlag | defaultMFlag);\r
+        pt.ignoreCase = ignoreCase;\r
+        pt.no_check = false;\r
+        if(pt.marks != null)\r
+            for(int i=0;i<pt.marks.length;i++)\r
+                pt.marks[i]=-1;\r
+       pt.marks = null;\r
+        pt.nMarks = numSubs_;\r
+        pt.src = s;\r
+        if(dontMatchInQuotes)\r
+            setCbits(s,pt);\r
+        else\r
+            pt.cbits = null;\r
+        return pt;\r
+    }\r
+    /** Attempt to match a Pattern beginning\r
+        at a specified location within the string.\r
+        @see com.stevesoft.pat.Regex#search\r
+        */\r
+    public boolean matchAt(String s,int start_pos) {\r
+        return _search(s,start_pos,start_pos);\r
+    }\r
+    /** Attempt to match a Pattern beginning\r
+        at a specified location within the StringLike.\r
+        @see com.stevesoft.pat.Regex#search\r
+        */\r
+    public boolean matchAt(StringLike s,int start_pos) {\r
+        return _search(s,start_pos,start_pos);\r
+    }\r
+\r
+\r
+    /** Search through a String for the first\r
+        occurrence of a match.\r
+        @see com.stevesoft.pat.Regex#searchFrom\r
+        @see com.stevesoft.pat.Regex#matchAt\r
+        */\r
+    public boolean search(String s) {\r
+        if(s==null)\r
+            throw new NullPointerException("Null String Given to Regex.search");\r
+        return _search(s,0,s.length());\r
+    }\r
+    public boolean search(StringLike sl) {\r
+        if(sl==null)\r
+            throw new NullPointerException("Null StringLike Given to Regex.search");\r
+        return _search(sl,0,sl.length());\r
+    }\r
+    public boolean reverseSearch(String s) {\r
+        if(s==null)\r
+            throw new NullPointerException("Null String Given to Regex.reverseSearch");\r
+        return _reverseSearch(s,0,s.length());\r
+    }\r
+    public boolean reverseSearch(StringLike sl) {\r
+        if(sl==null)\r
+            throw new NullPointerException("Null StringLike Given to Regex.reverseSearch");\r
+        return _reverseSearch(sl,0,sl.length());\r
+    }\r
+    /** Search through a String for the first\r
+                occurence of a match, but start at position <pre>start</pre>*/\r
+    public boolean searchFrom(String s,int start) {\r
+        if(s==null)\r
+            throw new NullPointerException("Null String Given to Regex.searchFrom");\r
+        return _search(s,start,s.length());\r
+    }\r
+    public boolean searchFrom(StringLike s,int start) {\r
+        if(s==null)\r
+            throw new NullPointerException("Null String Given to Regex.searchFrom");\r
+        return _search(s,start,s.length());\r
+    }\r
+    /** Search through a region of a String\r
+        for the first occurence of a match. */\r
+    public boolean searchRegion(String s,int start,int end) {\r
+        if(s==null)\r
+            throw new NullPointerException("Null String Given to Regex.searchRegion");\r
+        return _search(s,start,end);\r
+    }\r
+    /** Set this to change the default behavior of the "." pattern.\r
+                By default it now matches perl's behavior and fails to\r
+                match the '\n' character. */\r
+    public static boolean dotDoesntMatchCR = true;\r
+    StringLike gFlags;\r
+    int gFlagto = 0;\r
+    boolean gFlag = false;\r
+    /** Set the 'g' flag */\r
+    public void setGFlag(boolean b) {\r
+      gFlag = b;\r
+    }\r
+    /** Get the state of the 'g' flag. */\r
+    public boolean getGFlag() {\r
+      return gFlag;\r
+    }\r
+    boolean sFlag = false;\r
+    /** Get the state of the sFlag */\r
+    public boolean getSFlag() {\r
+      return sFlag;\r
+    }\r
+    boolean mFlag = false;\r
+    /** Get the state of the sFlag */\r
+    public boolean getMFlag() {\r
+      return mFlag;\r
+    }\r
+\r
+    final boolean _search(String s,int start,int end) {\r
+        return _search(new StringWrap(s),start,end);\r
+    }\r
+    final boolean _search(StringLike s,int start,int end) {\r
+        if(gFlag && gFlagto > 0 && gFlags!=null && s.unwrap()==gFlags.unwrap())\r
+            start = gFlagto;\r
+        gFlags = null;\r
+\r
+        Pthings pt=prep(s);\r
+\r
+        int up = (minMatch == null ? end : end-minMatch.i);\r
+\r
+        if(up < start && end >= start) up = start;\r
+\r
+        if(skipper == null) {\r
+            for(int i=start;i<=up;i++) {\r
+                charsMatched_ = thePattern.matchAt(s,i,pt);\r
+                if(charsMatched_ >= 0) {\r
+                    matchFrom_ = thePattern.mfrom;\r
+                    marks = pt.marks;\r
+                    gFlagto = matchFrom_+charsMatched_;\r
+                    gFlags = s;\r
+                    return didMatch_=true;\r
+                }\r
+            }\r
+        } else {\r
+            pt.no_check = true;\r
+            for(int i=start;i<=up;i++) {\r
+                i = skipper.find(src,i,up);\r
+                if(i<0) {\r
+                    charsMatched_ = matchFrom_ = -1;\r
+                    return didMatch_ = false;\r
+                }\r
+                charsMatched_ = thePattern.matchAt(s,i,pt);\r
+                if(charsMatched_ >= 0) {\r
+                    matchFrom_ = thePattern.mfrom;\r
+                    marks = pt.marks;\r
+                    gFlagto = matchFrom_+charsMatched_;\r
+                    gFlags = s;\r
+                    return didMatch_=true;\r
+                }\r
+            }\r
+        }\r
+        return didMatch_=false;\r
+    }\r
+    /*final boolean _search(LongStringLike s,long start,long end) {\r
+        if(gFlag && gFlagto > 0 && s==gFlags)\r
+            start = gFlagto;\r
+        gFlags = null;\r
+\r
+        Pthings pt=prep(s);\r
+\r
+        int up = end;//(minMatch == null ? end : end-minMatch.i);\r
+\r
+        if(up < start && end >= start) up = start;\r
+\r
+        if(skipper == null) {\r
+            for(long i=start;i<=up;i++) {\r
+                charsMatched_ = thePattern.matchAt(s,i,pt);\r
+                if(charsMatched_ >= 0) {\r
+                    matchFrom_ = thePattern.mfrom;\r
+                    marks = pt.marks;\r
+                    gFlagto = matchFrom_+charsMatched_;\r
+                    return didMatch_=true;\r
+                }\r
+            }\r
+        } else {\r
+            pt.no_check = true;\r
+            for(long i=start;i<=up;i++) {\r
+                i = skipper.find(src,i,up);\r
+                if(i<0) {\r
+                    charsMatched_ = matchFrom_ = -1;\r
+                    return didMatch_ = false;\r
+                }\r
+                charsMatched_ = thePattern.matchAt(s,i,pt);\r
+                if(charsMatched_ >= 0) {\r
+                    matchFrom_ = thePattern.mfrom;\r
+                    marks = pt.marks;\r
+                    gFlagto = matchFrom_+charsMatched_;\r
+                    gFlags = s;\r
+                    return didMatch_=true;\r
+                } else {\r
+                  i = s.adjustIndex(i);\r
+                  up = s.adjustEnd(i);\r
+                }\r
+            }\r
+        }\r
+        return didMatch_=false;\r
+    }*/\r
+\r
+    boolean _reverseSearch(String s,int start,int end) {\r
+        return _reverseSearch(new StringWrap(s),start,end);\r
+    }\r
+    boolean _reverseSearch(StringLike s,int start,int end) {\r
+        if(gFlag && gFlagto > 0 && s.unwrap()==gFlags.unwrap())\r
+            end = gFlagto;\r
+        gFlags = null;\r
+        Pthings pt=prep(s);\r
+        for(int i=end;i>=start;i--) {\r
+            charsMatched_ = thePattern.matchAt(s,i,pt);\r
+            if(charsMatched_ >= 0) {\r
+                matchFrom_ = thePattern.mfrom;\r
+                marks = pt.marks;\r
+                gFlagto = matchFrom_-1;\r
+                gFlags = s;\r
+                return didMatch_=true;\r
+            }\r
+        }\r
+        return didMatch_=false;\r
+    }\r
+\r
+    // This routine sets the cbits variable\r
+    // of class Pattern.  Cbits is true for\r
+    // the bit corresponding to a character inside\r
+    // a set of quotes.\r
+    static StringLike lasts=null;\r
+    static BitSet lastbs=null;\r
+    static void setCbits(StringLike s,Pthings pt) {\r
+        if(s == lasts) {\r
+            pt.cbits = lastbs;\r
+            return;\r
+        }\r
+        BitSet bs = new BitSet(s.length());\r
+        char qc = ' ';\r
+        boolean setBit = false;\r
+        for(int i=0;i<s.length();i++) {\r
+            if(setBit) bs.set(i);\r
+            char c = s.charAt(i);\r
+            if(!setBit && c == '"') {\r
+                qc = c;\r
+                setBit = true;\r
+                bs.set(i);\r
+            } else if(!setBit && c == '\'') {\r
+                qc = c;\r
+                setBit = true;\r
+                bs.set(i);\r
+            } else if(setBit && c == qc) {\r
+                setBit = false;\r
+            } else if(setBit && c == '\\' && i+1<s.length()) {\r
+                i++;\r
+                if(setBit) bs.set(i);\r
+            }\r
+        }\r
+        pt.cbits = lastbs = bs;\r
+        lasts = s;\r
+    }\r
+\r
+    // Wanted user to over-ride this in alpha version,\r
+    // but it wasn't really necessary because of this trick:\r
+    Regex newRegex() {\r
+        try {\r
+            return (Regex)getClass().newInstance();\r
+        } catch(InstantiationException ie) {\r
+            return null;\r
+        } catch(IllegalAccessException iae) {\r
+            return null;\r
+        }\r
+    }\r
+    /** Only needed for creating your own extensions of\r
+         Regex.  This method adds the next Pattern in the chain\r
+         of patterns or sets the Pattern if it is the first call. */\r
+    protected void add(Pattern p2) {\r
+        if(p == null)\r
+            p = p2;\r
+        else {\r
+            p.add(p2);\r
+            p2 = p;\r
+        }\r
+    }\r
+\r
+    /** You only need to use this method if you are creating\r
+        your own extentions to Regex.\r
+        compile1 compiles one Pattern element, it can be\r
+        over-ridden to allow the Regex compiler to understand\r
+        new syntax.  See deriv.java for an example.  This routine\r
+        is the heart of class Regex. Rthings has one integer\r
+        member called intValue, it is used to keep track of the number\r
+        of ()'s in the Pattern.\r
+        @exception com.stevesoft.pat.RegSyntax is thrown when a nonsensensical\r
+        pattern is supplied.  For example, a pattern beginning\r
+        with *. */\r
+    protected void compile1(StrPos sp,Rthings mk) throws RegSyntax {\r
+        if(sp.match('[')) {\r
+            sp.inc();\r
+            add(matchBracket(sp));\r
+        } else if(sp.match('|')) {\r
+            if(or == null)\r
+                or = new Or();\r
+            if(p == null) p=new NullPattern();\r
+            or.addOr(p);\r
+            p = null;\r
+        } else if(sp.incMatch("(?<")) {\r
+            patInt i = sp.getPatInt();\r
+            if(i==null) RegSyntaxError.endItAll("No int after (?<");\r
+            add(new Backup(i.intValue()));\r
+            if(!sp.match(')')) RegSyntaxError.endItAll("No ) after (?<");\r
+        } else if(sp.incMatch("(?>")) {\r
+            patInt i = sp.getPatInt();\r
+            if(i==null) RegSyntaxError.endItAll("No int after (?>");\r
+            add(new Backup(-i.intValue()));\r
+            if(!sp.match(')')) RegSyntaxError.endItAll("No ) after (?<");\r
+        } else if(sp.incMatch("(?@")) {\r
+            char op = sp.c;\r
+            sp.inc();\r
+            char cl = sp.c;\r
+            sp.inc();\r
+            if(!sp.match(')'))\r
+                RegSyntaxError.endItAll(\r
+                    "(?@ does not have closing paren");\r
+            add(new Group(op,cl));\r
+        } else if(sp.incMatch("(?#")) {\r
+            while(!sp.match(')'))\r
+                sp.inc();\r
+        } else if(sp.dontMatch && sp.c == 'w') {\r
+            Regex r = new Regex();\r
+            //r._compile("[a-zA-Z0-9_]",mk);\r
+            //add(new Goop("\\w",r.thePattern));\r
+            Bracket b = new Bracket(false);\r
+            b.addOr(new Range('a','z'));\r
+            b.addOr(new Range('A','Z'));\r
+            b.addOr(new Range('0','9'));\r
+            b.addOr(new oneChar('_'));\r
+            add(b);\r
+        } else if(sp.dontMatch && sp.c == 'G') {\r
+            add(new BackG());\r
+        } else if(sp.dontMatch && sp.c == 's') {\r
+            //Regex r = new Regex();\r
+            //r._compile("[ \t\n\r\b]",mk);\r
+            //add(new Goop("\\s",r.thePattern));\r
+            Bracket b = new Bracket(false);\r
+            b.addOr(new oneChar((char)32));\r
+            b.addOr(new Range((char)8,(char)10));\r
+            b.addOr(new oneChar((char)13));\r
+            add(b);\r
+        } else if(sp.dontMatch && sp.c == 'd') {\r
+            Regex r = new Regex();\r
+            //r._compile("[0-9]",mk);\r
+            //add(new Goop("\\d",r.thePattern));\r
+            Range digit = new Range('0','9');\r
+            digit.printBrackets = true;\r
+            add(digit);\r
+        } else if(sp.dontMatch && sp.c == 'W') {\r
+            Regex r = new Regex();\r
+            //r._compile("[^a-zA-Z0-9_]",mk);\r
+            //add(new Goop("\\W",r.thePattern));\r
+            Bracket b = new Bracket(true);\r
+            b.addOr(new Range('a','z'));\r
+            b.addOr(new Range('A','Z'));\r
+            b.addOr(new Range('0','9'));\r
+            b.addOr(new oneChar('_'));\r
+            add(b);\r
+        } else if(sp.dontMatch && sp.c == 'S') {\r
+            //Regex r = new Regex();\r
+            //r._compile("[^ \t\n\r\b]",mk);\r
+            //add(new Goop("\\S",r.thePattern));\r
+            Bracket b = new Bracket(true);\r
+            b.addOr(new oneChar((char)32));\r
+            b.addOr(new Range((char)8,(char)10));\r
+            b.addOr(new oneChar((char)13));\r
+            add(b);\r
+        } else if(sp.dontMatch && sp.c == 'D') {\r
+            //Regex r = new Regex();\r
+            //r._compile("[^0-9]",mk);\r
+            //add(new Goop("\\D",r.thePattern));\r
+            Bracket b = new Bracket(true);\r
+            b.addOr(new Range('0','9'));\r
+            add(b);\r
+        } else if(sp.dontMatch && sp.c == 'B') {\r
+            Regex r = new Regex();\r
+            r._compile("(?!"+back_slash+"b)",mk);\r
+            add(r.thePattern);\r
+       } else if(isOctalString(sp)) {\r
+           int d = sp.c - '0';\r
+           sp.inc();\r
+           d = 8*d + sp.c - '0';\r
+           StrPos sp2 = new StrPos(sp);\r
+           sp2.inc();\r
+           if(isOctalDigit(sp2,false)) {\r
+             sp.inc();\r
+             d = 8*d + sp.c - '0';\r
+           }\r
+           add(new oneChar((char)d));\r
+        } else if(sp.dontMatch && sp.c >= '1' && sp.c <= '9') {\r
+            int iv = sp.c-'0';\r
+            StrPos s2 = new StrPos(sp);\r
+            s2.inc();\r
+            if(!s2.dontMatch && s2.c >= '0' && s2.c <= '9') {\r
+                iv = 10*iv+(s2.c-'0');\r
+                sp.inc();\r
+            }\r
+            add(new BackMatch(iv));\r
+        } else if(sp.dontMatch && sp.c == 'b') {\r
+            add(new Boundary());\r
+        } else if(sp.match('\b')) {\r
+            add(new Boundary());\r
+        } else if(sp.match('$')) {\r
+            add(new End(true));\r
+        } else if(sp.dontMatch && sp.c == 'Z') {\r
+            add(new End(false));\r
+        } else if(sp.match('.')) {\r
+            add(new Any());\r
+        } else if(sp.incMatch("(??")) {\r
+            StringBuffer sb = new StringBuffer();\r
+            StringBuffer sb2 = new StringBuffer();\r
+            while(!sp.match(')') && !sp.match(':')) {\r
+                sb.append(sp.c);\r
+                sp.inc();\r
+            }\r
+            if(sp.incMatch(":")) {\r
+                while(!sp.match(')')) {\r
+                    sb2.append(sp.c);\r
+                    sp.inc();\r
+                }\r
+            }\r
+            String sbs = sb.toString();\r
+            if(validators.get(sbs) instanceof String) {\r
+                String pat = (String)validators.get(sbs);\r
+                Regex r = newRegex();\r
+               Rthings rth = new Rthings(this);\r
+               rth.noBackRefs = true;\r
+                r._compile(pat,rth);\r
+                add(r.thePattern);\r
+            } else {\r
+                Custom cm = new Custom(sb.toString());\r
+                if(cm.v != null) {\r
+                    Validator v2 = cm.v.arg(sb2.toString());\r
+                    if(v2 != null) {\r
+                        v2.argsave = sb2.toString();\r
+                        String p = cm.v.pattern;\r
+                        cm.v = v2;\r
+                        v2.pattern = p;\r
+                    }\r
+                    Regex r = newRegex();\r
+                   Rthings rth = new Rthings(this);\r
+                   rth.noBackRefs = true;\r
+                    r._compile(cm.v.pattern,rth);\r
+                    cm.sub = r.thePattern;\r
+                    cm.sub.add(new CustomEndpoint(cm));\r
+                    cm.sub.setParent(cm);\r
+                    add(cm);\r
+                }\r
+            }\r
+        } else if(sp.match('(')) {\r
+            mk.parenLevel++;\r
+            Regex r = newRegex();\r
+            // r.or = new Or();\r
+            sp.inc();\r
+            if(sp.incMatch("?:")) {\r
+                r.or = new Or();\r
+            } else if(sp.incMatch("?=")) {\r
+                r.or = new lookAhead(false);\r
+            } else if(sp.incMatch("?!")) {\r
+                r.or = new lookAhead(true);\r
+            } else if(sp.match('?')) {\r
+                sp.inc();\r
+                do {\r
+                    if(sp.c=='i')mk.ignoreCase = true;\r
+                    if(sp.c=='Q')mk.dontMatchInQuotes = true;\r
+                    if(sp.c=='o')mk.optimizeMe = true;\r
+                    if(sp.c=='g')mk.gFlag = true;\r
+                    if(sp.c=='s')mk.sFlag = true;\r
+                   if(sp.c=='m')mk.mFlag = true;\r
+                    sp.inc();\r
+                } while(!sp.match(')') && !sp.eos);\r
+                r = null;\r
+                mk.parenLevel--;\r
+                if(sp.eos) //throw new RegSyntax\r
+                    RegSyntaxError.endItAll("Unclosed ()");\r
+            } else { // just ordinary parenthesis\r
+                r.or = mk.noBackRefs ? new Or() : new OrMark(mk.val++);\r
+            }\r
+            if(r != null) add(r._compile(sp,mk));\r
+        } else if(sp.match('^')) {\r
+            add(new Start(true));\r
+        } else if(sp.dontMatch && sp.c=='A') {\r
+            add(new Start(false));\r
+        } else if(sp.match('*')) {\r
+            addMulti(new patInt(0),new patInf());\r
+        } else if(sp.match('+')) {\r
+            addMulti(new patInt(1),new patInf());\r
+        } else if(sp.match('?')) {\r
+            addMulti(new patInt(0),new patInt(1));\r
+        } else if(sp.match('{')) {\r
+            boolean bad = false;\r
+            StrPos sp2 = new StrPos(sp);\r
+            StringBuffer sb = new StringBuffer();\r
+            sp.inc();\r
+            patInt i1 = sp.getPatInt();\r
+            patInt i2 = null;\r
+            if(sp.match('}')) {\r
+                i2 = i1;\r
+            } else {\r
+                if(!sp.match(','))/*\r
+                    RegSyntaxError.endItAll(\r
+                       "String \"{"+i2+\r
+                       "\" should be followed with , or }");*/\r
+                    bad = true;\r
+                sp.inc();\r
+                if(sp.match('}'))\r
+                    i2 = new patInf();\r
+                else\r
+                    i2 = sp.getPatInt();\r
+            }\r
+            if(i1 == null || i2 == null) /*\r
+                                throw new RegSyntax("Badly formatted Multi: "\r
+                                +"{"+i1+","+i2+"}"); */ bad = true;\r
+            if(bad) {\r
+                sp.dup(sp2);\r
+                add(new oneChar(sp.c));\r
+            } else\r
+                addMulti(i1,i2);\r
+       } else if(sp.escMatch('x') && next2Hex(sp)) { \r
+           sp.inc();\r
+           int d = getHexDigit(sp);\r
+           sp.inc();\r
+            d = 16*d + getHexDigit(sp);\r
+           add(new oneChar((char)d));\r
+       } else if(sp.escMatch('c')) {\r
+           sp.inc();\r
+           if(sp.c < Ctrl.cmap.length)\r
+             add(new oneChar(Ctrl.cmap[sp.c]));\r
+           else\r
+             add(new oneChar(sp.c));\r
+       } else if(sp.escMatch('f')) {\r
+           add(new oneChar((char)12));\r
+       } else if(sp.escMatch('a')) {\r
+           add(new oneChar((char)7));\r
+       } else if(sp.escMatch('t')) {\r
+           add(new oneChar('\t'));\r
+        } else if(sp.escMatch('n')) {\r
+            add(new oneChar('\n'));\r
+        } else if(sp.escMatch('r')) {\r
+            add(new oneChar('\r'));\r
+        } else if(sp.escMatch('b')) {\r
+            add(new oneChar('\b'));\r
+        } else if(sp.escMatch('e')) {\r
+            add(new oneChar((char)27));\r
+        } else {\r
+            add(new oneChar(sp.c));\r
+            if(sp.match(')'))\r
+                RegSyntaxError.endItAll("Unmatched right paren in pattern");\r
+        }\r
+    }\r
+\r
+    // compiles all Pattern elements, internal method\r
+    private Pattern _compile(String pat,Rthings mk) throws RegSyntax {\r
+        minMatch = null;\r
+        sFlag = mFlag = ignoreCase = gFlag = false;\r
+        StrPos sp = new StrPos(pat,0);\r
+        thePattern = _compile(sp,mk);\r
+        pt.marks = null;\r
+        return thePattern;\r
+    }\r
+\r
+    Pattern p = null;\r
+    Or or = null;\r
+    Pattern _compile(StrPos sp,Rthings mk) throws RegSyntax {\r
+        while(!(sp.eos || (or != null && sp.match(')')) )) {\r
+            compile1(sp,mk);\r
+            sp.inc();\r
+        }\r
+        if(sp.match(')')) mk.parenLevel--;\r
+        else if(sp.eos && mk.parenLevel != 0) {\r
+            RegSyntaxError.endItAll("Unclosed Parenthesis! lvl="+mk.parenLevel);\r
+        } if(or != null) {\r
+            if(p == null) p = new NullPattern();\r
+            or.addOr(p);\r
+            return or;\r
+        }\r
+        return p==null ? new NullPattern() : p;\r
+    }\r
+\r
+    // add a multi object to the end of the chain\r
+    // which applies to the last object\r
+    void addMulti(patInt i1,patInt i2) throws RegSyntax {\r
+        Pattern last,last2;\r
+        for(last = p;last != null && last.next != null;last=last.next)\r
+            ;\r
+        if(last == null || last == p)\r
+            last2 = null;\r
+        else\r
+            for(last2 = p;last2.next != last;last2=last2.next)\r
+                ;\r
+        if(last instanceof Multi && i1.intValue()==0 &&\r
+                i2.intValue()==1)\r
+            ((Multi)last).matchFewest = true;\r
+        else if(last instanceof FastMulti && i1.intValue()==0 &&\r
+                i2.intValue()==1)\r
+            ((FastMulti)last).matchFewest = true;\r
+        else if(last instanceof DotMulti && i1.intValue()==0 &&\r
+                i2.intValue()==1)\r
+            ((DotMulti)last).matchFewest = true;\r
+       else if(last instanceof Multi\r
+            || last instanceof DotMulti\r
+            || last instanceof FastMulti)\r
+           throw new RegSyntax("Syntax error.");\r
+        else if(last2 == null)\r
+            p = mkMulti(i1,i2,p);\r
+        else\r
+            last2.next = mkMulti(i1,i2,last);\r
+    }\r
+    final static Pattern mkMulti(patInt lo,patInt hi,Pattern p) throws RegSyntax {\r
+        if(p instanceof Any && p.next == null)\r
+            return (Pattern)new DotMulti(lo,hi);\r
+        return RegOpt.safe4fm(p) ? (Pattern)new FastMulti(lo,hi,p) :\r
+        (Pattern)new Multi(lo,hi,p);\r
+    }\r
+    // process the bracket operator\r
+    Pattern matchBracket(StrPos sp) throws RegSyntax {\r
+        Bracket ret;\r
+        if(sp.match('^')) {\r
+            ret = new Bracket(true);\r
+            sp.inc();\r
+        } else\r
+            ret = new Bracket(false);\r
+        if(sp.match(']'))\r
+            //throw new RegSyntax\r
+            RegSyntaxError.endItAll("Unmatched []");\r
+\r
+        while(!sp.eos && !sp.match(']')) {\r
+            StrPos s1 = new StrPos(sp);\r
+            s1.inc();\r
+            StrPos s1_ = new StrPos(s1);\r
+            s1_.inc();\r
+            if(s1.match('-') && !s1_.match(']')) {\r
+                StrPos s2 = new StrPos(s1);\r
+                s2.inc();\r
+                if(!s2.eos)\r
+                    ret.addOr(new Range(sp.c,s2.c));\r
+                sp.inc();\r
+                sp.inc();\r
+            } else if(sp.escMatch('Q')) {\r
+                sp.inc();\r
+                while(!sp.escMatch('E')) {\r
+                    ret.addOr(new oneChar(sp.c));\r
+                    sp.inc();\r
+                }\r
+            } else if(sp.escMatch('d')) {\r
+                ret.addOr(new Range('0','9'));\r
+            } else if(sp.escMatch('s')) {\r
+                ret.addOr(new oneChar((char)32));\r
+                ret.addOr(new Range((char)8,(char)10));\r
+                ret.addOr(new oneChar((char)13));\r
+            } else if(sp.escMatch('w')) {\r
+                ret.addOr(new Range('a','z'));\r
+                ret.addOr(new Range('A','Z'));\r
+                ret.addOr(new Range('0','9'));\r
+                ret.addOr(new oneChar('_'));\r
+            } else if(sp.escMatch('D')) {\r
+                ret.addOr(new Range((char)0,(char)47));\r
+                ret.addOr(new Range((char)58,(char)65535));\r
+            } else if(sp.escMatch('S')) {\r
+                ret.addOr(new Range((char)0,(char)7));\r
+                ret.addOr(new Range((char)11,(char)12));\r
+                ret.addOr(new Range((char)14,(char)31));\r
+                ret.addOr(new Range((char)33,(char)65535));\r
+            } else if(sp.escMatch('W')) {\r
+                ret.addOr(new Range((char)0,(char)64));\r
+                ret.addOr(new Range((char)91,(char)94));\r
+                ret.addOr(new oneChar((char)96));\r
+                ret.addOr(new Range((char)123,(char)65535));\r
+           } else if(sp.escMatch('x') && next2Hex(sp)) { \r
+               sp.inc();\r
+               int d = getHexDigit(sp);\r
+               sp.inc();\r
+                d = 16*d + getHexDigit(sp);\r
+               ret.addOr(new oneChar((char)d));\r
+           } else if(sp.escMatch('a')) {\r
+               ret.addOr(new oneChar((char)7));\r
+           } else if(sp.escMatch('f')) {\r
+               ret.addOr(new oneChar((char)12));\r
+           } else if(sp.escMatch('e')) {\r
+               ret.addOr(new oneChar((char)27));\r
+           } else if(sp.escMatch('n')) {\r
+               ret.addOr(new oneChar('\n'));\r
+           } else if(sp.escMatch('t')) {\r
+               ret.addOr(new oneChar('\t'));\r
+           } else if(sp.escMatch('r')) {\r
+               ret.addOr(new oneChar('\r'));\r
+           } else if(sp.escMatch('c')) {\r
+               sp.inc();\r
+               if(sp.c < Ctrl.cmap.length)\r
+                 ret.addOr(new oneChar(Ctrl.cmap[sp.c]));\r
+               else\r
+                 ret.addOr(new oneChar(sp.c));\r
+           } else if(isOctalString(sp)) {\r
+               int d = sp.c - '0';\r
+               sp.inc();\r
+               d = 8*d + sp.c - '0';\r
+               StrPos sp2 = new StrPos(sp);\r
+               sp2.inc();\r
+               if(isOctalDigit(sp2,false)) {\r
+                 sp.inc();\r
+                 d = 8*d + sp.c - '0';\r
+               }\r
+               ret.addOr(new oneChar((char)d));\r
+            } else\r
+                ret.addOr(new oneChar(sp.c));\r
+            sp.inc();\r
+        }\r
+        return ret;\r
+    }\r
+\r
+    /** Converts the stored Pattern to a String -- this is a\r
+          decompile.  Note that \t and \n will really print out here,\r
+          Not just the two character representations.\r
+          Also be prepared to see some strange output if your characters\r
+          are not printable. */\r
+    public String toString() {\r
+        if( false && thePattern == null )\r
+            return "";\r
+        else {\r
+            StringBuffer sb = new StringBuffer();\r
+            if(esc != Pattern.ESC) {\r
+                sb.append("(?e=");\r
+                sb.append(esc);\r
+                sb.append(")");\r
+            }\r
+            if(gFlag\r
+           ||mFlag\r
+           ||!dotDoesntMatchCR\r
+           ||sFlag\r
+           ||ignoreCase\r
+           ||dontMatchInQuotes\r
+           ||optimized()) {\r
+                sb.append("(?");\r
+                if(ignoreCase)sb.append("i");\r
+               if(mFlag)sb.append("m");\r
+               if(sFlag||!dotDoesntMatchCR)sb.append("s");\r
+                if(dontMatchInQuotes)sb.append("Q");\r
+                if(optimized())sb.append("o");\r
+                if(gFlag)sb.append("g");\r
+                sb.append(")");\r
+            }\r
+            String patstr = thePattern.toString();\r
+            if(esc != Pattern.ESC)\r
+                patstr = reEscape(patstr,Pattern.ESC,esc);\r
+            sb.append(patstr);\r
+            return sb.toString();\r
+        }\r
+    }\r
+    // Re-escape Pattern, allows us to use a different escape\r
+    // character.\r
+    static String reEscape(String s,char oldEsc,char newEsc) {\r
+        if(oldEsc == newEsc) return s;\r
+        int i;\r
+        StringBuffer sb = new StringBuffer();\r
+        for(i=0;i<s.length();i++) {\r
+            if(s.charAt(i)==oldEsc && i+1 < s.length()) {\r
+                if(s.charAt(i+1)==oldEsc) {\r
+                    sb.append(oldEsc);\r
+                } else {\r
+                    sb.append(newEsc);\r
+                    sb.append(s.charAt(i+1));\r
+                }\r
+                i++;\r
+            } else if(s.charAt(i)==newEsc) {\r
+                sb.append(newEsc);\r
+                sb.append(newEsc);\r
+            } else {\r
+                sb.append(s.charAt(i));\r
+            }\r
+        }\r
+        return sb.toString();\r
+    }\r
+    /** This method implements FilenameFilter, allowing one\r
+         to use a Regex to search through a directory using File.list.\r
+         There is a FileRegex now that does this better.\r
+         @see com.stevesoft.pat.FileRegex\r
+        */\r
+    public boolean accept(File dir,String s) {\r
+        return search(s);\r
+    }\r
+    /** The version of this package */\r
+    final static public String version() {\r
+        return "lgpl release 1.5.3";\r
+    }\r
+    /** Once this method is called, the state of variables\r
+        ignoreCase and dontMatchInQuotes should not be changed as the\r
+        results will be unpredictable.  However,\r
+        search and matchAt will run more quickly.  Note that you\r
+        can check to see if the pattern has been optimized by calling\r
+        the optimized() method.<p>This method will attempt to rewrite\r
+        your pattern in a way that makes it faster (not all patterns\r
+        execute at the same speed).  In general, "(?: ... )" will be\r
+        faster than "( ... )" so if you don't need the backreference,\r
+        you should group using the former pattern.<p>It will also\r
+        introduce new pattern elements that you can't get to otherwise,\r
+        for example if you have a large table of strings, i.e. the\r
+        months of the year "(January|February|...)" optimize() will make\r
+        a Hashtable that takes it to the next appropriate pattern\r
+        element -- eliminating the need for a linear search.\r
+        @see com.stevesoft.pat.Regex#optimized\r
+        @see com.stevesoft.pat.Regex#ignoreCase\r
+        @see com.stevesoft.pat.Regex#dontMatchInQuotes\r
+        @see com.stevesoft.pat.Regex#matchAt\r
+        @see com.stevesoft.pat.Regex#search\r
+        */\r
+    public void optimize() {\r
+        if(optimized()||thePattern==null) return;\r
+        minMatch = new patInt(0);//thePattern.countMinChars();\r
+        thePattern = RegOpt.opt(thePattern,ignoreCase,\r
+            dontMatchInQuotes);\r
+        skipper = Skip.findSkip(this);\r
+        //RegOpt.setParents(this);\r
+        return;\r
+    }\r
+    Skip skipper;\r
+    /** This function returns true if the optimize method has\r
+         been called. */\r
+    public boolean optimized() {\r
+        return minMatch != null;\r
+    }\r
+\r
+    /** A bit of syntactic surgar for those who want to make\r
+        their code look more perl-like.  To use this initialize\r
+        your Regex object by saying:\r
+        <pre>\r
+        Regex r1 = Regex.perlCode("s/hello/goodbye/");\r
+        Regex r2 = Regex.perlCode("s'fish'frog'i");\r
+        Regex r3 = Regex.perlCode("m'hello');\r
+        </pre>\r
+        The i for ignoreCase is supported in\r
+        this syntax, as well as m, s, and x.  The g flat\r
+       is a bit of a special case.<p>\r
+       If you wish to replace all occurences of a pattern, you\r
+        do not put a 'g' in the perlCode, but call Regex's\r
+        replaceAll method.<p>\r
+       If you wish to simply\r
+        and only do a search for r2's pattern, you can do this\r
+        by calling the searchFrom method method repeatedly, or\r
+       by calling search repeatedly if the g flag is set.\r
+        <p>\r
+        Note: Currently perlCode does <em>not</em>\r
+       support the (?e=#) syntax for\r
+        changing the escape character.\r
+    */\r
+\r
+    public static Regex perlCode(String s) {\r
+        // this file is big enough, see parsePerl.java\r
+        // for this function.\r
+        return parsePerl.parse(s);\r
+    }\r
+    static final char back_slash = '\\';\r
+\r
+    /** Checks to see if there are only literal and no special\r
+        pattern elements in this Regex. */\r
+    public boolean isLiteral() {\r
+        Pattern x = thePattern;\r
+        while(x != null) {\r
+            if(x instanceof oneChar)\r
+                ;\r
+            else if(x instanceof Skipped)\r
+                ;\r
+            else\r
+                return false;\r
+            x = x.next;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /** You only need to know about this if you are inventing\r
+        your own pattern elements. */\r
+    public patInt countMinChars() { return thePattern.countMinChars(); }\r
+    /** You only need to know about this if you are inventing\r
+        your own pattern elements. */\r
+    public patInt countMaxChars() { return thePattern.countMaxChars(); }\r
+\r
+    boolean isHexDigit(StrPos sp) {\r
+      boolean r =\r
+        !sp.eos && !sp.dontMatch\r
+        && ((sp.c>='0'&&sp.c<='9')\r
+         ||(sp.c>='a'&&sp.c<='f')\r
+         ||(sp.c>='A'&&sp.c<='F'));\r
+      return r;\r
+    }\r
+    boolean isOctalDigit(StrPos sp,boolean first) {\r
+      boolean r =\r
+        !sp.eos && !(first^sp.dontMatch)\r
+        && sp.c>='0'&&sp.c<='7';\r
+      return r;\r
+    }\r
+    int getHexDigit(StrPos sp) {\r
+      if(sp.c >= '0' && sp.c <= '9')\r
+        return sp.c - '0';\r
+      if(sp.c >= 'a' && sp.c <= 'f')\r
+        return sp.c - 'a' + 10;\r
+      return sp.c - 'A' + 10;\r
+    }\r
+    boolean next2Hex(StrPos sp) {\r
+      StrPos sp2 = new StrPos(sp);\r
+      sp2.inc();\r
+      if(!isHexDigit(sp2))\r
+        return false;\r
+      sp2.inc();\r
+      if(!isHexDigit(sp2))\r
+        return false;\r
+      return true;\r
+    }\r
+    boolean isOctalString(StrPos sp) {\r
+      if(!isOctalDigit(sp,true))\r
+        return false;\r
+      StrPos sp2 = new StrPos(sp);\r
+      sp2.inc();\r
+      if(!isOctalDigit(sp2,false))\r
+        return false;\r
+      return true;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/RegexReader.java b/src/com/stevesoft/pat/RegexReader.java
new file mode 100755 (executable)
index 0000000..0ff33e3
--- /dev/null
@@ -0,0 +1,248 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.io.*;\r
+import com.stevesoft.pat.wrap.*;\r
+\r
+/** This class allows you to replace the text in strings\r
+    as you read them in.  Be careful what you do with\r
+    this freedom... using Regex.perlCode("s{.*}{x}s")\r
+    as your pattern will result in loading the entire\r
+    contents of the Reader into memory.\r
+    */\r
+public class RegexReader extends Reader {\r
+  RBuffer rb = new RBuffer(new StringBuffer());\r
+  PartialBuffer wrap = new PartialBuffer(rb.sb);\r
+  boolean moreToRead = true;\r
+  Reader r;\r
+  Replacer rp;\r
+\r
+  // the buffer size\r
+  int nmax = 2*1024;\r
+\r
+  public RegexReader(Regex rex,Reader r) {\r
+    this.r = r;\r
+    rp = rex.getReplacer();\r
+  }\r
+  public RegexReader(Transformer tex,Reader r) {\r
+    this.r = r;\r
+    rp = tex.getReplacer();\r
+  }\r
+  public void reset() throws IOException {\r
+    r.reset();\r
+    rb = new RBuffer(new StringBuffer());\r
+    wrap = new PartialBuffer(rb.sb);\r
+    moreToRead = true;\r
+  }\r
+  void readData() throws IOException {\r
+    int c;\r
+    int n = 0;\r
+    while( (c = r.read()) != -1) {\r
+      rb.sb.append((char)c);\r
+      if(n++ > nmax)\r
+        break;\r
+    }\r
+    if(c == -1 && n == 0) {\r
+      moreToRead = false;\r
+      wrap.allowOverRun = false;\r
+    }\r
+  }\r
+  void getMoreData() throws IOException {\r
+    while(rb.pos >= rb.epos) {\r
+      wrap.overRun = false;\r
+      if(rb.next != null) {\r
+       rb = rb.next;\r
+      } else if(rb.done) {\r
+        break;\r
+      } else if(rb.epos >= rb.sb.length()\r
+            && rb.epos > nmax) {\r
+       rb.pos = 1;\r
+       rb.epos = 1;\r
+       rb.sb.setLength(1);\r
+       readData();\r
+      } else if(rb.epos >= rb.sb.length()\r
+            && moreToRead) {\r
+        readData();\r
+      } else if(rp.getRegex().matchAt(wrap,rb.epos)) {\r
+       if(wrap.overRun) {\r
+         readData();\r
+       } else {\r
+         StringBufferWrap sbw = new StringBufferWrap();\r
+         StringBufferLike sbl = new StringBufferLike(sbw);\r
+         /*\r
+          ReplaceRule rr = rex.getReplaceRule();\r
+         while(rr != null) {\r
+           rr.apply(sbl,rex);\r
+           rr = rr.next;\r
+         }\r
+         */\r
+         Regex rex = rp.getRegex();\r
+         int npos = rex.matchedTo();\r
+         rp.setBuffer(sbl);\r
+         rp.setSource(wrap);\r
+         rp.setPos(npos);\r
+         rp.apply(rex,rex.getReplaceRule());\r
+         int opos = rb.epos;\r
+         RBuffer rb2 = new RBuffer((StringBuffer)sbw.unwrap());\r
+         rb2.epos = rb2.sb.length();\r
+         RBuffer rb3 = new RBuffer(rb.sb);\r
+\r
+         rb.next = rb2;\r
+         rb2.next = rb3;\r
+\r
+         if(npos == opos) {\r
+           rb3.epos = npos+1;\r
+           if(rb3.epos > rb3.sb.length()) {\r
+             if(rb.pos >= rb.epos)\r
+               rb = rb.next;\r
+             rb3.pos = rb3.epos = 0;\r
+             rb3.done = true;\r
+             //break;\r
+           }\r
+            rb3.pos = npos;\r
+         } else {\r
+           rb3.pos = rb3.epos = npos;\r
+         }\r
+\r
+        }\r
+      } else {\r
+       if(wrap.overRun) {\r
+         readData();\r
+        } else if(rb.epos<rb.sb.length()) {\r
+         rb.epos++;\r
+        } else {\r
+         break;\r
+       }\r
+      }\r
+    }\r
+  }\r
+  public int read() throws IOException {\r
+    if(rb.pos >= rb.epos) {\r
+      getMoreData();\r
+      if(rb.pos >= rb.epos)\r
+        return -1;\r
+    }\r
+    //System.out.println(rb);\r
+    return rb.sb.charAt(rb.pos++);\r
+  }\r
+  public int read(char[] buf,int off,int len)\r
+    throws IOException\r
+  {\r
+    int c = -1;\r
+    int end = off+len;\r
+    for(int i=off;i<end;i++) {\r
+      c = read();\r
+      if(c < 0) {\r
+       if(i == off)\r
+         return -1;\r
+        return i-off;\r
+      }\r
+      buf[i] = (char)c;\r
+    }\r
+    return len;\r
+  }\r
+  public void close()\r
+    throws IOException\r
+  {\r
+    r.close();\r
+  }\r
+\r
+  public boolean markSupported() { return false; }\r
+\r
+  /** Get the size of the working buffer.\r
+      The current buffer may be larger if\r
+      the pattern demands it. */\r
+  public int getBufferSize() {\r
+    return nmax;\r
+  }\r
+  /** Set the size of the working buffer.\r
+      The current buffer may be larger if\r
+      the pattern demands it. */\r
+  public void setBufferSize(int n) {\r
+    nmax = n;\r
+  }\r
+\r
+  int max_lines = 2;\r
+  /** This function no longer serves any purpose.\r
+      @deprecated\r
+      */\r
+  public int getMaxLines() { return max_lines; }\r
+  /** This function no longer serves any purpose.\r
+      @deprecated\r
+      */\r
+  public void setMaxLines(int ml) { max_lines = ml; }\r
+\r
+  char EOLchar = '\n';\r
+  /** This function no longer serves any purpose.\r
+      @deprecated\r
+      */\r
+  public char getEOLchar() {\r
+    return EOLchar;\r
+  }\r
+  /** This function no longer serves any purpose.\r
+      @deprecated\r
+      */\r
+  public void setEOLchar(char c) {\r
+    EOLchar = c;\r
+  }\r
+\r
+  public long skip(long d) throws IOException {\r
+    // This is probably inefficient, I just did it\r
+    // this way to avoid possible bugs.\r
+    long n = 0;\r
+    while(n<d && read() != -1)\r
+      n++;\r
+    return n;\r
+  }\r
+\r
+  /*\r
+  static void test(String re,String inp,int n) throws Exception {\r
+    Reader r = new StringReader(inp);\r
+    r = new BufferedReader(r);\r
+    Regex rex = Regex.perlCode(re);\r
+    String res1 = rex.replaceAll(inp);\r
+    int c = -1;\r
+    StringBuffer sb = new StringBuffer();\r
+    RegexReader rr = new RegexReader(rex,r);\r
+    rr.setBufferSize(n);\r
+    while( (c = rr.read()) != -1)\r
+      sb.append((char)c);\r
+    String res2 = sb.toString();\r
+    if(!res1.equals(res2)) {\r
+      System.out.println("nmax="+n);\r
+      System.out.println("re="+re);\r
+      System.out.println("inp="+inp);\r
+      System.out.println("res1="+res1);\r
+      System.out.println("res2="+res2);\r
+      System.exit(255);\r
+    }\r
+  }\r
+  public static void main(String[] args) throws Exception {\r
+    for(int n=6;n<15;n++) {\r
+      test("s/x/y/","-----x123456789",n);\r
+      test("s/x/y/","x123456789",n);\r
+      test("s/x/y/","-----x",n);\r
+      test("s/x.*?x/y/",".xx..x..x...x...x....x....x",n);\r
+      test("s/x.*x/[$&]/","--x........x--xx",n);\r
+      test("s/x.*x/[$&]/","--x........x------",n);\r
+      test("s/.$/a/m","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb",n);\r
+      test("s/.$/a/","123",n);\r
+      test("s/.$/a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n);\r
+      test("s/^./a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n);\r
+      test("s/$/a/","bbb",n);\r
+      test("s/^/a/","bbb",n);\r
+      test("s/^/a/","",n);\r
+      test("s{.*}{N}","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",n);\r
+      test("s/.{0,7}/y/","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",n);\r
+      test("s/x/$&/","xxx",n);\r
+    }\r
+    System.out.println("Success!!!");\r
+  }\r
+  */\r
+}\r
diff --git a/src/com/stevesoft/pat/RegexTokenizer.java b/src/com/stevesoft/pat/RegexTokenizer.java
new file mode 100755 (executable)
index 0000000..40302a4
--- /dev/null
@@ -0,0 +1,110 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.*;\r
+/** \r
+        Shareware: package pat\r
+   <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>\r
+*/ /**\r
+The RegexTokenizer is similar to the StringTokenizer class\r
+provided with java, but allows one to tokenize using\r
+regular expressions, rather than a simple list of characters.\r
+Tokens are any strings between the supplied regular expression,\r
+as well as any backreferences (things in parenthesis)\r
+contained within the regular expression. */\r
+public class RegexTokenizer implements Enumeration {\r
+    String toParse;\r
+    Regex r;\r
+    int count = 0;\r
+    Vector v = new Vector();\r
+    Vector vi = new Vector();\r
+    int pos=0;\r
+\r
+    int offset = 1;\r
+    void getMore() {\r
+        String s = r.right();\r
+        if(r.searchFrom(toParse,pos)) {\r
+            v.addElement(r.left().substring(pos));\r
+            vi.addElement(new Integer(r.matchFrom()+\r
+                r.charsMatched()));\r
+            for(int i=0;i<r.numSubs();i++)\r
+                if(r.substring() != null) {\r
+                    v.addElement(r.substring(i+offset));\r
+                    vi.addElement(\r
+                        new Integer(r.matchFrom(i+offset)+\r
+                        r.charsMatched(i+offset)));\r
+                }\r
+            pos = r.matchFrom()+r.charsMatched();\r
+        } else if(s != null) v.addElement(s);\r
+    }\r
+\r
+    /** Initialize the tokenizer with a string of text and a pattern */\r
+    public RegexTokenizer(String txt,String ptrn) {\r
+        toParse = txt;\r
+        r = new Regex(ptrn);\r
+        offset = r.BackRefOffset;\r
+        getMore();\r
+    }\r
+    /** Initialize the tokenizer with a Regex object. */\r
+    public RegexTokenizer(String txt,Regex r) {\r
+        toParse = txt;\r
+        this.r = r;\r
+        offset = r.BackRefOffset;\r
+        getMore();\r
+    }\r
+    /** This should always be cast to a String, as in StringTokenizer,\r
+         and as in StringTokenizer one can do this by calling\r
+         nextString(). */\r
+    public Object nextElement() {\r
+        if(count >= v.size()) getMore();\r
+        return v.elementAt(count++);\r
+    }\r
+    /** This is the equivalent (String)nextElement(). */\r
+    public String nextToken() { return (String)nextElement(); }\r
+    /** This asks for the next token, and changes the pattern\r
+         being used at the same time. */\r
+    public String nextToken(String newpat) {\r
+        try { r.compile(newpat); } catch (RegSyntax r_) {}\r
+        return nextToken(r);\r
+    }\r
+    /** This asks for the next token, and changes the pattern\r
+         being used at the same time. */\r
+    public String nextToken(Regex nr) {\r
+        r = nr;\r
+        if(vi.size() > count) {\r
+            pos = ((Integer)vi.elementAt(count)).intValue();\r
+            v.setSize(count);\r
+            vi.setSize(count);\r
+        }\r
+        getMore();\r
+        return nextToken();\r
+    }\r
+    /** Tells whether there are more tokens in the pattern. */\r
+    public boolean hasMoreElements() {\r
+        if(count >= v.size()) getMore();\r
+        return count < v.size();\r
+    }\r
+    /** Tells whether there are more tokens in the pattern, but\r
+         in the fashion of StringTokenizer. */\r
+    public boolean hasMoreTokens() { return hasMoreElements(); }\r
+    /** Determines the # of remaining tokens */\r
+    public int countTokens() {\r
+        int old_pos=pos,_count=count;\r
+        while(hasMoreTokens())\r
+            nextToken();\r
+        count=_count;\r
+        return v.size()-count;\r
+    }\r
+    /** Returns all tokens in the String */\r
+    public String[] allTokens() {\r
+        countTokens();\r
+        String[] ret = new String[v.size()];\r
+        v.copyInto(ret);\r
+        return ret;\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/RegexWriter.java b/src/com/stevesoft/pat/RegexWriter.java
new file mode 100755 (executable)
index 0000000..008f6ac
--- /dev/null
@@ -0,0 +1,205 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.io.*;\r
+import com.stevesoft.pat.wrap.*;\r
+\r
+/** A basic extension of FilterWriter that uses Transformer\r
+ to make replacements in data as it is written out.  It attempts\r
+ to transform a string whenever the End-of-Line (EOL) character\r
+ is written (which is, by default, the carriage return '\n').\r
+ Only the transformed portion of the line is written out, allowing\r
+ the RegexWriter to wait until a complete pattern is present before\r
+ attempting to write out info.  Until a pattern completes, data is\r
+ stored in a StringBuffer -- which can be accessed through the\r
+ length() and charAt() methods of this class.\r
+ <p>\r
+ Note a subtlety here -- while a Transformer normally matches\r
+ at higher priority against the pattern added to it first, this\r
+ will not necessarily be true when a multi-line match is in progress\r
+ because one of the complete multi-line patterns may not be completely\r
+ loaded in RegexWriter's buffer.  For this reason, the Transformer\r
+ class is equipped with a way to add a pattern and replacement rule\r
+ in three pieces -- a beginning (once this matches, nothing else in\r
+ the Transformer can match until the whole pattern matches), an\r
+ ending (the whole pattern is a String formed by adding the beginning\r
+ and ending), and a ReplaceRule.\r
+ <p>\r
+ An illustration of this is given in the this\r
+ <a href="../test/trans.java">example.</a>\r
+ */\r
+public class RegexWriter extends Writer {\r
+    Replacer repr;\r
+    Writer w;\r
+    WriterWrap ww;\r
+    StringBuffer sb = new StringBuffer();\r
+    PartialBuffer wrap = new PartialBuffer(sb);\r
+    int pos, epos;\r
+    int interval = 128;\r
+    int bufferSize = 2*1024;\r
+\r
+    public RegexWriter(Transformer t,Writer w) {\r
+       this.w = w;\r
+        ww = new WriterWrap(w);\r
+        repr = t.getReplacer();\r
+       repr.setBuffer(new StringBufferLike(ww));\r
+       repr.setSource(wrap);\r
+    }\r
+    public RegexWriter(Regex r,Writer w) {\r
+       this.w = w;\r
+        ww = new WriterWrap(w);\r
+        repr = r.getReplacer();\r
+       repr.setBuffer(new StringBufferLike(ww));\r
+       repr.setSource(wrap);\r
+    }\r
+\r
+    char EOLchar = '\n';\r
+    /** This method no longer serves any purpose.\r
+        @deprecated\r
+      */\r
+    public char getEOLchar() {\r
+        return EOLchar;\r
+    }\r
+    /** This method no longer serves any purpose.\r
+     @deprecated\r
+     */\r
+    public void setEOLchar(char c) {\r
+        EOLchar = c;\r
+    }\r
+\r
+    int max_lines=2;\r
+    /** This method no longer serves any purpose.\r
+     @deprecated\r
+     */\r
+    public int getMaxLines() { return max_lines; }\r
+    /** This method no longer serves any purpose.\r
+     @deprecated\r
+     */\r
+    public void setMaxLines(int ml) { max_lines = ml; }\r
+\r
+    void write() throws IOException {\r
+      Regex rex = repr.getRegex();\r
+      int eposOld = epos;\r
+      if(rex.matchAt(wrap,epos) && !wrap.overRun) {\r
+        while(pos < epos)\r
+          w.write(sb.charAt(pos++));\r
+        int to = rex.matchedTo();\r
+       repr.setPos(to);\r
+       repr.apply(rex,rex.getReplaceRule());\r
+       epos = pos = to;\r
+       if(epos == eposOld && epos < sb.length())\r
+         epos++;\r
+      } else if(!wrap.overRun && epos < sb.length()) {\r
+        epos++;\r
+      }\r
+      while(pos < epos)\r
+        w.write(sb.charAt(pos++));\r
+      if(epos == sb.length()) {\r
+       sb.setLength(1);\r
+       pos = epos = 1;\r
+      } else if(pos > bufferSize) {\r
+        for(int i=bufferSize;i<sb.length();i++)\r
+         sb.setCharAt(i-bufferSize,sb.charAt(i));\r
+        pos -= bufferSize;\r
+       epos -= bufferSize;\r
+       sb.setLength(sb.length()-bufferSize);\r
+      }\r
+    }\r
+\r
+    public void write(char[] ca,int b,int n) throws IOException {\r
+      int m = b+n;\r
+      for(int i=b;i<m;i++) {\r
+        sb.append(ca[i]);\r
+       if(sb.length() % interval == interval - 1) {\r
+         wrap.overRun = false;\r
+          while(epos+interval < sb.length() && !wrap.overRun) {\r
+            write();\r
+         }\r
+        }\r
+      }\r
+    }\r
+\r
+    public void flush() throws IOException {\r
+    }\r
+\r
+    public void close() throws IOException {\r
+       wrap.allowOverRun = false;\r
+       wrap.overRun = false;\r
+       while(epos < sb.length())\r
+         write();\r
+       write();\r
+       w.close();\r
+    }\r
+\r
+    /** The current size of the StringBuffer in use by RegexWriter. */\r
+    public int length() { return sb.length(); }\r
+\r
+    /** The character at location i in the StringBuffer. */\r
+    public char charAt(int i) { return sb.charAt(i); }\r
+\r
+    /** Set the interval at which regex patterns are checked. */\r
+    public void setInterval(int i) {\r
+      interval = i;\r
+    }\r
+\r
+    /** Get the interval at which regex matches are checked. */\r
+    public int getInterval() {\r
+      return interval;\r
+    }\r
+\r
+    /** Get the buffer size. */\r
+    public int getBufferSize() {\r
+      return bufferSize;\r
+    }\r
+\r
+    /** Set the buffer size. */\r
+    public void setBufferSize(int i) {\r
+      bufferSize = i;\r
+    }\r
+\r
+  static void test(String re,String inp,int n) throws Exception {\r
+    StringWriter sw = new StringWriter();\r
+    Regex rex = Regex.perlCode(re);\r
+    String res1 = rex.replaceAll(inp);\r
+    RegexWriter rw = new RegexWriter(rex,sw);\r
+    for(int i=0;i<inp.length();i++)\r
+      rw.write(inp.charAt(i));\r
+    rw.close();\r
+    String res2 = sw.toString();\r
+    if(!res1.equals(res2)) {\r
+      System.out.println("nmax="+n);\r
+      System.out.println("re="+re);\r
+      System.out.println("inp="+inp);\r
+      System.out.println("res1="+res1);\r
+      System.out.println("res2="+res2);\r
+      System.exit(255);\r
+    }\r
+  }\r
+  public static void main(String[] args) throws Exception {\r
+    for(int n=1;n<=1;n++) {\r
+      test("s/x/y/","-----x123456789",n);\r
+      test("s/x/y/","x123456789",n);\r
+      test("s/x/y/","-----x",n);\r
+      test("s/x.*?x/y/",".xx..x..x...x...x....x....x",n);\r
+      test("s/x.*x/[$&]/","--x........x--xx",n);\r
+      test("s/x.*x/[$&]/","--x........x------",n);\r
+      test("s/.$/a/m","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb",n);\r
+      test("s/.$/a/","123",n);\r
+      test("s/.$/a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n);\r
+      test("s/^./a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n);\r
+      test("s/$/a/","bbb",n);\r
+      test("s/^/a/","bbb",n);\r
+      test("s/^/a/","",n);\r
+      test("s{.*}{N}","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",n);\r
+      test("s/.{0,7}/y/","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",n);\r
+      test("s/x/$&/","xxx",n);\r
+    }\r
+    System.out.println("Success!!!");\r
+  }\r
+}\r
diff --git a/src/com/stevesoft/pat/ReplaceRule.java b/src/com/stevesoft/pat/ReplaceRule.java
new file mode 100755 (executable)
index 0000000..002ffa1
--- /dev/null
@@ -0,0 +1,255 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.util.*;\r
+\r
+/** ReplaceRule is a singly linked list of Objects which describe how\r
+    to replace the matched portion of a String.  The only member method\r
+    that you absolutely need to define to use this class is apply(StringBuffer,RegRes) --\r
+    although you may want define toString1() and clone1() (if you are\r
+    unhappy with the default methods) that are needed by\r
+    the clone() or toString() methods on this class.\r
+    During the replacement process, each ReplaceRule tells the replacer\r
+    what to add to StringBuffer and uses the contents of the Regular\r
+    expression result to get the information it needs to\r
+    do this.  Here is an <a href="http://javaregex.com/code/fancy.java.html">example</a>\r
+\r
+    @see com.stevesoft.pat.NullRule\r
+    @see com.stevesoft.pat.AmpersandRule\r
+    @see com.stevesoft.pat.BackRefRule\r
+    @see com.stevesoft.pat.LeftRule\r
+    @see com.stevesoft.pat.RightRule\r
+    @see com.stevesoft.pat.StringRule\r
+    */\r
+public abstract class ReplaceRule {\r
+    /** points to the next ReplaceRule in the linked list. */\r
+    protected ReplaceRule next = null;\r
+    /** This function appends to the StringBufferLike the text you want\r
+        to replaced the portion of the String last matched. */\r
+    public abstract void apply(StringBufferLike sb,RegRes r);\r
+\r
+    /** A rule describing how to clone only the current ReplaceRule,\r
+        and none of the others in this linked list.  It is called by\r
+        clone() for each item in the list. */\r
+    public Object clone1() {\r
+        return new RuleHolder(this);\r
+    }\r
+    public final Object clone() {\r
+        ReplaceRule x = (ReplaceRule)clone1();\r
+        ReplaceRule xsav = x;\r
+        ReplaceRule y = this;\r
+        while(y.next != null) {\r
+            x.next = (ReplaceRule)y.next.clone1();\r
+            x.name = y.name;\r
+            x = x.next;\r
+            y = y.next;\r
+        }\r
+        return xsav;\r
+    }\r
+    static ReplaceRule add(ReplaceRule head,ReplaceRule adding) {\r
+        if(head == null)\r
+            return head = adding;\r
+        head.addRule(adding);\r
+        return head;\r
+    }\r
+    public ReplaceRule add(ReplaceRule adding) {\r
+        return add(this,adding);\r
+    }\r
+    /** Add another ReplaceRule to the linked list. */\r
+    public void addRule(ReplaceRule r) {\r
+        if(next == null) next = r;\r
+        else next.addRule(r);\r
+    }\r
+    static Regex getvar = null;\r
+    final static Regex getv() {\r
+        // Thanks to Michael Jimenez for pointing out the need\r
+        // to clone getvar rather than simply returning it.\r
+        // Previously this was not thread safe.\r
+        //if(getvar != null) return getvar;\r
+        if(getvar != null) return (Regex)getvar.clone();\r
+        getvar=\r
+            new Regex(\r
+           "(?:\\\\(\\d+)|"+ // ref 1\r
+           "\\$(?:"+\r
+             "(\\d+)|"+ // ref 2\r
+             "(\\w+)|"+ // ref 3\r
+              "([&'`])|"+ // ref 4\r
+             "\\{(?:(\\d+)|"+ // ref 5\r
+               "([^\n}\\\\]+))}"+ // ref 6\r
+             ")|"+ \r
+           "\\\\([nrbtaef])|"+ // ref 7\r
+           "\\\\c([\u0000-\uFFFF])|"+ // ref 8\r
+           "\\\\x([A-Fa-f0-9]{2})|"+ // ref 9\r
+           "\\\\([\u0000-\uFFFF])"+ // ref 10\r
+           ")");\r
+        getvar.optimize();\r
+        return getvar;\r
+    }\r
+    /** Compile a ReplaceRule using the text that would go between\r
+        the second and third /'s in a typical substitution pattern\r
+        in Perl: s/ ... / <i>The argument to ReplaceRule.perlCode</i> /.\r
+        */\r
+    public static ReplaceRule perlCode(String s) {\r
+        //String sav_backGs = Regex.backGs;\r
+        //int sav_backGto = Regex.backGto;\r
+        try {\r
+            int mf = 0, mt = 0;\r
+            Regex gv = getv();\r
+            ReplaceRule head = null;\r
+            Object tmp = null;\r
+            while(gv.searchFrom(s,mt)) {\r
+                int off=Regex.BackRefOffset-1;\r
+                mf = gv.matchedFrom();\r
+                if(mf > mt)\r
+                    head=add(head,\r
+                        new StringRule(s.substring(mt,mf)));\r
+                String var = null;\r
+                if((var=gv.stringMatched(1+off)) != null\r
+                        || (var=gv.stringMatched(2+off)) != null\r
+                        || (var=gv.stringMatched(5+off)) != null) {\r
+                    int d=0;\r
+                    for(int i=0;i<var.length();i++)\r
+                        d = 8*d+( var.charAt(i)-'0' );\r
+                   if(var.length() == 1)\r
+                      head=add(head,new BackRefRule(d));\r
+                   else\r
+                     head=new StringRule(""+(char)d);\r
+                } else if(\r
+                        (var=gv.stringMatched(10+off)) != null) {\r
+                    if("QELlUu".indexOf(var) >= 0)\r
+                        head=add(head,new CodeRule(var.charAt(0)) );\r
+                    else\r
+                        head=add(head,new StringRule(var) );\r
+                } else if(\r
+                        (var=gv.stringMatched(3+off)) != null\r
+                        || (var=gv.stringMatched(4+off)) != null\r
+                        || (var=gv.stringMatched(6+off)) != null) {\r
+                    String arg = "";\r
+                    int pc;\r
+                    if((pc=var.indexOf(':')) > 0) {\r
+                        arg = var.substring(pc+1);\r
+                        var = var.substring(0,pc);\r
+                    }\r
+                    if(var.equals("&")||var.equals("MATCH")) {\r
+                        head=add(head,new AmpersandRule());\r
+                    } else if(var.equals("`")||var.equals("PREMATCH")) {\r
+                        head=add(head,new LeftRule());\r
+                    } else if(var.equals("'")||var.equals("POSTMATCH")) {\r
+                        head=add(head,new RightRule());\r
+                    } else if(var.equals("WANT_MORE_TEXT")) {\r
+                        head=add(head,new WantMoreTextReplaceRule());\r
+                    } else if(var.equals("POP")) {\r
+                        head=add(head,new PopRule());\r
+                    } else if(var.startsWith("+") && (tmp=defs.get(var.substring(1))) != null) {\r
+                        if(tmp instanceof Regex)\r
+                            head=add(head,new PushRule(var.substring(1),(Regex)tmp));\r
+                        else if(tmp instanceof Transformer)\r
+                            head=add(head,new PushRule(var.substring(1),(Transformer)tmp));\r
+                        else head=add(head,new StringRule("${"+var+"}"));\r
+                    } else if(var.startsWith("=") && (tmp=defs.get(var.substring(1))) != null) {\r
+                        if(tmp instanceof Regex)\r
+                            head=add(head,new ChangeRule(var.substring(1),(Regex)tmp));\r
+                        else if(tmp instanceof Transformer)\r
+                            head=add(head,new ChangeRule(var.substring(1),(Transformer)tmp));\r
+                        else head=add(head,new StringRule("${"+var+"}"));\r
+                    } else if( (tmp=defs.get(var)) != null) {\r
+                        if(tmp instanceof ReplaceRule) {\r
+                            ReplaceRule alt = ((ReplaceRule)tmp).arg(arg);\r
+                            if(alt == null) alt = ((ReplaceRule)tmp);\r
+                            head=add(head,(ReplaceRule)(alt.clone()));\r
+                        }\r
+                    } else // can't figure out how to transform this thing...\r
+                        head=add(head,new StringRule("${"+var+"}"));\r
+                } else if(\r
+                 (var = gv.stringMatched(7+off)) != null) {\r
+                 char c = var.charAt(0);\r
+                 if(c == 'n')\r
+                   head=add(head,new StringRule("\n"));\r
+                 else if(c == 't')\r
+                   head=add(head,new StringRule("\t"));\r
+                 else if(c == 'r')\r
+                   head=add(head,new StringRule("\r"));\r
+                 else if(c == 'b')\r
+                   head=add(head,new StringRule("\r"));\r
+                 else if(c == 'a')\r
+                   head=add(head,new StringRule(""+(char)7));\r
+                 else if(c == 'e')\r
+                   head=add(head,new StringRule(""+(char)27));\r
+                 else if(c == 'f')\r
+                   head=add(head,new StringRule(""+(char)12));\r
+               } else if(\r
+                 (var = gv.stringMatched(8+off)) != null) {\r
+                 char c = var.charAt(0);\r
+                 if(c < Ctrl.cmap.length)\r
+                   c = Ctrl.cmap[c];\r
+                 head=add(head,new StringRule(""+c));\r
+               } else if(\r
+                 (var = gv.stringMatched(9+off)) != null) {\r
+                 int d =\r
+                   16*getHexDigit(var.charAt(0))+\r
+                   getHexDigit(var.charAt(1));\r
+                 head=add(head,new StringRule(""+(char)d));\r
+               }\r
+                mt = gv.matchedTo();\r
+            }\r
+            if(mt <= s.length())\r
+                head=add(head,new StringRule(s.substring(mt)));\r
+            return head;\r
+        } finally {\r
+            //Regex.backGs = sav_backGs;\r
+            //Regex.backGto = sav_backGto;\r
+        }\r
+    }\r
+    static Hashtable defs = new Hashtable();\r
+    public static boolean isDefined(String s) { return defs.get(s) != null; }\r
+    public static void define(String s,Regex r) { defs.put(s,r); }\r
+    public static void define(String s,ReplaceRule r) {\r
+        defs.put(s,r);\r
+        r.name = s;\r
+    }\r
+    String name = getClass().getName();\r
+    public static void define(String s,Transformer t) { defs.put(s,t); }\r
+    public static void undefine(String s) { defs.remove(s); }\r
+    /** This tells how to convert just the current element (and none\r
+        of the other items in the linked list) to a String. This\r
+        method is called by toString() for each item in the linked\r
+        list. */\r
+    public String toString1() {\r
+        return "${"+name+"}";\r
+    }\r
+    /** Convert to a String. */\r
+    public final String toString() {\r
+        StringBuffer sb = new StringBuffer();\r
+        sb.append(toString1());\r
+        ReplaceRule rr = this.next;\r
+        while(rr != null) {\r
+            sb.append(rr.toString1());\r
+            rr = rr.next;\r
+        }\r
+        return sb.toString();\r
+    }\r
+    /** Modified the behavior of a ReplaceRule by supplying\r
+        an argument.  If a ReplaceRule named "foo" is defined\r
+        and the pattern "s/x/${foo:5}/" is given to Regex.perlCode,\r
+        then the "foo" the definition of "foo" will be retrieved\r
+        and arg("5") will be called.  If the result is non-null,\r
+        that is the ReplaceRule that will be used.  If the result\r
+        is null, then the pattern works just as if it were\r
+        "s/x/${foo}/".\r
+        @see com.stevesoft.pat.Validator#arg(java.lang.String)\r
+        */\r
+    public ReplaceRule arg(String s) { return null; }\r
+    static int getHexDigit(char c) {\r
+      if(c >= '0' && c <= '9')\r
+        return c - '0';\r
+      if(c >= 'a' && c <= 'f')\r
+        return c - 'a'+10;\r
+      return c - 'A'+10;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/Replacer.java b/src/com/stevesoft/pat/Replacer.java
new file mode 100755 (executable)
index 0000000..c78a11d
--- /dev/null
@@ -0,0 +1,261 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.util.*;\r
+import com.stevesoft.pat.wrap.StringWrap;\r
+\r
+/** Internally used class. */\r
+class RegHolder {\r
+    Regex me = null;\r
+    RegHolder prev = null;\r
+}\r
+\r
+/** Internally used class.\r
+  * @see CodeRule\r
+  */\r
+class CodeVal {\r
+    int pos;\r
+    char code;\r
+    CodeVal(int p,char c) {\r
+        pos = p;\r
+        code = c;\r
+    }\r
+    public String toString() {\r
+        return "("+pos+","+code+")";\r
+    }\r
+}\r
+\r
+/**\r
+  To use this class, first use either the getReplacer() method from\r
+  Transformer or Regex.  You can then use replaceAll, replaceFirst,\r
+  etc. methods on the Replacer in the same way that you can from\r
+  either of those two classes.\r
+  <p>\r
+  The only potential difference between using the methods of\r
+  Replacer to do the replacing is that Replacer remembers changes\r
+  to the replacing object between calls to replaceAll, replaceFirst\r
+  etc.  For details, see the example file\r
+  <a href="http://javaregex.com/code/trans3.java.html">trans3.java</a>.\r
+  @see com.stevesoft.pat.Transformer\r
+  @see com.stevesoft.pat.Regex\r
+*/\r
+public class Replacer {\r
+    boolean first;\r
+\r
+    /** Instantiate a new Replacer. */\r
+    public Replacer() {}\r
+\r
+    public StringLike replaceFirstRegion(String s,Regex r,\r
+        int start,int end) {\r
+        return replaceFirstRegion(new StringWrap(s),r,start,end);\r
+    }\r
+    /** This method replaces the first occurence of the Regex in the\r
+        String starting with position pos\r
+        according to the Replacer rule of this object. */\r
+    public StringLike replaceFirstRegion(StringLike s,Regex r,\r
+        int start,int end) {\r
+        first = true;\r
+        rh.me = r;\r
+        rh.prev = null;\r
+        return dorep(s,start,end);\r
+    }\r
+    public StringLike replaceFirst(StringLike s) {\r
+        return replaceFirstRegion(s,0,s.length());\r
+    }\r
+    public StringLike replaceFirstFrom(StringLike s,int start) {\r
+        return replaceFirstRegion(s,start,s.length());\r
+    }\r
+    public StringLike replaceFirstRegion(StringLike s,int start,int end) {\r
+        first = true;\r
+        return dorep(s,start,end);\r
+    }\r
+\r
+    RegHolder rh = new RegHolder();\r
+\r
+    public StringLike replaceAllRegion(String s,Regex r,\r
+        int start, int end) {\r
+        return replaceAllRegion(new StringWrap(s),r,start,end);\r
+    }\r
+    /** This method replaces all occurences of the Regex in the\r
+        String starting with postition pos\r
+        according to the Replacer rule of this object. */\r
+    public StringLike replaceAllRegion(StringLike s,Regex r,\r
+        int start,int end) {\r
+        first = false;\r
+        // reset\r
+        rh.me = r;\r
+        rh.prev = null;\r
+        return dorep(s,start,end);\r
+    }\r
+    public StringLike replaceAll(StringLike s) {\r
+        return replaceAllRegion(s,0,s.length());\r
+    }\r
+    public StringLike replaceAllFrom(StringLike s,int start) {\r
+        return replaceAllRegion(s,start,s.length());\r
+    }\r
+    public StringLike replaceAllRegion(StringLike s,int start,int end) {\r
+        first = false;\r
+        return dorep(s,start,end);\r
+    }\r
+\r
+    public String replaceAll(String s) {\r
+        return replaceAllRegion(new StringWrap(s),0,s.length()).toString();\r
+    }\r
+    public String replaceAllFrom(String s,int start) {\r
+        return replaceAllRegion(new StringWrap(s),start,s.length()).toString();\r
+    }\r
+    public String replaceAllRegion(String s,int start,int end) {\r
+        first = false;\r
+        return dorep(new StringWrap(s),start,end).toString();\r
+    }\r
+\r
+    final public boolean isSpecial(ReplaceRule x) {\r
+        while(x != null) {\r
+            if(x instanceof SpecialRule\r
+                    || (x instanceof RuleHolder && ((RuleHolder)x).held instanceof SpecialRule))\r
+                return true;\r
+            x = x.next;\r
+        }\r
+        return false;\r
+    }\r
+    final public void apply1(RegRes rr) {\r
+        rr.charsMatched_++;\r
+        apply(rr,null);\r
+        rr.charsMatched_--;\r
+    }\r
+\r
+    final StringLike dorep(StringLike s,int start,int end) {\r
+        StringLike ret = s;\r
+        want_more_text = false;\r
+        lastMatchedTo = 0;\r
+        if(rh.me == null)\r
+            throw new NullPointerException("Replacer has null Regex pointer");\r
+        if(rh.me._search(s,start,end)) {\r
+            int rmn = rh.me.matchedTo();\r
+            if(rh.me.charsMatched()==0 && !isSpecial(rh.me.getReplaceRule())) {\r
+                apply1(rh.me);\r
+                rmn++;\r
+            }\r
+            apply(rh.me);\r
+            if(!first)\r
+                for(int i=rmn;\r
+                        !want_more_text && rh.me._search(s,i,end);i=rmn) {\r
+                    rmn = rh.me.matchedTo();\r
+                    if(rh.me.charsMatched()==0) {\r
+                        if(!isSpecial(rh.me.getReplaceRule()))\r
+                            apply1(rh.me);\r
+                        rmn++;\r
+                    }\r
+                    apply(rh.me);\r
+                }\r
+            ret = finish();\r
+            ret = ret == null ? s : ret;\r
+        }\r
+        return ret;\r
+    }\r
+\r
+    StringBufferLike sb = null;\r
+    StringLike src = null;\r
+    int pos = 0;\r
+    /** This method allows you to apply the results of several\r
+        matches in a sequence to modify a String of text.  Each\r
+        call in the sequence must operate on the same piece of\r
+        text and the matchedFrom() of each RegRes given to this\r
+        method must be greater in value than the preceeding\r
+        RegRes's matchedTo() value.\r
+        */\r
+    public void apply(RegRes r,ReplaceRule rp) {\r
+        if(rp==null ||(rp.next == null && rp instanceof AmpersandRule))\r
+            return;\r
+        if(r.didMatch()) {\r
+            if(src == null)\r
+                src = r.getStringLike();\r
+           if(sb == null)\r
+                sb = new StringBufferLike(src.newStringBufferLike());\r
+            int rmf = r.matchedFrom();\r
+            for(int ii=pos;ii<rmf;ii++)\r
+              sb.append(src.charAt(ii));\r
+\r
+            Vector v = new Vector();\r
+            for(ReplaceRule x=rp;x != null;x=x.next) {\r
+                x.apply(sb,r);\r
+                if(x instanceof SpecialRule) {\r
+                    if(x instanceof WantMoreTextReplaceRule\r
+                            && want_more_text_enable)\r
+                        want_more_text = true;\r
+                    else if(x instanceof PushRule) {\r
+                        RegHolder rh2 = new RegHolder();\r
+                        rh2.me = ( (PushRule)x ).NewRule;\r
+                        rh2.prev = rh;\r
+                        rh = rh2;\r
+                    } else if(x instanceof PopRule) {\r
+                        if(rh.prev != null)\r
+                            rh = rh.prev;\r
+                    } else if(x instanceof ChangeRule) {\r
+                        rh.me = ( (ChangeRule) x).NewRule;\r
+                    }\r
+                }\r
+            }\r
+            if(!want_more_text)\r
+                pos = r.matchedTo();\r
+        }\r
+    }\r
+    boolean want_more_text = false, want_more_text_enable = false;\r
+    public boolean WantMoreText() { return want_more_text; }\r
+    /** Another form of apply, it is the same as\r
+        apply(r,r.getReplaceRule()). */\r
+    public void apply(Regex r) { apply(r,r.getReplaceRule()); }\r
+\r
+    /** This finishes the replacement, appending the right() part of\r
+        the last RegRes given to substitute(RegRes).  After this method\r
+        is called, the Replace object is reset to perform another\r
+        substitution. If no RegRes objects with a true didMatch are\r
+        applied, this returns null. */\r
+    public StringLike finish() {\r
+        if(src==null)\r
+            return null;\r
+        //sb.append(src.substring(pos,src.length()));\r
+        int s_end = src.length();\r
+        for(int ii=pos;ii<s_end;ii++)\r
+          sb.append(src.charAt(ii));\r
+        src = null;\r
+        lastMatchedTo = pos;\r
+        pos = 0;\r
+        StringLike retstr = sb.toStringLike();\r
+        sb = null;\r
+        return retstr;\r
+    }\r
+    int lastMatchedTo = 0;\r
+    public Object clone() {\r
+        Replacer r = new Replacer();\r
+        r.first = first;\r
+        r.src = src;\r
+        r.sb = sb;\r
+        r.pos = pos;\r
+        r.lastMatchedTo = lastMatchedTo;\r
+        r.want_more_text = want_more_text;\r
+        r.want_more_text_enable = want_more_text_enable;\r
+        r.rh.me = rh.me;\r
+        r.rh.prev = rh.prev;\r
+        return r;\r
+    }\r
+    public int lastMatchedTo() { return lastMatchedTo; }\r
+    public Regex getRegex() {\r
+      return rh.me;\r
+    }\r
+    public void setSource(StringLike sl) {\r
+      src = sl;\r
+    }\r
+    public void setBuffer(StringBufferLike sbl) {\r
+      sb = sbl;\r
+    }\r
+    public void setPos(int pos) {\r
+      this.pos = pos;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/RightRule.java b/src/com/stevesoft/pat/RightRule.java
new file mode 100755 (executable)
index 0000000..9e6394f
--- /dev/null
@@ -0,0 +1,22 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** The apply(StringBufferLike sb,RegRes res) method of this derivation\r
+    of ReplaceRule appends the contents of res.right() to the     StringBufferLike sb.\r
+    @see com.stevesoft.pat.ReplaceRule\r
+    */\r
+public class RightRule extends ReplaceRule {\r
+    public RightRule() {}\r
+    public void apply(StringBufferLike sb,RegRes res) {\r
+        sb.append(res.right());\r
+    }\r
+    public String toString1() {\r
+        return "$'";\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/Rthings.java b/src/com/stevesoft/pat/Rthings.java
new file mode 100755 (executable)
index 0000000..0868eaa
--- /dev/null
@@ -0,0 +1,44 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** \r
+        Shareware: package pat\r
+   <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>\r
+*/ /**\r
+This class only exists to store data needed during the\r
+compilation of a regular expression. */\r
+public class Rthings {\r
+    /** The numeric identity of the next () to be encountered\r
+         while compiling the pattern. */\r
+    public int val=Regex.BackRefOffset;\r
+    /** Needed in case (?i) is encountered, to pass back the\r
+         message that ignoreCase should be set. */\r
+    public boolean ignoreCase;\r
+    /** Needed in case (?Q) is encountered, to pass back the\r
+         message that dontMatchInQuotes should be set. */\r
+    public boolean dontMatchInQuotes;\r
+    public boolean optimizeMe = false;\r
+    public boolean noBackRefs = false;\r
+    public int parenLevel = 0;\r
+    boolean gFlag = false, mFlag = false, sFlag = false;\r
+    Pattern p;\r
+    Or o;\r
+    Rthings(Regex r) {\r
+        ignoreCase = r.ignoreCase;\r
+        dontMatchInQuotes = r.dontMatchInQuotes;\r
+    }\r
+    void set(Regex r) {\r
+        r.gFlag = gFlag;\r
+       r.mFlag = mFlag;\r
+       r.sFlag = sFlag;\r
+        r.ignoreCase = ignoreCase;\r
+        r.dontMatchInQuotes = dontMatchInQuotes;\r
+        if(optimizeMe) r.optimize();\r
+    }\r
+};\r
diff --git a/src/com/stevesoft/pat/RuleHolder.java b/src/com/stevesoft/pat/RuleHolder.java
new file mode 100755 (executable)
index 0000000..e732d58
--- /dev/null
@@ -0,0 +1,20 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+/** This class is used internally. */\r
+class RuleHolder extends ReplaceRule {\r
+    ReplaceRule held = null;\r
+    RuleHolder() {}\r
+    RuleHolder(ReplaceRule h) { held = h; }\r
+    public Object clone1() { return new RuleHolder(held); }\r
+    public String toString1() { return held.toString1(); }\r
+    public void apply(StringBufferLike sb,RegRes rr) {\r
+        held.apply(sb,rr);\r
+    }\r
+    public ReplaceRule arg(String s) { return new RuleHolder(held.arg(s)); }\r
+}\r
diff --git a/src/com/stevesoft/pat/Skip.java b/src/com/stevesoft/pat/Skip.java
new file mode 100755 (executable)
index 0000000..664c712
--- /dev/null
@@ -0,0 +1,127 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This class is used internally to search ahead for some\r
+    optimized Regex objects.  It searches within a String\r
+    for occrences of a given String -- like a more flexible\r
+    version of String.indexOf.\r
+    @see com.stevesoft.pat.Skip2\r
+    @see com.stevesoft.pat.SkipBMH\r
+    */\r
+public class Skip {\r
+    static int mkmask(int c) {\r
+        char x = (char)c;\r
+        return ~( CaseMgr.toUpperCase(x) |\r
+            CaseMgr.toLowerCase(x) |\r
+            CaseMgr.toTitleCase(x));\r
+    }\r
+    static { int x = Regex.BackRefOffset; }\r
+    String src;\r
+    int c,mask;\r
+    int offset;\r
+    boolean ign,m1;\r
+    /** Examine a Regex to determine what String it will\r
+        attempt to skip to when searching for patterns.\r
+        Return -1 if we aren't doing this. */\r
+    public static String string(Regex r) {\r
+        return r.skipper == null ? null : r.skipper.src;\r
+    }\r
+    /** Determine the offset of the String within the pattern\r
+        that we are skipping to. Return -1 if we aren't doing\r
+        this.  */\r
+    public static int offset(Regex r) {\r
+        return r.skipper == null ? -1 : r.skipper.offset;\r
+    }\r
+    /** Initialize, give it a String to search for, tell it\r
+        whether or not to ignoreCase, and what the offset is\r
+        of the String within the String to be searched. */\r
+    public Skip(String s,boolean ign,int o) {\r
+        src = s;\r
+        c = s.charAt(0);\r
+        if(ign) {\r
+            mask = mkmask(c);\r
+        } else mask = 0;\r
+        offset = o;\r
+        this.ign = ign;\r
+        m1 = (s.length()==1);\r
+    }\r
+    /** The same as find(s,0,s.length()) */\r
+    public final int find(StringLike s) {\r
+        return find(s,0,s.length());\r
+    }\r
+    static final int min(int a,int b) { return a<b ? a : b; }\r
+    /** Searches a given region of text beginning at position start\r
+        and ending at position end for the skip object. */\r
+    public int find(StringLike s,int start,int end) {\r
+        if(start > end) return -1;\r
+        start += offset;\r
+        int vend = min(s.length()-1,end+offset);\r
+        if(mask != c) {\r
+            for(int i=start;i<=vend;i++)\r
+                if(0 == (s.charAt(i) & mask))\r
+                    //if(m1||s.regionMatches(ign,i,src,0,src.length()) )\r
+                    if(m1||CaseMgr.regionMatches(s,ign,i,src,0,src.length()) )\r
+                        return i-offset;\r
+        } else {\r
+            for(int i=start;i<=vend;i++)\r
+                if(c == s.charAt(i))\r
+                    //if(m1||s.regionMatches(ign,i,src,0,src.length()) )\r
+                    if(m1||CaseMgr.regionMatches(s,ign,i,src,0,src.length()) )\r
+                        return i-offset;\r
+        }\r
+        return -1;\r
+    }\r
+    static Skip findSkip(Regex r) {\r
+        return findSkip(r.thePattern,r.ignoreCase,!r.dontMatchInQuotes);\r
+    }\r
+    // look for things that can be skipped\r
+    static Skip findSkip(Pattern p,boolean ignoreCase,boolean trnc) {\r
+        StringBuffer sb = new StringBuffer();\r
+        Skip subsk = null;\r
+        int offset = 0;\r
+        int skipc = -1,skipoff=0;\r
+        for(;p != null;p = p.next) {\r
+            if(p instanceof oneChar) {\r
+                skipc = ((oneChar)p).c;\r
+                skipoff = offset;\r
+            }\r
+            if(p instanceof oneChar && p.next instanceof oneChar) {\r
+                Pattern psav = p;\r
+                sb.append(((oneChar)p).c);\r
+                while(p.next instanceof oneChar) {\r
+                    sb.append(((oneChar)p.next).c);\r
+                    p = p.next;\r
+                }\r
+                String st = sb.toString();\r
+                char c0 = st.charAt(0), c1 = st.charAt(1);\r
+                Skip sk=null;\r
+                if(st.length()>2)\r
+                    sk = new SkipBMH(st,ignoreCase,offset);\r
+                else\r
+                    sk = new Skip2(st,ignoreCase,offset);\r
+                if(trnc && st.length()>2) { // chop out a whole string...\r
+                    psav.next = new Skipped(st.substring(1));\r
+                    psav.next.next = p.next;\r
+                    psav.next.parent = p.parent;\r
+                }\r
+                return sk;\r
+            } else if(p instanceof Or && ((Or)p).v.size()==1\r
+                    && !((Or)p).leftForm().equals("(?!")\r
+                    && null != (subsk=\r
+                    findSkip( (Pattern)((Or)p).v.elementAt(0),ignoreCase,trnc) )) {\r
+                subsk.offset += offset;\r
+                return subsk;\r
+            } else if(p.minChars().equals(p.maxChars())) {\r
+                offset += p.minChars().intValue();\r
+            } else return skipc < 0 ? null :\r
+                new Skip(""+(char)skipc,ignoreCase,skipoff);\r
+        }\r
+        return null;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/Skip2.java b/src/com/stevesoft/pat/Skip2.java
new file mode 100755 (executable)
index 0000000..f2b03ca
--- /dev/null
@@ -0,0 +1,38 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This is the same as Skip, except it needs a minimum\r
+    of two characters in the initializing String.\r
+    @see com.stevesoft.pat.Skip\r
+    @see com.stevesoft.pat.SkipBMH\r
+    */\r
+public class Skip2 extends Skip {\r
+    int c1,mask1;\r
+    public Skip2(String s,boolean ign,int offset) {\r
+        super(s,ign,offset);\r
+        c1 = s.charAt(1);\r
+        m1 = 2==s.length();\r
+        if(ign) {\r
+            mask1=mkmask(c1);\r
+        } else\r
+            mask1 = 0;\r
+    }\r
+    public int find(StringLike s,int start,int end) {\r
+        if(start > end) return -1;\r
+        start += offset;\r
+        int vend = min(s.length()-2,end+offset);\r
+        for(int i=start;i<=vend;i++)\r
+            if(0 == (s.charAt(i)&mask) && 0 == (s.charAt(i+1)&mask1)) {\r
+                //if(m1||s.regionMatches(ign,i,src,0,src.length()) )\r
+                if(m1||CaseMgr.regionMatches(s,ign,i,src,0,src.length()) )\r
+                    return i-offset;\r
+            }\r
+        return -1;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/SkipBMH.java b/src/com/stevesoft/pat/SkipBMH.java
new file mode 100755 (executable)
index 0000000..4fbe381
--- /dev/null
@@ -0,0 +1,183 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import com.stevesoft.pat.wrap.StringWrap;\r
+\r
+/** Like Skip, but implements a\r
+    <a href="http://www.dcc.uchile.cl/~rbaeza/handbook/algs/7/713b.srch.p.html">\r
+    Boyer-Moore-Horspool</a> type search\r
+    method that has been modified to be more like a "T-search" (see\r
+    the Michael Tamm''s article in <i>C'T, magazin fuer computer und technic</i>, August 97\r
+    p 292).  Yet another important source of information for me was\r
+    the <a href="http://www.go2net.com/people/paulp/deep/1997/05/14/">\r
+    Deep Magic</a> article on string searching.  As of this writing, I can\r
+    beat String's indexOf method in many cases.\r
+    @see com.stevesoft.pat.Skip\r
+    @see com.stevesoft.pat.Skip2\r
+    */\r
+public class SkipBMH extends Skip {\r
+    // This number could be 256, but I think it's\r
+    // big enough.  Note, it must be a power of 2.\r
+    final int MAX_CHAR = 64;\r
+    final char[] skip = new char[MAX_CHAR];\r
+    int sm1;\r
+    int jump_ahead = 0;\r
+    char uc,lc,tc,x;\r
+    final boolean exact(char c) {\r
+        return (ign && anyc(c))||c==x;\r
+    }\r
+    final boolean anyc(char c) {\r
+        return c==uc||c==lc||c==tc;\r
+    }\r
+    public SkipBMH(String pt,boolean ign) { this(pt,ign,0); }\r
+    public SkipBMH(String pt) { this(pt,false,0); }\r
+    public SkipBMH(String pt,boolean ign,int offset) {\r
+        super(pt,ign,offset);\r
+        for(int k=0;k<MAX_CHAR;k++)\r
+            skip[k] = (char)src.length();\r
+\r
+        sm1 = src.length()-1;\r
+        x = src.charAt(sm1);\r
+        uc=CaseMgr.toUpperCase(x);\r
+        lc=CaseMgr.toLowerCase(x);\r
+        tc=CaseMgr.toTitleCase(x);\r
+\r
+        // We don't really want 65536 long arrays in skip[],\r
+        // so we mask of the higher bits.  This can be combined\r
+        // with ignore case, so accounting for upper\r
+        // case costs us nothing extra.\r
+        for(int k=0;k<src.length()-1;k++) {\r
+            char x_ = src.charAt(k);\r
+            if(ign) {\r
+                char uc_ = CaseMgr.toUpperCase(x_);\r
+                char lc_ = CaseMgr.toLowerCase(x_);\r
+                char tc_ = CaseMgr.toTitleCase(x_);\r
+                skip[uc_ & (MAX_CHAR-1)]=(char)(src.length()-k-1);\r
+                skip[lc_ & (MAX_CHAR-1)]=(char)(src.length()-k-1);\r
+                skip[tc_ & (MAX_CHAR-1)]=(char)(src.length()-k-1);\r
+            } else\r
+                skip[x_ & (MAX_CHAR-1)] = (char)(src.length()-k-1);\r
+        }\r
+\r
+        // This trick can be found in the July issue of\r
+        // C-T magazine.  This makes the method a type of\r
+        // "T-search."\r
+        jump_ahead = src.length()-1;\r
+        for(int k=0;k<src.length()-1;k++) {\r
+            char y=src.charAt(sm1-k-1);\r
+            if(exact(y)) {\r
+                jump_ahead = k;\r
+                break;\r
+            }\r
+        }\r
+    }\r
+    /** Set to true if you only want to compare two of the\r
+        characters in the String. */\r
+    final public int searchRegion(String s,int start,int end) {\r
+        return find(s,start,end);\r
+    }\r
+    final public int searchFrom(String s,int start) {\r
+        return find(s,start,s.length());\r
+    }\r
+    final public int search(String s) { return find(s,0,s.length()); }\r
+    public int find(String s,int start,int end) {\r
+        start += offset+sm1;\r
+        int vend = min(s.length()-1,end+sm1+offset),k;\r
+        int vend1 = vend-jump_ahead;\r
+        if(ign) {\r
+            for(k=start; k <= vend1;k += skip[s.charAt(k) & (MAX_CHAR-1)] ) {\r
+                // table look-up is expensive, avoid it if possible\r
+                if( anyc(s.charAt(k)) ) {\r
+                    if(CaseMgr.regionMatches(src,ign,0,s,k-sm1,sm1))\r
+                        return k-sm1-offset;\r
+                    k += jump_ahead;\r
+                }\r
+            }\r
+            for(; k <= vend;k += skip[s.charAt(k) & (MAX_CHAR-1)] ) {\r
+                // table look-up is expensive, avoid it if possible\r
+                if( anyc(s.charAt(k)) ) {\r
+                    if(CaseMgr.regionMatches(src,ign,0,s,k-sm1,sm1))\r
+                        return k-sm1-offset;\r
+                    k += jump_ahead;\r
+                    if(k > vend) return -1;\r
+                }\r
+            }\r
+        } else {\r
+            for(k=start; k <= vend1;k += skip[s.charAt(k) & (MAX_CHAR-1)] ) {\r
+                // table look-up is expensive, avoid it if possible\r
+                if( x==s.charAt(k) ) {\r
+                    //if(src.regionMatches(0,s,k-sm1,sm1))\r
+                    if(CaseMgr.regionMatches(src,false,0,s,k-sm1,sm1))\r
+                        return k-sm1-offset;\r
+                    k += jump_ahead;\r
+                }\r
+            }\r
+            for(; k <= vend;k += skip[s.charAt(k) & (MAX_CHAR-1)] ) {\r
+                // table look-up is expensive, avoid it if possible\r
+                if( x==s.charAt(k) ) {\r
+                    //if(src.regionMatches(0,s,k-sm1,sm1))\r
+                    if(CaseMgr.regionMatches(src,false,0,s,k-sm1,sm1))\r
+                        return k-sm1-offset;\r
+                    k += jump_ahead;\r
+                    if(k > vend) return -1;\r
+                }\r
+            }\r
+        }\r
+\r
+        return -1;\r
+    }\r
+    public int find(StringLike s,int start,int end) {\r
+        if(s instanceof StringWrap)\r
+          return find(s.toString(),start,end);\r
+        start += offset+sm1;\r
+        int vend = min(s.length()-1,end+sm1+offset),k;\r
+        int vend1 = vend-jump_ahead;\r
+        if(ign) {\r
+            for(k=start; k <= vend1;k += skip[s.charAt(k) & (MAX_CHAR-1)] ) {\r
+                // table look-up is expensive, avoid it if possible\r
+                if( anyc(s.charAt(k)) ) {\r
+                    if(CaseMgr.regionMatches(src,ign,0,s,k-sm1,sm1))\r
+                        return k-sm1-offset;\r
+                    k += jump_ahead;\r
+                }\r
+            }\r
+            for(; k <= vend;k += skip[s.charAt(k) & (MAX_CHAR-1)] ) {\r
+                // table look-up is expensive, avoid it if possible\r
+                if( anyc(s.charAt(k)) ) {\r
+                    if(CaseMgr.regionMatches(src,ign,0,s,k-sm1,sm1))\r
+                        return k-sm1-offset;\r
+                    k += jump_ahead;\r
+                    if(k > vend) return -1;\r
+                }\r
+            }\r
+        } else {\r
+            for(k=start; k <= vend1;k += skip[s.charAt(k) & (MAX_CHAR-1)] ) {\r
+                // table look-up is expensive, avoid it if possible\r
+                if( x==s.charAt(k) ) {\r
+                    //if(src.regionMatches(0,s,k-sm1,sm1))\r
+                    if(CaseMgr.regionMatches(src,false,0,s,k-sm1,sm1))\r
+                        return k-sm1-offset;\r
+                    k += jump_ahead;\r
+                }\r
+            }\r
+            for(; k <= vend;k += skip[s.charAt(k) & (MAX_CHAR-1)] ) {\r
+                // table look-up is expensive, avoid it if possible\r
+                if( x==s.charAt(k) ) {\r
+                    //if(src.regionMatches(0,s,k-sm1,sm1))\r
+                    if(CaseMgr.regionMatches(src,false,0,s,k-sm1,sm1))\r
+                        return k-sm1-offset;\r
+                    k += jump_ahead;\r
+                    if(k > vend) return -1;\r
+                }\r
+            }\r
+        }\r
+\r
+        return -1;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/Skipped.java b/src/com/stevesoft/pat/Skipped.java
new file mode 100755 (executable)
index 0000000..9d963ae
--- /dev/null
@@ -0,0 +1,27 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** Implements the (?&lt;number) Pattern, where number is\r
+ an integer telling us how far to back up in the Pattern.\r
+ Not in perl 5. */\r
+class Skipped extends Pattern {\r
+    String s;\r
+    Skipped(String s) { this.s = s; }\r
+    public String toString() { return s+nextString(); }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        //if(pt.no_check || s.regionMatches(pt.ignoreCase,0,pt.src,pos,s.length()))\r
+        if(pt.no_check || CaseMgr.regionMatches(s,pt.ignoreCase,0,pt.src,pos,s.length()))\r
+            return nextMatch(pos+s.length(),pt);\r
+        return -1;\r
+    }\r
+    public patInt minChars() { return new patInt(s.length()); }\r
+    public patInt maxChars() { return new patInt(s.length()); }\r
+    Pattern clone1(Hashtable h) { return new Skipped(s); }\r
+};\r
diff --git a/src/com/stevesoft/pat/SpecialRule.java b/src/com/stevesoft/pat/SpecialRule.java
new file mode 100755 (executable)
index 0000000..72df8d2
--- /dev/null
@@ -0,0 +1,13 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+public class SpecialRule extends ReplaceRule {\r
+    public SpecialRule() {}\r
+    public void apply(StringBufferLike sb,RegRes rr) {}\r
+}\r
diff --git a/src/com/stevesoft/pat/Start.java b/src/com/stevesoft/pat/Start.java
new file mode 100755 (executable)
index 0000000..9784358
--- /dev/null
@@ -0,0 +1,31 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** The '^' or the '\A' Pattern, matches the start of a string. */\r
+class Start extends Pattern {\r
+    boolean retIsStart;\r
+    Start(boolean b) { retIsStart = b; }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(retIsStart\r
+       && pt.mFlag\r
+       && pos > 0 && pt.src.charAt(pos-1)=='\n')\r
+            return nextMatch(pos,pt);\r
+        if(pos == 0) return nextMatch(pos,pt);\r
+        return -1;\r
+    }\r
+    public String toString() {\r
+        if(retIsStart)\r
+            return "^"+nextString();\r
+        else\r
+            return "\\A"+nextString();\r
+    }\r
+    public patInt maxChars() { return new patInt(0); }\r
+    Pattern clone1(Hashtable h) { return new Start(retIsStart); }\r
+};\r
diff --git a/src/com/stevesoft/pat/StrPos.java b/src/com/stevesoft/pat/StrPos.java
new file mode 100755 (executable)
index 0000000..4a9f287
--- /dev/null
@@ -0,0 +1,117 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+/** \r
+        Shareware: package pat\r
+   <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>\r
+*/ /**\r
+StrPos is used internally by regex to parse the regular expression. */\r
+public class StrPos {\r
+    String s;\r
+    int pos;\r
+    /** Return the position in the string pointed to */\r
+    public int pos() { return pos; }\r
+\r
+    /** This contains the escape character, which is \ by default. */\r
+    public char esc=Pattern.ESC;\r
+    char c;\r
+    /** Returns the current, possibly escaped, character. */\r
+    public char thisChar() { return c; }\r
+\r
+    boolean dontMatch,eos;\r
+\r
+    /** tell whether we are at end of string */\r
+    public boolean eos() { return eos; }\r
+    /** initialize a StrPos from another StrPos. */\r
+    public StrPos(StrPos sp) {\r
+        dup(sp);\r
+    }\r
+    /** copy a StrPos from sp to this. */\r
+    public void dup(StrPos sp) {\r
+        s = sp.s;\r
+        pos = sp.pos;\r
+        c = sp.c;\r
+        dontMatch = sp.dontMatch;\r
+        eos = sp.eos;\r
+    }\r
+    /** Initialize a StrPos by giving it a String, and a\r
+         position within the String. */\r
+    public StrPos(String s,int pos) {\r
+        this.s=s;\r
+        this.pos=pos-1;\r
+        inc();\r
+    }\r
+    /** Advance the place where StrPos points within the String.\r
+         Counts a backslash as part of the next character. */\r
+    public StrPos inc() {\r
+        pos++;\r
+        if(pos >= s.length()) {\r
+            eos = true;\r
+            return this;\r
+        }\r
+        eos = false;\r
+        c = s.charAt(pos);\r
+        if(c == esc && pos+1<s.length()) {\r
+            pos++;\r
+            c = s.charAt(pos);\r
+            if(c != esc)\r
+                dontMatch = true;\r
+            else\r
+                dontMatch = false;\r
+        } else\r
+            dontMatch = false;\r
+        return this;\r
+    }\r
+    /** Compare the (possibly escaped) character\r
+         pointed to by StrPos.  Return true if they are the\r
+         same, but lways return if character pointed to is escaped. */\r
+    public boolean match(char ch) {\r
+        if(dontMatch || eos) return false;\r
+        return c == ch;\r
+    }\r
+    /** As match, but only matches if the character is escaped. */\r
+    public boolean escMatch(char ch) {\r
+        if(!dontMatch || eos) return false;\r
+        return c == ch;\r
+    }\r
+\r
+    /** Returns true if the current\r
+        character is escaped (preceeded by "\"). */\r
+    public boolean escaped() { return dontMatch; }\r
+    /** Increment the string pointer by each character in\r
+         <pre>st</pre> that matches a non-escaped\r
+         character. */\r
+    public boolean incMatch(String st) {\r
+        StrPos sp = new StrPos(this);\r
+        int i;\r
+        for(i=0;i<st.length();i++) {\r
+            if(!sp.match(st.charAt(i)) )\r
+                return false;\r
+            sp.inc();\r
+        }\r
+        dup(sp);\r
+        return true;\r
+    }\r
+    /** Read in an integer. */\r
+    public patInt getPatInt() {\r
+        patInt pi = null;\r
+        if(incMatch("inf"))\r
+            return new patInf();\r
+        int i,cnt=0;\r
+        StrPos sp = new StrPos(this);\r
+        for(i=0;!sp.eos && sp.c >= '0' && sp.c <= '9';i++) {\r
+            cnt = 10*cnt+sp.c-'0';\r
+            sp.inc();\r
+        }\r
+        if(i==0) return null;\r
+        dup(sp);\r
+        return new patInt(cnt);\r
+    }\r
+    /** get the string that we are processing. */\r
+    public String getString() { return s; }\r
+};\r
diff --git a/src/com/stevesoft/pat/StringBufferLike.java b/src/com/stevesoft/pat/StringBufferLike.java
new file mode 100755 (executable)
index 0000000..6987eec
--- /dev/null
@@ -0,0 +1,65 @@
+package//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+com.stevesoft.pat;\r
+\r
+import com.stevesoft.pat.*;\r
+\r
+/** A tool that is used to make the \E, \U, \L, and \Q\r
+    elements of a substitution. */\r
+public class StringBufferLike implements BasicStringBufferLike {\r
+  BasicStringBufferLike sbl;\r
+  public StringBufferLike(BasicStringBufferLike sbl) {\r
+    this.sbl = sbl;\r
+  }\r
+  char mode = 'E', altMode = ' ';\r
+  public StringLike toStringLike() {\r
+    return sbl.toStringLike();\r
+  }\r
+  public String toString() {\r
+    return sbl.toString();\r
+  }\r
+  public void append(char c) {\r
+    \r
+    switch(mode) {\r
+    case 'u':\r
+      mode = altMode;\r
+      altMode = ' ';\r
+    case 'U':\r
+      sbl.append(CaseMgr.toUpperCase(c));\r
+      break;\r
+    case 'l':\r
+      mode = altMode;\r
+      altMode = ' ';\r
+    case 'L':\r
+      sbl.append(CaseMgr.toLowerCase(c));\r
+      break;\r
+    case 'Q':\r
+      if((c >= 'a' && c <= 'z')\r
+      || (c >= 'A' && c <= 'Z')\r
+      || (c >= '0' && c <= '9'))\r
+        ;\r
+      else\r
+        sbl.append('\\');\r
+    default:\r
+      sbl.append(c);\r
+      break;\r
+    }\r
+  }\r
+  public void append(String s) {\r
+    for(int i=0;i<s.length();i++)\r
+      append(s.charAt(i));\r
+  }\r
+  public void setMode(char c) {\r
+    if(c == 'u' || c == 'l')\r
+      if(altMode == ' ') altMode = mode;\r
+    mode = c;\r
+  }\r
+  public Object unwrap() {\r
+    return sbl.unwrap();\r
+  }\r
+}\r
diff --git a/src/com/stevesoft/pat/StringLike.java b/src/com/stevesoft/pat/StringLike.java
new file mode 100755 (executable)
index 0000000..a6cd318
--- /dev/null
@@ -0,0 +1,37 @@
+package//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+com.stevesoft.pat;\r
+\r
+/** Package pat can search anything that implements this\r
+    interface.  Package pat assumes the following:\r
+    <ul>\r
+    <li>The StringLike object will not change.  Calls to\r
+        charAt(int) will not vary with time.\r
+    <li>The length of the object being searched is known\r
+        before the search begins and does not vary with time.\r
+    </ul>\r
+    Note that searching String is probably faster than searching\r
+    other objects, so searching String is still preferred if\r
+    possible.\r
+*/\r
+public interface StringLike {\r
+    public char charAt(int i);\r
+    public String toString();\r
+    public int length();\r
+    public String substring(int i1,int i2);\r
+    /** Obtain the underlying object, be it a String, char[],\r
+        RandomAccessFile, whatever. */\r
+    public Object unwrap();\r
+    /** By default, the result is put in a String or char[]\r
+        when a replace is done.  If you wish to save the result\r
+        in some other StringBufferLike then you can do this\r
+        by implementing this method, or over-riding it's behavior\r
+        from an existing class. */\r
+    public BasicStringBufferLike newStringBufferLike();\r
+    public int indexOf(char c);\r
+}\r
diff --git a/src/com/stevesoft/pat/StringRule.java b/src/com/stevesoft/pat/StringRule.java
new file mode 100755 (executable)
index 0000000..c37b6bb
--- /dev/null
@@ -0,0 +1,22 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** The apply method of this ReplaceRule simply appends the text\r
+    it was initialized with to the StringBufferLike.\r
+    @see com.stevesoft.pat.ReplaceRule\r
+    */\r
+public class StringRule extends ReplaceRule {\r
+    String s;\r
+    public StringRule(String s) { this.s = s; }\r
+    public void apply(StringBufferLike sb,RegRes res) {\r
+        sb.append(s);\r
+    }\r
+    public String toString1() { return s; }\r
+    public Object clone1() { return new StringRule(s); }\r
+}\r
diff --git a/src/com/stevesoft/pat/SubMark.java b/src/com/stevesoft/pat/SubMark.java
new file mode 100755 (executable)
index 0000000..ab5e431
--- /dev/null
@@ -0,0 +1,22 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** OrMark and SubMark together implement ( ... ) */\r
+class SubMark extends Pattern {\r
+    int end_pos,start_pos;\r
+    OrMark om;\r
+    public String toString() { return ""; }\r
+    public int matchInternal(int i,Pthings pt) {\r
+        pt.marks[om.id+pt.nMarks] = i;\r
+        int ret=nextMatch(i,pt);\r
+        if(ret < 0)\r
+            pt.marks[om.id+pt.nMarks] = -1;\r
+        return ret;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/TransPat.java b/src/com/stevesoft/pat/TransPat.java
new file mode 100755 (executable)
index 0000000..27c1fb2
--- /dev/null
@@ -0,0 +1,40 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.util.*;\r
+\r
+/** This class is used to implement the Transformer\r
+    @see com.stevesoft.pat.Transform\r
+    */\r
+class TransPat extends Pattern {\r
+    Regex[] ra = new Regex[10];\r
+    int ra_len = 0;\r
+    int pn = -1;\r
+    public String toString() {\r
+        return "(?#TransPat)";\r
+    }\r
+\r
+    TransPat() {}\r
+\r
+    int lastMatchedTo = -1;\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        for(int i=0;i<ra_len;i++) {\r
+            pt.ignoreCase = ra[i].ignoreCase;\r
+            pt.mFlag = ra[i].mFlag;\r
+            pt.dotDoesntMatchCR = ra[i].dotDoesntMatchCR;\r
+            int r = ra[i].thePattern.matchInternal(pos,pt);\r
+            if(r >= 0) {\r
+                pn = i;\r
+                return r;\r
+            }\r
+        }\r
+        pn = -1;\r
+        return -1;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/Transformer.java b/src/com/stevesoft/pat/Transformer.java
new file mode 100755 (executable)
index 0000000..f65afb4
--- /dev/null
@@ -0,0 +1,155 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.util.Vector;\r
+import com.stevesoft.pat.wrap.StringWrap;\r
+\r
+/** Replacement rule used by the Transformer.\r
+    @see com.stevesoft.pat.Transformer\r
+    */\r
+class TransRepRule extends ReplaceRule {\r
+    Transformer t;\r
+    TransRepRule(Transformer t) { this.t = t; }\r
+    public String toString1() { return ""; }\r
+    public Object clone1() { return new TransRepRule(t); }\r
+    public void apply(StringBufferLike sb,RegRes rr) {\r
+        // get the ReplaceRule of the Regex that matched.\r
+        next = t.tp.ra[t.tp.pn].getReplaceRule();\r
+    }\r
+}\r
+\r
+/** Sometimes you want to replace a whole bunch of things\r
+  that might occur within a single line of text.  One efficient\r
+  way to do this, both in terms of performance and programming\r
+  ease, is with Transformer. The Transformer contains an array\r
+  of Regex's and uses the Regex that matches earliest within the\r
+  text to do the replacing, if two Regex's match at the same\r
+  time it uses the one put in the Transformer first.\r
+  <p>\r
+  This feature can be used to prevent transformations from\r
+  occurring in certain regions. For example, if I add the rule\r
+  s'//.*'$&' and then add the\r
+  rule s/hello/goodbye/ the Transformer will replace "hello"\r
+  with "goodbye" except when it occurs inside a double-slash\r
+  style of comment.   The transformation on the comment goes first,\r
+  does nothing, and precludes transformation on the same region\r
+  of text as the s/hello/goodbye/ rule.\r
+  <p>\r
+  So far, at least, this class does not have the capability of\r
+  turning into a giant robot :-)\r
+  */\r
+public class Transformer {\r
+    TransPat tp;\r
+    Regex rp = new Regex();\r
+    boolean auto_optimize;\r
+\r
+    /** Get a replacer to that works with the current Regex.\r
+     @see com.stevesoft.pat.Replacer\r
+     */\r
+    public Replacer getReplacer() { return rp.getReplacer(); }\r
+\r
+    /** Instantiate a new Transformer object. */\r
+    public Transformer(boolean auto) {\r
+        auto_optimize = auto;\r
+        tp = new TransPat();\r
+        rp.setReplaceRule(new TransRepRule(this));\r
+        rp.thePattern = tp;\r
+    }\r
+\r
+    /** Add a new Regex to the set of Regex's. */\r
+    public void add(Regex r) {\r
+        if(auto_optimize) r.optimize();\r
+        tp.ra[tp.ra_len++] = r;\r
+        if(tp.ra.length==tp.ra_len) {\r
+            Regex[] ra2 = new Regex[tp.ra_len+10];\r
+            for(int i=0;i<tp.ra_len;i++)\r
+                ra2[i] = tp.ra[i];\r
+            tp.ra = ra2;\r
+        }\r
+        rp.numSubs_ = r.numSubs_ > rp.numSubs_ ? r.numSubs_ : rp.numSubs_;\r
+    }\r
+\r
+    /** Returns the number of Regex's in this Transformer. */\r
+    public int patterns() { return tp.ra_len; }\r
+\r
+    /** Get the Regex at position i in this Transformer. */\r
+    public Regex getRegexAt(int i) {\r
+        if(i >= tp.ra_len)\r
+            throw new ArrayIndexOutOfBoundsException("i="+i+">="+patterns());\r
+        if(i < 0)\r
+            throw new ArrayIndexOutOfBoundsException("i="+i+"< 0");\r
+        return tp.ra[i];\r
+    }\r
+    /** Set the Regex at position i in this Transformer. */\r
+    public void setRegexAt(Regex rx,int i) {\r
+        if(i >= tp.ra_len)\r
+            throw new ArrayIndexOutOfBoundsException("i="+i+">="+patterns());\r
+        if(i < 0)\r
+            throw new ArrayIndexOutOfBoundsException("i="+i+"< 0");\r
+        tp.ra[i] = rx;\r
+    }\r
+\r
+    /** Add a new Regex by calling Regex.perlCode\r
+        @see com.stevesoft.pat.Regex#perlCode(java.lang.String)\r
+        */\r
+    public void add(String rs) {\r
+        Regex r = Regex.perlCode(rs);\r
+        if(r == null) throw new NullPointerException("bad pattern to Regex.perlCode: "+rs);\r
+        add(r);\r
+    }\r
+    /** Add an array of Strings (which will be converted to\r
+        Regex's via the Regex.perlCode method.\r
+        @see com.stevesoft.pat.Regex#perlCode(java.lang.String)\r
+        */\r
+    public void add(String[] array) {\r
+        for(int i=0;i<array.length;i++)\r
+            add(array[i]);\r
+    }\r
+    /** Replace all matches in the current String. */\r
+    public String replaceAll(String s) {\r
+        return dorep(s,0,s.length());\r
+    }\r
+    public StringLike replaceAll(StringLike s) {\r
+        return dorep(s,0,s.length());\r
+    }\r
+    /** Replace all matching patterns beginning at position start. */\r
+    public String replaceAllFrom(String s,int start) {\r
+        return dorep(s,start,s.length());\r
+    }\r
+    /** Replace all matching patterns beginning between the positions\r
+        start and end inclusive. */\r
+    public String replaceAllRegion(String s,int start,int end) {\r
+        return dorep(s,start,end);\r
+    }\r
+\r
+    Replacer repr = new Replacer();\r
+    final StringLike dorep(StringLike s,int start,int end) {\r
+        StringLike tfmd = repr.replaceAllRegion(s,rp,start,end);\r
+        tp.lastMatchedTo = repr.lastMatchedTo;\r
+        return tfmd;\r
+    }\r
+    final String dorep(String s,int start,int end) {\r
+        return dorep(new StringWrap(s),start,end).toString();\r
+    }\r
+\r
+    /** Replace the first matching pattern in String s. */\r
+    public String replaceFirst(String s) {\r
+        return dorep(s,0,s.length());\r
+    }\r
+    /** Replace the first matching pattern after position start in\r
+        String s. */\r
+    public String replaceFirstFrom(String s,int start) {\r
+        return dorep(s,start,s.length());\r
+    }\r
+    /** Replace the first matching pattern that begins between\r
+        start and end inclusive. */\r
+    public String replaceFirstRegion(String s,int start,int end) {\r
+        return dorep(s,start,end);\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/UniValidator.java b/src/com/stevesoft/pat/UniValidator.java
new file mode 100755 (executable)
index 0000000..7fbac56
--- /dev/null
@@ -0,0 +1,16 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This provides a base class for all the Unicode character\r
+  * matching rules.\r
+  */\r
+class UniValidator extends Validator {\r
+    public patInt minChars() { return new patInt(1); }\r
+    public patInt maxChars() { return new patInt(1); }\r
+}\r
diff --git a/src/com/stevesoft/pat/Validator.java b/src/com/stevesoft/pat/Validator.java
new file mode 100755 (executable)
index 0000000..facd3f7
--- /dev/null
@@ -0,0 +1,58 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This class makes it easy to create your own patterns\r
+and integrate them into Regex.  For more detail, see the\r
+example file <a href="http://javaregex.com/code/deriv2.java.html">deriv2.java</a> or\r
+<a href="http://javaregex.com/code/deriv3.java.html">deriv3.java</a>. */\r
+\r
+public class Validator {\r
+    String argsave = null;\r
+    String pattern = ".";\r
+    /**\r
+    This method does extra checking on a matched section of\r
+    a String beginning at position start and ending at end.\r
+    The idea is that you can do extra checking with this\r
+    that you don't know how to do with a standard Regex.\r
+\r
+    If this method is successful, it returns the location\r
+    of the end of this pattern element -- that may be the\r
+    value end provided or some other value.  A negative\r
+    value signifies that a match failure.\r
+    \r
+    By default, this method just returns end and thus\r
+    does nothing.\r
+    @see com.stevesoft.pat.Regex#define(java.lang.String,java.lang.String,com.stevesoft.pat.Validator)\r
+    */\r
+    public int validate(StringLike src,int start,int end) {\r
+        return end;\r
+    }\r
+    /* This method allows you to modify the behavior of this\r
+    validator by making a new Validator object.  If a Validator\r
+    named "foo" is defined, then the pattern "{??foo:bar}" will\r
+    cause Regex to first get the Validator given to Regex.define\r
+    and then to call its arg method with the string "bar".\r
+    If this method returns a null (the default) you get the same\r
+    behavior as the pattern "{??foo}" would supply. */\r
+    public Validator arg(String s) { return null; }\r
+\r
+    /** For optimization it is helpful, but not necessary, that\r
+    you define the minimum number of characters this validator\r
+    will allow to match.  To do this \r
+    return new patInt(number) where number is the smallest\r
+    number of characters that can match. */\r
+    public patInt minChars() { return new patInt(0); }\r
+\r
+    /** For optimization it is helpful, but not necessary, that\r
+    you define the maximum number of characters this validator\r
+    will allow to match.  To do this either\r
+    return new patInt(number), or new patInf() if an infinite\r
+    number of characters may match. */\r
+    public patInt maxChars() { return new patInf(); }\r
+}\r
diff --git a/src/com/stevesoft/pat/WantMoreTextReplaceRule.java b/src/com/stevesoft/pat/WantMoreTextReplaceRule.java
new file mode 100755 (executable)
index 0000000..5cc6722
--- /dev/null
@@ -0,0 +1,19 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** Triggers the reading of another line of text, allowing a longer\r
+    pattern to match -- for details see\r
+    <a href="http://javaregex.com/code/WantMore.java.html">WantMore.java</a>.\r
+    */\r
+public class WantMoreTextReplaceRule extends SpecialRule {\r
+    public WantMoreTextReplaceRule() {}\r
+    public void apply(StringBufferLike sb,RegRes res) {\r
+    }\r
+    public String toString1() { return "${WANT_MORE_TEXT}"; }\r
+}\r
diff --git a/src/com/stevesoft/pat/lookAhead.java b/src/com/stevesoft/pat/lookAhead.java
new file mode 100755 (executable)
index 0000000..112db7c
--- /dev/null
@@ -0,0 +1,46 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** Implements "(?=  )" and "(?! )" */\r
+class lookAhead extends Or {\r
+    boolean reverse;\r
+    lookAhead(boolean b) { reverse = b; }\r
+    public Pattern getNext() { return null; }\r
+    public int nextMatch(int pos,Pthings pt) {\r
+        Pattern p = super.getNext();\r
+        if(p != null) return p.matchInternal(pos,pt);\r
+        else return pos;\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        if(super.matchInternal(pos,pt) >= 0) {\r
+            if(reverse) return -1;\r
+            else return nextMatch(pos,pt);\r
+        } else {\r
+            if(reverse) return nextMatch(pos,pt);\r
+            else return -1;\r
+        }\r
+    }\r
+    String leftForm() {\r
+        if(reverse)\r
+            return "(?!";\r
+        else\r
+            return "(?=";\r
+    }\r
+    public patInt minChars() { return new patInt(0); }\r
+    public patInt maxChars() { return new patInt(0); }\r
+    Pattern clone1(Hashtable h) {\r
+        lookAhead la=new lookAhead(reverse);\r
+        h.put(this,la);\r
+        h.put(la,la);\r
+        for(int i=0;i<v.size();i++)\r
+            la.v.addElement( ((Pattern)v.elementAt(i)).clone(h) );\r
+        return la;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/oneChar.java b/src/com/stevesoft/pat/oneChar.java
new file mode 100755 (executable)
index 0000000..f9c8498
--- /dev/null
@@ -0,0 +1,48 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+import java.util.Hashtable;\r
+\r
+/** This class matches a single character. */\r
+class oneChar extends Pattern {\r
+    char c,altc,altc2;\r
+    int mask;\r
+    public oneChar(char ci) {\r
+        c = ci;\r
+        char cu,cl,ct;\r
+        cu = CaseMgr.toUpperCase(c);\r
+        cl = CaseMgr.toLowerCase(c);\r
+        ct = CaseMgr.toTitleCase(c);\r
+        if(c == cu) {\r
+            altc = cl;\r
+            altc2 = ct;\r
+        } else if(c == cl) {\r
+            altc = cu;\r
+            altc2 = ct;\r
+        } else {\r
+            altc = cl;\r
+            altc2 = cu;\r
+        }\r
+        mask = c & altc & altc2;\r
+    }\r
+    public int matchInternal(int pos,Pthings pt) {\r
+        char p;\r
+        int ret=-1;\r
+        if (pos < pt.src.length() && !Masked(pos,pt)\r
+                && ((p=pt.src.charAt(pos))==c ||\r
+                (pt.ignoreCase&& (p==altc||p==altc2) ) ))\r
+            ret = nextMatch(pos+1,pt);\r
+        return ret;\r
+    }\r
+    public String toString() {\r
+        return protect(""+c,PROTECT_THESE,ESC)+nextString();\r
+    }\r
+    public patInt minChars() { return new patInt(1); }\r
+    public patInt maxChars() { return new patInt(1); }\r
+    Pattern clone1(Hashtable h) { return new oneChar(c); }\r
+};\r
diff --git a/src/com/stevesoft/pat/parsePerl.java b/src/com/stevesoft/pat/parsePerl.java
new file mode 100755 (executable)
index 0000000..5cdbabe
--- /dev/null
@@ -0,0 +1,266 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This class provides a method for parsing the "s/.../.../" constructs\r
+of Regex.perlCode.\r
+@see Regex#perlCode\r
+*/\r
+class parsePerl {\r
+    final static char close(char c) {\r
+        // This switch statement does not behave\r
+        // properly when compiled with jdk1.1.5\r
+        // and the -O flag.\r
+        /*\r
+        switch(c) {\r
+        case '[':\r
+          return ']';\r
+        case '(':\r
+          return ')';\r
+        case '{':\r
+          return '}';\r
+        }\r
+        return c;*/\r
+       if(c == '<')\r
+           return '>';\r
+        if(c == '[')\r
+            return ']';\r
+        if(c == '(')\r
+            return ')';\r
+        if(c == '{')\r
+            return '}';\r
+        return c;\r
+    }\r
+\r
+    final public static String codify(String s,boolean keepbs) {\r
+        return codify(s,0,s.length(),keepbs);\r
+    }\r
+    final public static String codify(String s,int i0,int iN,boolean keepbs) {\r
+        StringBuffer sb = new StringBuffer();\r
+        boolean ucmode = false, lcmode = false, litmode = false;\r
+        boolean uc1 = false, lc1 = false;\r
+        boolean modified = false;\r
+        for(int i=i0;i<iN;i++) {\r
+            char c = s.charAt(i);\r
+            boolean mf = true, app=true;\r
+            if(c=='\\') {\r
+                app=false;\r
+                i++;\r
+                if(i<s.length()) {\r
+                    char c2 = s.charAt(i);\r
+                    switch(c2) {\r
+                    case 'Q':\r
+                        litmode = true;\r
+                        break;\r
+                    case 'U':\r
+                        ucmode = true;\r
+                        break;\r
+                    case 'L':\r
+                        lcmode = true;\r
+                        break;\r
+                    case 'u':\r
+                        uc1 = true;\r
+                        break;\r
+                    case 'l':\r
+                        lc1 = true;\r
+                        break;\r
+                    case 'E':\r
+                        uc1=lc1=ucmode=lcmode=litmode=false;\r
+                        break;\r
+                    default:\r
+                        if(keepbs)\r
+                            sb.append('\\');\r
+                        c=c2;\r
+                        if(keepbs) mf = false;\r
+                        app = true;\r
+                        break;\r
+                    }\r
+                    modified |= mf;\r
+                }\r
+            }\r
+            if(app) {\r
+                if(lc1) {\r
+                    c=lc(c);\r
+                    lc1=false;\r
+                } else if(uc1) {\r
+                    c=uc(c);\r
+                    uc1=false;\r
+                } else if(ucmode) {\r
+                    c=uc(c);\r
+                } else if(lcmode) {\r
+                    c=lc(c);\r
+                }\r
+                if(litmode && needbs(c))\r
+                    sb.append('\\');\r
+                sb.append(c);\r
+            }\r
+        }\r
+        return modified ? sb.toString() : s;\r
+    }\r
+    final static char uc(char c) {\r
+        return CaseMgr.toUpperCase(c);\r
+    }\r
+    final static char lc(char c) {\r
+        return CaseMgr.toLowerCase(c);\r
+    }\r
+    final static boolean needbs(char c) {\r
+        if(c >= 'a' && c <= 'z')\r
+            return false;\r
+        if(c >= 'A' && c <= 'Z')\r
+            return false;\r
+        if(c >= '0' && c <= '9')\r
+            return false;\r
+        if(c == '_')\r
+            return false;\r
+        return true;\r
+    }\r
+    final static Regex parse(String s) {\r
+        boolean igncase = false, optim = false, gFlag = false;\r
+        boolean sFlag = false, mFlag = false, xFlag = false;\r
+\r
+        StringBuffer s1 = new StringBuffer();\r
+        StringBuffer s2 = new StringBuffer();\r
+        int i=0,count=0;\r
+        char mode,delim='/',cdelim='/';\r
+        if(s.length() >= 3 && s.charAt(0)=='s') {\r
+            mode = 's';\r
+            delim = s.charAt(1);\r
+            cdelim = close(delim);\r
+            i=2;\r
+        } else if(s.length() >= 2 && s.charAt(0)=='m') {\r
+            mode = 'm';\r
+            delim = s.charAt(1);\r
+            cdelim = close(delim);\r
+            i=2;\r
+        } else if(s.length() >= 1 && s.charAt(0)=='/') {\r
+            mode = 'm';\r
+            i=1;\r
+        } else {\r
+            try {\r
+                RegSyntaxError.endItAll(\r
+                   "Regex.perlCode should be of the "+\r
+                    "form s/// or m// or //");\r
+            } catch(RegSyntax rs) {}\r
+            return null;\r
+        }\r
+        for(;i<s.length();i++) {\r
+            if(s.charAt(i)=='\\') {\r
+                s1.append('\\');\r
+                i++;\r
+            } else if(s.charAt(i)==cdelim && count==0) {\r
+                i++;\r
+                break;\r
+            } else if(s.charAt(i)==delim && cdelim != delim) {\r
+                count++;\r
+            } else if(s.charAt(i)==cdelim && cdelim != delim) {\r
+                count--;\r
+            }\r
+            s1.append(s.charAt(i));\r
+        }\r
+        if(mode=='s' && cdelim != delim) {\r
+            while(i<s.length() && Prop.isWhite(s.charAt(i)) )\r
+                i++;\r
+            if(i>=s.length()) {\r
+                try {\r
+                    RegSyntaxError.endItAll(""+mode+delim+" needs "+cdelim);\r
+                } catch(RegSyntax rs) {}\r
+                return null;\r
+            }\r
+            cdelim = close(delim = s.charAt(i));\r
+            i++;\r
+        }\r
+        count=0;\r
+        if(mode=='s') {\r
+            for(;i<s.length();i++) {\r
+                if(s.charAt(i)=='\\') {\r
+                    s2.append('\\');\r
+                    i++;\r
+                } else if(s.charAt(i)==cdelim && count==0) {\r
+                    i++;\r
+                    break;\r
+                } else if(s.charAt(i)==delim && cdelim != delim) {\r
+                    count++;\r
+                } else if(s.charAt(i)==cdelim && cdelim != delim) {\r
+                    count--;\r
+                }\r
+                s2.append(s.charAt(i));\r
+            }\r
+        }\r
+        for(;i<s.length();i++) {\r
+            char c = s.charAt(i);\r
+            switch(c) {\r
+           case 'x':\r
+               xFlag = true;\r
+               break;\r
+            case 'i':\r
+                igncase = true;\r
+                break;\r
+            case 'o':\r
+                optim = true;\r
+                break;\r
+            case 's':\r
+                sFlag = true;\r
+                break;\r
+            case 'm':\r
+               mFlag = true;\r
+                break;\r
+            case 'g':\r
+                gFlag = true;\r
+                break;\r
+            default:\r
+                // syntax error!\r
+                try {\r
+                    RegSyntaxError.endItAll("Illegal flag to pattern: "+c);\r
+                } catch(RegSyntax rs) {}\r
+                return null;\r
+            }\r
+        }\r
+        Regex r = new Regex();\r
+        try {\r
+            String pat=s1.toString(),reprul=s2.toString();\r
+           if(xFlag) {\r
+             pat = strip(pat);\r
+             reprul = strip(reprul);\r
+           }\r
+            r.compile(pat);\r
+            r.ignoreCase |= igncase;\r
+            r.gFlag |= gFlag;\r
+            r.sFlag |= sFlag;\r
+           r.mFlag |= mFlag;\r
+            if(optim) r.optimize();\r
+           if(delim=='\'')\r
+              r.setReplaceRule(new StringRule(reprul));\r
+           else\r
+              r.setReplaceRule(ReplaceRule.perlCode(reprul));\r
+        } catch(RegSyntax rs) {\r
+            r = null;\r
+        }\r
+        return r;\r
+    }\r
+    static String strip(String s) {\r
+      StringBuffer sb = new StringBuffer();\r
+      for(int i=0;i<s.length();i++) {\r
+        char c = s.charAt(i);\r
+       if(Prop.isWhite(c)) {\r
+         ;\r
+       } else if(c == '#') {\r
+         i++;\r
+         while(i<s.length()) {\r
+           if(s.charAt(i) == '\n')\r
+             break;\r
+           i++;\r
+         }\r
+        } else if(c == '\\') {\r
+         sb.append(c);\r
+         sb.append(s.charAt(++i));\r
+       } else\r
+         sb.append(c);\r
+      }\r
+      return sb.toString();\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/patInf.java b/src/com/stevesoft/pat/patInf.java
new file mode 100755 (executable)
index 0000000..09da207
--- /dev/null
@@ -0,0 +1,12 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+final class patInf extends patInt {\r
+    patInf() { inf = true; }\r
+};\r
diff --git a/src/com/stevesoft/pat/patInt.java b/src/com/stevesoft/pat/patInt.java
new file mode 100755 (executable)
index 0000000..e18c627
--- /dev/null
@@ -0,0 +1,88 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+/** This is just an integer that can have infinite value.\r
+    It is used internally to implement the *, and + parts\r
+    of regular expressions.\r
+*/\r
+public class patInt {\r
+    int i;\r
+    boolean inf;\r
+    /** Initialize to zero. */\r
+    public patInt() { i = 0; inf = false; }\r
+    /** Initialize to the value of init. */\r
+    public patInt(int init) { i = init; inf = false; }\r
+    /** Initialize to the value of p. */\r
+    public patInt(patInt p) { i = p.i; inf = p.inf; }\r
+    /** set this int to infinity. */\r
+    public void setInf(boolean b) {\r
+        inf = b;\r
+        if(b) i = Integer.MAX_VALUE;\r
+    }\r
+    /** Increment the value of this by 1. */\r
+    public final void inc() {\r
+        if(!inf) i++;\r
+    }\r
+    /** Decrement the value of this by 1. */\r
+    public final void dec() {\r
+        if(!inf) i--;\r
+    }\r
+    /** Test to see if this is less than or equal to j. */\r
+    public final boolean lessEq(patInt j) { /*\r
+                if(inf) return false;\r
+                if(j.inf) return true;\r
+                return i <= j.i; */\r
+        return !inf && (j.inf || i <= j.i);\r
+    }\r
+    /** Test to see if two patterns are equal. */\r
+    public final boolean equals(patInt j) {\r
+        return !j.inf && !inf && i==j.i;\r
+    }\r
+    /** Formats the pattern as a String.  Contrary to\r
+         what you might expect, infinity is formatted as "" */\r
+    final public String toString() {\r
+        if(inf) return "";\r
+        else return ""+i;\r
+    }\r
+    /** This would be operator+=(patInt) if I were programming\r
+         in C++. */\r
+    public final patInt pluseq(patInt p) {\r
+        if(inf||p.inf) setInf(true);\r
+        else i += p.i;\r
+        return this;\r
+    }\r
+    /** Returns a patInt with value equal to the product\r
+         of the value of p and this. */\r
+    public final patInt mul(patInt p) {\r
+        if(inf||p.inf) return new patInf();\r
+        return new patInt(i*p.i);\r
+    }\r
+    /** If the argument p has a smaller value than this,\r
+         then set this Object equal to p. */\r
+    public final patInt mineq(patInt p) {\r
+        if(p.inf) return this;\r
+        if(inf) i = p.i;\r
+        else if(p.i < i) i = p.i;\r
+        setInf(false);\r
+        return this;\r
+    }\r
+    /** If the argument p has a greater than this,\r
+         then set this object equal to p. */\r
+    public final patInt maxeq(patInt p) {\r
+        if(inf || p.inf) { setInf(true); return this; }\r
+        if(p.i > i) i = p.i;\r
+        return this;\r
+    }\r
+    /** Tests to see if this represents an infinite quantity. */\r
+    public boolean finite() { return !inf; }\r
+    /** Converts to a patInt to an int.  Infinity is\r
+         mapped Integer.MAX_VALUE;\r
+        */\r
+    public int intValue() { return inf ? Integer.MAX_VALUE : i; }\r
+};\r
diff --git a/src/com/stevesoft/pat/wrap/CharArrayBufferWrap.java b/src/com/stevesoft/pat/wrap/CharArrayBufferWrap.java
new file mode 100755 (executable)
index 0000000..4e11067
--- /dev/null
@@ -0,0 +1,38 @@
+package//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+com.stevesoft.pat.wrap;\r
+\r
+import com.stevesoft.pat.*;\r
+\r
+/** Allows the outcome of a replaceAll() or replaceFirst()\r
+    to be an array of characters rather than a String.\r
+    */\r
+public class CharArrayBufferWrap\r
+  implements BasicStringBufferLike\r
+  {\r
+  StringBuffer sb = new StringBuffer();\r
+  public void append(char c) {\r
+    sb.append(c);\r
+  }\r
+  public void append(String s) {\r
+    sb.append(s);\r
+  }\r
+  public StringLike toStringLike() {\r
+    char[] ca = new char[sb.length()];\r
+    for(int i=0;i<ca.length;i++)\r
+      ca[i] = sb.charAt(i);\r
+    return new CharArrayWrap(ca);\r
+  }\r
+  public int length() { return sb.length(); }\r
+  public String toString() {\r
+    return sb.toString();\r
+  }\r
+  public Object unwrap() {\r
+    return sb;\r
+  }\r
+}\r
diff --git a/src/com/stevesoft/pat/wrap/CharArrayWrap.java b/src/com/stevesoft/pat/wrap/CharArrayWrap.java
new file mode 100755 (executable)
index 0000000..e490cc9
--- /dev/null
@@ -0,0 +1,39 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat.wrap;\r
+\r
+import com.stevesoft.pat.*;\r
+\r
+/** This provides a wrapper for a char array so that\r
+    it can be searched by Regex. */\r
+public class CharArrayWrap implements StringLike {\r
+    char[] ca;\r
+    public char[] getCharArray() { return ca; }\r
+    public CharArrayWrap(char[] ca) { this.ca = ca; }\r
+    public String toString() {\r
+      return new String(ca);\r
+    }\r
+    public char charAt(int i) { return ca[i]; }\r
+    public int length() { return ca.length; }\r
+    public String substring(int i1,int i2) {\r
+        StringBuffer sb = new StringBuffer();\r
+        for(int i=i1;i<i2;i++)\r
+            sb.append(ca[i]);\r
+        return sb.toString();\r
+    }\r
+    public Object unwrap() { return ca; }\r
+    public BasicStringBufferLike newStringBufferLike() {\r
+      return new CharArrayBufferWrap();\r
+    }\r
+    public int indexOf(char c) {\r
+      for(int i=0;i<ca.length;i++)\r
+        if(ca[i] == c)\r
+          return i;\r
+      return -1;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/wrap/RandomAccessFileWrap.java b/src/com/stevesoft/pat/wrap/RandomAccessFileWrap.java
new file mode 100755 (executable)
index 0000000..23782ad
--- /dev/null
@@ -0,0 +1,116 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat.wrap;\r
+\r
+import com.stevesoft.pat.*;\r
+import java.io.*;\r
+\r
+/** Provides a wrapper for a RandomAccessFile so that it\r
+    can be searched by Regex. */\r
+public class RandomAccessFileWrap implements StringLike {\r
+\r
+    long offset = 0;\r
+    public void setOffset(long o) {\r
+      offset = o;\r
+      i0 = iend = 0;\r
+    }\r
+    public long getOffset() {\r
+      return offset;\r
+    }\r
+    RandomAccessFile raf;\r
+    int i0=0,iend=0;\r
+    byte[] buf = new byte[1024];\r
+\r
+    public int getBufferSize() {\r
+      return buf.length;\r
+    }\r
+\r
+    public void setBufferSize(int bs) {\r
+      buf = new byte[bs];\r
+      i0 = iend = 0;\r
+    }\r
+\r
+    public RandomAccessFileWrap(String file) throws IOException {\r
+        this.raf = new RandomAccessFile(file,"r");\r
+    }\r
+    public RandomAccessFileWrap(RandomAccessFile raf) {\r
+        this.raf = raf;\r
+    }\r
+\r
+    public char charAt(int i) {\r
+        if(i >= i0 && i < iend)\r
+            return (char)buf[i-i0];\r
+\r
+        try {\r
+            i0 = i-5;\r
+            //if(i0+offset<0) i0=(int)(-offset);\r
+            if(i0<0) i0=0;\r
+            raf.seek(i0+offset);\r
+            iend = i0+raf.read(buf,0,buf.length);\r
+\r
+            if(i >= i0 && i < iend)\r
+                return (char)buf[i-i0];\r
+        } catch(Throwable t) {}\r
+\r
+        throw new ArrayIndexOutOfBoundsException("Out of bounds for file:"+\r
+          " i="+i+\r
+          ", Final Buffer: i0="+i0+\r
+          " iend="+iend);\r
+    }\r
+\r
+    public String toString() { throw new Error("Not implemented"); }\r
+    public int length() {\r
+      try {\r
+        long len = raf.length()-offset;\r
+        if(len > Integer.MAX_VALUE)\r
+          return Integer.MAX_VALUE;\r
+        return (int)len;\r
+      } catch(IOException ioe) {\r
+        return 0;\r
+      }\r
+    }\r
+    public String substring(int i1,int i2) {\r
+        StringBuffer sb = new StringBuffer();\r
+        for(int i=i1;i<i2;i++)\r
+            sb.append(charAt(i));\r
+        return sb.toString();\r
+    }\r
+    public Object unwrap() { return raf; }\r
+\r
+    public static void main(String[] files) throws IOException {\r
+      for(int i=0;i<files.length;i++) {\r
+        RandomAccessFileWrap fw =\r
+          new RandomAccessFileWrap(new RandomAccessFile(files[i],"r"));\r
+        Regex r = new Regex("toString\\(\\) *(?@{})");\r
+        r.setGFlag(true);\r
+        r.optimize();\r
+        System.out.print(files[i]+" ");\r
+        int j=0;\r
+        do {\r
+          if(r.searchFrom(fw,j)) {\r
+            System.out.println("Matched at index: "+\r
+             r.matchedFrom());\r
+            j=r.matchedTo();\r
+          } else\r
+            System.out.println("not found");\r
+          System.out.println(r.stringMatched());\r
+        } while(r.didMatch());\r
+      }\r
+    }\r
+\r
+    public BasicStringBufferLike newStringBufferLike() {\r
+      return new StringBufferWrap();\r
+    }\r
+\r
+    public int indexOf(char c) {\r
+      for(int i=0;i<length();i++)\r
+        if(charAt(i)==c)\r
+          return i;\r
+      return -1;\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/wrap/StringBufferWrap.java b/src/com/stevesoft/pat/wrap/StringBufferWrap.java
new file mode 100755 (executable)
index 0000000..f42cfde
--- /dev/null
@@ -0,0 +1,36 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat.wrap;\r
+\r
+import com.stevesoft.pat.*;\r
+\r
+/** This provides a wrapper for StringBuffer to\r
+    capture the output of a replacement. */\r
+public class StringBufferWrap\r
+    implements BasicStringBufferLike\r
+  {\r
+  StringBuffer sb = new StringBuffer();\r
+  public void append(char c) {\r
+    sb.append(c);\r
+  }\r
+  public void append(String s) {\r
+    sb.append(s);\r
+  }\r
+  public int length() {\r
+    return sb.length();\r
+  }\r
+  public String toString() {\r
+    return sb.toString();\r
+  }\r
+  public StringLike toStringLike() {\r
+    return new StringWrap(sb.toString());\r
+  }\r
+  public Object unwrap() {\r
+    return sb;\r
+  }\r
+}\r
diff --git a/src/com/stevesoft/pat/wrap/StringWrap.java b/src/com/stevesoft/pat/wrap/StringWrap.java
new file mode 100755 (executable)
index 0000000..6c07ca1
--- /dev/null
@@ -0,0 +1,33 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat.wrap;\r
+\r
+import com.stevesoft.pat.*;\r
+\r
+/** A basic wrapper for the String object. Regex does\r
+    not search String directly any longer, it searches StringLike. */\r
+public class StringWrap implements StringLike {\r
+    String s;\r
+    public StringWrap(String s) {\r
+      this.s = s;\r
+    }\r
+    public String toString() { return s; }\r
+    public char charAt(int i) { return s.charAt(i); }\r
+    public int length() { return s.length(); }\r
+    public String substring(int i1,int i2) {\r
+        return s.substring(i1,i2);\r
+    }\r
+    public Object unwrap() { return s; }\r
+    public BasicStringBufferLike newStringBufferLike() {\r
+      return new StringBufferWrap();\r
+    }\r
+\r
+    public int indexOf(char c) {\r
+      return s.indexOf(c);\r
+    }\r
+}\r
diff --git a/src/com/stevesoft/pat/wrap/WriterWrap.java b/src/com/stevesoft/pat/wrap/WriterWrap.java
new file mode 100755 (executable)
index 0000000..a1be479
--- /dev/null
@@ -0,0 +1,45 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat.wrap;\r
+\r
+import com.stevesoft.pat.*;\r
+import java.io.*;\r
+\r
+/** Allows the outcome of a replaceAll() or replaceFirst()\r
+    to be directed to a Writer rather than a String.\r
+    <p>\r
+    The method toStringLike() cannot work, however.\r
+    This means that the return value of replaceAll() will\r
+    be null if this Object is used as the StringBufferLike.*/\r
+public class WriterWrap\r
+  implements BasicStringBufferLike\r
+  {\r
+  Writer w;\r
+  public WriterWrap(Writer w) {\r
+    this.w = w;\r
+  }\r
+  public void append(char c) {\r
+    try {\r
+      w.write((int)c);\r
+    } catch(IOException ioe) {}\r
+  }\r
+  public void append(String s) {\r
+    try {\r
+      w.write(s);\r
+    } catch(IOException ioe) {}\r
+  }\r
+\r
+  /** This operation can't really be done. */\r
+  public StringLike toStringLike() {\r
+    return null;\r
+  }\r
+\r
+  public Object unwrap() {\r
+    return w;\r
+  }\r
+}\r