Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / icu / source / i18n / regexcmp.cpp
index 6c68bc0..afad2bd 100644 (file)
@@ -1,7 +1,7 @@
 //
 //  file:  regexcmp.cpp
 //
-//  Copyright (C) 2002-2010 International Business Machines Corporation and others.
+//  Copyright (C) 2002-2013 International Business Machines Corporation and others.
 //  All Rights Reserved.
 //
 //  This file contains the ICU regular expression compiler, which is responsible
@@ -21,7 +21,9 @@
 #include "unicode/parsepos.h"
 #include "unicode/parseerr.h"
 #include "unicode/regex.h"
-#include "util.h"
+#include "unicode/utf.h"
+#include "unicode/utf16.h"
+#include "patternprops.h"
 #include "putilimp.h"
 #include "cmemory.h"
 #include "cstring.h"
@@ -69,7 +71,6 @@ RegexCompile::RegexCompile(RegexPattern *rxp, UErrorCode &status) :
 
     fMatchOpenParen   = -1;
     fMatchCloseParen  = -1;
-    fStringOpStart    = -1;
 
     if (U_SUCCESS(status) && U_FAILURE(rxp->fDeferredStatus)) {
         status = rxp->fDeferredStatus;
@@ -105,7 +106,7 @@ void    RegexCompile::compile(
                          UParseError &pp,            // Error position info
                          UErrorCode &e)              // Error Code
 {
-       fRXPat->fPatternString = new UnicodeString(pat);
+    fRXPat->fPatternString = new UnicodeString(pat);
     UText patternText = UTEXT_INITIALIZER;
     utext_openConstUnicodeString(&patternText, fRXPat->fPatternString, &e);
     
@@ -146,6 +147,12 @@ void    RegexCompile::compile(
     fPatternLength = utext_nativeLength(pat);
     uint16_t                state = 1;
     const RegexTableEl      *tableEl;
+
+    // UREGEX_LITERAL force entire pattern to be treated as a literal string.
+    if (fModeFlags & UREGEX_LITERAL) {
+        fQuoteMode = TRUE;
+    }
+
     nextChar(fC);                        // Fetch the first char from the pattern string.
 
     //
@@ -202,6 +209,7 @@ void    RegexCompile::compile(
             if (tableEl->fCharClass >= 128 && tableEl->fCharClass < 240 &&   // Table specs a char class &&
                 fC.fQuoted == FALSE &&                                       //   char is not escaped &&
                 fC.fChar != (UChar32)-1) {                                   //   char is not EOF
+                U_ASSERT(tableEl->fCharClass <= 137);
                 if (RegexStaticSets::gStaticSets->fRuleSets[tableEl->fCharClass-128].contains(fC.fChar)) {
                     // Table row specified a character class, or set of characters,
                     //   and the current char matches it.
@@ -294,7 +302,7 @@ void    RegexCompile::compile(
     //   present in the saved state:  the input string position (int64_t) and
     //   the position in the compiled pattern.
     //
-    fRXPat->fFrameSize+=RESTACKFRAME_HDRCOUNT;
+    allocateStackData(RESTACKFRAME_HDRCOUNT);
 
     //
     // Optimization pass 1: NOPs, back-references, and case-folding
@@ -360,9 +368,9 @@ UBool RegexCompile::doParseActions(int32_t action)
         //                    the start of an ( grouping.
         //4   NOP             Resreved, will be replaced by a save if there are
         //                    OR | operators at the top level
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_STATE_SAVE, 2), *fStatus);
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_JMP,  3), *fStatus);
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_FAIL, 0), *fStatus);
+        appendOp(URX_BUILD(URX_STATE_SAVE, 2));
+        appendOp(URX_BUILD(URX_JMP,  3));
+        appendOp(URX_BUILD(URX_FAIL, 0));
 
         // Standard open nonCapture paren action emits the two NOPs and
         //   sets up the paren stack frame.
@@ -385,7 +393,7 @@ UBool RegexCompile::doParseActions(int32_t action)
         }
 
         // add the END operation to the compiled pattern.
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_END, 0), *fStatus);
+        appendOp(URX_BUILD(URX_END, 0));
 
         // Terminate the pattern compilation state machine.
         returnVal = FALSE;
@@ -396,6 +404,9 @@ UBool RegexCompile::doParseActions(int32_t action)
     case doOrOperator:
         // Scanning a '|', as in (A|B)
         {
+            // Generate code for any pending literals preceding the '|'
+            fixLiterals(FALSE);
+
             // Insert a SAVE operation at the start of the pattern section preceding
             //   this OR at this level.  This SAVE will branch the match forward
             //   to the right hand side of the OR in the event that the left hand
@@ -411,7 +422,7 @@ UBool RegexCompile::doParseActions(int32_t action)
             //  the JMP will eventually be the location following the ')' for the
             //  group.  This will be patched in later, when the ')' is encountered.
             op = URX_BUILD(URX_JMP, 0);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // Push the position of the newly added JMP op onto the parentheses stack.
             // This registers if for fixup when this block's close paren is encountered.
@@ -420,7 +431,7 @@ UBool RegexCompile::doParseActions(int32_t action)
             // Append a NOP to the compiled pattern.  This is the slot reserved
             //   for a SAVE in the event that there is yet another '|' following
             //   this one.
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
+            appendOp(URX_BUILD(URX_NOP, 0));
             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);
         }
         break;
@@ -445,12 +456,12 @@ UBool RegexCompile::doParseActions(int32_t action)
         //      encountered.  This will be promoted to a completed capture when (and if) the corresponding
         //      END_CAPTURE is encountered.
         {
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
-            int32_t  varsLoc    = fRXPat->fFrameSize;    // Reserve three slots in match stack frame.
-            fRXPat->fFrameSize += 3;
-            int32_t  cop        = URX_BUILD(URX_START_CAPTURE, varsLoc);
-            fRXPat->fCompiledPat->addElement(cop, *fStatus);
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
+            fixLiterals();
+            appendOp(URX_BUILD(URX_NOP, 0));
+            int32_t  varsLoc = allocateStackData(3);    // Reserve three slots in match stack frame.
+            int32_t  cop     = URX_BUILD(URX_START_CAPTURE, varsLoc);
+            appendOp(cop);
+            appendOp(URX_BUILD(URX_NOP, 0));
 
             // On the Parentheses stack, start a new frame and add the postions
             //   of the two NOPs.  Depending on what follows in the pattern, the
@@ -474,8 +485,9 @@ UBool RegexCompile::doParseActions(int32_t action)
         //      - NOP, which may later be replaced by a save-state if there
         //             is an '|' alternation within the parens.
         {
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
+            fixLiterals();
+            appendOp(URX_BUILD(URX_NOP, 0));
+            appendOp(URX_BUILD(URX_NOP, 0));
 
             // On the Parentheses stack, start a new frame and add the postions
             //   of the two NOPs.
@@ -496,12 +508,12 @@ UBool RegexCompile::doParseActions(int32_t action)
         //      - NOP, which may later be replaced by a save-state if there
         //             is an '|' alternation within the parens.
         {
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
-            int32_t  varLoc    = fRXPat->fDataSize;    // Reserve a data location for saving the
-            fRXPat->fDataSize += 1;                    //  state stack ptr.
-            int32_t  stoOp     = URX_BUILD(URX_STO_SP, varLoc);
-            fRXPat->fCompiledPat->addElement(stoOp, *fStatus);
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
+            fixLiterals();
+            appendOp(URX_BUILD(URX_NOP, 0));
+            int32_t  varLoc = allocateData(1);    // Reserve a data location for saving the state stack ptr.
+            int32_t  stoOp = URX_BUILD(URX_STO_SP, varLoc);
+            appendOp(stoOp);
+            appendOp(URX_BUILD(URX_NOP, 0));
 
             // On the Parentheses stack, start a new frame and add the postions
             //   of the two NOPs.  Depending on what follows in the pattern, the
@@ -543,26 +555,26 @@ UBool RegexCompile::doParseActions(int32_t action)
         //
         //  Two data slots are reserved, for saving the stack ptr and the input position.
         {
-            int32_t dataLoc = fRXPat->fDataSize;
-            fRXPat->fDataSize += 2;
+            fixLiterals();
+            int32_t dataLoc = allocateData(2);
             int32_t op = URX_BUILD(URX_LA_START, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             op = URX_BUILD(URX_STATE_SAVE, fRXPat->fCompiledPat->size()+ 2);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             op = URX_BUILD(URX_JMP, fRXPat->fCompiledPat->size()+ 3);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
-            
+            appendOp(op);
+
             op = URX_BUILD(URX_LA_END, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             op = URX_BUILD(URX_BACKTRACK, 0);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
-            
+            appendOp(op);
+
             op = URX_BUILD(URX_NOP, 0);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
+            appendOp(op);
 
             // On the Parentheses stack, start a new frame and add the postions
             //   of the NOPs.
@@ -586,16 +598,16 @@ UBool RegexCompile::doParseActions(int32_t action)
         //    7.    END_LA                // Restore match region, in case look-ahead was using
         //                                        an alternate (transparent) region.
         {
-            int32_t dataLoc = fRXPat->fDataSize;
-            fRXPat->fDataSize += 2;
+            fixLiterals();
+            int32_t dataLoc = allocateData(2);
             int32_t op = URX_BUILD(URX_LA_START, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             op = URX_BUILD(URX_STATE_SAVE, 0);    // dest address will be patched later.
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             op = URX_BUILD(URX_NOP, 0);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // On the Parentheses stack, start a new frame and add the postions
             //   of the StateSave and NOP.
@@ -629,24 +641,26 @@ UBool RegexCompile::doParseActions(int32_t action)
             //              2:    Start index of match current match attempt.
             //              3:    Original Input String len.
 
+            // Generate match code for any pending literals.
+            fixLiterals();
+
             // Allocate data space
-            int32_t dataLoc = fRXPat->fDataSize;
-            fRXPat->fDataSize += 4;
+            int32_t dataLoc = allocateData(4);
 
             // Emit URX_LB_START
             int32_t op = URX_BUILD(URX_LB_START, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // Emit URX_LB_CONT
             op = URX_BUILD(URX_LB_CONT, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
-            fRXPat->fCompiledPat->addElement(0,  *fStatus);    // MinMatchLength.  To be filled later.
-            fRXPat->fCompiledPat->addElement(0,  *fStatus);    // MaxMatchLength.  To be filled later.
+            appendOp(op);
+            appendOp(0);    // MinMatchLength.  To be filled later.
+            appendOp(0);    // MaxMatchLength.  To be filled later.
 
             // Emit the NOP
             op = URX_BUILD(URX_NOP, 0);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
+            appendOp(op);
 
             // On the Parentheses stack, start a new frame and add the postions
             //   of the URX_LB_CONT and the NOP.
@@ -682,25 +696,27 @@ UBool RegexCompile::doParseActions(int32_t action)
             //              2:    Start index of match current match attempt.
             //              3:    Original Input String len.
 
+            // Generate match code for any pending literals.
+            fixLiterals();
+
             // Allocate data space
-            int32_t dataLoc = fRXPat->fDataSize;
-            fRXPat->fDataSize += 4;
+            int32_t dataLoc = allocateData(4);
 
             // Emit URX_LB_START
             int32_t op = URX_BUILD(URX_LB_START, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // Emit URX_LBN_CONT
             op = URX_BUILD(URX_LBN_CONT, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
-            fRXPat->fCompiledPat->addElement(0,  *fStatus);    // MinMatchLength.  To be filled later.
-            fRXPat->fCompiledPat->addElement(0,  *fStatus);    // MaxMatchLength.  To be filled later.
-            fRXPat->fCompiledPat->addElement(0,  *fStatus);    // Continue Loc.    To be filled later.
+            appendOp(op);
+            appendOp(0);    // MinMatchLength.  To be filled later.
+            appendOp(0);    // MaxMatchLength.  To be filled later.
+            appendOp(0);    // Continue Loc.    To be filled later.
 
             // Emit the NOP
             op = URX_BUILD(URX_NOP, 0);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
+            appendOp(op);
 
             // On the Parentheses stack, start a new frame and add the postions
             //   of the URX_LB_CONT and the NOP.
@@ -771,11 +787,10 @@ UBool RegexCompile::doParseActions(int32_t action)
                 if (URX_TYPE(repeatedOp) == URX_SETREF) {
                     // Emit optimized code for [char set]+
                     int32_t loopOpI = URX_BUILD(URX_LOOP_SR_I, URX_VAL(repeatedOp));
-                    fRXPat->fCompiledPat->addElement(loopOpI, *fStatus);
-                    frameLoc = fRXPat->fFrameSize;
-                    fRXPat->fFrameSize++;
+                    appendOp(loopOpI);
+                    frameLoc = allocateStackData(1);
                     int32_t loopOpC = URX_BUILD(URX_LOOP_C, frameLoc);
-                    fRXPat->fCompiledPat->addElement(loopOpC, *fStatus);
+                    appendOp(loopOpC);
                     break;
                 }
 
@@ -791,11 +806,10 @@ UBool RegexCompile::doParseActions(int32_t action)
                     if (fModeFlags & UREGEX_UNIX_LINES) {
                         loopOpI |= 2;
                     }
-                    fRXPat->fCompiledPat->addElement(loopOpI, *fStatus);
-                    frameLoc = fRXPat->fFrameSize;
-                    fRXPat->fFrameSize++;
+                    appendOp(loopOpI);
+                    frameLoc = allocateStackData(1);
                     int32_t loopOpC = URX_BUILD(URX_LOOP_C, frameLoc);
-                    fRXPat->fCompiledPat->addElement(loopOpC, *fStatus);
+                    appendOp(loopOpC);
                     break;
                 }
 
@@ -809,18 +823,17 @@ UBool RegexCompile::doParseActions(int32_t action)
                 // Zero length match is possible.
                 // Emit the code sequence that can handle it.
                 insertOp(topLoc);
-                frameLoc =  fRXPat->fFrameSize;
-                fRXPat->fFrameSize++;
+                frameLoc = allocateStackData(1);
 
                 int32_t op = URX_BUILD(URX_STO_INP_LOC, frameLoc);
                 fRXPat->fCompiledPat->setElementAt(op, topLoc);
 
                 op = URX_BUILD(URX_JMP_SAV_X, topLoc+1);
-                fRXPat->fCompiledPat->addElement(op, *fStatus);
+                appendOp(op);
             } else {
                 // Simpler code when the repeated body must match something non-empty
                 int32_t  jmpOp  = URX_BUILD(URX_JMP_SAV, topLoc);
-                fRXPat->fCompiledPat->addElement(jmpOp, *fStatus);
+                appendOp(jmpOp);
             }
         }
         break;
@@ -833,7 +846,7 @@ UBool RegexCompile::doParseActions(int32_t action)
         {
             int32_t topLoc      = blockTopLoc(FALSE);
             int32_t saveStateOp = URX_BUILD(URX_STATE_SAVE, topLoc);
-            fRXPat->fCompiledPat->addElement(saveStateOp, *fStatus);
+            appendOp(saveStateOp);
         }
         break;
 
@@ -870,10 +883,10 @@ UBool RegexCompile::doParseActions(int32_t action)
             fRXPat->fCompiledPat->setElementAt(jmp1_op, jmp1_loc);
 
             int32_t  jmp2_op  = URX_BUILD(URX_JMP, jmp2_loc+2);
-            fRXPat->fCompiledPat->addElement(jmp2_op, *fStatus);
+            appendOp(jmp2_op);
 
             int32_t  save_op  = URX_BUILD(URX_STATE_SAVE, jmp1_loc+1);
-            fRXPat->fCompiledPat->addElement(save_op, *fStatus);
+            appendOp(save_op);
         }
         break;
 
@@ -915,10 +928,9 @@ UBool RegexCompile::doParseActions(int32_t action)
                     // Emit optimized code for a [char set]*
                     int32_t loopOpI = URX_BUILD(URX_LOOP_SR_I, URX_VAL(repeatedOp));
                     fRXPat->fCompiledPat->setElementAt(loopOpI, topLoc);
-                    dataLoc = fRXPat->fFrameSize;
-                    fRXPat->fFrameSize++;
+                    dataLoc = allocateStackData(1);
                     int32_t loopOpC = URX_BUILD(URX_LOOP_C, dataLoc);
-                    fRXPat->fCompiledPat->addElement(loopOpC, *fStatus);
+                    appendOp(loopOpC);
                     break;
                 }
 
@@ -935,10 +947,9 @@ UBool RegexCompile::doParseActions(int32_t action)
                         loopOpI |= 2;
                     }
                     fRXPat->fCompiledPat->setElementAt(loopOpI, topLoc);
-                    dataLoc = fRXPat->fFrameSize;
-                    fRXPat->fFrameSize++;
+                    dataLoc = allocateStackData(1);
                     int32_t loopOpC = URX_BUILD(URX_LOOP_C, dataLoc);
-                    fRXPat->fCompiledPat->addElement(loopOpC, *fStatus);
+                    appendOp(loopOpC);
                     break;
                 }
             }
@@ -953,8 +964,7 @@ UBool RegexCompile::doParseActions(int32_t action)
             //    extra loop-breaking code.
             if (minMatchLength(saveStateLoc, fRXPat->fCompiledPat->size()-1) == 0) {
                 insertOp(saveStateLoc);
-                dataLoc =  fRXPat->fFrameSize;
-                fRXPat->fFrameSize++;
+                dataLoc = allocateStackData(1);
 
                 int32_t op = URX_BUILD(URX_STO_INP_LOC, dataLoc);
                 fRXPat->fCompiledPat->setElementAt(op, saveStateLoc+1);
@@ -970,7 +980,7 @@ UBool RegexCompile::doParseActions(int32_t action)
             fRXPat->fCompiledPat->setElementAt(saveStateOp, saveStateLoc);
 
             // Append the URX_JMP_SAV or URX_JMPX operation to the compiled pattern.
-            fRXPat->fCompiledPat->addElement(jmpOp, *fStatus);
+            appendOp(jmpOp);
         }
         break;
 
@@ -987,7 +997,7 @@ UBool RegexCompile::doParseActions(int32_t action)
             int32_t     jmpOp   = URX_BUILD(URX_JMP, saveLoc);
             int32_t     stateSaveOp = URX_BUILD(URX_STATE_SAVE, jmpLoc+1);
             fRXPat->fCompiledPat->setElementAt(jmpOp, jmpLoc);
-            fRXPat->fCompiledPat->addElement(stateSaveOp, *fStatus);
+            appendOp(stateSaveOp);
         }
         break;
 
@@ -1056,9 +1066,9 @@ UBool RegexCompile::doParseActions(int32_t action)
 
             // First the STO_SP before the start of the loop
             insertOp(topLoc);
-            int32_t  varLoc    = fRXPat->fDataSize;    // Reserve a data location for saving the
-            fRXPat->fDataSize += 1;                    //  state stack ptr.
-            int32_t  op        = URX_BUILD(URX_STO_SP, varLoc);
+
+            int32_t  varLoc = allocateData(1);   // Reserve a data location for saving the
+            int32_t  op     = URX_BUILD(URX_STO_SP, varLoc);
             fRXPat->fCompiledPat->setElementAt(op, topLoc);
 
             int32_t loopOp = (int32_t)fRXPat->fCompiledPat->popi();
@@ -1068,7 +1078,7 @@ UBool RegexCompile::doParseActions(int32_t action)
 
             // Then the LD_SP after the end of the loop
             op = URX_BUILD(URX_LD_SP, varLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
         }
 
         break;
@@ -1103,6 +1113,7 @@ UBool RegexCompile::doParseActions(int32_t action)
     case doDotAny:
         // scanned a ".",  match any single character.
         {
+            fixLiterals(FALSE);
             int32_t   op;
             if (fModeFlags & UREGEX_DOTALL) {
                 op = URX_BUILD(URX_DOTANY_ALL, 0);
@@ -1111,12 +1122,13 @@ UBool RegexCompile::doParseActions(int32_t action)
             } else {
                 op = URX_BUILD(URX_DOTANY, 0);
             }
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
         }
         break;
 
     case doCaret:
         {
+            fixLiterals(FALSE);
             int32_t op = 0;
             if (       (fModeFlags & UREGEX_MULTILINE) == 0 && (fModeFlags & UREGEX_UNIX_LINES) == 0) {
                 op = URX_CARET;
@@ -1127,12 +1139,13 @@ UBool RegexCompile::doParseActions(int32_t action)
             } else if ((fModeFlags & UREGEX_MULTILINE) != 0 && (fModeFlags & UREGEX_UNIX_LINES) != 0) {
                 op = URX_CARET_M_UNIX;
             }
-            fRXPat->fCompiledPat->addElement(URX_BUILD(op, 0), *fStatus);
+            appendOp(URX_BUILD(op, 0));
         }
         break;
 
     case doDollar:
         {
+            fixLiterals(FALSE);
             int32_t op = 0;
             if (       (fModeFlags & UREGEX_MULTILINE) == 0 && (fModeFlags & UREGEX_UNIX_LINES) == 0) {
                 op = URX_DOLLAR;
@@ -1143,12 +1156,13 @@ UBool RegexCompile::doParseActions(int32_t action)
             } else if ((fModeFlags & UREGEX_MULTILINE) != 0 && (fModeFlags & UREGEX_UNIX_LINES) != 0) {
                 op = URX_DOLLAR_MD;
             }
-            fRXPat->fCompiledPat->addElement(URX_BUILD(op, 0), *fStatus);
+            appendOp(URX_BUILD(op, 0));
         }
         break;
 
     case doBackslashA:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_CARET, 0), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_CARET, 0));
         break;
 
     case doBackslashB:
@@ -1158,8 +1172,9 @@ UBool RegexCompile::doParseActions(int32_t action)
                 error(U_UNSUPPORTED_ERROR);
             }
             #endif
+            fixLiterals(FALSE);
             int32_t op = (fModeFlags & UREGEX_UWORD)? URX_BACKSLASH_BU : URX_BACKSLASH_B;
-            fRXPat->fCompiledPat->addElement(URX_BUILD(op, 1), *fStatus);
+            appendOp(URX_BUILD(op, 1));
         }
         break;
 
@@ -1170,54 +1185,61 @@ UBool RegexCompile::doParseActions(int32_t action)
                 error(U_UNSUPPORTED_ERROR);
             }
             #endif
+            fixLiterals(FALSE);
             int32_t op = (fModeFlags & UREGEX_UWORD)? URX_BACKSLASH_BU : URX_BACKSLASH_B;
-            fRXPat->fCompiledPat->addElement(URX_BUILD(op, 0), *fStatus);
+            appendOp(URX_BUILD(op, 0));
         }
         break;
 
     case doBackslashD:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_D, 1), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_BACKSLASH_D, 1));
         break;
 
     case doBackslashd:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_D, 0), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_BACKSLASH_D, 0));
         break;
 
     case doBackslashG:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_G, 0), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_BACKSLASH_G, 0));
         break;
 
     case doBackslashS:
-        fRXPat->fCompiledPat->addElement(
-            URX_BUILD(URX_STAT_SETREF_N, URX_ISSPACE_SET), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_STAT_SETREF_N, URX_ISSPACE_SET));
         break;
 
     case doBackslashs:
-        fRXPat->fCompiledPat->addElement(
-            URX_BUILD(URX_STATIC_SETREF, URX_ISSPACE_SET), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_STATIC_SETREF, URX_ISSPACE_SET));
         break;
 
     case doBackslashW:
-        fRXPat->fCompiledPat->addElement(
-            URX_BUILD(URX_STAT_SETREF_N, URX_ISWORD_SET), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_STAT_SETREF_N, URX_ISWORD_SET));
         break;
 
     case doBackslashw:
-        fRXPat->fCompiledPat->addElement(
-            URX_BUILD(URX_STATIC_SETREF, URX_ISWORD_SET), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_STATIC_SETREF, URX_ISWORD_SET));
         break;
 
     case doBackslashX:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_X, 0), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_BACKSLASH_X, 0));
         break;
 
 
     case doBackslashZ:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_DOLLAR, 0), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_DOLLAR, 0));
         break;
 
     case doBackslashz:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_Z, 0), *fStatus);
+        fixLiterals(FALSE);
+        appendOp(URX_BUILD(URX_BACKSLASH_Z, 0));
         break;
 
     case doEscapeError:
@@ -1225,11 +1247,13 @@ UBool RegexCompile::doParseActions(int32_t action)
         break;
 
     case doExit:
+        fixLiterals(FALSE);
         returnVal = FALSE;
         break;
 
     case doProperty:
         {
+            fixLiterals(FALSE);
             UnicodeSet *theSet = scanProp();
             compileSet(theSet);
         }
@@ -1272,14 +1296,16 @@ UBool RegexCompile::doParseActions(int32_t action)
             // Because capture groups can be forward-referenced by back-references,
             //  we fill the operand with the capture group number.  At the end
             //  of compilation, it will be changed to the variable's location.
-            U_ASSERT(groupNum > 0);
+            U_ASSERT(groupNum > 0);  // Shouldn't happen.  '\0' begins an octal escape sequence,
+                                     //    and shouldn't enter this code path at all.
+            fixLiterals(FALSE);
             int32_t  op;
             if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
                 op = URX_BUILD(URX_BACKREF_I, groupNum);
             } else {
                 op = URX_BUILD(URX_BACKREF, groupNum);
             }
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
         }
         break;
 
@@ -1300,22 +1326,21 @@ UBool RegexCompile::doParseActions(int32_t action)
         {
             // Emit the STO_SP
             int32_t   topLoc = blockTopLoc(TRUE);
-            int32_t   stoLoc = fRXPat->fDataSize;
-            fRXPat->fDataSize++;       // Reserve the data location for storing save stack ptr.
+            int32_t   stoLoc = allocateData(1);  // Reserve the data location for storing save stack ptr.
             int32_t   op     = URX_BUILD(URX_STO_SP, stoLoc);
             fRXPat->fCompiledPat->setElementAt(op, topLoc);
 
             // Emit the STATE_SAVE
             op = URX_BUILD(URX_STATE_SAVE, fRXPat->fCompiledPat->size()+2);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // Emit the JMP
             op = URX_BUILD(URX_JMP, topLoc+1);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // Emit the LD_SP
             op = URX_BUILD(URX_LD_SP, stoLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
         }
         break;
 
@@ -1335,8 +1360,7 @@ UBool RegexCompile::doParseActions(int32_t action)
             insertOp(topLoc);
 
             // emit   STO_SP     loc
-            int32_t   stoLoc = fRXPat->fDataSize;
-            fRXPat->fDataSize++;       // Reserve the data location for storing save stack ptr.
+            int32_t   stoLoc = allocateData(1);    // Reserve the data location for storing save stack ptr.
             int32_t   op     = URX_BUILD(URX_STO_SP, stoLoc);
             fRXPat->fCompiledPat->setElementAt(op, topLoc);
 
@@ -1347,11 +1371,11 @@ UBool RegexCompile::doParseActions(int32_t action)
 
             // Append the JMP operation.
             op = URX_BUILD(URX_JMP, topLoc+1);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // Emit the LD_SP       loc
             op = URX_BUILD(URX_LD_SP, stoLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
         }
         break;
 
@@ -1370,8 +1394,7 @@ UBool RegexCompile::doParseActions(int32_t action)
             insertOp(topLoc);
 
             // Emit the STO_SP
-            int32_t   stoLoc = fRXPat->fDataSize;
-            fRXPat->fDataSize++;       // Reserve the data location for storing save stack ptr.
+            int32_t   stoLoc = allocateData(1);   // Reserve the data location for storing save stack ptr.
             int32_t   op     = URX_BUILD(URX_STO_SP, stoLoc);
             fRXPat->fCompiledPat->setElementAt(op, topLoc);
 
@@ -1382,7 +1405,7 @@ UBool RegexCompile::doParseActions(int32_t action)
 
             // Emit the LD_SP
             op = URX_BUILD(URX_LD_SP, stoLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
         }
         break;
 
@@ -1417,14 +1440,14 @@ UBool RegexCompile::doParseActions(int32_t action)
         break;
 
     case doSetMatchMode:
+        // Emit code to match any pending literals, using the not-yet changed match mode.
+        fixLiterals();
+
         // We've got a (?i) or similar.  The match mode is being changed, but
         //   the change is not scoped to a parenthesized block.
         U_ASSERT(fNewModeFlags < 0);
         fModeFlags = fNewModeFlags;
 
-        // Prevent any string from spanning across the change of match mode.
-        //   Otherwise the pattern "abc(?i)def" would make a single string of "abcdef"
-        fixLiterals();
         break;
 
 
@@ -1438,8 +1461,9 @@ UBool RegexCompile::doParseActions(int32_t action)
         //      - NOP, which may later be replaced by a save-state if there
         //             is an '|' alternation within the parens.
         {
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
+            fixLiterals(FALSE);
+            appendOp(URX_BUILD(URX_NOP, 0));
+            appendOp(URX_BUILD(URX_NOP, 0));
 
             // On the Parentheses stack, start a new frame and add the postions
             //   of the two NOPs (a normal non-capturing () frame, except for the
@@ -1533,6 +1557,7 @@ UBool RegexCompile::doParseActions(int32_t action)
         }
 
     case doSetBegin:
+        fixLiterals(FALSE);
         fSetStack.push(new UnicodeSet(), *fStatus);
         fSetOpStack.push(setStart, *fStatus);
         if ((fModeFlags & UREGEX_CASE_INSENSITIVE) != 0) {
@@ -1734,7 +1759,6 @@ UBool RegexCompile::doParseActions(int32_t action)
         break;
         }
 
-
     default:
         U_ASSERT(FALSE);
         error(U_REGEX_INTERNAL_ERROR);
@@ -1756,111 +1780,18 @@ UBool RegexCompile::doParseActions(int32_t action)
 //                             or an escape sequence that reduces to a character.
 //                         Add it to the string containing all literal chars/strings from
 //                             the pattern.
-//                         If we are in a pattern string already, add the new char to it.
-//                         If we aren't in a pattern string, begin one now.
 //
 //------------------------------------------------------------------------------
 void RegexCompile::literalChar(UChar32 c)  {
-    int32_t           op;            // An operation in the compiled pattern.
-    int32_t           opType;
-    int32_t           patternLoc;   // A position in the compiled pattern.
-    int32_t           stringLen;
-
-
-    // If the last thing compiled into the pattern was not a literal char,
-    //   force this new literal char to begin a new string, and not append to the previous.
-    op     = (int32_t)fRXPat->fCompiledPat->lastElementi();
-    opType = URX_TYPE(op);
-    if (!(opType == URX_STRING_LEN || opType == URX_ONECHAR || opType == URX_ONECHAR_I)) {
-        fixLiterals();
-    }
-
-    if (fStringOpStart == -1) {
-        // First char of a string in the pattern.
-        // Emit a OneChar op into the compiled pattern.
-        emitONE_CHAR(c);
-        
-        // Mark that we might actually be starting a string here
-        fStringOpStart = fRXPat->fLiteralText.length();
-        return;
-    }
-
-    op     = (int32_t)fRXPat->fCompiledPat->lastElementi();
-    opType = URX_TYPE(op);
-    U_ASSERT(opType == URX_ONECHAR || opType == URX_ONECHAR_I || opType == URX_STRING_LEN);
-
-    // If the most recently emitted op is a URX_ONECHAR,
-    if (opType == URX_ONECHAR || opType == URX_ONECHAR_I) {
-        if (U16_IS_TRAIL(c) && U16_IS_LEAD(URX_VAL(op))) {
-            // The most recently emitted op is a ONECHAR that was the first half
-            //   of a surrogate pair.  Update the ONECHAR's operand to be the
-            //   supplementary code point resulting from both halves of the pair.
-            c = U16_GET_SUPPLEMENTARY(URX_VAL(op), c);
-            op = URX_BUILD(opType, c);
-            patternLoc = fRXPat->fCompiledPat->size() - 1;
-            fRXPat->fCompiledPat->setElementAt(op, patternLoc);
-            return;
-        }
-        
-        // The most recently emitted op is a ONECHAR.
-        //  We've now received another adjacent char.  Change the ONECHAR op
-        //   to a string op.
-        fRXPat->fLiteralText.append(URX_VAL(op));
-
-        if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
-            op     = URX_BUILD(URX_STRING_I, fStringOpStart);
-        } else {
-            op     = URX_BUILD(URX_STRING, fStringOpStart);
-        }
-        patternLoc = fRXPat->fCompiledPat->size() - 1;
-        fRXPat->fCompiledPat->setElementAt(op, patternLoc);
-        op         = URX_BUILD(URX_STRING_LEN, 0);
-        fRXPat->fCompiledPat->addElement(op, *fStatus);
-    }
-    
-    // We are adding onto an existing string
-    fRXPat->fLiteralText.append(c);
-    
-    // The pattern contains a URX_SRING / URX_STRING_LEN.  Update the
-    //  string length to reflect the new char we just added to the string.
-    stringLen  = fRXPat->fLiteralText.length() - fStringOpStart;
-    op         = URX_BUILD(URX_STRING_LEN, stringLen);
-    patternLoc = fRXPat->fCompiledPat->size() - 1;
-    fRXPat->fCompiledPat->setElementAt(op, patternLoc);
-}
-
-
-
-//------------------------------------------------------------------------------
-//
-//    emitONE_CHAR         emit a ONE_CHAR op into the generated code.
-//                         Choose cased or uncased version, depending on the
-//                         match mode and whether the character itself is cased.
-//
-//------------------------------------------------------------------------------
-void RegexCompile::emitONE_CHAR(UChar32  c) {
-    int32_t op;
-    if ((fModeFlags & UREGEX_CASE_INSENSITIVE) &&
-        u_hasBinaryProperty(c, UCHAR_CASE_SENSITIVE)) {
-        // We have a cased character, and are in case insensitive matching mode.
-        //c  = u_foldCase(c, U_FOLD_CASE_DEFAULT);  // !!!: handled in stripNOPs() now
-        op = URX_BUILD(URX_ONECHAR_I, c);
-    } else {
-        // Uncased char, or case sensitive match mode.
-        //  Either way, just generate a literal compare of the char.
-        op = URX_BUILD(URX_ONECHAR, c);
-    }
-    fRXPat->fCompiledPat->addElement(op, *fStatus);
+    fLiteralChars.append(c);
 }
 
 
 //------------------------------------------------------------------------------
 //
 //    fixLiterals           When compiling something that can follow a literal
-//                          string in a pattern, we need to "fix" any preceding
-//                          string, which will cause any subsequent literals to
-//                          begin a new string, rather than appending to the
-//                          old one.
+//                          string in a pattern, emit the code to match the
+//                          accumulated literal string.
 //
 //                          Optionally, split the last char of the string off into
 //                          a single "ONE_CHAR" operation, so that quantifiers can
@@ -1869,68 +1800,92 @@ void RegexCompile::emitONE_CHAR(UChar32  c) {
 //
 //------------------------------------------------------------------------------
 void    RegexCompile::fixLiterals(UBool split) {
-    int32_t  stringStart = fStringOpStart;    // start index of the current literal string
-    int32_t  op;                              // An op from/for the compiled pattern.
-    int32_t  opType;                          // An opcode type from the compiled pattern.
-    int32_t  stringLastCharIdx;
-    UChar32  lastChar;
-    int32_t  stringNextToLastCharIdx;
-    UChar32  nextToLastChar;
-    int32_t  stringLen;
-
-    fStringOpStart = -1;
-    if (!split) {
+    int32_t  op = 0;                       // An op from/for the compiled pattern.
+
+    // If no literal characters have been scanned but not yet had code generated
+    //   for them, nothing needs to be done.
+    if (fLiteralChars.length() == 0) {
         return;
     }
 
-    // Split:  We need to  ensure that the last item in the compiled pattern does
-    //   not refer to a literal string of more than one char.  If it does,
-    //   separate the last char from the rest of the string.
+    int32_t indexOfLastCodePoint = fLiteralChars.moveIndex32(fLiteralChars.length(), -1);
+    UChar32 lastCodePoint = fLiteralChars.char32At(indexOfLastCodePoint);
+
+    // Split:  We need to  ensure that the last item in the compiled pattern 
+    //     refers only to the last literal scanned in the pattern, so that
+    //     quantifiers (*, +, etc.) affect only it, and not a longer string.
+    //     Split before case folding for case insensitive matches.
 
-    // If the last operation from the compiled pattern is not a string,
-    //   nothing needs to be done
-    op     = (int32_t)fRXPat->fCompiledPat->lastElementi();
-    opType = URX_TYPE(op);
-    if (opType != URX_STRING_LEN) {
+    if (split) {
+        fLiteralChars.truncate(indexOfLastCodePoint);
+        fixLiterals(FALSE);   // Recursive call, emit code to match the first part of the string.
+                              //  Note that the truncated literal string may be empty, in which case
+                              //  nothing will be emitted.
+
+        literalChar(lastCodePoint);  // Re-add the last code point as if it were a new literal.
+        fixLiterals(FALSE);          // Second recursive call, code for the final code point.
         return;
     }
-    stringLen = URX_VAL(op);
 
-    //
-    // Find the position of the last code point in the string  (might be a surrogate pair)
-    //
-    stringLastCharIdx = fRXPat->fLiteralText.length();
-    stringLastCharIdx = fRXPat->fLiteralText.moveIndex32(stringLastCharIdx, -1);
-    lastChar          = fRXPat->fLiteralText.char32At(stringLastCharIdx);
-
-    // The string should always be at least two code points long, meaning that there
-    //   should be something before the last char position that we just found.
-    U_ASSERT(stringLastCharIdx > stringStart);
-    stringNextToLastCharIdx = fRXPat->fLiteralText.moveIndex32(stringLastCharIdx, -1);
-    U_ASSERT(stringNextToLastCharIdx >= stringStart);
-    nextToLastChar          = fRXPat->fLiteralText.char32At(stringNextToLastCharIdx);
-
-    if (stringNextToLastCharIdx > stringStart) {
-        // The length of string remaining after removing one char is two or more.
-        // Leave the string in the compiled pattern, shorten it by one char,
-        //   and append a URX_ONECHAR op for the last char.
-        stringLen -= (fRXPat->fLiteralText.length() - stringLastCharIdx);
-        op = URX_BUILD(URX_STRING_LEN, stringLen);
-        fRXPat->fCompiledPat->setElementAt(op, fRXPat->fCompiledPat->size() -1);
-        emitONE_CHAR(lastChar);
-    } else {
-        // The original string consisted of exactly two characters.  Replace
-        // the existing compiled URX_STRING/URX_STRING_LEN ops with a pair
-        // of URX_ONECHARs.
-        fRXPat->fCompiledPat->setSize(fRXPat->fCompiledPat->size() -2);
-        emitONE_CHAR(nextToLastChar);
-        emitONE_CHAR(lastChar);
+    // If we are doing case-insensitive matching, case fold the string.  This may expand
+    //   the string, e.g. the German sharp-s turns into "ss"
+    if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
+        fLiteralChars.foldCase();
+        indexOfLastCodePoint = fLiteralChars.moveIndex32(fLiteralChars.length(), -1);
+        lastCodePoint = fLiteralChars.char32At(indexOfLastCodePoint);
     }
-}
 
+    if (indexOfLastCodePoint == 0) {
+        // Single character, emit a URX_ONECHAR op to match it.
+        if ((fModeFlags & UREGEX_CASE_INSENSITIVE) && 
+                 u_hasBinaryProperty(lastCodePoint, UCHAR_CASE_SENSITIVE)) {
+            op = URX_BUILD(URX_ONECHAR_I, lastCodePoint);
+        } else {
+            op = URX_BUILD(URX_ONECHAR, lastCodePoint);
+        }
+        appendOp(op);
+    } else {
+        // Two or more chars, emit a URX_STRING to match them.
+        if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
+            op = URX_BUILD(URX_STRING_I, fRXPat->fLiteralText.length());
+        } else {
+            // TODO here:  add optimization to split case sensitive strings of length two
+            //             into two single char ops, for efficiency.
+            op = URX_BUILD(URX_STRING, fRXPat->fLiteralText.length());
+        }
+        appendOp(op);
+        op = URX_BUILD(URX_STRING_LEN, fLiteralChars.length());
+        appendOp(op);
+
+        // Add this string into the accumulated strings of the compiled pattern.
+        // The total size of the accumulated strings must be restricted to 24 bits because
+        // string indexes appear as compiled pattern operand values.
+        // This is the only place that the pattern.fLiteralText string is modified.
+
+        fRXPat->fLiteralText.append(fLiteralChars);
+        if (U_SUCCESS(*fStatus) && fRXPat->fLiteralText.length() > 0x00ffffff) {
+            *fStatus = U_REGEX_PATTERN_TOO_BIG;
+        }
+    }
 
+    fLiteralChars.remove();
+}
 
 
+//------------------------------------------------------------------------------
+//
+//   appendOp()             Append a new instruction onto the compiled pattern
+//                          Includes error checking, limiting the size of the
+//                          pattern to lengths that can be represented in the
+//                          24 bit operand field of an instruction.
+//
+//------------------------------------------------------------------------------
+void RegexCompile::appendOp(int32_t op) {
+    fRXPat->fCompiledPat->addElement(op, *fStatus);
+    if ((fRXPat->fCompiledPat->size() > 0x00fffff0) && U_SUCCESS(*fStatus)) {
+        *fStatus = U_REGEX_PATTERN_TOO_BIG;
+    }
+}
 
 
 //------------------------------------------------------------------------------
@@ -1992,6 +1947,58 @@ void   RegexCompile::insertOp(int32_t where) {
 }
 
 
+//------------------------------------------------------------------------------
+//
+//   allocateData()        Allocate storage in the matcher's static data area.
+//                         Return the index for the newly allocated data.
+//                         The storage won't actually exist until we are running a match
+//                         operation, but the storage indexes are inserted into various
+//                         opcodes while compiling the pattern.
+//
+//------------------------------------------------------------------------------
+int32_t RegexCompile::allocateData(int32_t size) {
+    if (U_FAILURE(*fStatus)) {
+        return 0;
+    }
+    if (size <= 0 || size > 0x100 || fRXPat->fDataSize < 0) {
+        *fStatus = U_REGEX_INTERNAL_ERROR;
+        return 0;
+    }
+    int32_t dataIndex = fRXPat->fDataSize;
+    fRXPat->fDataSize += size;
+    if (fRXPat->fDataSize >= 0x00fffff0) {
+        *fStatus = U_REGEX_PATTERN_TOO_BIG;
+    }
+    return dataIndex;
+}
+
+
+//------------------------------------------------------------------------------
+//
+//   allocateStackData()   Allocate space in the back-tracking stack frame.
+//                         Return the index for the newly allocated data.
+//                         The frame indexes are inserted into various
+//                         opcodes while compiling the pattern, meaning that frame
+//                         size must be restricted to the size that will fit
+//                         as an operand (24 bits).
+//
+//------------------------------------------------------------------------------
+int32_t RegexCompile::allocateStackData(int32_t size) {
+    if (U_FAILURE(*fStatus)) {
+        return 0;
+    }
+    if (size <= 0 || size > 0x100 || fRXPat->fFrameSize < 0) {
+        *fStatus = U_REGEX_INTERNAL_ERROR;
+        return 0;
+    }
+    int32_t dataIndex = fRXPat->fFrameSize;
+    fRXPat->fFrameSize += size;
+    if (fRXPat->fFrameSize >= 0x00fffff0) {
+        *fStatus = U_REGEX_PATTERN_TOO_BIG;
+    }
+    return dataIndex;
+}
+
 
 //------------------------------------------------------------------------------
 //
@@ -2013,6 +2020,8 @@ void   RegexCompile::insertOp(int32_t where) {
 //------------------------------------------------------------------------------
 int32_t   RegexCompile::blockTopLoc(UBool reserveLoc) {
     int32_t   theLoc;
+    fixLiterals(TRUE);  // Emit code for any pending literals.
+                        //   If last item was a string, emit separate op for the its last char.
     if (fRXPat->fCompiledPat->size() == fMatchCloseParen)
     {
         // The item just processed is a parenthesized block.
@@ -2021,13 +2030,17 @@ int32_t   RegexCompile::blockTopLoc(UBool reserveLoc) {
         U_ASSERT(URX_TYPE(((uint32_t)fRXPat->fCompiledPat->elementAti(theLoc))) == URX_NOP);
     }
     else {
-        // Item just compiled is a single thing, a ".", or a single char, or a set reference.
+        // Item just compiled is a single thing, a ".", or a single char, a string or a set reference.
         // No slot for STATE_SAVE was pre-reserved in the compiled code.
         // We need to make space now.
-        fixLiterals(TRUE);  // If last item was a string, separate the last char.
         theLoc = fRXPat->fCompiledPat->size()-1;
+        int32_t opAtTheLoc = (int32_t)fRXPat->fCompiledPat->elementAti(theLoc);
+        if (URX_TYPE(opAtTheLoc) == URX_STRING_LEN) {
+            // Strings take two opcode, we want the position of the first one.
+            // We can have a string at this point if a single character case-folded to two.
+            theLoc--;
+        }
         if (reserveLoc) {
-            /*int32_t opAtTheLoc = fRXPat->fCompiledPat->elementAti(theLoc);*/
             int32_t  nop = URX_BUILD(URX_NOP, 0);
             fRXPat->fCompiledPat->insertElementAt(nop, theLoc, *fStatus);
         }
@@ -2057,8 +2070,7 @@ void  RegexCompile::handleCloseParen() {
         return;
     }
 
-    // Force any literal chars that may follow the close paren to start a new string,
-    //   and not attach to any preceding it.
+    // Emit code for any pending literals.
     fixLiterals(FALSE);
 
     // Fixup any operations within the just-closed parenthesized group
@@ -2105,7 +2117,7 @@ void  RegexCompile::handleCloseParen() {
 
             int32_t   frameVarLocation = URX_VAL(captureOp);
             int32_t   endCaptureOp = URX_BUILD(URX_END_CAPTURE, frameVarLocation);
-            fRXPat->fCompiledPat->addElement(endCaptureOp, *fStatus);
+            appendOp(endCaptureOp);
         }
         break;
     case atomic:
@@ -2117,7 +2129,7 @@ void  RegexCompile::handleCloseParen() {
             U_ASSERT(URX_TYPE(stoOp) == URX_STO_SP);
             int32_t   stoLoc = URX_VAL(stoOp);
             int32_t   ldOp   = URX_BUILD(URX_LD_SP, stoLoc);
-            fRXPat->fCompiledPat->addElement(ldOp, *fStatus);
+            appendOp(ldOp);
         }
         break;
 
@@ -2127,7 +2139,7 @@ void  RegexCompile::handleCloseParen() {
             U_ASSERT(URX_TYPE(startOp) == URX_LA_START);
             int32_t dataLoc  = URX_VAL(startOp);
             int32_t op       = URX_BUILD(URX_LA_END, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
         }
         break;
 
@@ -2138,11 +2150,11 @@ void  RegexCompile::handleCloseParen() {
             U_ASSERT(URX_TYPE(startOp) == URX_LA_START);
             int32_t dataLoc  = URX_VAL(startOp);
             int32_t op       = URX_BUILD(URX_LA_END, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
             op               = URX_BUILD(URX_BACKTRACK, 0);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
             op               = URX_BUILD(URX_LA_END, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // Patch the URX_SAVE near the top of the block.
             // The destination of the SAVE is the final LA_END that was just added.
@@ -2163,9 +2175,9 @@ void  RegexCompile::handleCloseParen() {
             U_ASSERT(URX_TYPE(startOp) == URX_LB_START);
             int32_t dataLoc  = URX_VAL(startOp);
             int32_t op       = URX_BUILD(URX_LB_END, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
-                    op       = URX_BUILD(URX_LA_END, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
+            op = URX_BUILD(URX_LA_END, dataLoc);
+            appendOp(op);
 
             // Determine the min and max bounds for the length of the
             //  string that the pattern can match.
@@ -2173,6 +2185,10 @@ void  RegexCompile::handleCloseParen() {
             int32_t patEnd   = fRXPat->fCompiledPat->size() - 1;
             int32_t minML    = minMatchLength(fMatchOpenParen, patEnd);
             int32_t maxML    = maxMatchLength(fMatchOpenParen, patEnd);
+            if (URX_TYPE(maxML) != 0) {
+                error(U_REGEX_LOOK_BEHIND_LIMIT);
+                break;
+            }
             if (maxML == INT32_MAX) {
                 error(U_REGEX_LOOK_BEHIND_LIMIT);
                 break;
@@ -2198,7 +2214,7 @@ void  RegexCompile::handleCloseParen() {
             U_ASSERT(URX_TYPE(startOp) == URX_LB_START);
             int32_t dataLoc  = URX_VAL(startOp);
             int32_t op       = URX_BUILD(URX_LBN_END, dataLoc);
-            fRXPat->fCompiledPat->addElement(op, *fStatus);
+            appendOp(op);
 
             // Determine the min and max bounds for the length of the
             //  string that the pattern can match.
@@ -2206,6 +2222,10 @@ void  RegexCompile::handleCloseParen() {
             int32_t patEnd   = fRXPat->fCompiledPat->size() - 1;
             int32_t minML    = minMatchLength(fMatchOpenParen, patEnd);
             int32_t maxML    = maxMatchLength(fMatchOpenParen, patEnd);
+            if (URX_TYPE(maxML) != 0) {
+                error(U_REGEX_LOOK_BEHIND_LIMIT);
+                break;
+            }
             if (maxML == INT32_MAX) {
                 error(U_REGEX_LOOK_BEHIND_LIMIT);
                 break;
@@ -2260,7 +2280,7 @@ void        RegexCompile::compileSet(UnicodeSet *theSet)
     case 0:
         {
             // Set of no elements.   Always fails to match.
-            fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKTRACK, 0), *fStatus);
+            appendOp(URX_BUILD(URX_BACKTRACK, 0));
             delete theSet;
         }
         break;
@@ -2282,7 +2302,7 @@ void        RegexCompile::compileSet(UnicodeSet *theSet)
             int32_t setNumber = fRXPat->fSets->size();
             fRXPat->fSets->addElement(theSet, *fStatus);
             int32_t setOp = URX_BUILD(URX_SETREF, setNumber);
-            fRXPat->fCompiledPat->addElement(setOp, *fStatus);
+            appendOp(setOp);
         }
     }
 }
@@ -2294,6 +2314,8 @@ void        RegexCompile::compileSet(UnicodeSet *theSet)
 //                      Except for the specific opcodes used, the code is the same
 //                      for all three types (greedy, non-greedy, possessive) of
 //                      intervals.  The opcodes are supplied as parameters.
+//                      (There are two sets of opcodes - greedy & possessive use the
+//                      same ones, while non-greedy has it's own.)
 //
 //                      The code for interval loops has this form:
 //                         0  CTR_INIT   counter loc (in stack frame)
@@ -2315,9 +2337,12 @@ void        RegexCompile::compileInterval(int32_t InitOp,  int32_t LoopOp)
     insertOp(topOfBlock);
 
     // The operands for the CTR_INIT opcode include the index in the matcher data
-    //   of the counter.  Allocate it now.
-    int32_t   counterLoc = fRXPat->fFrameSize;
-    fRXPat->fFrameSize++;
+    //   of the counter.  Allocate it now. There are two data items
+    //        counterLoc   -->  Loop counter
+    //               +1    -->  Input index (for breaking non-progressing loops)
+    //                          (Only present if unbounded upper limit on loop)
+    int32_t   dataSize = fIntervalUpper < 0 ? 2 : 1;
+    int32_t   counterLoc = allocateStackData(dataSize);
 
     int32_t   op = URX_BUILD(InitOp, counterLoc);
     fRXPat->fCompiledPat->setElementAt(op, topOfBlock);
@@ -2337,7 +2362,7 @@ void        RegexCompile::compileInterval(int32_t InitOp,  int32_t LoopOp)
     // Apend the CTR_LOOP op.  The operand is the location of the CTR_INIT op.
     //   Goes at end of the block being looped over, so just append to the code so far.
     op = URX_BUILD(LoopOp, topOfBlock);
-    fRXPat->fCompiledPat->addElement(op, *fStatus);
+    appendOp(op);
 
     if ((fIntervalLow & 0xff000000) != 0 ||
         (fIntervalUpper > 0 && (fIntervalUpper & 0xff000000) != 0)) {
@@ -2361,7 +2386,15 @@ UBool RegexCompile::compileInlineInterval() {
     int32_t   topOfBlock = blockTopLoc(FALSE);
     if (fIntervalUpper == 0) {
         // Pathological case.  Attempt no matches, as if the block doesn't exist.
+        // Discard the generated code for the block.
+        // If the block included parens, discard the info pertaining to them as well.
         fRXPat->fCompiledPat->setSize(topOfBlock);
+        if (fMatchOpenParen >= topOfBlock) {
+            fMatchOpenParen = -1;
+        }
+        if (fMatchCloseParen >= topOfBlock) {
+            fMatchCloseParen = -1;
+        }
         return TRUE;
     }
 
@@ -2396,12 +2429,12 @@ UBool RegexCompile::compileInlineInterval() {
     int32_t i;
     for (i=1; i<fIntervalUpper; i++ ) {
         if (i == fIntervalLow) {
-            fRXPat->fCompiledPat->addElement(saveOp, *fStatus);
+            appendOp(saveOp);
         }
         if (i > fIntervalLow) {
-            fRXPat->fCompiledPat->addElement(saveOp, *fStatus);
+            appendOp(saveOp);
         }
-        fRXPat->fCompiledPat->addElement(op, *fStatus);
+        appendOp(op);
     }
     return TRUE;
 }
@@ -2598,11 +2631,17 @@ void   RegexCompile::matchStartType() {
             if (currentLen == 0) {
                 UChar32  c = URX_VAL(op);
                 if (u_hasBinaryProperty(c, UCHAR_CASE_SENSITIVE)) {
-                    // character may have distinct cased forms.  Add all of them
-                    //   to the set of possible starting match chars.
-                    UnicodeSet s(c, c);
-                    s.closeOver(USET_CASE_INSENSITIVE);
-                    fRXPat->fInitialChars->addAll(s);
+
+                    // Disable optimizations on first char of match.
+                    // TODO: Compute the set of chars that case fold to this char, or to
+                    //       a string that begins with this char.
+                    //       For simple case folding, this code worked:
+                    //   UnicodeSet s(c, c);
+                    //   s.closeOver(USET_CASE_INSENSITIVE);
+                    //   fRXPat->fInitialChars->addAll(s);
+
+                    fRXPat->fInitialChars->clear();
+                    fRXPat->fInitialChars->complement();
                 } else {
                     // Char has no case variants.  Just add it as-is to the
                     //   set of possible starting chars.
@@ -2726,7 +2765,13 @@ void   RegexCompile::matchStartType() {
                     int32_t stringStartIdx = URX_VAL(op);
                     UChar32  c = fRXPat->fLiteralText.char32At(stringStartIdx);
                     UnicodeSet s(c, c);
-                    s.closeOver(USET_CASE_INSENSITIVE);
+
+                    // TODO:  compute correct set of starting chars for full case folding.
+                    //        For the moment, say any char can start.
+                    // s.closeOver(USET_CASE_INSENSITIVE);
+                    s.clear();
+                    s.complement();
+
                     fRXPat->fInitialChars->addAll(s);
                     numInitialStrings += 2;  // Matching on an initial string not possible.
                 }
@@ -3033,7 +3078,6 @@ int32_t   RegexCompile::minMatchLength(int32_t start, int32_t end) {
 
 
         case URX_STRING:
-        case URX_STRING_I:
             {
                 loc++;
                 int32_t stringLenOp = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
@@ -3042,6 +3086,18 @@ int32_t   RegexCompile::minMatchLength(int32_t start, int32_t end) {
             break;
 
 
+        case URX_STRING_I:
+            {
+                loc++;
+                // TODO: with full case folding, matching input text may be shorter than
+                //       the string we have here.  More smarts could put some bounds on it.
+                //       Assume a min length of one for now.  A min length of zero causes
+                //        optimization failures for a pattern like "string"+
+                // currentLen += URX_VAL(stringLenOp);
+                currentLen += 1;
+            }
+            break;
+
         case URX_CTR_INIT:
         case URX_CTR_INIT_NG:
             {
@@ -3148,6 +3204,16 @@ int32_t   RegexCompile::minMatchLength(int32_t start, int32_t end) {
     return currentLen;
 }
 
+// Increment with overflow check.
+// val and delta will both be positive.
+
+static int32_t safeIncrement(int32_t val, int32_t delta) {
+    if (INT32_MAX - val > delta) {
+        return val + delta;
+    } else {
+        return INT32_MAX;
+    }
+}
 
 
 //------------------------------------------------------------------------------
@@ -3244,15 +3310,15 @@ int32_t   RegexCompile::maxMatchLength(int32_t start, int32_t end) {
         case URX_DOTANY_ALL:
         case URX_DOTANY:
         case URX_DOTANY_UNIX:
-            currentLen+=2;
+            currentLen = safeIncrement(currentLen, 2);
             break;
 
             // Single literal character.  Increase current max length by one or two,
             //       depending on whether the char is in the supplementary range.
         case URX_ONECHAR:
-            currentLen++;
+            currentLen = safeIncrement(currentLen, 1);
             if (URX_VAL(op) > 0x10000) {
-                currentLen++;
+                currentLen = safeIncrement(currentLen, 1);
             }
             break;
 
@@ -3305,25 +3371,83 @@ int32_t   RegexCompile::maxMatchLength(int32_t start, int32_t end) {
 
 
         case URX_STRING:
+            {
+                loc++;
+                int32_t stringLenOp = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
+                currentLen = safeIncrement(currentLen, URX_VAL(stringLenOp));
+                break;
+            }
+
         case URX_STRING_I:
+            // TODO:  This code assumes that any user string that matches will be no longer
+            //        than our compiled string, with case insensitive matching.
+            //        Our compiled string has been case-folded already.
+            //
+            //        Any matching user string will have no more code points than our
+            //        compiled (folded) string.  Folding may add code points, but
+            //        not remove them.
+            //
+            //        There is a potential problem if a supplemental code point 
+            //        case-folds to a BMP code point.  In this case our compiled string
+            //        could be shorter (in code units) than a matching user string.
+            //
+            //        At this time (Unicode 6.1) there are no such characters, and this case
+            //        is not being handled.  A test, intltest regex/Bug9283, will fail if
+            //        any problematic characters are added to Unicode.
+            //
+            //        If this happens, we can make a set of the BMP chars that the
+            //        troublesome supplementals fold to, scan our string, and bump the
+            //        currentLen one extra for each that is found.
+            //
             {
                 loc++;
                 int32_t stringLenOp = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
-                currentLen += URX_VAL(stringLenOp);
+                currentLen = safeIncrement(currentLen, URX_VAL(stringLenOp));
             }
             break;
 
-
         case URX_CTR_INIT:
         case URX_CTR_INIT_NG:
+            // For Loops, recursively call this function on the pattern for the loop body,
+            //   then multiply the result by the maximum loop count.
+            {
+                int32_t  loopEndLoc = URX_VAL(fRXPat->fCompiledPat->elementAti(loc+1));
+                if (loopEndLoc == loc+4) {
+                    // Loop has an empty body. No affect on max match length.
+                    // Continue processing with code after the loop end.
+                    loc = loopEndLoc;
+                    break;
+                }
+                
+                int32_t maxLoopCount = fRXPat->fCompiledPat->elementAti(loc+3);
+                if (maxLoopCount == -1) {
+                    // Unbounded Loop. No upper bound on match length.
+                    currentLen = INT32_MAX;
+                    break;
+                }
+
+                U_ASSERT(loopEndLoc >= loc+4);
+                int32_t  blockLen = maxMatchLength(loc+4, loopEndLoc-1);  // Recursive call.
+                if (blockLen == INT32_MAX) {
+                    currentLen = blockLen;
+                    break;
+                }
+                currentLen += blockLen * maxLoopCount;
+                loc = loopEndLoc;
+                break;
+            }
+
         case URX_CTR_LOOP:
         case URX_CTR_LOOP_NG:
+            // These opcodes will be skipped over by code for URX_CRT_INIT.
+            // We shouldn't encounter them here.
+            U_ASSERT(FALSE);
+            break;
+
         case URX_LOOP_SR_I:
         case URX_LOOP_DOT_I:
         case URX_LOOP_C:
             // For anything to do with loops, make the match length unbounded.
-            //   Note:  INIT instructions are multi-word.  Can ignore because
-            //          INT32_MAX length will stop the per-instruction loop.
             currentLen = INT32_MAX;
             break;
 
@@ -3391,10 +3515,6 @@ int32_t   RegexCompile::maxMatchLength(int32_t start, int32_t end) {
 //                back-reference fixup is also performed here (adjusting
 //                back-reference operands to point to the correct frame offsets).
 //
-//                In addition, case-insensitive character and string literals are
-//                now case-folded here, rather than when first parsed or at match
-//                time.
-//
 //------------------------------------------------------------------------------
 void RegexCompile::stripNOPs() {
 
@@ -3418,7 +3538,6 @@ void RegexCompile::stripNOPs() {
     }
     
     UnicodeString caseStringBuffer;
-    int32_t stringDelta = 0;
 
     // Make a second pass over the code, removing the NOPs by moving following
     //  code up, and patching operands that refer to code locations that
@@ -3452,45 +3571,6 @@ void RegexCompile::stripNOPs() {
                 break;
             }
 
-        case URX_ONECHAR_I:
-            {
-                UChar32 c = URX_VAL(op);
-                if (u_hasBinaryProperty(c, UCHAR_CASE_SENSITIVE)) {
-                    // We have a cased character to fold
-                    c  = u_foldCase(c, U_FOLD_CASE_DEFAULT);
-                    op = URX_BUILD(URX_ONECHAR_I, c);
-                }
-                
-                fRXPat->fCompiledPat->setElementAt(op, dst);
-                dst++;
-                break;
-            }
-        case URX_STRING_I:
-            {
-                op = URX_BUILD(URX_STRING_I, URX_VAL(op)+stringDelta);
-                
-                src++;
-                int32_t lengthOp = (int32_t)fRXPat->fCompiledPat->elementAti(src);
-                
-                caseStringBuffer.setTo(fRXPat->fLiteralText, URX_VAL(op), URX_VAL(lengthOp));
-                caseStringBuffer.foldCase(U_FOLD_CASE_DEFAULT);
-                
-                int32_t newLen = caseStringBuffer.length();
-                if (newLen <= URX_VAL(lengthOp)) {
-                    // don't shift if we don't have to, take the tiny memory hit of a smaller string
-                    fRXPat->fLiteralText.replace(URX_VAL(op), newLen, caseStringBuffer);
-                } else {
-                    // shift other strings over...at least UnicodeString handles this for us!
-                    fRXPat->fLiteralText.replace(URX_VAL(op), URX_VAL(lengthOp), caseStringBuffer);
-                    stringDelta += newLen - URX_VAL(lengthOp);
-                }
-                lengthOp = URX_BUILD(URX_STRING_LEN, newLen);
-                
-                fRXPat->fCompiledPat->setElementAt(op, dst);
-                fRXPat->fCompiledPat->setElementAt(lengthOp, dst+1);
-                dst += 2;
-                break;
-            }
         case URX_BACKREF:
         case URX_BACKREF_I:
             {
@@ -3507,14 +3587,12 @@ void RegexCompile::stripNOPs() {
                 fRXPat->fNeedsAltInput = TRUE;
                 break;
             }
-        case URX_STRING:
-            op = URX_BUILD(URX_STRING, URX_VAL(op)+stringDelta);
-            // continue
         case URX_RESERVED_OP:
         case URX_RESERVED_OP_N:
         case URX_BACKTRACK:
         case URX_END:
         case URX_ONECHAR:
+        case URX_STRING:
         case URX_STRING_LEN:
         case URX_START_CAPTURE:
         case URX_END_CAPTURE:
@@ -3540,6 +3618,8 @@ void RegexCompile::stripNOPs() {
         case URX_STO_INP_LOC:
         case URX_LA_START:
         case URX_LA_END:
+        case URX_ONECHAR_I:
+        case URX_STRING_I:
         case URX_DOLLAR_M:
         case URX_CARET_M:
         case URX_CARET_M_UNIX:
@@ -3620,10 +3700,10 @@ static const UChar      chDigit7    = 0x37;      // '9'
 static const UChar      chColon     = 0x3A;      // ':'
 static const UChar      chE         = 0x45;      // 'E'
 static const UChar      chQ         = 0x51;      // 'Q'
-static const UChar      chN         = 0x4E;      // 'N'
+//static const UChar      chN         = 0x4E;      // 'N'
 static const UChar      chP         = 0x50;      // 'P'
 static const UChar      chBackSlash = 0x5c;      // '\'  introduces a char escape
-static const UChar      chLBracket  = 0x5b;      // '['
+//static const UChar      chLBracket  = 0x5b;      // '['
 static const UChar      chRBracket  = 0x5d;      // ']'
 static const UChar      chUp        = 0x5e;      // '^'
 static const UChar      chLowerP    = 0x70;
@@ -3704,10 +3784,11 @@ void RegexCompile::nextChar(RegexPatternChar &c) {
 
     if (fQuoteMode) {
         c.fQuoted = TRUE;
-        if ((c.fChar==chBackSlash && peekCharLL()==chE) || c.fChar == (UChar32)-1) {
+        if ((c.fChar==chBackSlash && peekCharLL()==chE && ((fModeFlags & UREGEX_LITERAL) == 0)) || 
+            c.fChar == (UChar32)-1) {
             fQuoteMode = FALSE;  //  Exit quote mode,
-            nextCharLL();       // discard the E
-            nextChar(c);        // recurse to get the real next char
+            nextCharLL();        // discard the E
+            nextChar(c);         // recurse to get the real next char
         }
     }
     else if (fInBackslashQuote) {
@@ -3744,7 +3825,7 @@ void RegexCompile::nextChar(RegexPatternChar &c) {
                     }
                 }
                 // TODO:  check what Java & Perl do with non-ASCII white spaces.  Ticket 6061.
-                if (uprv_isRuleWhiteSpace(c.fChar) == FALSE) {
+                if (PatternProps::isWhiteSpace(c.fChar) == FALSE) {
                     break;
                 }
                 c.fChar = nextCharLL();