intl/icu/source/i18n/regexcmp.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 //
     2 //  file:  regexcmp.cpp
     3 //
     4 //  Copyright (C) 2002-2013 International Business Machines Corporation and others.
     5 //  All Rights Reserved.
     6 //
     7 //  This file contains the ICU regular expression compiler, which is responsible
     8 //  for processing a regular expression pattern into the compiled form that
     9 //  is used by the match finding engine.
    10 //
    12 #include "unicode/utypes.h"
    14 #if !UCONFIG_NO_REGULAR_EXPRESSIONS
    16 #include "unicode/ustring.h"
    17 #include "unicode/unistr.h"
    18 #include "unicode/uniset.h"
    19 #include "unicode/uchar.h"
    20 #include "unicode/uchriter.h"
    21 #include "unicode/parsepos.h"
    22 #include "unicode/parseerr.h"
    23 #include "unicode/regex.h"
    24 #include "unicode/utf.h"
    25 #include "unicode/utf16.h"
    26 #include "patternprops.h"
    27 #include "putilimp.h"
    28 #include "cmemory.h"
    29 #include "cstring.h"
    30 #include "uvectr32.h"
    31 #include "uvectr64.h"
    32 #include "uassert.h"
    33 #include "ucln_in.h"
    34 #include "uinvchar.h"
    36 #include "regeximp.h"
    37 #include "regexcst.h"   // Contains state table for the regex pattern parser.
    38                         //   generated by a Perl script.
    39 #include "regexcmp.h"
    40 #include "regexst.h"
    41 #include "regextxt.h"
    45 U_NAMESPACE_BEGIN
    48 //------------------------------------------------------------------------------
    49 //
    50 //  Constructor.
    51 //
    52 //------------------------------------------------------------------------------
    53 RegexCompile::RegexCompile(RegexPattern *rxp, UErrorCode &status) :
    54    fParenStack(status), fSetStack(status), fSetOpStack(status)
    55 {
    56     // Lazy init of all shared global sets (needed for init()'s empty text)
    57     RegexStaticSets::initGlobals(&status);
    59     fStatus           = &status;
    61     fRXPat            = rxp;
    62     fScanIndex        = 0;
    63     fLastChar         = -1;
    64     fPeekChar         = -1;
    65     fLineNum          = 1;
    66     fCharNum          = 0;
    67     fQuoteMode        = FALSE;
    68     fInBackslashQuote = FALSE;
    69     fModeFlags        = fRXPat->fFlags | 0x80000000;
    70     fEOLComments      = TRUE;
    72     fMatchOpenParen   = -1;
    73     fMatchCloseParen  = -1;
    75     if (U_SUCCESS(status) && U_FAILURE(rxp->fDeferredStatus)) {
    76         status = rxp->fDeferredStatus;
    77     }
    78 }
    80 static const UChar      chAmp       = 0x26;      // '&'
    81 static const UChar      chDash      = 0x2d;      // '-'
    84 //------------------------------------------------------------------------------
    85 //
    86 //  Destructor
    87 //
    88 //------------------------------------------------------------------------------
    89 RegexCompile::~RegexCompile() {
    90 }
    92 static inline void addCategory(UnicodeSet *set, int32_t value, UErrorCode& ec) {
    93     set->addAll(UnicodeSet().applyIntPropertyValue(UCHAR_GENERAL_CATEGORY_MASK, value, ec));
    94 }
    96 //------------------------------------------------------------------------------
    97 //
    98 //  Compile regex pattern.   The state machine for rexexp pattern parsing is here.
    99 //                           The state tables are hand-written in the file regexcst.txt,
   100 //                           and converted to the form used here by a perl
   101 //                           script regexcst.pl
   102 //
   103 //------------------------------------------------------------------------------
   104 void    RegexCompile::compile(
   105                          const UnicodeString &pat,   // Source pat to be compiled.
   106                          UParseError &pp,            // Error position info
   107                          UErrorCode &e)              // Error Code
   108 {
   109     fRXPat->fPatternString = new UnicodeString(pat);
   110     UText patternText = UTEXT_INITIALIZER;
   111     utext_openConstUnicodeString(&patternText, fRXPat->fPatternString, &e);
   113     if (U_SUCCESS(e)) {
   114         compile(&patternText, pp, e);
   115         utext_close(&patternText);
   116     }
   117 }
   119 //
   120 //   compile, UText mode
   121 //     All the work is actually done here.
   122 //
   123 void    RegexCompile::compile(
   124                          UText *pat,                 // Source pat to be compiled.
   125                          UParseError &pp,            // Error position info
   126                          UErrorCode &e)              // Error Code
   127 {
   128     fStatus             = &e;
   129     fParseErr           = &pp;
   130     fStackPtr           = 0;
   131     fStack[fStackPtr]   = 0;
   133     if (U_FAILURE(*fStatus)) {
   134         return;
   135     }
   137     // There should be no pattern stuff in the RegexPattern object.  They can not be reused.
   138     U_ASSERT(fRXPat->fPattern == NULL || utext_nativeLength(fRXPat->fPattern) == 0);
   140     // Prepare the RegexPattern object to receive the compiled pattern.
   141     fRXPat->fPattern        = utext_clone(fRXPat->fPattern, pat, FALSE, TRUE, fStatus);
   142     fRXPat->fStaticSets     = RegexStaticSets::gStaticSets->fPropSets;
   143     fRXPat->fStaticSets8    = RegexStaticSets::gStaticSets->fPropSets8;
   146     // Initialize the pattern scanning state machine
   147     fPatternLength = utext_nativeLength(pat);
   148     uint16_t                state = 1;
   149     const RegexTableEl      *tableEl;
   151     // UREGEX_LITERAL force entire pattern to be treated as a literal string.
   152     if (fModeFlags & UREGEX_LITERAL) {
   153         fQuoteMode = TRUE;
   154     }
   156     nextChar(fC);                        // Fetch the first char from the pattern string.
   158     //
   159     // Main loop for the regex pattern parsing state machine.
   160     //   Runs once per state transition.
   161     //   Each time through optionally performs, depending on the state table,
   162     //      - an advance to the the next pattern char
   163     //      - an action to be performed.
   164     //      - pushing or popping a state to/from the local state return stack.
   165     //   file regexcst.txt is the source for the state table.  The logic behind
   166     //     recongizing the pattern syntax is there, not here.
   167     //
   168     for (;;) {
   169         //  Bail out if anything has gone wrong.
   170         //  Regex pattern parsing stops on the first error encountered.
   171         if (U_FAILURE(*fStatus)) {
   172             break;
   173         }
   175         U_ASSERT(state != 0);
   177         // Find the state table element that matches the input char from the pattern, or the
   178         //    class of the input character.  Start with the first table row for this
   179         //    state, then linearly scan forward until we find a row that matches the
   180         //    character.  The last row for each state always matches all characters, so
   181         //    the search will stop there, if not before.
   182         //
   183         tableEl = &gRuleParseStateTable[state];
   184         REGEX_SCAN_DEBUG_PRINTF(("char, line, col = (\'%c\', %d, %d)    state=%s ",
   185             fC.fChar, fLineNum, fCharNum, RegexStateNames[state]));
   187         for (;;) {    // loop through table rows belonging to this state, looking for one
   188                       //   that matches the current input char.
   189             REGEX_SCAN_DEBUG_PRINTF(("."));
   190             if (tableEl->fCharClass < 127 && fC.fQuoted == FALSE &&   tableEl->fCharClass == fC.fChar) {
   191                 // Table row specified an individual character, not a set, and
   192                 //   the input character is not quoted, and
   193                 //   the input character matched it.
   194                 break;
   195             }
   196             if (tableEl->fCharClass == 255) {
   197                 // Table row specified default, match anything character class.
   198                 break;
   199             }
   200             if (tableEl->fCharClass == 254 && fC.fQuoted)  {
   201                 // Table row specified "quoted" and the char was quoted.
   202                 break;
   203             }
   204             if (tableEl->fCharClass == 253 && fC.fChar == (UChar32)-1)  {
   205                 // Table row specified eof and we hit eof on the input.
   206                 break;
   207             }
   209             if (tableEl->fCharClass >= 128 && tableEl->fCharClass < 240 &&   // Table specs a char class &&
   210                 fC.fQuoted == FALSE &&                                       //   char is not escaped &&
   211                 fC.fChar != (UChar32)-1) {                                   //   char is not EOF
   212                 U_ASSERT(tableEl->fCharClass <= 137);
   213                 if (RegexStaticSets::gStaticSets->fRuleSets[tableEl->fCharClass-128].contains(fC.fChar)) {
   214                     // Table row specified a character class, or set of characters,
   215                     //   and the current char matches it.
   216                     break;
   217                 }
   218             }
   220             // No match on this row, advance to the next  row for this state,
   221             tableEl++;
   222         }
   223         REGEX_SCAN_DEBUG_PRINTF(("\n"));
   225         //
   226         // We've found the row of the state table that matches the current input
   227         //   character from the rules string.
   228         // Perform any action specified  by this row in the state table.
   229         if (doParseActions(tableEl->fAction) == FALSE) {
   230             // Break out of the state machine loop if the
   231             //   the action signalled some kind of error, or
   232             //   the action was to exit, occurs on normal end-of-rules-input.
   233             break;
   234         }
   236         if (tableEl->fPushState != 0) {
   237             fStackPtr++;
   238             if (fStackPtr >= kStackSize) {
   239                 error(U_REGEX_INTERNAL_ERROR);
   240                 REGEX_SCAN_DEBUG_PRINTF(("RegexCompile::parse() - state stack overflow.\n"));
   241                 fStackPtr--;
   242             }
   243             fStack[fStackPtr] = tableEl->fPushState;
   244         }
   246         //
   247         //  NextChar.  This is where characters are actually fetched from the pattern.
   248         //             Happens under control of the 'n' tag in the state table.
   249         //
   250         if (tableEl->fNextChar) {
   251             nextChar(fC);
   252         }
   254         // Get the next state from the table entry, or from the
   255         //   state stack if the next state was specified as "pop".
   256         if (tableEl->fNextState != 255) {
   257             state = tableEl->fNextState;
   258         } else {
   259             state = fStack[fStackPtr];
   260             fStackPtr--;
   261             if (fStackPtr < 0) {
   262                 // state stack underflow
   263                 // This will occur if the user pattern has mis-matched parentheses,
   264                 //   with extra close parens.
   265                 //
   266                 fStackPtr++;
   267                 error(U_REGEX_MISMATCHED_PAREN);
   268             }
   269         }
   271     }
   273     if (U_FAILURE(*fStatus)) {
   274         // Bail out if the pattern had errors.
   275         //   Set stack cleanup:  a successful compile would have left it empty,
   276         //   but errors can leave temporary sets hanging around.
   277         while (!fSetStack.empty()) {
   278             delete (UnicodeSet *)fSetStack.pop();
   279         }
   280         return;
   281     }
   283     //
   284     // The pattern has now been read and processed, and the compiled code generated.
   285     //
   287     //
   288     // Compute the number of digits requried for the largest capture group number.
   289     //
   290     fRXPat->fMaxCaptureDigits = 1;
   291     int32_t  n = 10;
   292     int32_t  groupCount = fRXPat->fGroupMap->size();
   293     while (n <= groupCount) {
   294         fRXPat->fMaxCaptureDigits++;
   295         n *= 10;
   296     }
   298     //
   299     // The pattern's fFrameSize so far has accumulated the requirements for
   300     //   storage for capture parentheses, counters, etc. that are encountered
   301     //   in the pattern.  Add space for the two variables that are always
   302     //   present in the saved state:  the input string position (int64_t) and
   303     //   the position in the compiled pattern.
   304     //
   305     fRXPat->fFrameSize+=RESTACKFRAME_HDRCOUNT;
   307     //
   308     // Optimization pass 1: NOPs, back-references, and case-folding
   309     //
   310     stripNOPs();
   312     //
   313     // Get bounds for the minimum and maximum length of a string that this
   314     //   pattern can match.  Used to avoid looking for matches in strings that
   315     //   are too short.
   316     //
   317     fRXPat->fMinMatchLen = minMatchLength(3, fRXPat->fCompiledPat->size()-1);
   319     //
   320     // Optimization pass 2: match start type
   321     //
   322     matchStartType();
   324     //
   325     // Set up fast latin-1 range sets
   326     //
   327     int32_t numSets = fRXPat->fSets->size();
   328     fRXPat->fSets8 = new Regex8BitSet[numSets];
   329     // Null pointer check.
   330     if (fRXPat->fSets8 == NULL) {
   331         e = *fStatus = U_MEMORY_ALLOCATION_ERROR;
   332         return;
   333     }
   334     int32_t i;
   335     for (i=0; i<numSets; i++) {
   336         UnicodeSet *s = (UnicodeSet *)fRXPat->fSets->elementAt(i);
   337         fRXPat->fSets8[i].init(s);
   338     }
   340 }
   346 //------------------------------------------------------------------------------
   347 //
   348 //  doParseAction        Do some action during regex pattern parsing.
   349 //                       Called by the parse state machine.
   350 //
   351 //                       Generation of the match engine PCode happens here, or
   352 //                       in functions called from the parse actions defined here.
   353 //
   354 //
   355 //------------------------------------------------------------------------------
   356 UBool RegexCompile::doParseActions(int32_t action)
   357 {
   358     UBool   returnVal = TRUE;
   360     switch ((Regex_PatternParseAction)action) {
   362     case doPatStart:
   363         // Start of pattern compiles to:
   364         //0   SAVE   2        Fall back to position of FAIL
   365         //1   jmp    3
   366         //2   FAIL            Stop if we ever reach here.
   367         //3   NOP             Dummy, so start of pattern looks the same as
   368         //                    the start of an ( grouping.
   369         //4   NOP             Resreved, will be replaced by a save if there are
   370         //                    OR | operators at the top level
   371         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_STATE_SAVE, 2), *fStatus);
   372         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_JMP,  3), *fStatus);
   373         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_FAIL, 0), *fStatus);
   375         // Standard open nonCapture paren action emits the two NOPs and
   376         //   sets up the paren stack frame.
   377         doParseActions(doOpenNonCaptureParen);
   378         break;
   380     case doPatFinish:
   381         // We've scanned to the end of the pattern
   382         //  The end of pattern compiles to:
   383         //        URX_END
   384         //    which will stop the runtime match engine.
   385         //  Encountering end of pattern also behaves like a close paren,
   386         //   and forces fixups of the State Save at the beginning of the compiled pattern
   387         //   and of any OR operations at the top level.
   388         //
   389         handleCloseParen();
   390         if (fParenStack.size() > 0) {
   391             // Missing close paren in pattern.
   392             error(U_REGEX_MISMATCHED_PAREN);
   393         }
   395         // add the END operation to the compiled pattern.
   396         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_END, 0), *fStatus);
   398         // Terminate the pattern compilation state machine.
   399         returnVal = FALSE;
   400         break;
   404     case doOrOperator:
   405         // Scanning a '|', as in (A|B)
   406         {
   407             // Generate code for any pending literals preceding the '|'
   408             fixLiterals(FALSE);
   410             // Insert a SAVE operation at the start of the pattern section preceding
   411             //   this OR at this level.  This SAVE will branch the match forward
   412             //   to the right hand side of the OR in the event that the left hand
   413             //   side fails to match and backtracks.  Locate the position for the
   414             //   save from the location on the top of the parentheses stack.
   415             int32_t savePosition = fParenStack.popi();
   416             int32_t op = (int32_t)fRXPat->fCompiledPat->elementAti(savePosition);
   417             U_ASSERT(URX_TYPE(op) == URX_NOP);  // original contents of reserved location
   418             op = URX_BUILD(URX_STATE_SAVE, fRXPat->fCompiledPat->size()+1);
   419             fRXPat->fCompiledPat->setElementAt(op, savePosition);
   421             // Append an JMP operation into the compiled pattern.  The operand for
   422             //  the JMP will eventually be the location following the ')' for the
   423             //  group.  This will be patched in later, when the ')' is encountered.
   424             op = URX_BUILD(URX_JMP, 0);
   425             fRXPat->fCompiledPat->addElement(op, *fStatus);
   427             // Push the position of the newly added JMP op onto the parentheses stack.
   428             // This registers if for fixup when this block's close paren is encountered.
   429             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);
   431             // Append a NOP to the compiled pattern.  This is the slot reserved
   432             //   for a SAVE in the event that there is yet another '|' following
   433             //   this one.
   434             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
   435             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);
   436         }
   437         break;
   440     case doOpenCaptureParen:
   441         // Open Paren.
   442         //   Compile to a
   443         //      - NOP, which later may be replaced by a save-state if the
   444         //         parenthesized group gets a * quantifier, followed by
   445         //      - START_CAPTURE  n    where n is stack frame offset to the capture group variables.
   446         //      - NOP, which may later be replaced by a save-state if there
   447         //             is an '|' alternation within the parens.
   448         //
   449         //    Each capture group gets three slots in the save stack frame:
   450         //         0: Capture Group start position (in input string being matched.)
   451         //         1: Capture Group end position.
   452         //         2: Start of Match-in-progress.
   453         //    The first two locations are for a completed capture group, and are
   454         //     referred to by back references and the like.
   455         //    The third location stores the capture start position when an START_CAPTURE is
   456         //      encountered.  This will be promoted to a completed capture when (and if) the corresponding
   457         //      END_CAPTURE is encountered.
   458         {
   459             fixLiterals();
   460             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
   461             int32_t  varsLoc    = fRXPat->fFrameSize;    // Reserve three slots in match stack frame.
   462             fRXPat->fFrameSize += 3;
   463             int32_t  cop        = URX_BUILD(URX_START_CAPTURE, varsLoc);
   464             fRXPat->fCompiledPat->addElement(cop, *fStatus);
   465             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
   467             // On the Parentheses stack, start a new frame and add the postions
   468             //   of the two NOPs.  Depending on what follows in the pattern, the
   469             //   NOPs may be changed to SAVE_STATE or JMP ops, with a target
   470             //   address of the end of the parenthesized group.
   471             fParenStack.push(fModeFlags, *fStatus);                       // Match mode state
   472             fParenStack.push(capturing, *fStatus);                        // Frame type.
   473             fParenStack.push(fRXPat->fCompiledPat->size()-3, *fStatus);   // The first  NOP location
   474             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The second NOP loc
   476             // Save the mapping from group number to stack frame variable position.
   477             fRXPat->fGroupMap->addElement(varsLoc, *fStatus);
   478         }
   479          break;
   481     case doOpenNonCaptureParen:
   482         // Open non-caputuring (grouping only) Paren.
   483         //   Compile to a
   484         //      - NOP, which later may be replaced by a save-state if the
   485         //         parenthesized group gets a * quantifier, followed by
   486         //      - NOP, which may later be replaced by a save-state if there
   487         //             is an '|' alternation within the parens.
   488         {
   489             fixLiterals();
   490             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
   491             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
   493             // On the Parentheses stack, start a new frame and add the postions
   494             //   of the two NOPs.
   495             fParenStack.push(fModeFlags, *fStatus);                       // Match mode state
   496             fParenStack.push(plain,      *fStatus);                       // Begin a new frame.
   497             fParenStack.push(fRXPat->fCompiledPat->size()-2, *fStatus);   // The first  NOP location
   498             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The second NOP loc
   499         }
   500          break;
   503     case doOpenAtomicParen:
   504         // Open Atomic Paren.  (?>
   505         //   Compile to a
   506         //      - NOP, which later may be replaced if the parenthesized group
   507         //         has a quantifier, followed by
   508         //      - STO_SP  save state stack position, so it can be restored at the ")"
   509         //      - NOP, which may later be replaced by a save-state if there
   510         //             is an '|' alternation within the parens.
   511         {
   512             fixLiterals();
   513             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
   514             int32_t  varLoc    = fRXPat->fDataSize;    // Reserve a data location for saving the
   515             fRXPat->fDataSize += 1;                    //  state stack ptr.
   516             int32_t  stoOp     = URX_BUILD(URX_STO_SP, varLoc);
   517             fRXPat->fCompiledPat->addElement(stoOp, *fStatus);
   518             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
   520             // On the Parentheses stack, start a new frame and add the postions
   521             //   of the two NOPs.  Depending on what follows in the pattern, the
   522             //   NOPs may be changed to SAVE_STATE or JMP ops, with a target
   523             //   address of the end of the parenthesized group.
   524             fParenStack.push(fModeFlags, *fStatus);                       // Match mode state
   525             fParenStack.push(atomic, *fStatus);                           // Frame type.
   526             fParenStack.push(fRXPat->fCompiledPat->size()-3, *fStatus);   // The first NOP
   527             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The second NOP
   528         }
   529         break;
   532     case doOpenLookAhead:
   533         // Positive Look-ahead   (?=  stuff  )
   534         //
   535         //   Note:   Addition of transparent input regions, with the need to
   536         //           restore the original regions when failing out of a lookahead
   537         //           block, complicated this sequence.  Some conbined opcodes
   538         //           might make sense - or might not, lookahead aren't that common.
   539         //
   540         //      Caution:  min match length optimization knows about this
   541         //               sequence; don't change without making updates there too.
   542         //
   543         // Compiles to
   544         //    1    START_LA     dataLoc     Saves SP, Input Pos
   545         //    2.   STATE_SAVE   4            on failure of lookahead, goto 4
   546         //    3    JMP          6           continue ...
   547         //
   548         //    4.   LA_END                   Look Ahead failed.  Restore regions.
   549         //    5.   BACKTRACK                and back track again.
   550         //
   551         //    6.   NOP              reserved for use by quantifiers on the block.
   552         //                          Look-ahead can't have quantifiers, but paren stack
   553         //                             compile time conventions require the slot anyhow.
   554         //    7.   NOP              may be replaced if there is are '|' ops in the block.
   555         //    8.     code for parenthesized stuff.
   556         //    9.   LA_END
   557         //
   558         //  Two data slots are reserved, for saving the stack ptr and the input position.
   559         {
   560             fixLiterals();
   561             int32_t dataLoc = fRXPat->fDataSize;
   562             fRXPat->fDataSize += 2;
   563             int32_t op = URX_BUILD(URX_LA_START, dataLoc);
   564             fRXPat->fCompiledPat->addElement(op, *fStatus);
   566             op = URX_BUILD(URX_STATE_SAVE, fRXPat->fCompiledPat->size()+ 2);
   567             fRXPat->fCompiledPat->addElement(op, *fStatus);
   569             op = URX_BUILD(URX_JMP, fRXPat->fCompiledPat->size()+ 3);
   570             fRXPat->fCompiledPat->addElement(op, *fStatus);
   572             op = URX_BUILD(URX_LA_END, dataLoc);
   573             fRXPat->fCompiledPat->addElement(op, *fStatus);
   575             op = URX_BUILD(URX_BACKTRACK, 0);
   576             fRXPat->fCompiledPat->addElement(op, *fStatus);
   578             op = URX_BUILD(URX_NOP, 0);
   579             fRXPat->fCompiledPat->addElement(op, *fStatus);
   580             fRXPat->fCompiledPat->addElement(op, *fStatus);
   582             // On the Parentheses stack, start a new frame and add the postions
   583             //   of the NOPs.
   584             fParenStack.push(fModeFlags, *fStatus);                       // Match mode state
   585             fParenStack.push(lookAhead, *fStatus);                        // Frame type.
   586             fParenStack.push(fRXPat->fCompiledPat->size()-2, *fStatus);   // The first  NOP location
   587             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The second NOP location
   588         }
   589         break;
   591     case doOpenLookAheadNeg:
   592         // Negated Lookahead.   (?! stuff )
   593         // Compiles to
   594         //    1.    START_LA    dataloc
   595         //    2.    SAVE_STATE  7         // Fail within look-ahead block restores to this state,
   596         //                                //   which continues with the match.
   597         //    3.    NOP                   // Std. Open Paren sequence, for possible '|'
   598         //    4.       code for parenthesized stuff.
   599         //    5.    END_LA                // Cut back stack, remove saved state from step 2.
   600         //    6.    BACKTRACK             // code in block succeeded, so neg. lookahead fails.
   601         //    7.    END_LA                // Restore match region, in case look-ahead was using
   602         //                                        an alternate (transparent) region.
   603         {
   604             fixLiterals();
   605             int32_t dataLoc = fRXPat->fDataSize;
   606             fRXPat->fDataSize += 2;
   607             int32_t op = URX_BUILD(URX_LA_START, dataLoc);
   608             fRXPat->fCompiledPat->addElement(op, *fStatus);
   610             op = URX_BUILD(URX_STATE_SAVE, 0);    // dest address will be patched later.
   611             fRXPat->fCompiledPat->addElement(op, *fStatus);
   613             op = URX_BUILD(URX_NOP, 0);
   614             fRXPat->fCompiledPat->addElement(op, *fStatus);
   616             // On the Parentheses stack, start a new frame and add the postions
   617             //   of the StateSave and NOP.
   618             fParenStack.push(fModeFlags, *fStatus);                       // Match mode state
   619             fParenStack.push(negLookAhead, *fStatus);                    // Frame type
   620             fParenStack.push(fRXPat->fCompiledPat->size()-2, *fStatus);   // The STATE_SAVE location
   621             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The second NOP location
   623             // Instructions #5 - #7 will be added when the ')' is encountered.
   624         }
   625         break;
   627     case doOpenLookBehind:
   628         {
   629             //   Compile a (?<= look-behind open paren.
   630             //
   631             //          Compiles to
   632             //              0       URX_LB_START     dataLoc
   633             //              1       URX_LB_CONT      dataLoc
   634             //              2                        MinMatchLen
   635             //              3                        MaxMatchLen
   636             //              4       URX_NOP          Standard '(' boilerplate.
   637             //              5       URX_NOP          Reserved slot for use with '|' ops within (block).
   638             //              6         <code for LookBehind expression>
   639             //              7       URX_LB_END       dataLoc    # Check match len, restore input  len
   640             //              8       URX_LA_END       dataLoc    # Restore stack, input pos
   641             //
   642             //          Allocate a block of matcher data, to contain (when running a match)
   643             //              0:    Stack ptr on entry
   644             //              1:    Input Index on entry
   645             //              2:    Start index of match current match attempt.
   646             //              3:    Original Input String len.
   648             // Generate match code for any pending literals.
   649             fixLiterals();
   651             // Allocate data space
   652             int32_t dataLoc = fRXPat->fDataSize;
   653             fRXPat->fDataSize += 4;
   655             // Emit URX_LB_START
   656             int32_t op = URX_BUILD(URX_LB_START, dataLoc);
   657             fRXPat->fCompiledPat->addElement(op, *fStatus);
   659             // Emit URX_LB_CONT
   660             op = URX_BUILD(URX_LB_CONT, dataLoc);
   661             fRXPat->fCompiledPat->addElement(op, *fStatus);
   662             fRXPat->fCompiledPat->addElement(0,  *fStatus);    // MinMatchLength.  To be filled later.
   663             fRXPat->fCompiledPat->addElement(0,  *fStatus);    // MaxMatchLength.  To be filled later.
   665             // Emit the NOP
   666             op = URX_BUILD(URX_NOP, 0);
   667             fRXPat->fCompiledPat->addElement(op, *fStatus);
   668             fRXPat->fCompiledPat->addElement(op, *fStatus);
   670             // On the Parentheses stack, start a new frame and add the postions
   671             //   of the URX_LB_CONT and the NOP.
   672             fParenStack.push(fModeFlags, *fStatus);                       // Match mode state
   673             fParenStack.push(lookBehind, *fStatus);                       // Frame type
   674             fParenStack.push(fRXPat->fCompiledPat->size()-2, *fStatus);   // The first NOP location
   675             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The 2nd   NOP location
   677             // The final two instructions will be added when the ')' is encountered.
   678         }
   680         break;
   682     case doOpenLookBehindNeg:
   683         {
   684             //   Compile a (?<! negated look-behind open paren.
   685             //
   686             //          Compiles to
   687             //              0       URX_LB_START     dataLoc    # Save entry stack, input len
   688             //              1       URX_LBN_CONT     dataLoc    # Iterate possible match positions
   689             //              2                        MinMatchLen
   690             //              3                        MaxMatchLen
   691             //              4                        continueLoc (9)
   692             //              5       URX_NOP          Standard '(' boilerplate.
   693             //              6       URX_NOP          Reserved slot for use with '|' ops within (block).
   694             //              7         <code for LookBehind expression>
   695             //              8       URX_LBN_END      dataLoc    # Check match len, cause a FAIL
   696             //              9       ...
   697             //
   698             //          Allocate a block of matcher data, to contain (when running a match)
   699             //              0:    Stack ptr on entry
   700             //              1:    Input Index on entry
   701             //              2:    Start index of match current match attempt.
   702             //              3:    Original Input String len.
   704             // Generate match code for any pending literals.
   705             fixLiterals();
   707             // Allocate data space
   708             int32_t dataLoc = fRXPat->fDataSize;
   709             fRXPat->fDataSize += 4;
   711             // Emit URX_LB_START
   712             int32_t op = URX_BUILD(URX_LB_START, dataLoc);
   713             fRXPat->fCompiledPat->addElement(op, *fStatus);
   715             // Emit URX_LBN_CONT
   716             op = URX_BUILD(URX_LBN_CONT, dataLoc);
   717             fRXPat->fCompiledPat->addElement(op, *fStatus);
   718             fRXPat->fCompiledPat->addElement(0,  *fStatus);    // MinMatchLength.  To be filled later.
   719             fRXPat->fCompiledPat->addElement(0,  *fStatus);    // MaxMatchLength.  To be filled later.
   720             fRXPat->fCompiledPat->addElement(0,  *fStatus);    // Continue Loc.    To be filled later.
   722             // Emit the NOP
   723             op = URX_BUILD(URX_NOP, 0);
   724             fRXPat->fCompiledPat->addElement(op, *fStatus);
   725             fRXPat->fCompiledPat->addElement(op, *fStatus);
   727             // On the Parentheses stack, start a new frame and add the postions
   728             //   of the URX_LB_CONT and the NOP.
   729             fParenStack.push(fModeFlags, *fStatus);                       // Match mode state
   730             fParenStack.push(lookBehindN, *fStatus);                      // Frame type
   731             fParenStack.push(fRXPat->fCompiledPat->size()-2, *fStatus);   // The first NOP location
   732             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The 2nd   NOP location
   734             // The final two instructions will be added when the ')' is encountered.
   735         }
   736         break;
   738     case doConditionalExpr:
   739         // Conditionals such as (?(1)a:b)
   740     case doPerlInline:
   741         // Perl inline-condtionals.  (?{perl code}a|b) We're not perl, no way to do them.
   742         error(U_REGEX_UNIMPLEMENTED);
   743         break;
   746     case doCloseParen:
   747         handleCloseParen();
   748         if (fParenStack.size() <= 0) {
   749             //  Extra close paren, or missing open paren.
   750             error(U_REGEX_MISMATCHED_PAREN);
   751         }
   752         break;
   754     case doNOP:
   755         break;
   758     case doBadOpenParenType:
   759     case doRuleError:
   760         error(U_REGEX_RULE_SYNTAX);
   761         break;
   764     case doMismatchedParenErr:
   765         error(U_REGEX_MISMATCHED_PAREN);
   766         break;
   768     case doPlus:
   769         //  Normal '+'  compiles to
   770         //     1.   stuff to be repeated  (already built)
   771         //     2.   jmp-sav 1
   772         //     3.   ...
   773         //
   774         //  Or, if the item to be repeated can match a zero length string,
   775         //     1.   STO_INP_LOC  data-loc
   776         //     2.      body of stuff to be repeated
   777         //     3.   JMP_SAV_X    2
   778         //     4.   ...
   780         //
   781         //  Or, if the item to be repeated is simple
   782         //     1.   Item to be repeated.
   783         //     2.   LOOP_SR_I    set number  (assuming repeated item is a set ref)
   784         //     3.   LOOP_C       stack location
   785         {
   786             int32_t  topLoc = blockTopLoc(FALSE);        // location of item #1
   787             int32_t  frameLoc;
   789             // Check for simple constructs, which may get special optimized code.
   790             if (topLoc == fRXPat->fCompiledPat->size() - 1) {
   791                 int32_t repeatedOp = (int32_t)fRXPat->fCompiledPat->elementAti(topLoc);
   793                 if (URX_TYPE(repeatedOp) == URX_SETREF) {
   794                     // Emit optimized code for [char set]+
   795                     int32_t loopOpI = URX_BUILD(URX_LOOP_SR_I, URX_VAL(repeatedOp));
   796                     fRXPat->fCompiledPat->addElement(loopOpI, *fStatus);
   797                     frameLoc = fRXPat->fFrameSize;
   798                     fRXPat->fFrameSize++;
   799                     int32_t loopOpC = URX_BUILD(URX_LOOP_C, frameLoc);
   800                     fRXPat->fCompiledPat->addElement(loopOpC, *fStatus);
   801                     break;
   802                 }
   804                 if (URX_TYPE(repeatedOp) == URX_DOTANY ||
   805                     URX_TYPE(repeatedOp) == URX_DOTANY_ALL ||
   806                     URX_TYPE(repeatedOp) == URX_DOTANY_UNIX) {
   807                     // Emit Optimized code for .+ operations.
   808                     int32_t loopOpI = URX_BUILD(URX_LOOP_DOT_I, 0);
   809                     if (URX_TYPE(repeatedOp) == URX_DOTANY_ALL) {
   810                         // URX_LOOP_DOT_I operand is a flag indicating ". matches any" mode.
   811                         loopOpI |= 1;
   812                     }
   813                     if (fModeFlags & UREGEX_UNIX_LINES) {
   814                         loopOpI |= 2;
   815                     }
   816                     fRXPat->fCompiledPat->addElement(loopOpI, *fStatus);
   817                     frameLoc = fRXPat->fFrameSize;
   818                     fRXPat->fFrameSize++;
   819                     int32_t loopOpC = URX_BUILD(URX_LOOP_C, frameLoc);
   820                     fRXPat->fCompiledPat->addElement(loopOpC, *fStatus);
   821                     break;
   822                 }
   824             }
   826             // General case.
   828             // Check for minimum match length of zero, which requires
   829             //    extra loop-breaking code.
   830             if (minMatchLength(topLoc, fRXPat->fCompiledPat->size()-1) == 0) {
   831                 // Zero length match is possible.
   832                 // Emit the code sequence that can handle it.
   833                 insertOp(topLoc);
   834                 frameLoc =  fRXPat->fFrameSize;
   835                 fRXPat->fFrameSize++;
   837                 int32_t op = URX_BUILD(URX_STO_INP_LOC, frameLoc);
   838                 fRXPat->fCompiledPat->setElementAt(op, topLoc);
   840                 op = URX_BUILD(URX_JMP_SAV_X, topLoc+1);
   841                 fRXPat->fCompiledPat->addElement(op, *fStatus);
   842             } else {
   843                 // Simpler code when the repeated body must match something non-empty
   844                 int32_t  jmpOp  = URX_BUILD(URX_JMP_SAV, topLoc);
   845                 fRXPat->fCompiledPat->addElement(jmpOp, *fStatus);
   846             }
   847         }
   848         break;
   850     case doNGPlus:
   851         //  Non-greedy '+?'  compiles to
   852         //     1.   stuff to be repeated  (already built)
   853         //     2.   state-save  1
   854         //     3.   ...
   855         {
   856             int32_t topLoc      = blockTopLoc(FALSE);
   857             int32_t saveStateOp = URX_BUILD(URX_STATE_SAVE, topLoc);
   858             fRXPat->fCompiledPat->addElement(saveStateOp, *fStatus);
   859         }
   860         break;
   863     case doOpt:
   864         // Normal (greedy) ? quantifier.
   865         //  Compiles to
   866         //     1. state save 3
   867         //     2.    body of optional block
   868         //     3. ...
   869         // Insert the state save into the compiled pattern, and we're done.
   870         {
   871             int32_t   saveStateLoc = blockTopLoc(TRUE);
   872             int32_t   saveStateOp  = URX_BUILD(URX_STATE_SAVE, fRXPat->fCompiledPat->size());
   873             fRXPat->fCompiledPat->setElementAt(saveStateOp, saveStateLoc);
   874         }
   875         break;
   877     case doNGOpt:
   878         // Non-greedy ?? quantifier
   879         //   compiles to
   880         //    1.  jmp   4
   881         //    2.     body of optional block
   882         //    3   jmp   5
   883         //    4.  state save 2
   884         //    5    ...
   885         //  This code is less than ideal, with two jmps instead of one, because we can only
   886         //  insert one instruction at the top of the block being iterated.
   887         {
   888             int32_t  jmp1_loc = blockTopLoc(TRUE);
   889             int32_t  jmp2_loc = fRXPat->fCompiledPat->size();
   891             int32_t  jmp1_op  = URX_BUILD(URX_JMP, jmp2_loc+1);
   892             fRXPat->fCompiledPat->setElementAt(jmp1_op, jmp1_loc);
   894             int32_t  jmp2_op  = URX_BUILD(URX_JMP, jmp2_loc+2);
   895             fRXPat->fCompiledPat->addElement(jmp2_op, *fStatus);
   897             int32_t  save_op  = URX_BUILD(URX_STATE_SAVE, jmp1_loc+1);
   898             fRXPat->fCompiledPat->addElement(save_op, *fStatus);
   899         }
   900         break;
   903     case doStar:
   904         // Normal (greedy) * quantifier.
   905         // Compiles to
   906         //       1.   STATE_SAVE   4
   907         //       2.      body of stuff being iterated over
   908         //       3.   JMP_SAV      2
   909         //       4.   ...
   910         //
   911         // Or, if the body is a simple [Set],
   912         //       1.   LOOP_SR_I    set number
   913         //       2.   LOOP_C       stack location
   914         //       ...
   915         //
   916         // Or if this is a .*
   917         //       1.   LOOP_DOT_I    (. matches all mode flag)
   918         //       2.   LOOP_C        stack location
   919         //
   920         // Or, if the body can match a zero-length string, to inhibit infinite loops,
   921         //       1.   STATE_SAVE   5
   922         //       2.   STO_INP_LOC  data-loc
   923         //       3.      body of stuff
   924         //       4.   JMP_SAV_X    2
   925         //       5.   ...
   926         {
   927             // location of item #1, the STATE_SAVE
   928             int32_t   topLoc = blockTopLoc(FALSE);
   929             int32_t   dataLoc = -1;
   931             // Check for simple *, where the construct being repeated
   932             //   compiled to single opcode, and might be optimizable.
   933             if (topLoc == fRXPat->fCompiledPat->size() - 1) {
   934                 int32_t repeatedOp = (int32_t)fRXPat->fCompiledPat->elementAti(topLoc);
   936                 if (URX_TYPE(repeatedOp) == URX_SETREF) {
   937                     // Emit optimized code for a [char set]*
   938                     int32_t loopOpI = URX_BUILD(URX_LOOP_SR_I, URX_VAL(repeatedOp));
   939                     fRXPat->fCompiledPat->setElementAt(loopOpI, topLoc);
   940                     dataLoc = fRXPat->fFrameSize;
   941                     fRXPat->fFrameSize++;
   942                     int32_t loopOpC = URX_BUILD(URX_LOOP_C, dataLoc);
   943                     fRXPat->fCompiledPat->addElement(loopOpC, *fStatus);
   944                     break;
   945                 }
   947                 if (URX_TYPE(repeatedOp) == URX_DOTANY ||
   948                     URX_TYPE(repeatedOp) == URX_DOTANY_ALL ||
   949                     URX_TYPE(repeatedOp) == URX_DOTANY_UNIX) {
   950                     // Emit Optimized code for .* operations.
   951                     int32_t loopOpI = URX_BUILD(URX_LOOP_DOT_I, 0);
   952                     if (URX_TYPE(repeatedOp) == URX_DOTANY_ALL) {
   953                         // URX_LOOP_DOT_I operand is a flag indicating . matches any mode.
   954                         loopOpI |= 1;
   955                     }
   956                     if ((fModeFlags & UREGEX_UNIX_LINES) != 0) {
   957                         loopOpI |= 2;
   958                     }
   959                     fRXPat->fCompiledPat->setElementAt(loopOpI, topLoc);
   960                     dataLoc = fRXPat->fFrameSize;
   961                     fRXPat->fFrameSize++;
   962                     int32_t loopOpC = URX_BUILD(URX_LOOP_C, dataLoc);
   963                     fRXPat->fCompiledPat->addElement(loopOpC, *fStatus);
   964                     break;
   965                 }
   966             }
   968             // Emit general case code for this *
   969             // The optimizations did not apply.
   971             int32_t   saveStateLoc = blockTopLoc(TRUE);
   972             int32_t   jmpOp        = URX_BUILD(URX_JMP_SAV, saveStateLoc+1);
   974             // Check for minimum match length of zero, which requires
   975             //    extra loop-breaking code.
   976             if (minMatchLength(saveStateLoc, fRXPat->fCompiledPat->size()-1) == 0) {
   977                 insertOp(saveStateLoc);
   978                 dataLoc =  fRXPat->fFrameSize;
   979                 fRXPat->fFrameSize++;
   981                 int32_t op = URX_BUILD(URX_STO_INP_LOC, dataLoc);
   982                 fRXPat->fCompiledPat->setElementAt(op, saveStateLoc+1);
   983                 jmpOp      = URX_BUILD(URX_JMP_SAV_X, saveStateLoc+2);
   984             }
   986             // Locate the position in the compiled pattern where the match will continue
   987             //   after completing the *.   (4 or 5 in the comment above)
   988             int32_t continueLoc = fRXPat->fCompiledPat->size()+1;
   990             // Put together the save state op store it into the compiled code.
   991             int32_t saveStateOp = URX_BUILD(URX_STATE_SAVE, continueLoc);
   992             fRXPat->fCompiledPat->setElementAt(saveStateOp, saveStateLoc);
   994             // Append the URX_JMP_SAV or URX_JMPX operation to the compiled pattern.
   995             fRXPat->fCompiledPat->addElement(jmpOp, *fStatus);
   996         }
   997         break;
   999     case doNGStar:
  1000         // Non-greedy *? quantifier
  1001         // compiles to
  1002         //     1.   JMP    3
  1003         //     2.      body of stuff being iterated over
  1004         //     3.   STATE_SAVE  2
  1005         //     4    ...
  1007             int32_t     jmpLoc  = blockTopLoc(TRUE);                   // loc  1.
  1008             int32_t     saveLoc = fRXPat->fCompiledPat->size();        // loc  3.
  1009             int32_t     jmpOp   = URX_BUILD(URX_JMP, saveLoc);
  1010             int32_t     stateSaveOp = URX_BUILD(URX_STATE_SAVE, jmpLoc+1);
  1011             fRXPat->fCompiledPat->setElementAt(jmpOp, jmpLoc);
  1012             fRXPat->fCompiledPat->addElement(stateSaveOp, *fStatus);
  1014         break;
  1017     case doIntervalInit:
  1018         // The '{' opening an interval quantifier was just scanned.
  1019         // Init the counter varaiables that will accumulate the values as the digits
  1020         //    are scanned.
  1021         fIntervalLow = 0;
  1022         fIntervalUpper = -1;
  1023         break;
  1025     case doIntevalLowerDigit:
  1026         // Scanned a digit from the lower value of an {lower,upper} interval
  1028             int32_t digitValue = u_charDigitValue(fC.fChar);
  1029             U_ASSERT(digitValue >= 0);
  1030             fIntervalLow = fIntervalLow*10 + digitValue;
  1031             if (fIntervalLow < 0) {
  1032                 error(U_REGEX_NUMBER_TOO_BIG);
  1035         break;
  1037     case doIntervalUpperDigit:
  1038         // Scanned a digit from the upper value of an {lower,upper} interval
  1040             if (fIntervalUpper < 0) {
  1041                 fIntervalUpper = 0;
  1043             int32_t digitValue = u_charDigitValue(fC.fChar);
  1044             U_ASSERT(digitValue >= 0);
  1045             fIntervalUpper = fIntervalUpper*10 + digitValue;
  1046             if (fIntervalUpper < 0) {
  1047                 error(U_REGEX_NUMBER_TOO_BIG);
  1050         break;
  1052     case doIntervalSame:
  1053         // Scanned a single value interval like {27}.  Upper = Lower.
  1054         fIntervalUpper = fIntervalLow;
  1055         break;
  1057     case doInterval:
  1058         // Finished scanning a normal {lower,upper} interval.  Generate the code for it.
  1059         if (compileInlineInterval() == FALSE) {
  1060             compileInterval(URX_CTR_INIT, URX_CTR_LOOP);
  1062         break;
  1064     case doPossessiveInterval:
  1065         // Finished scanning a Possessive {lower,upper}+ interval.  Generate the code for it.
  1067             // Remember the loc for the top of the block being looped over.
  1068             //   (Can not reserve a slot in the compiled pattern at this time, because
  1069             //    compileInterval needs to reserve also, and blockTopLoc can only reserve
  1070             //    once per block.)
  1071             int32_t topLoc = blockTopLoc(FALSE);
  1073             // Produce normal looping code.
  1074             compileInterval(URX_CTR_INIT, URX_CTR_LOOP);
  1076             // Surround the just-emitted normal looping code with a STO_SP ... LD_SP
  1077             //  just as if the loop was inclosed in atomic parentheses.
  1079             // First the STO_SP before the start of the loop
  1080             insertOp(topLoc);
  1081             int32_t  varLoc    = fRXPat->fDataSize;    // Reserve a data location for saving the
  1082             fRXPat->fDataSize += 1;                    //  state stack ptr.
  1083             int32_t  op        = URX_BUILD(URX_STO_SP, varLoc);
  1084             fRXPat->fCompiledPat->setElementAt(op, topLoc);
  1086             int32_t loopOp = (int32_t)fRXPat->fCompiledPat->popi();
  1087             U_ASSERT(URX_TYPE(loopOp) == URX_CTR_LOOP && URX_VAL(loopOp) == topLoc);
  1088             loopOp++;     // point LoopOp after the just-inserted STO_SP
  1089             fRXPat->fCompiledPat->push(loopOp, *fStatus);
  1091             // Then the LD_SP after the end of the loop
  1092             op = URX_BUILD(URX_LD_SP, varLoc);
  1093             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1096         break;
  1098     case doNGInterval:
  1099         // Finished scanning a non-greedy {lower,upper}? interval.  Generate the code for it.
  1100         compileInterval(URX_CTR_INIT_NG, URX_CTR_LOOP_NG);
  1101         break;
  1103     case doIntervalError:
  1104         error(U_REGEX_BAD_INTERVAL);
  1105         break;
  1107     case doLiteralChar:
  1108         // We've just scanned a "normal" character from the pattern,
  1109         literalChar(fC.fChar);
  1110         break;
  1113     case doEscapedLiteralChar:
  1114         // We've just scanned an backslashed escaped character with  no
  1115         //   special meaning.  It represents itself.
  1116         if ((fModeFlags & UREGEX_ERROR_ON_UNKNOWN_ESCAPES) != 0 &&
  1117             ((fC.fChar >= 0x41 && fC.fChar<= 0x5A) ||     // in [A-Z]
  1118             (fC.fChar >= 0x61 && fC.fChar <= 0x7a))) {   // in [a-z]
  1119                error(U_REGEX_BAD_ESCAPE_SEQUENCE);
  1121         literalChar(fC.fChar);
  1122         break;
  1125     case doDotAny:
  1126         // scanned a ".",  match any single character.
  1128             fixLiterals(FALSE);
  1129             int32_t   op;
  1130             if (fModeFlags & UREGEX_DOTALL) {
  1131                 op = URX_BUILD(URX_DOTANY_ALL, 0);
  1132             } else if (fModeFlags & UREGEX_UNIX_LINES) {
  1133                 op = URX_BUILD(URX_DOTANY_UNIX, 0);
  1134             } else {
  1135                 op = URX_BUILD(URX_DOTANY, 0);
  1137             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1139         break;
  1141     case doCaret:
  1143             fixLiterals(FALSE);
  1144             int32_t op = 0;
  1145             if (       (fModeFlags & UREGEX_MULTILINE) == 0 && (fModeFlags & UREGEX_UNIX_LINES) == 0) {
  1146                 op = URX_CARET;
  1147             } else if ((fModeFlags & UREGEX_MULTILINE) != 0 && (fModeFlags & UREGEX_UNIX_LINES) == 0) {
  1148                 op = URX_CARET_M;
  1149             } else if ((fModeFlags & UREGEX_MULTILINE) == 0 && (fModeFlags & UREGEX_UNIX_LINES) != 0) {
  1150                 op = URX_CARET;   // Only testing true start of input. 
  1151             } else if ((fModeFlags & UREGEX_MULTILINE) != 0 && (fModeFlags & UREGEX_UNIX_LINES) != 0) {
  1152                 op = URX_CARET_M_UNIX;
  1154             fRXPat->fCompiledPat->addElement(URX_BUILD(op, 0), *fStatus);
  1156         break;
  1158     case doDollar:
  1160             fixLiterals(FALSE);
  1161             int32_t op = 0;
  1162             if (       (fModeFlags & UREGEX_MULTILINE) == 0 && (fModeFlags & UREGEX_UNIX_LINES) == 0) {
  1163                 op = URX_DOLLAR;
  1164             } else if ((fModeFlags & UREGEX_MULTILINE) != 0 && (fModeFlags & UREGEX_UNIX_LINES) == 0) {
  1165                 op = URX_DOLLAR_M;
  1166             } else if ((fModeFlags & UREGEX_MULTILINE) == 0 && (fModeFlags & UREGEX_UNIX_LINES) != 0) {
  1167                 op = URX_DOLLAR_D;
  1168             } else if ((fModeFlags & UREGEX_MULTILINE) != 0 && (fModeFlags & UREGEX_UNIX_LINES) != 0) {
  1169                 op = URX_DOLLAR_MD;
  1171             fRXPat->fCompiledPat->addElement(URX_BUILD(op, 0), *fStatus);
  1173         break;
  1175     case doBackslashA:
  1176         fixLiterals(FALSE);
  1177         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_CARET, 0), *fStatus);
  1178         break;
  1180     case doBackslashB:
  1182             #if  UCONFIG_NO_BREAK_ITERATION==1
  1183             if (fModeFlags & UREGEX_UWORD) {
  1184                 error(U_UNSUPPORTED_ERROR);
  1186             #endif
  1187             fixLiterals(FALSE);
  1188             int32_t op = (fModeFlags & UREGEX_UWORD)? URX_BACKSLASH_BU : URX_BACKSLASH_B;
  1189             fRXPat->fCompiledPat->addElement(URX_BUILD(op, 1), *fStatus);
  1191         break;
  1193     case doBackslashb:
  1195             #if  UCONFIG_NO_BREAK_ITERATION==1
  1196             if (fModeFlags & UREGEX_UWORD) {
  1197                 error(U_UNSUPPORTED_ERROR);
  1199             #endif
  1200             fixLiterals(FALSE);
  1201             int32_t op = (fModeFlags & UREGEX_UWORD)? URX_BACKSLASH_BU : URX_BACKSLASH_B;
  1202             fRXPat->fCompiledPat->addElement(URX_BUILD(op, 0), *fStatus);
  1204         break;
  1206     case doBackslashD:
  1207         fixLiterals(FALSE);
  1208         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_D, 1), *fStatus);
  1209         break;
  1211     case doBackslashd:
  1212         fixLiterals(FALSE);
  1213         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_D, 0), *fStatus);
  1214         break;
  1216     case doBackslashG:
  1217         fixLiterals(FALSE);
  1218         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_G, 0), *fStatus);
  1219         break;
  1221     case doBackslashS:
  1222         fixLiterals(FALSE);
  1223         fRXPat->fCompiledPat->addElement(
  1224             URX_BUILD(URX_STAT_SETREF_N, URX_ISSPACE_SET), *fStatus);
  1225         break;
  1227     case doBackslashs:
  1228         fixLiterals(FALSE);
  1229         fRXPat->fCompiledPat->addElement(
  1230             URX_BUILD(URX_STATIC_SETREF, URX_ISSPACE_SET), *fStatus);
  1231         break;
  1233     case doBackslashW:
  1234         fixLiterals(FALSE);
  1235         fRXPat->fCompiledPat->addElement(
  1236             URX_BUILD(URX_STAT_SETREF_N, URX_ISWORD_SET), *fStatus);
  1237         break;
  1239     case doBackslashw:
  1240         fixLiterals(FALSE);
  1241         fRXPat->fCompiledPat->addElement(
  1242             URX_BUILD(URX_STATIC_SETREF, URX_ISWORD_SET), *fStatus);
  1243         break;
  1245     case doBackslashX:
  1246         fixLiterals(FALSE);
  1247         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_X, 0), *fStatus);
  1248         break;
  1251     case doBackslashZ:
  1252         fixLiterals(FALSE);
  1253         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_DOLLAR, 0), *fStatus);
  1254         break;
  1256     case doBackslashz:
  1257         fixLiterals(FALSE);
  1258         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_Z, 0), *fStatus);
  1259         break;
  1261     case doEscapeError:
  1262         error(U_REGEX_BAD_ESCAPE_SEQUENCE);
  1263         break;
  1265     case doExit:
  1266         fixLiterals(FALSE);
  1267         returnVal = FALSE;
  1268         break;
  1270     case doProperty:
  1272             fixLiterals(FALSE);
  1273             UnicodeSet *theSet = scanProp();
  1274             compileSet(theSet);
  1276         break;
  1278     case doNamedChar:
  1280             UChar32 c = scanNamedChar();
  1281             literalChar(c);
  1283         break;
  1286     case doBackRef:
  1287         // BackReference.  Somewhat unusual in that the front-end can not completely parse
  1288         //                 the regular expression, because the number of digits to be consumed
  1289         //                 depends on the number of capture groups that have been defined.  So
  1290         //                 we have to do it here instead.
  1292             int32_t  numCaptureGroups = fRXPat->fGroupMap->size();
  1293             int32_t  groupNum = 0;
  1294             UChar32  c        = fC.fChar;
  1296             for (;;) {
  1297                 // Loop once per digit, for max allowed number of digits in a back reference.
  1298                 int32_t digit = u_charDigitValue(c);
  1299                 groupNum = groupNum * 10 + digit;
  1300                 if (groupNum >= numCaptureGroups) {
  1301                     break;
  1303                 c = peekCharLL();
  1304                 if (RegexStaticSets::gStaticSets->fRuleDigitsAlias->contains(c) == FALSE) {
  1305                     break;
  1307                 nextCharLL();
  1310             // Scan of the back reference in the source regexp is complete.  Now generate
  1311             //  the compiled code for it.
  1312             // Because capture groups can be forward-referenced by back-references,
  1313             //  we fill the operand with the capture group number.  At the end
  1314             //  of compilation, it will be changed to the variable's location.
  1315             U_ASSERT(groupNum > 0);  // Shouldn't happen.  '\0' begins an octal escape sequence,
  1316                                      //    and shouldn't enter this code path at all.
  1317             fixLiterals(FALSE);
  1318             int32_t  op;
  1319             if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
  1320                 op = URX_BUILD(URX_BACKREF_I, groupNum);
  1321             } else {
  1322                 op = URX_BUILD(URX_BACKREF, groupNum);
  1324             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1326         break;
  1329     case doPossessivePlus:
  1330         // Possessive ++ quantifier.
  1331         // Compiles to
  1332         //       1.   STO_SP
  1333         //       2.      body of stuff being iterated over
  1334         //       3.   STATE_SAVE 5
  1335         //       4.   JMP        2
  1336         //       5.   LD_SP
  1337         //       6.   ...
  1338         //
  1339         //  Note:  TODO:  This is pretty inefficient.  A mass of saved state is built up
  1340         //                then unconditionally discarded.  Perhaps introduce a new opcode.  Ticket 6056
  1341         //
  1343             // Emit the STO_SP
  1344             int32_t   topLoc = blockTopLoc(TRUE);
  1345             int32_t   stoLoc = fRXPat->fDataSize;
  1346             fRXPat->fDataSize++;       // Reserve the data location for storing save stack ptr.
  1347             int32_t   op     = URX_BUILD(URX_STO_SP, stoLoc);
  1348             fRXPat->fCompiledPat->setElementAt(op, topLoc);
  1350             // Emit the STATE_SAVE
  1351             op = URX_BUILD(URX_STATE_SAVE, fRXPat->fCompiledPat->size()+2);
  1352             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1354             // Emit the JMP
  1355             op = URX_BUILD(URX_JMP, topLoc+1);
  1356             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1358             // Emit the LD_SP
  1359             op = URX_BUILD(URX_LD_SP, stoLoc);
  1360             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1362         break;
  1364     case doPossessiveStar:
  1365         // Possessive *+ quantifier.
  1366         // Compiles to
  1367         //       1.   STO_SP       loc
  1368         //       2.   STATE_SAVE   5
  1369         //       3.      body of stuff being iterated over
  1370         //       4.   JMP          2
  1371         //       5.   LD_SP        loc
  1372         //       6    ...
  1373         // TODO:  do something to cut back the state stack each time through the loop.
  1375             // Reserve two slots at the top of the block.
  1376             int32_t   topLoc = blockTopLoc(TRUE);
  1377             insertOp(topLoc);
  1379             // emit   STO_SP     loc
  1380             int32_t   stoLoc = fRXPat->fDataSize;
  1381             fRXPat->fDataSize++;       // Reserve the data location for storing save stack ptr.
  1382             int32_t   op     = URX_BUILD(URX_STO_SP, stoLoc);
  1383             fRXPat->fCompiledPat->setElementAt(op, topLoc);
  1385             // Emit the SAVE_STATE   5
  1386             int32_t L7 = fRXPat->fCompiledPat->size()+1;
  1387             op = URX_BUILD(URX_STATE_SAVE, L7);
  1388             fRXPat->fCompiledPat->setElementAt(op, topLoc+1);
  1390             // Append the JMP operation.
  1391             op = URX_BUILD(URX_JMP, topLoc+1);
  1392             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1394             // Emit the LD_SP       loc
  1395             op = URX_BUILD(URX_LD_SP, stoLoc);
  1396             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1398         break;
  1400     case doPossessiveOpt:
  1401         // Possessive  ?+ quantifier.
  1402         //  Compiles to
  1403         //     1. STO_SP      loc
  1404         //     2. SAVE_STATE  5
  1405         //     3.    body of optional block
  1406         //     4. LD_SP       loc
  1407         //     5. ...
  1408         //
  1410             // Reserve two slots at the top of the block.
  1411             int32_t   topLoc = blockTopLoc(TRUE);
  1412             insertOp(topLoc);
  1414             // Emit the STO_SP
  1415             int32_t   stoLoc = fRXPat->fDataSize;
  1416             fRXPat->fDataSize++;       // Reserve the data location for storing save stack ptr.
  1417             int32_t   op     = URX_BUILD(URX_STO_SP, stoLoc);
  1418             fRXPat->fCompiledPat->setElementAt(op, topLoc);
  1420             // Emit the SAVE_STATE
  1421             int32_t   continueLoc = fRXPat->fCompiledPat->size()+1;
  1422             op = URX_BUILD(URX_STATE_SAVE, continueLoc);
  1423             fRXPat->fCompiledPat->setElementAt(op, topLoc+1);
  1425             // Emit the LD_SP
  1426             op = URX_BUILD(URX_LD_SP, stoLoc);
  1427             fRXPat->fCompiledPat->addElement(op, *fStatus);
  1429         break;
  1432     case doBeginMatchMode:
  1433         fNewModeFlags = fModeFlags;
  1434         fSetModeFlag  = TRUE;
  1435         break;
  1437     case doMatchMode:   //  (?i)    and similar
  1439             int32_t  bit = 0;
  1440             switch (fC.fChar) {
  1441             case 0x69: /* 'i' */   bit = UREGEX_CASE_INSENSITIVE; break;
  1442             case 0x64: /* 'd' */   bit = UREGEX_UNIX_LINES;       break;
  1443             case 0x6d: /* 'm' */   bit = UREGEX_MULTILINE;        break;
  1444             case 0x73: /* 's' */   bit = UREGEX_DOTALL;           break;
  1445             case 0x75: /* 'u' */   bit = 0; /* Unicode casing */  break;
  1446             case 0x77: /* 'w' */   bit = UREGEX_UWORD;            break;
  1447             case 0x78: /* 'x' */   bit = UREGEX_COMMENTS;         break;
  1448             case 0x2d: /* '-' */   fSetModeFlag = FALSE;          break;
  1449             default:
  1450                 U_ASSERT(FALSE);   // Should never happen.  Other chars are filtered out
  1451                                    // by the scanner.
  1453             if (fSetModeFlag) {
  1454                 fNewModeFlags |= bit;
  1455             } else {
  1456                 fNewModeFlags &= ~bit;
  1459         break;
  1461     case doSetMatchMode:
  1462         // Emit code to match any pending literals, using the not-yet changed match mode.
  1463         fixLiterals();
  1465         // We've got a (?i) or similar.  The match mode is being changed, but
  1466         //   the change is not scoped to a parenthesized block.
  1467         U_ASSERT(fNewModeFlags < 0);
  1468         fModeFlags = fNewModeFlags;
  1470         break;
  1473     case doMatchModeParen:
  1474         // We've got a (?i: or similar.  Begin a parenthesized block, save old
  1475         //   mode flags so they can be restored at the close of the block.
  1476         //
  1477         //   Compile to a
  1478         //      - NOP, which later may be replaced by a save-state if the
  1479         //         parenthesized group gets a * quantifier, followed by
  1480         //      - NOP, which may later be replaced by a save-state if there
  1481         //             is an '|' alternation within the parens.
  1483             fixLiterals(FALSE);
  1484             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
  1485             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP, 0), *fStatus);
  1487             // On the Parentheses stack, start a new frame and add the postions
  1488             //   of the two NOPs (a normal non-capturing () frame, except for the
  1489             //   saving of the orignal mode flags.)
  1490             fParenStack.push(fModeFlags, *fStatus);
  1491             fParenStack.push(flags, *fStatus);                            // Frame Marker
  1492             fParenStack.push(fRXPat->fCompiledPat->size()-2, *fStatus);   // The first NOP
  1493             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The second NOP
  1495             // Set the current mode flags to the new values.
  1496             U_ASSERT(fNewModeFlags < 0);
  1497             fModeFlags = fNewModeFlags;
  1499         break;
  1501     case doBadModeFlag:
  1502         error(U_REGEX_INVALID_FLAG);
  1503         break;
  1505     case doSuppressComments:
  1506         // We have just scanned a '(?'.  We now need to prevent the character scanner from
  1507         // treating a '#' as a to-the-end-of-line comment.
  1508         //   (This Perl compatibility just gets uglier and uglier to do...)
  1509         fEOLComments = FALSE;
  1510         break;
  1513     case doSetAddAmp:
  1515           UnicodeSet *set = (UnicodeSet *)fSetStack.peek();
  1516           set->add(chAmp);
  1518         break;
  1520     case doSetAddDash:
  1522           UnicodeSet *set = (UnicodeSet *)fSetStack.peek();
  1523           set->add(chDash);
  1525         break;
  1527      case doSetBackslash_s:
  1529          UnicodeSet *set = (UnicodeSet *)fSetStack.peek();
  1530          set->addAll(*RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]);
  1531          break;
  1534      case doSetBackslash_S:
  1536             UnicodeSet *set = (UnicodeSet *)fSetStack.peek();
  1537             UnicodeSet SSet(*RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]);
  1538             SSet.complement();
  1539             set->addAll(SSet);
  1540             break;
  1543     case doSetBackslash_d:
  1545             UnicodeSet *set = (UnicodeSet *)fSetStack.peek();
  1546             // TODO - make a static set, ticket 6058.
  1547             addCategory(set, U_GC_ND_MASK, *fStatus);
  1548             break;
  1551     case doSetBackslash_D:
  1553             UnicodeSet *set = (UnicodeSet *)fSetStack.peek();
  1554             UnicodeSet digits;
  1555             // TODO - make a static set, ticket 6058.
  1556             digits.applyIntPropertyValue(UCHAR_GENERAL_CATEGORY_MASK, U_GC_ND_MASK, *fStatus);
  1557             digits.complement();
  1558             set->addAll(digits);
  1559             break;
  1562     case doSetBackslash_w:
  1564             UnicodeSet *set = (UnicodeSet *)fSetStack.peek();
  1565             set->addAll(*RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]);
  1566             break;
  1569     case doSetBackslash_W:
  1571             UnicodeSet *set = (UnicodeSet *)fSetStack.peek();
  1572             UnicodeSet SSet(*RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]);
  1573             SSet.complement();
  1574             set->addAll(SSet);
  1575             break;
  1578     case doSetBegin:
  1579         fixLiterals(FALSE);
  1580         fSetStack.push(new UnicodeSet(), *fStatus);
  1581         fSetOpStack.push(setStart, *fStatus);
  1582         if ((fModeFlags & UREGEX_CASE_INSENSITIVE) != 0) {
  1583             fSetOpStack.push(setCaseClose, *fStatus);
  1585         break;
  1587     case doSetBeginDifference1:
  1588         //  We have scanned something like [[abc]-[
  1589         //  Set up a new UnicodeSet for the set beginning with the just-scanned '['
  1590         //  Push a Difference operator, which will cause the new set to be subtracted from what
  1591         //    went before once it is created.
  1592         setPushOp(setDifference1);
  1593         fSetOpStack.push(setStart, *fStatus);
  1594         if ((fModeFlags & UREGEX_CASE_INSENSITIVE) != 0) {
  1595             fSetOpStack.push(setCaseClose, *fStatus);
  1597         break;
  1599     case doSetBeginIntersection1:
  1600         //  We have scanned something like  [[abc]&[
  1601         //   Need both the '&' operator and the open '[' operator.
  1602         setPushOp(setIntersection1);
  1603         fSetOpStack.push(setStart, *fStatus);
  1604         if ((fModeFlags & UREGEX_CASE_INSENSITIVE) != 0) {
  1605             fSetOpStack.push(setCaseClose, *fStatus);
  1607         break;
  1609     case doSetBeginUnion:
  1610         //  We have scanned something like  [[abc][
  1611         //     Need to handle the union operation explicitly [[abc] | [
  1612         setPushOp(setUnion);
  1613         fSetOpStack.push(setStart, *fStatus);
  1614         if ((fModeFlags & UREGEX_CASE_INSENSITIVE) != 0) {
  1615             fSetOpStack.push(setCaseClose, *fStatus);
  1617         break;
  1619     case doSetDifference2:
  1620         // We have scanned something like [abc--
  1621         //   Consider this to unambiguously be a set difference operator.
  1622         setPushOp(setDifference2);
  1623         break;
  1625     case doSetEnd:
  1626         // Have encountered the ']' that closes a set.
  1627         //    Force the evaluation of any pending operations within this set,
  1628         //    leave the completed set on the top of the set stack.
  1629         setEval(setEnd);
  1630         U_ASSERT(fSetOpStack.peeki()==setStart);
  1631         fSetOpStack.popi();
  1632         break;
  1634     case doSetFinish:
  1636         // Finished a complete set expression, including all nested sets.
  1637         //   The close bracket has already triggered clearing out pending set operators,
  1638         //    the operator stack should be empty and the operand stack should have just
  1639         //    one entry, the result set.
  1640         U_ASSERT(fSetOpStack.empty());
  1641         UnicodeSet *theSet = (UnicodeSet *)fSetStack.pop();
  1642         U_ASSERT(fSetStack.empty());
  1643         compileSet(theSet);
  1644         break;
  1647     case doSetIntersection2:
  1648         // Have scanned something like [abc&&
  1649         setPushOp(setIntersection2);
  1650         break;
  1652     case doSetLiteral:
  1653         // Union the just-scanned literal character into the set being built.
  1654         //    This operation is the highest precedence set operation, so we can always do
  1655         //    it immediately, without waiting to see what follows.  It is necessary to perform
  1656         //    any pending '-' or '&' operation first, because these have the same precedence
  1657         //    as union-ing in a literal' 
  1659             setEval(setUnion);
  1660             UnicodeSet *s = (UnicodeSet *)fSetStack.peek();
  1661             s->add(fC.fChar);
  1662             fLastSetLiteral = fC.fChar;
  1663             break;
  1666     case doSetLiteralEscaped:
  1667         // A back-slash escaped literal character was encountered.
  1668         // Processing is the same as with setLiteral, above, with the addition of
  1669         //  the optional check for errors on escaped ASCII letters.
  1671             if ((fModeFlags & UREGEX_ERROR_ON_UNKNOWN_ESCAPES) != 0 &&
  1672                 ((fC.fChar >= 0x41 && fC.fChar<= 0x5A) ||     // in [A-Z]
  1673                  (fC.fChar >= 0x61 && fC.fChar <= 0x7a))) {   // in [a-z]
  1674                 error(U_REGEX_BAD_ESCAPE_SEQUENCE);
  1676             setEval(setUnion);
  1677             UnicodeSet *s = (UnicodeSet *)fSetStack.peek();
  1678             s->add(fC.fChar);
  1679             fLastSetLiteral = fC.fChar;
  1680             break;
  1683         case doSetNamedChar:
  1684         // Scanning a \N{UNICODE CHARACTER NAME}
  1685         //  Aside from the source of the character, the processing is identical to doSetLiteral,
  1686         //    above.
  1688             UChar32  c = scanNamedChar();
  1689             setEval(setUnion);
  1690             UnicodeSet *s = (UnicodeSet *)fSetStack.peek();
  1691             s->add(c);
  1692             fLastSetLiteral = c;
  1693             break;
  1696     case doSetNamedRange:
  1697         // We have scanned literal-\N{CHAR NAME}.  Add the range to the set.
  1698         // The left character is already in the set, and is saved in fLastSetLiteral.
  1699         // The right side needs to be picked up, the scan is at the 'N'.
  1700         // Lower Limit > Upper limit being an error matches both Java
  1701         //        and ICU UnicodeSet behavior.
  1703             UChar32  c = scanNamedChar();
  1704             if (U_SUCCESS(*fStatus) && fLastSetLiteral > c) {
  1705                 error(U_REGEX_INVALID_RANGE);
  1707             UnicodeSet *s = (UnicodeSet *)fSetStack.peek();
  1708             s->add(fLastSetLiteral, c);
  1709             fLastSetLiteral = c;
  1710             break;
  1714     case  doSetNegate:
  1715         // Scanned a '^' at the start of a set.
  1716         // Push the negation operator onto the set op stack.
  1717         // A twist for case-insensitive matching:
  1718         //   the case closure operation must happen _before_ negation.
  1719         //   But the case closure operation will already be on the stack if it's required.
  1720         //   This requires checking for case closure, and swapping the stack order
  1721         //    if it is present.
  1723             int32_t  tosOp = fSetOpStack.peeki();
  1724             if (tosOp == setCaseClose) {
  1725                 fSetOpStack.popi();
  1726                 fSetOpStack.push(setNegation, *fStatus);
  1727                 fSetOpStack.push(setCaseClose, *fStatus);
  1728             } else {
  1729                 fSetOpStack.push(setNegation, *fStatus);
  1732         break;
  1734     case doSetNoCloseError:
  1735         error(U_REGEX_MISSING_CLOSE_BRACKET);
  1736         break;
  1738     case doSetOpError:
  1739         error(U_REGEX_RULE_SYNTAX);   //  -- or && at the end of a set.  Illegal.
  1740         break;
  1742     case doSetPosixProp:
  1744             UnicodeSet *s = scanPosixProp();
  1745             if (s != NULL) {
  1746                 UnicodeSet *tos = (UnicodeSet *)fSetStack.peek();
  1747                 tos->addAll(*s);
  1748                 delete s;
  1749             }  // else error.  scanProp() reported the error status already.
  1751         break;
  1753     case doSetProp:
  1754         //  Scanned a \p \P within [brackets].
  1756             UnicodeSet *s = scanProp();
  1757             if (s != NULL) {
  1758                 UnicodeSet *tos = (UnicodeSet *)fSetStack.peek();
  1759                 tos->addAll(*s);
  1760                 delete s;
  1761             }  // else error.  scanProp() reported the error status already.
  1763         break;
  1766     case doSetRange:
  1767         // We have scanned literal-literal.  Add the range to the set.
  1768         // The left character is already in the set, and is saved in fLastSetLiteral.
  1769         // The right side is the current character.
  1770         // Lower Limit > Upper limit being an error matches both Java
  1771         //        and ICU UnicodeSet behavior.
  1773         if (fLastSetLiteral > fC.fChar) {
  1774             error(U_REGEX_INVALID_RANGE);  
  1776         UnicodeSet *s = (UnicodeSet *)fSetStack.peek();
  1777         s->add(fLastSetLiteral, fC.fChar);
  1778         break;
  1781     default:
  1782         U_ASSERT(FALSE);
  1783         error(U_REGEX_INTERNAL_ERROR);
  1784         break;
  1787     if (U_FAILURE(*fStatus)) {
  1788         returnVal = FALSE;
  1791     return returnVal;
  1796 //------------------------------------------------------------------------------
  1797 //
  1798 //   literalChar           We've encountered a literal character from the pattern,
  1799 //                             or an escape sequence that reduces to a character.
  1800 //                         Add it to the string containing all literal chars/strings from
  1801 //                             the pattern.
  1802 //
  1803 //------------------------------------------------------------------------------
  1804 void RegexCompile::literalChar(UChar32 c)  {
  1805     fLiteralChars.append(c);
  1809 //------------------------------------------------------------------------------
  1810 //
  1811 //    fixLiterals           When compiling something that can follow a literal
  1812 //                          string in a pattern, emit the code to match the
  1813 //                          accumulated literal string.
  1814 //
  1815 //                          Optionally, split the last char of the string off into
  1816 //                          a single "ONE_CHAR" operation, so that quantifiers can
  1817 //                          apply to that char alone.  Example:   abc*
  1818 //                          The * must apply to the 'c' only.
  1819 //
  1820 //------------------------------------------------------------------------------
  1821 void    RegexCompile::fixLiterals(UBool split) {
  1822     int32_t  op = 0;                       // An op from/for the compiled pattern.
  1824     // If no literal characters have been scanned but not yet had code generated
  1825     //   for them, nothing needs to be done.
  1826     if (fLiteralChars.length() == 0) {
  1827         return;
  1830     int32_t indexOfLastCodePoint = fLiteralChars.moveIndex32(fLiteralChars.length(), -1);
  1831     UChar32 lastCodePoint = fLiteralChars.char32At(indexOfLastCodePoint);
  1833     // Split:  We need to  ensure that the last item in the compiled pattern 
  1834     //     refers only to the last literal scanned in the pattern, so that
  1835     //     quantifiers (*, +, etc.) affect only it, and not a longer string.
  1836     //     Split before case folding for case insensitive matches.
  1838     if (split) {
  1839         fLiteralChars.truncate(indexOfLastCodePoint);
  1840         fixLiterals(FALSE);   // Recursive call, emit code to match the first part of the string.
  1841                               //  Note that the truncated literal string may be empty, in which case
  1842                               //  nothing will be emitted.
  1844         literalChar(lastCodePoint);  // Re-add the last code point as if it were a new literal.
  1845         fixLiterals(FALSE);          // Second recursive call, code for the final code point.
  1846         return;
  1849     // If we are doing case-insensitive matching, case fold the string.  This may expand
  1850     //   the string, e.g. the German sharp-s turns into "ss"
  1851     if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
  1852         fLiteralChars.foldCase();
  1853         indexOfLastCodePoint = fLiteralChars.moveIndex32(fLiteralChars.length(), -1);
  1854         lastCodePoint = fLiteralChars.char32At(indexOfLastCodePoint);
  1857     if (indexOfLastCodePoint == 0) {
  1858         // Single character, emit a URX_ONECHAR op to match it.
  1859         if ((fModeFlags & UREGEX_CASE_INSENSITIVE) && 
  1860                  u_hasBinaryProperty(lastCodePoint, UCHAR_CASE_SENSITIVE)) {
  1861             op = URX_BUILD(URX_ONECHAR_I, lastCodePoint);
  1862         } else {
  1863             op = URX_BUILD(URX_ONECHAR, lastCodePoint);
  1865         fRXPat->fCompiledPat->addElement(op, *fStatus);
  1866     } else {
  1867         // Two or more chars, emit a URX_STRING to match them.
  1868         if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
  1869             op = URX_BUILD(URX_STRING_I, fRXPat->fLiteralText.length());
  1870         } else {
  1871             // TODO here:  add optimization to split case sensitive strings of length two
  1872             //             into two single char ops, for efficiency.
  1873             op = URX_BUILD(URX_STRING, fRXPat->fLiteralText.length());
  1875         fRXPat->fCompiledPat->addElement(op, *fStatus);
  1876         op = URX_BUILD(URX_STRING_LEN, fLiteralChars.length());
  1877         fRXPat->fCompiledPat->addElement(op, *fStatus);
  1879         // Add this string into the accumulated strings of the compiled pattern.
  1880         fRXPat->fLiteralText.append(fLiteralChars);
  1883     fLiteralChars.remove();
  1891 //------------------------------------------------------------------------------
  1892 //
  1893 //   insertOp()             Insert a slot for a new opcode into the already
  1894 //                          compiled pattern code.
  1895 //
  1896 //                          Fill the slot with a NOP.  Our caller will replace it
  1897 //                          with what they really wanted.
  1898 //
  1899 //------------------------------------------------------------------------------
  1900 void   RegexCompile::insertOp(int32_t where) {
  1901     UVector64 *code = fRXPat->fCompiledPat;
  1902     U_ASSERT(where>0 && where < code->size());
  1904     int32_t  nop = URX_BUILD(URX_NOP, 0);
  1905     code->insertElementAt(nop, where, *fStatus);
  1907     // Walk through the pattern, looking for any ops with targets that
  1908     //  were moved down by the insert.  Fix them.
  1909     int32_t loc;
  1910     for (loc=0; loc<code->size(); loc++) {
  1911         int32_t op = (int32_t)code->elementAti(loc);
  1912         int32_t opType = URX_TYPE(op);
  1913         int32_t opValue = URX_VAL(op);
  1914         if ((opType == URX_JMP         ||
  1915             opType == URX_JMPX         ||
  1916             opType == URX_STATE_SAVE   ||
  1917             opType == URX_CTR_LOOP     ||
  1918             opType == URX_CTR_LOOP_NG  ||
  1919             opType == URX_JMP_SAV      ||
  1920             opType == URX_JMP_SAV_X    ||
  1921             opType == URX_RELOC_OPRND)    && opValue > where) {
  1922             // Target location for this opcode is after the insertion point and
  1923             //   needs to be incremented to adjust for the insertion.
  1924             opValue++;
  1925             op = URX_BUILD(opType, opValue);
  1926             code->setElementAt(op, loc);
  1930     // Now fix up the parentheses stack.  All positive values in it are locations in
  1931     //  the compiled pattern.   (Negative values are frame boundaries, and don't need fixing.)
  1932     for (loc=0; loc<fParenStack.size(); loc++) {
  1933         int32_t x = fParenStack.elementAti(loc);
  1934         U_ASSERT(x < code->size());
  1935         if (x>where) {
  1936             x++;
  1937             fParenStack.setElementAt(x, loc);
  1941     if (fMatchCloseParen > where) {
  1942         fMatchCloseParen++;
  1944     if (fMatchOpenParen > where) {
  1945         fMatchOpenParen++;
  1951 //------------------------------------------------------------------------------
  1952 //
  1953 //   blockTopLoc()          Find or create a location in the compiled pattern
  1954 //                          at the start of the operation or block that has
  1955 //                          just been compiled.  Needed when a quantifier (* or
  1956 //                          whatever) appears, and we need to add an operation
  1957 //                          at the start of the thing being quantified.
  1958 //
  1959 //                          (Parenthesized Blocks) have a slot with a NOP that
  1960 //                          is reserved for this purpose.  .* or similar don't
  1961 //                          and a slot needs to be added.
  1962 //
  1963 //       parameter reserveLoc   :  TRUE -  ensure that there is space to add an opcode
  1964 //                                         at the returned location.
  1965 //                                 FALSE - just return the address,
  1966 //                                         do not reserve a location there.
  1967 //
  1968 //------------------------------------------------------------------------------
  1969 int32_t   RegexCompile::blockTopLoc(UBool reserveLoc) {
  1970     int32_t   theLoc;
  1971     fixLiterals(TRUE);  // Emit code for any pending literals.
  1972                         //   If last item was a string, emit separate op for the its last char.
  1973     if (fRXPat->fCompiledPat->size() == fMatchCloseParen)
  1975         // The item just processed is a parenthesized block.
  1976         theLoc = fMatchOpenParen;   // A slot is already reserved for us.
  1977         U_ASSERT(theLoc > 0);
  1978         U_ASSERT(URX_TYPE(((uint32_t)fRXPat->fCompiledPat->elementAti(theLoc))) == URX_NOP);
  1980     else {
  1981         // Item just compiled is a single thing, a ".", or a single char, a string or a set reference.
  1982         // No slot for STATE_SAVE was pre-reserved in the compiled code.
  1983         // We need to make space now.
  1984         theLoc = fRXPat->fCompiledPat->size()-1;
  1985         int32_t opAtTheLoc = (int32_t)fRXPat->fCompiledPat->elementAti(theLoc);
  1986         if (URX_TYPE(opAtTheLoc) == URX_STRING_LEN) {
  1987             // Strings take two opcode, we want the position of the first one.
  1988             // We can have a string at this point if a single character case-folded to two.
  1989             theLoc--;
  1991         if (reserveLoc) {
  1992             int32_t  nop = URX_BUILD(URX_NOP, 0);
  1993             fRXPat->fCompiledPat->insertElementAt(nop, theLoc, *fStatus);
  1996     return theLoc;
  2001 //------------------------------------------------------------------------------
  2002 //
  2003 //    handleCloseParen      When compiling a close paren, we need to go back
  2004 //                          and fix up any JMP or SAVE operations within the
  2005 //                          parenthesized block that need to target the end
  2006 //                          of the block.  The locations of these are kept on
  2007 //                          the paretheses stack.
  2008 //
  2009 //                          This function is called both when encountering a
  2010 //                          real ) and at the end of the pattern.
  2011 //
  2012 //------------------------------------------------------------------------------
  2013 void  RegexCompile::handleCloseParen() {
  2014     int32_t   patIdx;
  2015     int32_t   patOp;
  2016     if (fParenStack.size() <= 0) {
  2017         error(U_REGEX_MISMATCHED_PAREN);
  2018         return;
  2021     // Emit code for any pending literals.
  2022     fixLiterals(FALSE);
  2024     // Fixup any operations within the just-closed parenthesized group
  2025     //    that need to reference the end of the (block).
  2026     //    (The first one popped from the stack is an unused slot for
  2027     //     alternation (OR) state save, but applying the fixup to it does no harm.)
  2028     for (;;) {
  2029         patIdx = fParenStack.popi();
  2030         if (patIdx < 0) {
  2031             // value < 0 flags the start of the frame on the paren stack.
  2032             break;
  2034         U_ASSERT(patIdx>0 && patIdx <= fRXPat->fCompiledPat->size());
  2035         patOp = (int32_t)fRXPat->fCompiledPat->elementAti(patIdx);
  2036         U_ASSERT(URX_VAL(patOp) == 0);          // Branch target for JMP should not be set.
  2037         patOp |= fRXPat->fCompiledPat->size();  // Set it now.
  2038         fRXPat->fCompiledPat->setElementAt(patOp, patIdx);
  2039         fMatchOpenParen     = patIdx;
  2042     //  At the close of any parenthesized block, restore the match mode flags  to
  2043     //  the value they had at the open paren.  Saved value is
  2044     //  at the top of the paren stack.
  2045     fModeFlags = fParenStack.popi();
  2046     U_ASSERT(fModeFlags < 0);
  2048     // DO any additional fixups, depending on the specific kind of
  2049     // parentesized grouping this is
  2051     switch (patIdx) {
  2052     case plain:
  2053     case flags:
  2054         // No additional fixups required.
  2055         //   (Grouping-only parentheses)
  2056         break;
  2057     case capturing:
  2058         // Capturing Parentheses.
  2059         //   Insert a End Capture op into the pattern.
  2060         //   The frame offset of the variables for this cg is obtained from the
  2061         //       start capture op and put it into the end-capture op.
  2063             int32_t   captureOp = (int32_t)fRXPat->fCompiledPat->elementAti(fMatchOpenParen+1);
  2064             U_ASSERT(URX_TYPE(captureOp) == URX_START_CAPTURE);
  2066             int32_t   frameVarLocation = URX_VAL(captureOp);
  2067             int32_t   endCaptureOp = URX_BUILD(URX_END_CAPTURE, frameVarLocation);
  2068             fRXPat->fCompiledPat->addElement(endCaptureOp, *fStatus);
  2070         break;
  2071     case atomic:
  2072         // Atomic Parenthesis.
  2073         //   Insert a LD_SP operation to restore the state stack to the position
  2074         //   it was when the atomic parens were entered.
  2076             int32_t   stoOp = (int32_t)fRXPat->fCompiledPat->elementAti(fMatchOpenParen+1);
  2077             U_ASSERT(URX_TYPE(stoOp) == URX_STO_SP);
  2078             int32_t   stoLoc = URX_VAL(stoOp);
  2079             int32_t   ldOp   = URX_BUILD(URX_LD_SP, stoLoc);
  2080             fRXPat->fCompiledPat->addElement(ldOp, *fStatus);
  2082         break;
  2084     case lookAhead:
  2086             int32_t  startOp = (int32_t)fRXPat->fCompiledPat->elementAti(fMatchOpenParen-5);
  2087             U_ASSERT(URX_TYPE(startOp) == URX_LA_START);
  2088             int32_t dataLoc  = URX_VAL(startOp);
  2089             int32_t op       = URX_BUILD(URX_LA_END, dataLoc);
  2090             fRXPat->fCompiledPat->addElement(op, *fStatus);
  2092         break;
  2094     case negLookAhead:
  2096             // See comment at doOpenLookAheadNeg
  2097             int32_t  startOp = (int32_t)fRXPat->fCompiledPat->elementAti(fMatchOpenParen-1);
  2098             U_ASSERT(URX_TYPE(startOp) == URX_LA_START);
  2099             int32_t dataLoc  = URX_VAL(startOp);
  2100             int32_t op       = URX_BUILD(URX_LA_END, dataLoc);
  2101             fRXPat->fCompiledPat->addElement(op, *fStatus);
  2102             op               = URX_BUILD(URX_BACKTRACK, 0);
  2103             fRXPat->fCompiledPat->addElement(op, *fStatus);
  2104             op               = URX_BUILD(URX_LA_END, dataLoc);
  2105             fRXPat->fCompiledPat->addElement(op, *fStatus);
  2107             // Patch the URX_SAVE near the top of the block.
  2108             // The destination of the SAVE is the final LA_END that was just added.
  2109             int32_t saveOp   = (int32_t)fRXPat->fCompiledPat->elementAti(fMatchOpenParen);
  2110             U_ASSERT(URX_TYPE(saveOp) == URX_STATE_SAVE);
  2111             int32_t dest     = fRXPat->fCompiledPat->size()-1;
  2112             saveOp           = URX_BUILD(URX_STATE_SAVE, dest);
  2113             fRXPat->fCompiledPat->setElementAt(saveOp, fMatchOpenParen);
  2115         break;
  2117     case lookBehind:
  2119             // See comment at doOpenLookBehind.
  2121             // Append the URX_LB_END and URX_LA_END to the compiled pattern.
  2122             int32_t  startOp = (int32_t)fRXPat->fCompiledPat->elementAti(fMatchOpenParen-4);
  2123             U_ASSERT(URX_TYPE(startOp) == URX_LB_START);
  2124             int32_t dataLoc  = URX_VAL(startOp);
  2125             int32_t op       = URX_BUILD(URX_LB_END, dataLoc);
  2126             fRXPat->fCompiledPat->addElement(op, *fStatus);
  2127                     op       = URX_BUILD(URX_LA_END, dataLoc);
  2128             fRXPat->fCompiledPat->addElement(op, *fStatus);
  2130             // Determine the min and max bounds for the length of the
  2131             //  string that the pattern can match.
  2132             //  An unbounded upper limit is an error.
  2133             int32_t patEnd   = fRXPat->fCompiledPat->size() - 1;
  2134             int32_t minML    = minMatchLength(fMatchOpenParen, patEnd);
  2135             int32_t maxML    = maxMatchLength(fMatchOpenParen, patEnd);
  2136             if (maxML == INT32_MAX) {
  2137                 error(U_REGEX_LOOK_BEHIND_LIMIT);
  2138                 break;
  2140             U_ASSERT(minML <= maxML);
  2142             // Insert the min and max match len bounds into the URX_LB_CONT op that
  2143             //  appears at the top of the look-behind block, at location fMatchOpenParen+1
  2144             fRXPat->fCompiledPat->setElementAt(minML,  fMatchOpenParen-2);
  2145             fRXPat->fCompiledPat->setElementAt(maxML,  fMatchOpenParen-1);
  2148         break;
  2152     case lookBehindN:
  2154             // See comment at doOpenLookBehindNeg.
  2156             // Append the URX_LBN_END to the compiled pattern.
  2157             int32_t  startOp = (int32_t)fRXPat->fCompiledPat->elementAti(fMatchOpenParen-5);
  2158             U_ASSERT(URX_TYPE(startOp) == URX_LB_START);
  2159             int32_t dataLoc  = URX_VAL(startOp);
  2160             int32_t op       = URX_BUILD(URX_LBN_END, dataLoc);
  2161             fRXPat->fCompiledPat->addElement(op, *fStatus);
  2163             // Determine the min and max bounds for the length of the
  2164             //  string that the pattern can match.
  2165             //  An unbounded upper limit is an error.
  2166             int32_t patEnd   = fRXPat->fCompiledPat->size() - 1;
  2167             int32_t minML    = minMatchLength(fMatchOpenParen, patEnd);
  2168             int32_t maxML    = maxMatchLength(fMatchOpenParen, patEnd);
  2169             if (maxML == INT32_MAX) {
  2170                 error(U_REGEX_LOOK_BEHIND_LIMIT);
  2171                 break;
  2173             U_ASSERT(minML <= maxML);
  2175             // Insert the min and max match len bounds into the URX_LB_CONT op that
  2176             //  appears at the top of the look-behind block, at location fMatchOpenParen+1
  2177             fRXPat->fCompiledPat->setElementAt(minML,  fMatchOpenParen-3);
  2178             fRXPat->fCompiledPat->setElementAt(maxML,  fMatchOpenParen-2);
  2180             // Insert the pattern location to continue at after a successful match
  2181             //  as the last operand of the URX_LBN_CONT
  2182             op = URX_BUILD(URX_RELOC_OPRND, fRXPat->fCompiledPat->size());
  2183             fRXPat->fCompiledPat->setElementAt(op,  fMatchOpenParen-1);
  2185         break;
  2189     default:
  2190         U_ASSERT(FALSE);
  2193     // remember the next location in the compiled pattern.
  2194     // The compilation of Quantifiers will look at this to see whether its looping
  2195     //   over a parenthesized block or a single item
  2196     fMatchCloseParen = fRXPat->fCompiledPat->size();
  2201 //------------------------------------------------------------------------------
  2202 //
  2203 //   compileSet       Compile the pattern operations for a reference to a
  2204 //                    UnicodeSet.
  2205 //
  2206 //------------------------------------------------------------------------------
  2207 void        RegexCompile::compileSet(UnicodeSet *theSet)
  2209     if (theSet == NULL) {
  2210         return;
  2212     //  Remove any strings from the set.
  2213     //  There shoudn't be any, but just in case.
  2214     //     (Case Closure can add them; if we had a simple case closure avaialble that
  2215     //      ignored strings, that would be better.)
  2216     theSet->removeAllStrings();
  2217     int32_t  setSize = theSet->size();
  2219     switch (setSize) {
  2220     case 0:
  2222             // Set of no elements.   Always fails to match.
  2223             fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKTRACK, 0), *fStatus);
  2224             delete theSet;
  2226         break;
  2228     case 1:
  2230             // The set contains only a single code point.  Put it into
  2231             //   the compiled pattern as a single char operation rather
  2232             //   than a set, and discard the set itself.
  2233             literalChar(theSet->charAt(0));
  2234             delete theSet;
  2236         break;
  2238     default:
  2240             //  The set contains two or more chars.  (the normal case)
  2241             //  Put it into the compiled pattern as a set.
  2242             int32_t setNumber = fRXPat->fSets->size();
  2243             fRXPat->fSets->addElement(theSet, *fStatus);
  2244             int32_t setOp = URX_BUILD(URX_SETREF, setNumber);
  2245             fRXPat->fCompiledPat->addElement(setOp, *fStatus);
  2251 //------------------------------------------------------------------------------
  2252 //
  2253 //   compileInterval    Generate the code for a {min, max} style interval quantifier.
  2254 //                      Except for the specific opcodes used, the code is the same
  2255 //                      for all three types (greedy, non-greedy, possessive) of
  2256 //                      intervals.  The opcodes are supplied as parameters.
  2257 //                      (There are two sets of opcodes - greedy & possessive use the
  2258 //                      same ones, while non-greedy has it's own.)
  2259 //
  2260 //                      The code for interval loops has this form:
  2261 //                         0  CTR_INIT   counter loc (in stack frame)
  2262 //                         1             5  patt address of CTR_LOOP at bottom of block
  2263 //                         2             min count
  2264 //                         3             max count   (-1 for unbounded)
  2265 //                         4  ...        block to be iterated over
  2266 //                         5  CTR_LOOP
  2267 //
  2268 //                       In
  2269 //------------------------------------------------------------------------------
  2270 void        RegexCompile::compileInterval(int32_t InitOp,  int32_t LoopOp)
  2272     // The CTR_INIT op at the top of the block with the {n,m} quantifier takes
  2273     //   four slots in the compiled code.  Reserve them.
  2274     int32_t   topOfBlock = blockTopLoc(TRUE);
  2275     insertOp(topOfBlock);
  2276     insertOp(topOfBlock);
  2277     insertOp(topOfBlock);
  2279     // The operands for the CTR_INIT opcode include the index in the matcher data
  2280     //   of the counter.  Allocate it now. There are two data items
  2281     //        counterLoc   -->  Loop counter
  2282     //               +1    -->  Input index (for breaking non-progressing loops)
  2283     //                          (Only present if unbounded upper limit on loop)
  2284     int32_t   counterLoc = fRXPat->fFrameSize;
  2285     fRXPat->fFrameSize++;
  2286     if (fIntervalUpper < 0) {
  2287         fRXPat->fFrameSize++;
  2290     int32_t   op = URX_BUILD(InitOp, counterLoc);
  2291     fRXPat->fCompiledPat->setElementAt(op, topOfBlock);
  2293     // The second operand of CTR_INIT is the location following the end of the loop.
  2294     //   Must put in as a URX_RELOC_OPRND so that the value will be adjusted if the
  2295     //   compilation of something later on causes the code to grow and the target
  2296     //   position to move.
  2297     int32_t loopEnd = fRXPat->fCompiledPat->size();
  2298     op = URX_BUILD(URX_RELOC_OPRND, loopEnd);
  2299     fRXPat->fCompiledPat->setElementAt(op, topOfBlock+1);
  2301     // Followed by the min and max counts.
  2302     fRXPat->fCompiledPat->setElementAt(fIntervalLow, topOfBlock+2);
  2303     fRXPat->fCompiledPat->setElementAt(fIntervalUpper, topOfBlock+3);
  2305     // Apend the CTR_LOOP op.  The operand is the location of the CTR_INIT op.
  2306     //   Goes at end of the block being looped over, so just append to the code so far.
  2307     op = URX_BUILD(LoopOp, topOfBlock);
  2308     fRXPat->fCompiledPat->addElement(op, *fStatus);
  2310     if ((fIntervalLow & 0xff000000) != 0 ||
  2311         (fIntervalUpper > 0 && (fIntervalUpper & 0xff000000) != 0)) {
  2312             error(U_REGEX_NUMBER_TOO_BIG);
  2315     if (fIntervalLow > fIntervalUpper && fIntervalUpper != -1) {
  2316         error(U_REGEX_MAX_LT_MIN);
  2322 UBool RegexCompile::compileInlineInterval() {
  2323     if (fIntervalUpper > 10 || fIntervalUpper < fIntervalLow) {
  2324         // Too big to inline.  Fail, which will cause looping code to be generated.
  2325         //   (Upper < Lower picks up unbounded upper and errors, both.)
  2326         return FALSE;
  2329     int32_t   topOfBlock = blockTopLoc(FALSE);
  2330     if (fIntervalUpper == 0) {
  2331         // Pathological case.  Attempt no matches, as if the block doesn't exist.
  2332         fRXPat->fCompiledPat->setSize(topOfBlock);
  2333         return TRUE;
  2336     if (topOfBlock != fRXPat->fCompiledPat->size()-1 && fIntervalUpper != 1) {
  2337         // The thing being repeated is not a single op, but some
  2338         //   more complex block.  Do it as a loop, not inlines.
  2339         //   Note that things "repeated" a max of once are handled as inline, because
  2340         //     the one copy of the code already generated is just fine.
  2341         return FALSE;
  2344     // Pick up the opcode that is to be repeated
  2345     //
  2346     int32_t op = (int32_t)fRXPat->fCompiledPat->elementAti(topOfBlock);
  2348     // Compute the pattern location where the inline sequence
  2349     //   will end, and set up the state save op that will be needed.
  2350     //
  2351     int32_t endOfSequenceLoc = fRXPat->fCompiledPat->size()-1
  2352                                 + fIntervalUpper + (fIntervalUpper-fIntervalLow);
  2353     int32_t saveOp = URX_BUILD(URX_STATE_SAVE, endOfSequenceLoc);
  2354     if (fIntervalLow == 0) {
  2355         insertOp(topOfBlock);
  2356         fRXPat->fCompiledPat->setElementAt(saveOp, topOfBlock);
  2361     //  Loop, emitting the op for the thing being repeated each time.
  2362     //    Loop starts at 1 because one instance of the op already exists in the pattern,
  2363     //    it was put there when it was originally encountered.
  2364     int32_t i;
  2365     for (i=1; i<fIntervalUpper; i++ ) {
  2366         if (i == fIntervalLow) {
  2367             fRXPat->fCompiledPat->addElement(saveOp, *fStatus);
  2369         if (i > fIntervalLow) {
  2370             fRXPat->fCompiledPat->addElement(saveOp, *fStatus);
  2372         fRXPat->fCompiledPat->addElement(op, *fStatus);
  2374     return TRUE;
  2379 //------------------------------------------------------------------------------
  2380 //
  2381 //   matchStartType    Determine how a match can start.
  2382 //                     Used to optimize find() operations.
  2383 //
  2384 //                     Operation is very similar to minMatchLength().  Walk the compiled
  2385 //                     pattern, keeping an on-going minimum-match-length.  For any
  2386 //                     op where the min match coming in is zero, add that ops possible
  2387 //                     starting matches to the possible starts for the overall pattern.
  2388 //
  2389 //------------------------------------------------------------------------------
  2390 void   RegexCompile::matchStartType() {
  2391     if (U_FAILURE(*fStatus)) {
  2392         return;
  2396     int32_t    loc;                    // Location in the pattern of the current op being processed.
  2397     int32_t    op;                     // The op being processed
  2398     int32_t    opType;                 // The opcode type of the op
  2399     int32_t    currentLen = 0;         // Minimum length of a match to this point (loc) in the pattern
  2400     int32_t    numInitialStrings = 0;  // Number of strings encountered that could match at start.
  2402     UBool      atStart = TRUE;         // True if no part of the pattern yet encountered
  2403                                        //   could have advanced the position in a match.
  2404                                        //   (Maximum match length so far == 0)
  2406     // forwardedLength is a vector holding minimum-match-length values that
  2407     //   are propagated forward in the pattern by JMP or STATE_SAVE operations.
  2408     //   It must be one longer than the pattern being checked because some  ops
  2409     //   will jmp to a end-of-block+1 location from within a block, and we must
  2410     //   count those when checking the block.
  2411     int32_t end = fRXPat->fCompiledPat->size();
  2412     UVector32  forwardedLength(end+1, *fStatus);
  2413     forwardedLength.setSize(end+1);
  2414     for (loc=3; loc<end; loc++) {
  2415         forwardedLength.setElementAt(INT32_MAX, loc);
  2418     for (loc = 3; loc<end; loc++) {
  2419         op = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  2420         opType = URX_TYPE(op);
  2422         // The loop is advancing linearly through the pattern.
  2423         // If the op we are now at was the destination of a branch in the pattern,
  2424         // and that path has a shorter minimum length than the current accumulated value,
  2425         // replace the current accumulated value.
  2426         if (forwardedLength.elementAti(loc) < currentLen) {
  2427             currentLen = forwardedLength.elementAti(loc);
  2428             U_ASSERT(currentLen>=0 && currentLen < INT32_MAX);
  2431         switch (opType) {
  2432             // Ops that don't change the total length matched
  2433         case URX_RESERVED_OP:
  2434         case URX_END:
  2435         case URX_FAIL:
  2436         case URX_STRING_LEN:
  2437         case URX_NOP:
  2438         case URX_START_CAPTURE:
  2439         case URX_END_CAPTURE:
  2440         case URX_BACKSLASH_B:
  2441         case URX_BACKSLASH_BU:
  2442         case URX_BACKSLASH_G:
  2443         case URX_BACKSLASH_Z:
  2444         case URX_DOLLAR:
  2445         case URX_DOLLAR_M:
  2446         case URX_DOLLAR_D:
  2447         case URX_DOLLAR_MD:
  2448         case URX_RELOC_OPRND:
  2449         case URX_STO_INP_LOC:
  2450         case URX_BACKREF:         // BackRef.  Must assume that it might be a zero length match
  2451         case URX_BACKREF_I:
  2453         case URX_STO_SP:          // Setup for atomic or possessive blocks.  Doesn't change what can match.
  2454         case URX_LD_SP:
  2455             break;
  2457         case URX_CARET:
  2458             if (atStart) {
  2459                 fRXPat->fStartType = START_START;
  2461             break;
  2463         case URX_CARET_M:
  2464         case URX_CARET_M_UNIX:
  2465             if (atStart) {
  2466                 fRXPat->fStartType = START_LINE;
  2468             break;
  2470         case URX_ONECHAR:
  2471             if (currentLen == 0) {
  2472                 // This character could appear at the start of a match.
  2473                 //   Add it to the set of possible starting characters.
  2474                 fRXPat->fInitialChars->add(URX_VAL(op));
  2475                 numInitialStrings += 2;
  2477             currentLen++;
  2478             atStart = FALSE;
  2479             break;
  2482         case URX_SETREF:
  2483             if (currentLen == 0) {
  2484                 int32_t  sn = URX_VAL(op);
  2485                 U_ASSERT(sn > 0 && sn < fRXPat->fSets->size());
  2486                 const UnicodeSet *s = (UnicodeSet *)fRXPat->fSets->elementAt(sn);
  2487                 fRXPat->fInitialChars->addAll(*s);
  2488                 numInitialStrings += 2;
  2490             currentLen++;
  2491             atStart = FALSE;
  2492             break;
  2494         case URX_LOOP_SR_I:
  2495             // [Set]*, like a SETREF, above, in what it can match,
  2496             //  but may not match at all, so currentLen is not incremented.
  2497             if (currentLen == 0) {
  2498                 int32_t  sn = URX_VAL(op);
  2499                 U_ASSERT(sn > 0 && sn < fRXPat->fSets->size());
  2500                 const UnicodeSet *s = (UnicodeSet *)fRXPat->fSets->elementAt(sn);
  2501                 fRXPat->fInitialChars->addAll(*s);
  2502                 numInitialStrings += 2;
  2504             atStart = FALSE;
  2505             break;
  2507         case URX_LOOP_DOT_I:
  2508             if (currentLen == 0) {
  2509                 // .* at the start of a pattern.
  2510                 //    Any character can begin the match.
  2511                 fRXPat->fInitialChars->clear();
  2512                 fRXPat->fInitialChars->complement();
  2513                 numInitialStrings += 2;
  2515             atStart = FALSE;
  2516             break;
  2519         case URX_STATIC_SETREF:
  2520             if (currentLen == 0) {
  2521                 int32_t  sn = URX_VAL(op);
  2522                 U_ASSERT(sn>0 && sn<URX_LAST_SET);
  2523                 const UnicodeSet *s = fRXPat->fStaticSets[sn];
  2524                 fRXPat->fInitialChars->addAll(*s);
  2525                 numInitialStrings += 2;
  2527             currentLen++;
  2528             atStart = FALSE;
  2529             break;
  2533         case URX_STAT_SETREF_N:
  2534             if (currentLen == 0) {
  2535                 int32_t  sn = URX_VAL(op);
  2536                 const UnicodeSet *s = fRXPat->fStaticSets[sn];
  2537                 UnicodeSet sc(*s);
  2538                 sc.complement();
  2539                 fRXPat->fInitialChars->addAll(sc);
  2540                 numInitialStrings += 2;
  2542             currentLen++;
  2543             atStart = FALSE;
  2544             break;
  2548         case URX_BACKSLASH_D:
  2549             // Digit Char
  2550              if (currentLen == 0) {
  2551                  UnicodeSet s;
  2552                  s.applyIntPropertyValue(UCHAR_GENERAL_CATEGORY_MASK, U_GC_ND_MASK, *fStatus);
  2553                  if (URX_VAL(op) != 0) {
  2554                      s.complement();
  2556                  fRXPat->fInitialChars->addAll(s);
  2557                  numInitialStrings += 2;
  2559             currentLen++;
  2560             atStart = FALSE;
  2561             break;
  2564         case URX_ONECHAR_I:
  2565             // Case Insensitive Single Character.
  2566             if (currentLen == 0) {
  2567                 UChar32  c = URX_VAL(op);
  2568                 if (u_hasBinaryProperty(c, UCHAR_CASE_SENSITIVE)) {
  2570                     // Disable optimizations on first char of match.
  2571                     // TODO: Compute the set of chars that case fold to this char, or to
  2572                     //       a string that begins with this char.
  2573                     //       For simple case folding, this code worked:
  2574                     //   UnicodeSet s(c, c);
  2575                     //   s.closeOver(USET_CASE_INSENSITIVE);
  2576                     //   fRXPat->fInitialChars->addAll(s);
  2578                     fRXPat->fInitialChars->clear();
  2579                     fRXPat->fInitialChars->complement();
  2580                 } else {
  2581                     // Char has no case variants.  Just add it as-is to the
  2582                     //   set of possible starting chars.
  2583                     fRXPat->fInitialChars->add(c);
  2585                 numInitialStrings += 2;
  2587             currentLen++;
  2588             atStart = FALSE;
  2589             break;
  2592         case URX_BACKSLASH_X:   // Grahpeme Cluster.  Minimum is 1, max unbounded.
  2593         case URX_DOTANY_ALL:    // . matches one or two.
  2594         case URX_DOTANY:
  2595         case URX_DOTANY_UNIX:
  2596             if (currentLen == 0) {
  2597                 // These constructs are all bad news when they appear at the start
  2598                 //   of a match.  Any character can begin the match.
  2599                 fRXPat->fInitialChars->clear();
  2600                 fRXPat->fInitialChars->complement();
  2601                 numInitialStrings += 2;
  2603             currentLen++;
  2604             atStart = FALSE;
  2605             break;
  2608         case URX_JMPX:
  2609             loc++;             // Except for extra operand on URX_JMPX, same as URX_JMP.
  2610         case URX_JMP:
  2612                 int32_t  jmpDest = URX_VAL(op);
  2613                 if (jmpDest < loc) {
  2614                     // Loop of some kind.  Can safely ignore, the worst that will happen
  2615                     //  is that we understate the true minimum length
  2616                     currentLen = forwardedLength.elementAti(loc+1);
  2618                 } else {
  2619                     // Forward jump.  Propagate the current min length to the target loc of the jump.
  2620                     U_ASSERT(jmpDest <= end+1);
  2621                     if (forwardedLength.elementAti(jmpDest) > currentLen) {
  2622                         forwardedLength.setElementAt(currentLen, jmpDest);
  2626             atStart = FALSE;
  2627             break;
  2629         case URX_JMP_SAV:
  2630         case URX_JMP_SAV_X:
  2631             // Combo of state save to the next loc, + jmp backwards.
  2632             //   Net effect on min. length computation is nothing.
  2633             atStart = FALSE;
  2634             break;
  2636         case URX_BACKTRACK:
  2637             // Fails are kind of like a branch, except that the min length was
  2638             //   propagated already, by the state save.
  2639             currentLen = forwardedLength.elementAti(loc+1);
  2640             atStart = FALSE;
  2641             break;
  2644         case URX_STATE_SAVE:
  2646                 // State Save, for forward jumps, propagate the current minimum.
  2647                 //             of the state save.
  2648                 int32_t  jmpDest = URX_VAL(op);
  2649                 if (jmpDest > loc) {
  2650                     if (currentLen < forwardedLength.elementAti(jmpDest)) {
  2651                         forwardedLength.setElementAt(currentLen, jmpDest);
  2655             atStart = FALSE;
  2656             break;
  2661         case URX_STRING:
  2663                 loc++;
  2664                 int32_t stringLenOp = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  2665                 int32_t stringLen   = URX_VAL(stringLenOp);
  2666                 U_ASSERT(URX_TYPE(stringLenOp) == URX_STRING_LEN);
  2667                 U_ASSERT(stringLenOp >= 2);
  2668                 if (currentLen == 0) {
  2669                     // Add the starting character of this string to the set of possible starting
  2670                     //   characters for this pattern.
  2671                     int32_t stringStartIdx = URX_VAL(op);
  2672                     UChar32  c = fRXPat->fLiteralText.char32At(stringStartIdx);
  2673                     fRXPat->fInitialChars->add(c);
  2675                     // Remember this string.  After the entire pattern has been checked,
  2676                     //  if nothing else is identified that can start a match, we'll use it.
  2677                     numInitialStrings++;
  2678                     fRXPat->fInitialStringIdx = stringStartIdx;
  2679                     fRXPat->fInitialStringLen = stringLen;
  2682                 currentLen += stringLen;
  2683                 atStart = FALSE;
  2685             break;
  2687         case URX_STRING_I:
  2689                 // Case-insensitive string.  Unlike exact-match strings, we won't
  2690                 //   attempt a string search for possible match positions.  But we
  2691                 //   do update the set of possible starting characters.
  2692                 loc++;
  2693                 int32_t stringLenOp = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  2694                 int32_t stringLen   = URX_VAL(stringLenOp);
  2695                 U_ASSERT(URX_TYPE(stringLenOp) == URX_STRING_LEN);
  2696                 U_ASSERT(stringLenOp >= 2);
  2697                 if (currentLen == 0) {
  2698                     // Add the starting character of this string to the set of possible starting
  2699                     //   characters for this pattern.
  2700                     int32_t stringStartIdx = URX_VAL(op);
  2701                     UChar32  c = fRXPat->fLiteralText.char32At(stringStartIdx);
  2702                     UnicodeSet s(c, c);
  2704                     // TODO:  compute correct set of starting chars for full case folding.
  2705                     //        For the moment, say any char can start.
  2706                     // s.closeOver(USET_CASE_INSENSITIVE);
  2707                     s.clear();
  2708                     s.complement();
  2710                     fRXPat->fInitialChars->addAll(s);
  2711                     numInitialStrings += 2;  // Matching on an initial string not possible.
  2713                 currentLen += stringLen;
  2714                 atStart = FALSE;
  2716             break;
  2718         case URX_CTR_INIT:
  2719         case URX_CTR_INIT_NG:
  2721                 // Loop Init Ops.  These don't change the min length, but they are 4 word ops
  2722                 //   so location must be updated accordingly.
  2723                 // Loop Init Ops.
  2724                 //   If the min loop count == 0
  2725                 //      move loc forwards to the end of the loop, skipping over the body.
  2726                 //   If the min count is > 0,
  2727                 //      continue normal processing of the body of the loop.
  2728                 int32_t loopEndLoc   = (int32_t)fRXPat->fCompiledPat->elementAti(loc+1);
  2729                         loopEndLoc   = URX_VAL(loopEndLoc);
  2730                 int32_t minLoopCount = (int32_t)fRXPat->fCompiledPat->elementAti(loc+2);
  2731                 if (minLoopCount == 0) {
  2732                     // Min Loop Count of 0, treat like a forward branch and
  2733                     //   move the current minimum length up to the target
  2734                     //   (end of loop) location.
  2735                     U_ASSERT(loopEndLoc <= end+1);
  2736                     if (forwardedLength.elementAti(loopEndLoc) > currentLen) {
  2737                         forwardedLength.setElementAt(currentLen, loopEndLoc);
  2740                 loc+=3;  // Skips over operands of CTR_INIT
  2742             atStart = FALSE;
  2743             break;
  2746         case URX_CTR_LOOP:
  2747         case URX_CTR_LOOP_NG:
  2748             // Loop ops.
  2749             //  The jump is conditional, backwards only.
  2750             atStart = FALSE;
  2751             break;
  2753         case URX_LOOP_C:
  2754             // More loop ops.  These state-save to themselves.
  2755             //   don't change the minimum match
  2756             atStart = FALSE;
  2757             break;
  2760         case URX_LA_START:
  2761         case URX_LB_START:
  2763                 // Look-around.  Scan forward until the matching look-ahead end,
  2764                 //   without processing the look-around block.  This is overly pessimistic.
  2766                 // Keep track of the nesting depth of look-around blocks.  Boilerplate code for
  2767                 //   lookahead contains two LA_END instructions, so count goes up by two
  2768                 //   for each LA_START.
  2769                 int32_t  depth = (opType == URX_LA_START? 2: 1);
  2770                 for (;;) {
  2771                     loc++;
  2772                     op = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  2773                     if (URX_TYPE(op) == URX_LA_START) {
  2774                         depth+=2;
  2776                     if (URX_TYPE(op) == URX_LB_START) {
  2777                         depth++;
  2779                     if (URX_TYPE(op) == URX_LA_END || URX_TYPE(op)==URX_LBN_END) {
  2780                         depth--;
  2781                         if (depth == 0) {
  2782                             break;
  2785                     if (URX_TYPE(op) == URX_STATE_SAVE) {
  2786                         // Need this because neg lookahead blocks will FAIL to outside
  2787                         //   of the block.
  2788                         int32_t  jmpDest = URX_VAL(op);
  2789                         if (jmpDest > loc) {
  2790                             if (currentLen < forwardedLength.elementAti(jmpDest)) {
  2791                                 forwardedLength.setElementAt(currentLen, jmpDest);
  2795                     U_ASSERT(loc <= end);
  2798             break;
  2800         case URX_LA_END:
  2801         case URX_LB_CONT:
  2802         case URX_LB_END:
  2803         case URX_LBN_CONT:
  2804         case URX_LBN_END:
  2805             U_ASSERT(FALSE);     // Shouldn't get here.  These ops should be
  2806                                  //  consumed by the scan in URX_LA_START and LB_START
  2808             break;
  2810         default:
  2811             U_ASSERT(FALSE);
  2817     // We have finished walking through the ops.  Check whether some forward jump
  2818     //   propagated a shorter length to location end+1.
  2819     if (forwardedLength.elementAti(end+1) < currentLen) {
  2820         currentLen = forwardedLength.elementAti(end+1);
  2824     fRXPat->fInitialChars8->init(fRXPat->fInitialChars);
  2827     // Sort out what we should check for when looking for candidate match start positions.
  2828     // In order of preference,
  2829     //     1.   Start of input text buffer.
  2830     //     2.   A literal string.
  2831     //     3.   Start of line in multi-line mode.
  2832     //     4.   A single literal character.
  2833     //     5.   A character from a set of characters.
  2834     //
  2835     if (fRXPat->fStartType == START_START) {
  2836         // Match only at the start of an input text string.
  2837         //    start type is already set.  We're done.
  2838     } else if (numInitialStrings == 1 && fRXPat->fMinMatchLen > 0) {
  2839         // Match beginning only with a literal string.
  2840         UChar32  c = fRXPat->fLiteralText.char32At(fRXPat->fInitialStringIdx);
  2841         U_ASSERT(fRXPat->fInitialChars->contains(c));
  2842         fRXPat->fStartType   = START_STRING;
  2843         fRXPat->fInitialChar = c;
  2844     } else if (fRXPat->fStartType == START_LINE) {
  2845         // Match at start of line in Multi-Line mode.
  2846         // Nothing to do here; everything is already set.
  2847     } else if (fRXPat->fMinMatchLen == 0) {
  2848         // Zero length match possible.  We could start anywhere.
  2849         fRXPat->fStartType = START_NO_INFO;
  2850     } else if (fRXPat->fInitialChars->size() == 1) {
  2851         // All matches begin with the same char.
  2852         fRXPat->fStartType   = START_CHAR;
  2853         fRXPat->fInitialChar = fRXPat->fInitialChars->charAt(0);
  2854         U_ASSERT(fRXPat->fInitialChar != (UChar32)-1);
  2855     } else if (fRXPat->fInitialChars->contains((UChar32)0, (UChar32)0x10ffff) == FALSE &&
  2856         fRXPat->fMinMatchLen > 0) {
  2857         // Matches start with a set of character smaller than the set of all chars.
  2858         fRXPat->fStartType = START_SET;
  2859     } else {
  2860         // Matches can start with anything
  2861         fRXPat->fStartType = START_NO_INFO;
  2864     return;
  2869 //------------------------------------------------------------------------------
  2870 //
  2871 //   minMatchLength    Calculate the length of the shortest string that could
  2872 //                     match the specified pattern.
  2873 //                     Length is in 16 bit code units, not code points.
  2874 //
  2875 //                     The calculated length may not be exact.  The returned
  2876 //                     value may be shorter than the actual minimum; it must
  2877 //                     never be longer.
  2878 //
  2879 //                     start and end are the range of p-code operations to be
  2880 //                     examined.  The endpoints are included in the range.
  2881 //
  2882 //------------------------------------------------------------------------------
  2883 int32_t   RegexCompile::minMatchLength(int32_t start, int32_t end) {
  2884     if (U_FAILURE(*fStatus)) {
  2885         return 0;
  2888     U_ASSERT(start <= end);
  2889     U_ASSERT(end < fRXPat->fCompiledPat->size());
  2892     int32_t    loc;
  2893     int32_t    op;
  2894     int32_t    opType;
  2895     int32_t    currentLen = 0;
  2898     // forwardedLength is a vector holding minimum-match-length values that
  2899     //   are propagated forward in the pattern by JMP or STATE_SAVE operations.
  2900     //   It must be one longer than the pattern being checked because some  ops
  2901     //   will jmp to a end-of-block+1 location from within a block, and we must
  2902     //   count those when checking the block.
  2903     UVector32  forwardedLength(end+2, *fStatus);
  2904     forwardedLength.setSize(end+2);
  2905     for (loc=start; loc<=end+1; loc++) {
  2906         forwardedLength.setElementAt(INT32_MAX, loc);
  2909     for (loc = start; loc<=end; loc++) {
  2910         op = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  2911         opType = URX_TYPE(op);
  2913         // The loop is advancing linearly through the pattern.
  2914         // If the op we are now at was the destination of a branch in the pattern,
  2915         // and that path has a shorter minimum length than the current accumulated value,
  2916         // replace the current accumulated value.
  2917         // U_ASSERT(currentLen>=0 && currentLen < INT32_MAX);  // MinLength == INT32_MAX for some
  2918                                                                //   no-match-possible cases.
  2919         if (forwardedLength.elementAti(loc) < currentLen) {
  2920             currentLen = forwardedLength.elementAti(loc);
  2921             U_ASSERT(currentLen>=0 && currentLen < INT32_MAX);
  2924         switch (opType) {
  2925             // Ops that don't change the total length matched
  2926         case URX_RESERVED_OP:
  2927         case URX_END:
  2928         case URX_STRING_LEN:
  2929         case URX_NOP:
  2930         case URX_START_CAPTURE:
  2931         case URX_END_CAPTURE:
  2932         case URX_BACKSLASH_B:
  2933         case URX_BACKSLASH_BU:
  2934         case URX_BACKSLASH_G:
  2935         case URX_BACKSLASH_Z:
  2936         case URX_CARET:
  2937         case URX_DOLLAR:
  2938         case URX_DOLLAR_M:
  2939         case URX_DOLLAR_D:
  2940         case URX_DOLLAR_MD:
  2941         case URX_RELOC_OPRND:
  2942         case URX_STO_INP_LOC:
  2943         case URX_CARET_M:
  2944         case URX_CARET_M_UNIX:
  2945         case URX_BACKREF:         // BackRef.  Must assume that it might be a zero length match
  2946         case URX_BACKREF_I:
  2948         case URX_STO_SP:          // Setup for atomic or possessive blocks.  Doesn't change what can match.
  2949         case URX_LD_SP:
  2951         case URX_JMP_SAV:
  2952         case URX_JMP_SAV_X:
  2953             break;
  2956             // Ops that match a minimum of one character (one or two 16 bit code units.)
  2957             //
  2958         case URX_ONECHAR:
  2959         case URX_STATIC_SETREF:
  2960         case URX_STAT_SETREF_N:
  2961         case URX_SETREF:
  2962         case URX_BACKSLASH_D:
  2963         case URX_ONECHAR_I:
  2964         case URX_BACKSLASH_X:   // Grahpeme Cluster.  Minimum is 1, max unbounded.
  2965         case URX_DOTANY_ALL:    // . matches one or two.
  2966         case URX_DOTANY:
  2967         case URX_DOTANY_UNIX:
  2968             currentLen++;
  2969             break;
  2972         case URX_JMPX:
  2973             loc++;              // URX_JMPX has an extra operand, ignored here,
  2974                                 //   otherwise processed identically to URX_JMP.
  2975         case URX_JMP:
  2977                 int32_t  jmpDest = URX_VAL(op);
  2978                 if (jmpDest < loc) {
  2979                     // Loop of some kind.  Can safely ignore, the worst that will happen
  2980                     //  is that we understate the true minimum length
  2981                     currentLen = forwardedLength.elementAti(loc+1);
  2982                 } else {
  2983                     // Forward jump.  Propagate the current min length to the target loc of the jump.
  2984                     U_ASSERT(jmpDest <= end+1);
  2985                     if (forwardedLength.elementAti(jmpDest) > currentLen) {
  2986                         forwardedLength.setElementAt(currentLen, jmpDest);
  2990             break;
  2992         case URX_BACKTRACK:
  2994                 // Back-tracks are kind of like a branch, except that the min length was
  2995                 //   propagated already, by the state save.
  2996                 currentLen = forwardedLength.elementAti(loc+1);
  2998             break;
  3001         case URX_STATE_SAVE:
  3003                 // State Save, for forward jumps, propagate the current minimum.
  3004                 //             of the state save.
  3005                 int32_t  jmpDest = URX_VAL(op);
  3006                 if (jmpDest > loc) {
  3007                     if (currentLen < forwardedLength.elementAti(jmpDest)) {
  3008                         forwardedLength.setElementAt(currentLen, jmpDest);
  3012             break;
  3015         case URX_STRING:
  3017                 loc++;
  3018                 int32_t stringLenOp = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  3019                 currentLen += URX_VAL(stringLenOp);
  3021             break;
  3024         case URX_STRING_I:
  3026                 loc++;
  3027                 // TODO: with full case folding, matching input text may be shorter than
  3028                 //       the string we have here.  More smarts could put some bounds on it.
  3029                 //       Assume a min length of one for now.  A min length of zero causes
  3030                 //        optimization failures for a pattern like "string"+
  3031                 // currentLen += URX_VAL(stringLenOp);
  3032                 currentLen += 1;
  3034             break;
  3036         case URX_CTR_INIT:
  3037         case URX_CTR_INIT_NG:
  3039                 // Loop Init Ops.
  3040                 //   If the min loop count == 0
  3041                 //      move loc forwards to the end of the loop, skipping over the body.
  3042                 //   If the min count is > 0,
  3043                 //      continue normal processing of the body of the loop.
  3044                 int32_t loopEndLoc   = (int32_t)fRXPat->fCompiledPat->elementAti(loc+1);
  3045                         loopEndLoc   = URX_VAL(loopEndLoc);
  3046                 int32_t minLoopCount = (int32_t)fRXPat->fCompiledPat->elementAti(loc+2);
  3047                 if (minLoopCount == 0) {
  3048                     loc = loopEndLoc;
  3049                 } else {
  3050                     loc+=3;  // Skips over operands of CTR_INIT
  3053             break;
  3056         case URX_CTR_LOOP:
  3057         case URX_CTR_LOOP_NG:
  3058             // Loop ops.
  3059             //  The jump is conditional, backwards only.
  3060             break;
  3062         case URX_LOOP_SR_I:
  3063         case URX_LOOP_DOT_I:
  3064         case URX_LOOP_C:
  3065             // More loop ops.  These state-save to themselves.
  3066             //   don't change the minimum match - could match nothing at all.
  3067             break;
  3070         case URX_LA_START:
  3071         case URX_LB_START:
  3073                 // Look-around.  Scan forward until the matching look-ahead end,
  3074                 //   without processing the look-around block.  This is overly pessimistic for look-ahead,
  3075                 //   it assumes that the look-ahead match might be zero-length.
  3076                 //   TODO:  Positive lookahead could recursively do the block, then continue
  3077                 //          with the longer of the block or the value coming in.  Ticket 6060
  3078                 int32_t  depth = (opType == URX_LA_START? 2: 1);;
  3079                 for (;;) {
  3080                     loc++;
  3081                     op = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  3082                     if (URX_TYPE(op) == URX_LA_START) {
  3083                         // The boilerplate for look-ahead includes two LA_END insturctions,
  3084                         //    Depth will be decremented by each one when it is seen.
  3085                         depth += 2;
  3087                     if (URX_TYPE(op) == URX_LB_START) {
  3088                         depth++;
  3090                     if (URX_TYPE(op) == URX_LA_END) {
  3091                         depth--;
  3092                         if (depth == 0) {
  3093                             break;
  3096                     if (URX_TYPE(op)==URX_LBN_END) {
  3097                         depth--;
  3098                         if (depth == 0) {
  3099                             break;
  3102                     if (URX_TYPE(op) == URX_STATE_SAVE) {
  3103                         // Need this because neg lookahead blocks will FAIL to outside
  3104                         //   of the block.
  3105                         int32_t  jmpDest = URX_VAL(op);
  3106                         if (jmpDest > loc) {
  3107                             if (currentLen < forwardedLength.elementAti(jmpDest)) {
  3108                                 forwardedLength.setElementAt(currentLen, jmpDest);
  3112                     U_ASSERT(loc <= end);
  3115             break;
  3117         case URX_LA_END:
  3118         case URX_LB_CONT:
  3119         case URX_LB_END:
  3120         case URX_LBN_CONT:
  3121         case URX_LBN_END:
  3122             // Only come here if the matching URX_LA_START or URX_LB_START was not in the
  3123             //   range being sized, which happens when measuring size of look-behind blocks.
  3124             break;
  3126         default:
  3127             U_ASSERT(FALSE);
  3132     // We have finished walking through the ops.  Check whether some forward jump
  3133     //   propagated a shorter length to location end+1.
  3134     if (forwardedLength.elementAti(end+1) < currentLen) {
  3135         currentLen = forwardedLength.elementAti(end+1);
  3136         U_ASSERT(currentLen>=0 && currentLen < INT32_MAX);
  3139     return currentLen;
  3142 // Increment with overflow check.
  3143 // val and delta will both be positive.
  3145 static int32_t safeIncrement(int32_t val, int32_t delta) {
  3146     if (INT32_MAX - val > delta) {
  3147         return val + delta;
  3148     } else {
  3149         return INT32_MAX;
  3154 //------------------------------------------------------------------------------
  3155 //
  3156 //   maxMatchLength    Calculate the length of the longest string that could
  3157 //                     match the specified pattern.
  3158 //                     Length is in 16 bit code units, not code points.
  3159 //
  3160 //                     The calculated length may not be exact.  The returned
  3161 //                     value may be longer than the actual maximum; it must
  3162 //                     never be shorter.
  3163 //
  3164 //------------------------------------------------------------------------------
  3165 int32_t   RegexCompile::maxMatchLength(int32_t start, int32_t end) {
  3166     if (U_FAILURE(*fStatus)) {
  3167         return 0;
  3169     U_ASSERT(start <= end);
  3170     U_ASSERT(end < fRXPat->fCompiledPat->size());
  3173     int32_t    loc;
  3174     int32_t    op;
  3175     int32_t    opType;
  3176     int32_t    currentLen = 0;
  3177     UVector32  forwardedLength(end+1, *fStatus);
  3178     forwardedLength.setSize(end+1);
  3180     for (loc=start; loc<=end; loc++) {
  3181         forwardedLength.setElementAt(0, loc);
  3184     for (loc = start; loc<=end; loc++) {
  3185         op = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  3186         opType = URX_TYPE(op);
  3188         // The loop is advancing linearly through the pattern.
  3189         // If the op we are now at was the destination of a branch in the pattern,
  3190         // and that path has a longer maximum length than the current accumulated value,
  3191         // replace the current accumulated value.
  3192         if (forwardedLength.elementAti(loc) > currentLen) {
  3193             currentLen = forwardedLength.elementAti(loc);
  3196         switch (opType) {
  3197             // Ops that don't change the total length matched
  3198         case URX_RESERVED_OP:
  3199         case URX_END:
  3200         case URX_STRING_LEN:
  3201         case URX_NOP:
  3202         case URX_START_CAPTURE:
  3203         case URX_END_CAPTURE:
  3204         case URX_BACKSLASH_B:
  3205         case URX_BACKSLASH_BU:
  3206         case URX_BACKSLASH_G:
  3207         case URX_BACKSLASH_Z:
  3208         case URX_CARET:
  3209         case URX_DOLLAR:
  3210         case URX_DOLLAR_M:
  3211         case URX_DOLLAR_D:
  3212         case URX_DOLLAR_MD:
  3213         case URX_RELOC_OPRND:
  3214         case URX_STO_INP_LOC:
  3215         case URX_CARET_M:
  3216         case URX_CARET_M_UNIX:
  3218         case URX_STO_SP:          // Setup for atomic or possessive blocks.  Doesn't change what can match.
  3219         case URX_LD_SP:
  3221         case URX_LB_END:
  3222         case URX_LB_CONT:
  3223         case URX_LBN_CONT:
  3224         case URX_LBN_END:
  3225             break;
  3228             // Ops that increase that cause an unbounded increase in the length
  3229             //   of a matched string, or that increase it a hard to characterize way.
  3230             //   Call the max length unbounded, and stop further checking.
  3231         case URX_BACKREF:         // BackRef.  Must assume that it might be a zero length match
  3232         case URX_BACKREF_I:
  3233         case URX_BACKSLASH_X:   // Grahpeme Cluster.  Minimum is 1, max unbounded.
  3234             currentLen = INT32_MAX;
  3235             break;
  3238             // Ops that match a max of one character (possibly two 16 bit code units.)
  3239             //
  3240         case URX_STATIC_SETREF:
  3241         case URX_STAT_SETREF_N:
  3242         case URX_SETREF:
  3243         case URX_BACKSLASH_D:
  3244         case URX_ONECHAR_I:
  3245         case URX_DOTANY_ALL:
  3246         case URX_DOTANY:
  3247         case URX_DOTANY_UNIX:
  3248             currentLen = safeIncrement(currentLen, 2);
  3249             break;
  3251             // Single literal character.  Increase current max length by one or two,
  3252             //       depending on whether the char is in the supplementary range.
  3253         case URX_ONECHAR:
  3254             currentLen = safeIncrement(currentLen, 1);
  3255             if (URX_VAL(op) > 0x10000) {
  3256                 currentLen = safeIncrement(currentLen, 1);
  3258             break;
  3260             // Jumps.
  3261             //
  3262         case URX_JMP:
  3263         case URX_JMPX:
  3264         case URX_JMP_SAV:
  3265         case URX_JMP_SAV_X:
  3267                 int32_t  jmpDest = URX_VAL(op);
  3268                 if (jmpDest < loc) {
  3269                     // Loop of some kind.  Max match length is unbounded.
  3270                     currentLen = INT32_MAX;
  3271                 } else {
  3272                     // Forward jump.  Propagate the current min length to the target loc of the jump.
  3273                     if (forwardedLength.elementAti(jmpDest) < currentLen) {
  3274                         forwardedLength.setElementAt(currentLen, jmpDest);
  3276                     currentLen = 0;
  3279             break;
  3281         case URX_BACKTRACK:
  3282             // back-tracks are kind of like a branch, except that the max length was
  3283             //   propagated already, by the state save.
  3284             currentLen = forwardedLength.elementAti(loc+1);
  3285             break;
  3288         case URX_STATE_SAVE:
  3290                 // State Save, for forward jumps, propagate the current minimum.
  3291                 //               of the state save.
  3292                 //             For backwards jumps, they create a loop, maximum
  3293                 //               match length is unbounded.
  3294                 int32_t  jmpDest = URX_VAL(op);
  3295                 if (jmpDest > loc) {
  3296                     if (currentLen > forwardedLength.elementAti(jmpDest)) {
  3297                         forwardedLength.setElementAt(currentLen, jmpDest);
  3299                 } else {
  3300                     currentLen = INT32_MAX;
  3303             break;
  3308         case URX_STRING:
  3310                 loc++;
  3311                 int32_t stringLenOp = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  3312                 currentLen = safeIncrement(currentLen, URX_VAL(stringLenOp));
  3313                 break;
  3316         case URX_STRING_I:
  3317             // TODO:  This code assumes that any user string that matches will be no longer
  3318             //        than our compiled string, with case insensitive matching.
  3319             //        Our compiled string has been case-folded already.
  3320             //
  3321             //        Any matching user string will have no more code points than our
  3322             //        compiled (folded) string.  Folding may add code points, but
  3323             //        not remove them.
  3324             //
  3325             //        There is a potential problem if a supplemental code point 
  3326             //        case-folds to a BMP code point.  In this case our compiled string
  3327             //        could be shorter (in code units) than a matching user string.
  3328             //
  3329             //        At this time (Unicode 6.1) there are no such characters, and this case
  3330             //        is not being handled.  A test, intltest regex/Bug9283, will fail if
  3331             //        any problematic characters are added to Unicode.
  3332             //
  3333             //        If this happens, we can make a set of the BMP chars that the
  3334             //        troublesome supplementals fold to, scan our string, and bump the
  3335             //        currentLen one extra for each that is found.
  3336             //
  3338                 loc++;
  3339                 int32_t stringLenOp = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  3340                 currentLen = safeIncrement(currentLen, URX_VAL(stringLenOp));
  3342             break;
  3344         case URX_CTR_INIT:
  3345         case URX_CTR_INIT_NG:
  3346             // For Loops, recursively call this function on the pattern for the loop body,
  3347             //   then multiply the result by the maximum loop count.
  3349                 int32_t  loopEndLoc = URX_VAL(fRXPat->fCompiledPat->elementAti(loc+1));
  3350                 if (loopEndLoc == loc+4) {
  3351                     // Loop has an empty body. No affect on max match length.
  3352                     // Continue processing with code after the loop end.
  3353                     loc = loopEndLoc;
  3354                     break;
  3357                 int32_t maxLoopCount = fRXPat->fCompiledPat->elementAti(loc+3);
  3358                 if (maxLoopCount == -1) {
  3359                     // Unbounded Loop. No upper bound on match length.
  3360                     currentLen = INT32_MAX;
  3361                     break;
  3364                 U_ASSERT(loopEndLoc >= loc+4);
  3365                 int32_t  blockLen = maxMatchLength(loc+4, loopEndLoc-1);  // Recursive call.
  3366                 if (blockLen == INT32_MAX) {
  3367                     currentLen = blockLen;
  3368                     break;
  3370                 currentLen += blockLen * maxLoopCount;
  3371                 loc = loopEndLoc;
  3372                 break;
  3375         case URX_CTR_LOOP:
  3376         case URX_CTR_LOOP_NG:
  3377             // These opcodes will be skipped over by code for URX_CRT_INIT.
  3378             // We shouldn't encounter them here.
  3379             U_ASSERT(FALSE);
  3380             break;
  3382         case URX_LOOP_SR_I:
  3383         case URX_LOOP_DOT_I:
  3384         case URX_LOOP_C:
  3385             // For anything to do with loops, make the match length unbounded.
  3386             currentLen = INT32_MAX;
  3387             break;
  3391         case URX_LA_START:
  3392         case URX_LA_END:
  3393             // Look-ahead.  Just ignore, treat the look-ahead block as if
  3394             // it were normal pattern.  Gives a too-long match length,
  3395             //  but good enough for now.
  3396             break;
  3398             // End of look-ahead ops should always be consumed by the processing at
  3399             //  the URX_LA_START op.
  3400             // U_ASSERT(FALSE);
  3401             // break;
  3403         case URX_LB_START:
  3405                 // Look-behind.  Scan forward until the matching look-around end,
  3406                 //   without processing the look-behind block.
  3407                 int32_t  depth = 0;
  3408                 for (;;) {
  3409                     loc++;
  3410                     op = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  3411                     if (URX_TYPE(op) == URX_LA_START || URX_TYPE(op) == URX_LB_START) {
  3412                         depth++;
  3414                     if (URX_TYPE(op) == URX_LA_END || URX_TYPE(op)==URX_LBN_END) {
  3415                         if (depth == 0) {
  3416                             break;
  3418                         depth--;
  3420                     U_ASSERT(loc < end);
  3423             break;
  3425         default:
  3426             U_ASSERT(FALSE);
  3430         if (currentLen == INT32_MAX) {
  3431             //  The maximum length is unbounded.
  3432             //  Stop further processing of the pattern.
  3433             break;
  3437     return currentLen;
  3442 //------------------------------------------------------------------------------
  3443 //
  3444 //   stripNOPs    Remove any NOP operations from the compiled pattern code.
  3445 //                Extra NOPs are inserted for some constructs during the initial
  3446 //                code generation to provide locations that may be patched later.
  3447 //                Many end up unneeded, and are removed by this function.
  3448 //
  3449 //                In order to minimize the number of passes through the pattern,
  3450 //                back-reference fixup is also performed here (adjusting
  3451 //                back-reference operands to point to the correct frame offsets).
  3452 //
  3453 //------------------------------------------------------------------------------
  3454 void RegexCompile::stripNOPs() {
  3456     if (U_FAILURE(*fStatus)) {
  3457         return;
  3460     int32_t    end = fRXPat->fCompiledPat->size();
  3461     UVector32  deltas(end, *fStatus);
  3463     // Make a first pass over the code, computing the amount that things
  3464     //   will be offset at each location in the original code.
  3465     int32_t   loc;
  3466     int32_t   d = 0;
  3467     for (loc=0; loc<end; loc++) {
  3468         deltas.addElement(d, *fStatus);
  3469         int32_t op = (int32_t)fRXPat->fCompiledPat->elementAti(loc);
  3470         if (URX_TYPE(op) == URX_NOP) {
  3471             d++;
  3475     UnicodeString caseStringBuffer;
  3477     // Make a second pass over the code, removing the NOPs by moving following
  3478     //  code up, and patching operands that refer to code locations that
  3479     //  are being moved.  The array of offsets from the first step is used
  3480     //  to compute the new operand values.
  3481     int32_t src;
  3482     int32_t dst = 0;
  3483     for (src=0; src<end; src++) {
  3484         int32_t op = (int32_t)fRXPat->fCompiledPat->elementAti(src);
  3485         int32_t opType = URX_TYPE(op);
  3486         switch (opType) {
  3487         case URX_NOP:
  3488             break;
  3490         case URX_STATE_SAVE:
  3491         case URX_JMP:
  3492         case URX_CTR_LOOP:
  3493         case URX_CTR_LOOP_NG:
  3494         case URX_RELOC_OPRND:
  3495         case URX_JMPX:
  3496         case URX_JMP_SAV:
  3497         case URX_JMP_SAV_X:
  3498             // These are instructions with operands that refer to code locations.
  3500                 int32_t  operandAddress = URX_VAL(op);
  3501                 U_ASSERT(operandAddress>=0 && operandAddress<deltas.size());
  3502                 int32_t fixedOperandAddress = operandAddress - deltas.elementAti(operandAddress);
  3503                 op = URX_BUILD(opType, fixedOperandAddress);
  3504                 fRXPat->fCompiledPat->setElementAt(op, dst);
  3505                 dst++;
  3506                 break;
  3509         case URX_BACKREF:
  3510         case URX_BACKREF_I:
  3512                 int32_t where = URX_VAL(op);
  3513                 if (where > fRXPat->fGroupMap->size()) {
  3514                     error(U_REGEX_INVALID_BACK_REF);
  3515                     break;
  3517                 where = fRXPat->fGroupMap->elementAti(where-1);
  3518                 op    = URX_BUILD(opType, where);
  3519                 fRXPat->fCompiledPat->setElementAt(op, dst);
  3520                 dst++;
  3522                 fRXPat->fNeedsAltInput = TRUE;
  3523                 break;
  3525         case URX_RESERVED_OP:
  3526         case URX_RESERVED_OP_N:
  3527         case URX_BACKTRACK:
  3528         case URX_END:
  3529         case URX_ONECHAR:
  3530         case URX_STRING:
  3531         case URX_STRING_LEN:
  3532         case URX_START_CAPTURE:
  3533         case URX_END_CAPTURE:
  3534         case URX_STATIC_SETREF:
  3535         case URX_STAT_SETREF_N:
  3536         case URX_SETREF:
  3537         case URX_DOTANY:
  3538         case URX_FAIL:
  3539         case URX_BACKSLASH_B:
  3540         case URX_BACKSLASH_BU:
  3541         case URX_BACKSLASH_G:
  3542         case URX_BACKSLASH_X:
  3543         case URX_BACKSLASH_Z:
  3544         case URX_DOTANY_ALL:
  3545         case URX_BACKSLASH_D:
  3546         case URX_CARET:
  3547         case URX_DOLLAR:
  3548         case URX_CTR_INIT:
  3549         case URX_CTR_INIT_NG:
  3550         case URX_DOTANY_UNIX:
  3551         case URX_STO_SP:
  3552         case URX_LD_SP:
  3553         case URX_STO_INP_LOC:
  3554         case URX_LA_START:
  3555         case URX_LA_END:
  3556         case URX_ONECHAR_I:
  3557         case URX_STRING_I:
  3558         case URX_DOLLAR_M:
  3559         case URX_CARET_M:
  3560         case URX_CARET_M_UNIX:
  3561         case URX_LB_START:
  3562         case URX_LB_CONT:
  3563         case URX_LB_END:
  3564         case URX_LBN_CONT:
  3565         case URX_LBN_END:
  3566         case URX_LOOP_SR_I:
  3567         case URX_LOOP_DOT_I:
  3568         case URX_LOOP_C:
  3569         case URX_DOLLAR_D:
  3570         case URX_DOLLAR_MD:
  3571             // These instructions are unaltered by the relocation.
  3572             fRXPat->fCompiledPat->setElementAt(op, dst);
  3573             dst++;
  3574             break;
  3576         default:
  3577             // Some op is unaccounted for.
  3578             U_ASSERT(FALSE);
  3579             error(U_REGEX_INTERNAL_ERROR);
  3583     fRXPat->fCompiledPat->setSize(dst);
  3589 //------------------------------------------------------------------------------
  3590 //
  3591 //  Error         Report a rule parse error.
  3592 //                Only report it if no previous error has been recorded.
  3593 //
  3594 //------------------------------------------------------------------------------
  3595 void RegexCompile::error(UErrorCode e) {
  3596     if (U_SUCCESS(*fStatus)) {
  3597         *fStatus = e;
  3598         // Hmm. fParseErr (UParseError) line & offset fields are int32_t in public
  3599         // API (see common/unicode/parseerr.h), while fLineNum and fCharNum are
  3600         // int64_t. If the values of the latter are out of range for the former,
  3601         // set them to the appropriate "field not supported" values.
  3602         if (fLineNum > 0x7FFFFFFF) {
  3603             fParseErr->line   = 0;
  3604             fParseErr->offset = -1;
  3605         } else if (fCharNum > 0x7FFFFFFF) {
  3606             fParseErr->line   = (int32_t)fLineNum;
  3607             fParseErr->offset = -1;
  3608         } else {
  3609             fParseErr->line   = (int32_t)fLineNum;
  3610             fParseErr->offset = (int32_t)fCharNum;
  3613         UErrorCode status = U_ZERO_ERROR; // throwaway status for extracting context
  3615         // Fill in the context.
  3616         //   Note: extractBetween() pins supplied indicies to the string bounds.
  3617         uprv_memset(fParseErr->preContext,  0, sizeof(fParseErr->preContext));
  3618         uprv_memset(fParseErr->postContext, 0, sizeof(fParseErr->postContext));
  3619         utext_extract(fRXPat->fPattern, fScanIndex-U_PARSE_CONTEXT_LEN+1, fScanIndex, fParseErr->preContext, U_PARSE_CONTEXT_LEN, &status);
  3620         utext_extract(fRXPat->fPattern, fScanIndex, fScanIndex+U_PARSE_CONTEXT_LEN-1, fParseErr->postContext, U_PARSE_CONTEXT_LEN, &status);
  3625 //
  3626 //  Assorted Unicode character constants.
  3627 //     Numeric because there is no portable way to enter them as literals.
  3628 //     (Think EBCDIC).
  3629 //
  3630 static const UChar      chCR        = 0x0d;      // New lines, for terminating comments.
  3631 static const UChar      chLF        = 0x0a;      // Line Feed
  3632 static const UChar      chPound     = 0x23;      // '#', introduces a comment.
  3633 static const UChar      chDigit0    = 0x30;      // '0'
  3634 static const UChar      chDigit7    = 0x37;      // '9'
  3635 static const UChar      chColon     = 0x3A;      // ':'
  3636 static const UChar      chE         = 0x45;      // 'E'
  3637 static const UChar      chQ         = 0x51;      // 'Q'
  3638 //static const UChar      chN         = 0x4E;      // 'N'
  3639 static const UChar      chP         = 0x50;      // 'P'
  3640 static const UChar      chBackSlash = 0x5c;      // '\'  introduces a char escape
  3641 //static const UChar      chLBracket  = 0x5b;      // '['
  3642 static const UChar      chRBracket  = 0x5d;      // ']'
  3643 static const UChar      chUp        = 0x5e;      // '^'
  3644 static const UChar      chLowerP    = 0x70;
  3645 static const UChar      chLBrace    = 0x7b;      // '{'
  3646 static const UChar      chRBrace    = 0x7d;      // '}'
  3647 static const UChar      chNEL       = 0x85;      //    NEL newline variant
  3648 static const UChar      chLS        = 0x2028;    //    Unicode Line Separator
  3651 //------------------------------------------------------------------------------
  3652 //
  3653 //  nextCharLL    Low Level Next Char from the regex pattern.
  3654 //                Get a char from the string, keep track of input position
  3655 //                     for error reporting.
  3656 //
  3657 //------------------------------------------------------------------------------
  3658 UChar32  RegexCompile::nextCharLL() {
  3659     UChar32       ch;
  3661     if (fPeekChar != -1) {
  3662         ch = fPeekChar;
  3663         fPeekChar = -1;
  3664         return ch;
  3667     // assume we're already in the right place
  3668     ch = UTEXT_NEXT32(fRXPat->fPattern);
  3669     if (ch == U_SENTINEL) {
  3670         return ch;
  3673     if (ch == chCR ||
  3674         ch == chNEL ||
  3675         ch == chLS   ||
  3676         (ch == chLF && fLastChar != chCR)) {
  3677         // Character is starting a new line.  Bump up the line number, and
  3678         //  reset the column to 0.
  3679         fLineNum++;
  3680         fCharNum=0;
  3682     else {
  3683         // Character is not starting a new line.  Except in the case of a
  3684         //   LF following a CR, increment the column position.
  3685         if (ch != chLF) {
  3686             fCharNum++;
  3689     fLastChar = ch;
  3690     return ch;
  3693 //------------------------------------------------------------------------------
  3694 //
  3695 //   peekCharLL    Low Level Character Scanning, sneak a peek at the next
  3696 //                 character without actually getting it.
  3697 //
  3698 //------------------------------------------------------------------------------
  3699 UChar32  RegexCompile::peekCharLL() {
  3700     if (fPeekChar == -1) {
  3701         fPeekChar = nextCharLL();
  3703     return fPeekChar;
  3707 //------------------------------------------------------------------------------
  3708 //
  3709 //   nextChar     for pattern scanning.  At this level, we handle stripping
  3710 //                out comments and processing some backslash character escapes.
  3711 //                The rest of the pattern grammar is handled at the next level up.
  3712 //
  3713 //------------------------------------------------------------------------------
  3714 void RegexCompile::nextChar(RegexPatternChar &c) {
  3716     fScanIndex = UTEXT_GETNATIVEINDEX(fRXPat->fPattern);
  3717     c.fChar    = nextCharLL();
  3718     c.fQuoted  = FALSE;
  3720     if (fQuoteMode) {
  3721         c.fQuoted = TRUE;
  3722         if ((c.fChar==chBackSlash && peekCharLL()==chE && ((fModeFlags & UREGEX_LITERAL) == 0)) || 
  3723             c.fChar == (UChar32)-1) {
  3724             fQuoteMode = FALSE;  //  Exit quote mode,
  3725             nextCharLL();        // discard the E
  3726             nextChar(c);         // recurse to get the real next char
  3729     else if (fInBackslashQuote) {
  3730         // The current character immediately follows a '\'
  3731         // Don't check for any further escapes, just return it as-is.
  3732         // Don't set c.fQuoted, because that would prevent the state machine from
  3733         //    dispatching on the character.
  3734         fInBackslashQuote = FALSE;
  3736     else
  3738         // We are not in a \Q quoted region \E of the source.
  3739         //
  3740         if (fModeFlags & UREGEX_COMMENTS) {
  3741             //
  3742             // We are in free-spacing and comments mode.
  3743             //  Scan through any white space and comments, until we
  3744             //  reach a significant character or the end of inut.
  3745             for (;;) {
  3746                 if (c.fChar == (UChar32)-1) {
  3747                     break;     // End of Input
  3749                 if  (c.fChar == chPound && fEOLComments == TRUE) {
  3750                     // Start of a comment.  Consume the rest of it, until EOF or a new line
  3751                     for (;;) {
  3752                         c.fChar = nextCharLL();
  3753                         if (c.fChar == (UChar32)-1 ||  // EOF
  3754                             c.fChar == chCR        ||
  3755                             c.fChar == chLF        ||
  3756                             c.fChar == chNEL       ||
  3757                             c.fChar == chLS)       {
  3758                             break;
  3762                 // TODO:  check what Java & Perl do with non-ASCII white spaces.  Ticket 6061.
  3763                 if (PatternProps::isWhiteSpace(c.fChar) == FALSE) {
  3764                     break;
  3766                 c.fChar = nextCharLL();
  3770         //
  3771         //  check for backslash escaped characters.
  3772         //
  3773         if (c.fChar == chBackSlash) {
  3774             int64_t pos = UTEXT_GETNATIVEINDEX(fRXPat->fPattern);
  3775             if (RegexStaticSets::gStaticSets->fUnescapeCharSet.contains(peekCharLL())) {
  3776                 //
  3777                 // A '\' sequence that is handled by ICU's standard unescapeAt function.
  3778                 //   Includes \uxxxx, \n, \r, many others.
  3779                 //   Return the single equivalent character.
  3780                 //
  3781                 nextCharLL();                 // get & discard the peeked char.
  3782                 c.fQuoted = TRUE;
  3784                 if (UTEXT_FULL_TEXT_IN_CHUNK(fRXPat->fPattern, fPatternLength)) {
  3785                     int32_t endIndex = (int32_t)pos;
  3786                     c.fChar = u_unescapeAt(uregex_ucstr_unescape_charAt, &endIndex, (int32_t)fPatternLength, (void *)fRXPat->fPattern->chunkContents);
  3788                     if (endIndex == pos) {
  3789                         error(U_REGEX_BAD_ESCAPE_SEQUENCE);
  3791                     fCharNum += endIndex - pos;
  3792                     UTEXT_SETNATIVEINDEX(fRXPat->fPattern, endIndex);
  3793                 } else {
  3794                     int32_t offset = 0;
  3795                     struct URegexUTextUnescapeCharContext context = U_REGEX_UTEXT_UNESCAPE_CONTEXT(fRXPat->fPattern);
  3797                     UTEXT_SETNATIVEINDEX(fRXPat->fPattern, pos);
  3798                     c.fChar = u_unescapeAt(uregex_utext_unescape_charAt, &offset, INT32_MAX, &context);
  3800                     if (offset == 0) {
  3801                         error(U_REGEX_BAD_ESCAPE_SEQUENCE);
  3802                     } else if (context.lastOffset == offset) {
  3803                         UTEXT_PREVIOUS32(fRXPat->fPattern);
  3804                     } else if (context.lastOffset != offset-1) {
  3805                         utext_moveIndex32(fRXPat->fPattern, offset - context.lastOffset - 1);
  3807                     fCharNum += offset;
  3810             else if (peekCharLL() == chDigit0) {
  3811                 //  Octal Escape, using Java Regexp Conventions
  3812                 //    which are \0 followed by 1-3 octal digits.
  3813                 //    Different from ICU Unescape handling of Octal, which does not
  3814                 //    require the leading 0.
  3815                 //  Java also has the convention of only consuming 2 octal digits if
  3816                 //    the three digit number would be > 0xff
  3817                 //
  3818                 c.fChar = 0;
  3819                 nextCharLL();    // Consume the initial 0.
  3820                 int index;
  3821                 for (index=0; index<3; index++) {
  3822                     int32_t ch = peekCharLL();
  3823                     if (ch<chDigit0 || ch>chDigit7) {
  3824                         if (index==0) {
  3825                            // \0 is not followed by any octal digits.
  3826                            error(U_REGEX_BAD_ESCAPE_SEQUENCE);
  3828                         break;
  3830                     c.fChar <<= 3;
  3831                     c.fChar += ch&7;
  3832                     if (c.fChar <= 255) {
  3833                         nextCharLL();
  3834                     } else {
  3835                         // The last digit made the number too big.  Forget we saw it.
  3836                         c.fChar >>= 3;
  3839                 c.fQuoted = TRUE; 
  3841             else if (peekCharLL() == chQ) {
  3842                 //  "\Q"  enter quote mode, which will continue until "\E"
  3843                 fQuoteMode = TRUE;
  3844                 nextCharLL();       // discard the 'Q'.
  3845                 nextChar(c);        // recurse to get the real next char.
  3847             else
  3849                 // We are in a '\' escape that will be handled by the state table scanner.
  3850                 // Just return the backslash, but remember that the following char is to
  3851                 //  be taken literally.
  3852                 fInBackslashQuote = TRUE;
  3857     // re-enable # to end-of-line comments, in case they were disabled.
  3858     // They are disabled by the parser upon seeing '(?', but this lasts for
  3859     //  the fetching of the next character only.
  3860     fEOLComments = TRUE;
  3862     // putc(c.fChar, stdout);
  3867 //------------------------------------------------------------------------------
  3868 //
  3869 //  scanNamedChar
  3870  //            Get a UChar32 from a \N{UNICODE CHARACTER NAME} in the pattern.
  3871 //
  3872 //             The scan position will be at the 'N'.  On return
  3873 //             the scan position should be just after the '}'
  3874 //
  3875 //             Return the UChar32
  3876 //
  3877 //------------------------------------------------------------------------------
  3878 UChar32  RegexCompile::scanNamedChar() {
  3879     if (U_FAILURE(*fStatus)) {
  3880         return 0;
  3883     nextChar(fC);
  3884     if (fC.fChar != chLBrace) {
  3885         error(U_REGEX_PROPERTY_SYNTAX);
  3886         return 0;
  3889     UnicodeString  charName;
  3890     for (;;) {
  3891         nextChar(fC);
  3892         if (fC.fChar == chRBrace) {
  3893             break;
  3895         if (fC.fChar == -1) {
  3896             error(U_REGEX_PROPERTY_SYNTAX);
  3897             return 0;
  3899         charName.append(fC.fChar);
  3902     char name[100];
  3903     if (!uprv_isInvariantUString(charName.getBuffer(), charName.length()) ||
  3904          (uint32_t)charName.length()>=sizeof(name)) {
  3905         // All Unicode character names have only invariant characters.
  3906         // The API to get a character, given a name, accepts only char *, forcing us to convert,
  3907         //   which requires this error check
  3908         error(U_REGEX_PROPERTY_SYNTAX);
  3909         return 0;
  3911     charName.extract(0, charName.length(), name, sizeof(name), US_INV);
  3913     UChar32  theChar = u_charFromName(U_UNICODE_CHAR_NAME, name, fStatus);
  3914     if (U_FAILURE(*fStatus)) {
  3915         error(U_REGEX_PROPERTY_SYNTAX);
  3918     nextChar(fC);      // Continue overall regex pattern processing with char after the '}'
  3919     return theChar;
  3922 //------------------------------------------------------------------------------
  3923 //
  3924 //  scanProp   Construct a UnicodeSet from the text at the current scan
  3925 //             position, which will be of the form \p{whaterver}
  3926 //
  3927 //             The scan position will be at the 'p' or 'P'.  On return
  3928 //             the scan position should be just after the '}'
  3929 //
  3930 //             Return a UnicodeSet, constructed from the \P pattern,
  3931 //             or NULL if the pattern is invalid.
  3932 //
  3933 //------------------------------------------------------------------------------
  3934 UnicodeSet *RegexCompile::scanProp() {
  3935     UnicodeSet    *uset = NULL;
  3937     if (U_FAILURE(*fStatus)) {
  3938         return NULL;
  3940     U_ASSERT(fC.fChar == chLowerP || fC.fChar == chP);
  3941     UBool negated = (fC.fChar == chP);
  3943     UnicodeString propertyName;
  3944     nextChar(fC);
  3945     if (fC.fChar != chLBrace) {
  3946         error(U_REGEX_PROPERTY_SYNTAX);
  3947         return NULL;
  3949     for (;;) {
  3950         nextChar(fC);
  3951         if (fC.fChar == chRBrace) {
  3952             break;
  3954         if (fC.fChar == -1) {
  3955             // Hit the end of the input string without finding the closing '}'
  3956             error(U_REGEX_PROPERTY_SYNTAX);
  3957             return NULL;
  3959         propertyName.append(fC.fChar);
  3961     uset = createSetForProperty(propertyName, negated);
  3962     nextChar(fC);    // Move input scan to position following the closing '}'
  3963     return uset;
  3966 //------------------------------------------------------------------------------
  3967 //
  3968 //  scanPosixProp   Construct a UnicodeSet from the text at the current scan
  3969 //             position, which is expected be of the form [:property expression:]
  3970 //
  3971 //             The scan position will be at the opening ':'.  On return
  3972 //             the scan position must be on the closing ']'
  3973 //
  3974 //             Return a UnicodeSet constructed from the pattern,
  3975 //             or NULL if this is not a valid POSIX-style set expression.
  3976 //             If not a property expression, restore the initial scan position
  3977 //                (to the opening ':')
  3978 //
  3979 //               Note:  the opening '[:' is not sufficient to guarantee that
  3980 //                      this is a [:property:] expression.
  3981 //                      [:'+=,] is a perfectly good ordinary set expression that
  3982 //                              happens to include ':' as one of its characters.
  3983 //
  3984 //------------------------------------------------------------------------------
  3985 UnicodeSet *RegexCompile::scanPosixProp() {
  3986     UnicodeSet    *uset = NULL;
  3988     if (U_FAILURE(*fStatus)) {
  3989         return NULL;
  3992     U_ASSERT(fC.fChar == chColon);
  3994     // Save the scanner state.
  3995     // TODO:  move this into the scanner, with the state encapsulated in some way.  Ticket 6062
  3996     int64_t     savedScanIndex        = fScanIndex;
  3997     int64_t     savedNextIndex        = UTEXT_GETNATIVEINDEX(fRXPat->fPattern);
  3998     UBool       savedQuoteMode        = fQuoteMode;
  3999     UBool       savedInBackslashQuote = fInBackslashQuote;
  4000     UBool       savedEOLComments      = fEOLComments;
  4001     int64_t     savedLineNum          = fLineNum;
  4002     int64_t     savedCharNum          = fCharNum;
  4003     UChar32     savedLastChar         = fLastChar;
  4004     UChar32     savedPeekChar         = fPeekChar;
  4005     RegexPatternChar savedfC          = fC;
  4007     // Scan for a closing ].   A little tricky because there are some perverse
  4008     //   edge cases possible.  "[:abc\Qdef:] \E]"  is a valid non-property expression,
  4009     //   ending on the second closing ]. 
  4011     UnicodeString propName;
  4012     UBool         negated  = FALSE;
  4014     // Check for and consume the '^' in a negated POSIX property, e.g.  [:^Letter:]
  4015     nextChar(fC);
  4016     if (fC.fChar == chUp) {
  4017        negated = TRUE;
  4018        nextChar(fC);
  4021     // Scan for the closing ":]", collecting the property name along the way.
  4022     UBool  sawPropSetTerminator = FALSE;
  4023     for (;;) {
  4024         propName.append(fC.fChar);
  4025         nextChar(fC);
  4026         if (fC.fQuoted || fC.fChar == -1) {
  4027             // Escaped characters or end of input - either says this isn't a [:Property:]
  4028             break;
  4030         if (fC.fChar == chColon) {
  4031             nextChar(fC);
  4032             if (fC.fChar == chRBracket) {
  4033                 sawPropSetTerminator = TRUE;
  4035             break;
  4039     if (sawPropSetTerminator) {
  4040         uset = createSetForProperty(propName, negated);
  4042     else
  4044         // No closing ":]".
  4045         //  Restore the original scan position.
  4046         //  The main scanner will retry the input as a normal set expression,
  4047         //    not a [:Property:] expression.
  4048         fScanIndex        = savedScanIndex;
  4049         fQuoteMode        = savedQuoteMode;
  4050         fInBackslashQuote = savedInBackslashQuote;
  4051         fEOLComments      = savedEOLComments;
  4052         fLineNum          = savedLineNum;
  4053         fCharNum          = savedCharNum;
  4054         fLastChar         = savedLastChar;
  4055         fPeekChar         = savedPeekChar;
  4056         fC                = savedfC;
  4057         UTEXT_SETNATIVEINDEX(fRXPat->fPattern, savedNextIndex);
  4059     return uset;
  4062 static inline void addIdentifierIgnorable(UnicodeSet *set, UErrorCode& ec) {
  4063     set->add(0, 8).add(0x0e, 0x1b).add(0x7f, 0x9f);
  4064     addCategory(set, U_GC_CF_MASK, ec);
  4067 //
  4068 //  Create a Unicode Set from a Unicode Property expression.
  4069 //     This is common code underlying both \p{...} ane [:...:] expressions.
  4070 //     Includes trying the Java "properties" that aren't supported as
  4071 //     normal ICU UnicodeSet properties 
  4072 //
  4073 static const UChar posSetPrefix[] = {0x5b, 0x5c, 0x70, 0x7b, 0}; // "[\p{"
  4074 static const UChar negSetPrefix[] = {0x5b, 0x5c, 0x50, 0x7b, 0}; // "[\P{"
  4075 UnicodeSet *RegexCompile::createSetForProperty(const UnicodeString &propName, UBool negated) {
  4076     UnicodeString   setExpr;
  4077     UnicodeSet      *set;
  4078     uint32_t        usetFlags = 0;
  4080     if (U_FAILURE(*fStatus)) {
  4081         return NULL;
  4084     //
  4085     //  First try the property as we received it
  4086     //
  4087     if (negated) {
  4088         setExpr.append(negSetPrefix, -1);
  4089     } else {
  4090         setExpr.append(posSetPrefix, -1);
  4092     setExpr.append(propName);
  4093     setExpr.append(chRBrace);
  4094     setExpr.append(chRBracket);
  4095     if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
  4096         usetFlags |= USET_CASE_INSENSITIVE;
  4098     set = new UnicodeSet(setExpr, usetFlags, NULL, *fStatus);
  4099     if (U_SUCCESS(*fStatus)) {
  4100        return set;
  4102     delete set;
  4103     set = NULL;
  4105     //
  4106     //  The property as it was didn't work.
  4108     //  Do [:word:]. It is not recognized as a property by UnicodeSet.  "word" not standard POSIX 
  4109     //     or standard Java, but many other regular expression packages do recognize it.
  4111     if (propName.caseCompare(UNICODE_STRING_SIMPLE("word"), 0) == 0) {
  4112         *fStatus = U_ZERO_ERROR;
  4113         set = new UnicodeSet(*(fRXPat->fStaticSets[URX_ISWORD_SET]));
  4114         if (set == NULL) {
  4115             *fStatus = U_MEMORY_ALLOCATION_ERROR;
  4116             return set;
  4118         if (negated) {
  4119             set->complement();
  4121         return set;
  4125     //    Do Java fixes -
  4126     //       InGreek -> InGreek or Coptic, that being the official Unicode name for that block.
  4127     //       InCombiningMarksforSymbols -> InCombiningDiacriticalMarksforSymbols.
  4128     //
  4129     //       Note on Spaces:  either "InCombiningMarksForSymbols" or "InCombining Marks for Symbols"
  4130     //                        is accepted by Java.  The property part of the name is compared 
  4131     //                        case-insenstively.  The spaces must be exactly as shown, either
  4132     //                        all there, or all omitted, with exactly one at each position
  4133     //                        if they are present.  From checking against JDK 1.6
  4134     //
  4135     //       This code should be removed when ICU properties support the Java  compatibility names
  4136     //          (ICU 4.0?)
  4137     //
  4138     UnicodeString mPropName = propName;
  4139     if (mPropName.caseCompare(UNICODE_STRING_SIMPLE("InGreek"), 0) == 0) {
  4140         mPropName = UNICODE_STRING_SIMPLE("InGreek and Coptic");
  4142     if (mPropName.caseCompare(UNICODE_STRING_SIMPLE("InCombining Marks for Symbols"), 0) == 0 ||
  4143         mPropName.caseCompare(UNICODE_STRING_SIMPLE("InCombiningMarksforSymbols"), 0) == 0) {
  4144         mPropName = UNICODE_STRING_SIMPLE("InCombining Diacritical Marks for Symbols");
  4146     else if (mPropName.compare(UNICODE_STRING_SIMPLE("all")) == 0) {
  4147         mPropName = UNICODE_STRING_SIMPLE("javaValidCodePoint");
  4150     //    See if the property looks like a Java "InBlockName", which
  4151     //    we will recast as "Block=BlockName"
  4152     //
  4153     static const UChar IN[] = {0x49, 0x6E, 0};  // "In"
  4154     static const UChar BLOCK[] = {0x42, 0x6C, 0x6f, 0x63, 0x6b, 0x3d, 00};  // "Block="
  4155     if (mPropName.startsWith(IN, 2) && propName.length()>=3) {
  4156         setExpr.truncate(4);   // Leaves "[\p{", or "[\P{"
  4157         setExpr.append(BLOCK, -1);
  4158         setExpr.append(UnicodeString(mPropName, 2));  // Property with the leading "In" removed.
  4159         setExpr.append(chRBrace);
  4160         setExpr.append(chRBracket);
  4161         *fStatus = U_ZERO_ERROR;
  4162         set = new UnicodeSet(setExpr, usetFlags, NULL, *fStatus);
  4163         if (U_SUCCESS(*fStatus)) {
  4164             return set;
  4166         delete set;
  4167         set = NULL;
  4170     if (propName.startsWith(UNICODE_STRING_SIMPLE("java")) ||
  4171         propName.compare(UNICODE_STRING_SIMPLE("all")) == 0)
  4173         UErrorCode localStatus = U_ZERO_ERROR;
  4174         //setExpr.remove();
  4175         set = new UnicodeSet();
  4176         //
  4177         //  Try the various Java specific properties.
  4178         //   These all begin with "java"
  4179         //
  4180         if (mPropName.compare(UNICODE_STRING_SIMPLE("javaDefined")) == 0) {
  4181             addCategory(set, U_GC_CN_MASK, localStatus);
  4182             set->complement();
  4184         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaDigit")) == 0) {
  4185             addCategory(set, U_GC_ND_MASK, localStatus);
  4187         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaIdentifierIgnorable")) == 0) {
  4188             addIdentifierIgnorable(set, localStatus);
  4190         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaISOControl")) == 0) {
  4191             set->add(0, 0x1F).add(0x7F, 0x9F);
  4193         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaJavaIdentifierPart")) == 0) {
  4194             addCategory(set, U_GC_L_MASK, localStatus);
  4195             addCategory(set, U_GC_SC_MASK, localStatus);
  4196             addCategory(set, U_GC_PC_MASK, localStatus);
  4197             addCategory(set, U_GC_ND_MASK, localStatus);
  4198             addCategory(set, U_GC_NL_MASK, localStatus);
  4199             addCategory(set, U_GC_MC_MASK, localStatus);
  4200             addCategory(set, U_GC_MN_MASK, localStatus);
  4201             addIdentifierIgnorable(set, localStatus);
  4203         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaJavaIdentifierStart")) == 0) {
  4204             addCategory(set, U_GC_L_MASK, localStatus);
  4205             addCategory(set, U_GC_NL_MASK, localStatus);
  4206             addCategory(set, U_GC_SC_MASK, localStatus);
  4207             addCategory(set, U_GC_PC_MASK, localStatus);
  4209         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaLetter")) == 0) {
  4210             addCategory(set, U_GC_L_MASK, localStatus);
  4212         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaLetterOrDigit")) == 0) {
  4213             addCategory(set, U_GC_L_MASK, localStatus);
  4214             addCategory(set, U_GC_ND_MASK, localStatus);
  4216         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaLowerCase")) == 0) {
  4217             addCategory(set, U_GC_LL_MASK, localStatus);
  4219         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaMirrored")) == 0) {
  4220             set->applyIntPropertyValue(UCHAR_BIDI_MIRRORED, 1, localStatus);
  4222         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaSpaceChar")) == 0) {
  4223             addCategory(set, U_GC_Z_MASK, localStatus);
  4225         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaSupplementaryCodePoint")) == 0) {
  4226             set->add(0x10000, UnicodeSet::MAX_VALUE);
  4228         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaTitleCase")) == 0) {
  4229             addCategory(set, U_GC_LT_MASK, localStatus);
  4231         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaUnicodeIdentifierStart")) == 0) {
  4232             addCategory(set, U_GC_L_MASK, localStatus);
  4233             addCategory(set, U_GC_NL_MASK, localStatus);
  4235         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaUnicodeIdentifierPart")) == 0) {
  4236             addCategory(set, U_GC_L_MASK, localStatus);
  4237             addCategory(set, U_GC_PC_MASK, localStatus);
  4238             addCategory(set, U_GC_ND_MASK, localStatus);
  4239             addCategory(set, U_GC_NL_MASK, localStatus);
  4240             addCategory(set, U_GC_MC_MASK, localStatus);
  4241             addCategory(set, U_GC_MN_MASK, localStatus);
  4242             addIdentifierIgnorable(set, localStatus);
  4244         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaUpperCase")) == 0) {
  4245             addCategory(set, U_GC_LU_MASK, localStatus);
  4247         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaValidCodePoint")) == 0) {
  4248             set->add(0, UnicodeSet::MAX_VALUE);
  4250         else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaWhitespace")) == 0) {
  4251             addCategory(set, U_GC_Z_MASK, localStatus);
  4252             set->removeAll(UnicodeSet().add(0xa0).add(0x2007).add(0x202f));
  4253             set->add(9, 0x0d).add(0x1c, 0x1f);
  4255         else if (mPropName.compare(UNICODE_STRING_SIMPLE("all")) == 0) {
  4256             set->add(0, UnicodeSet::MAX_VALUE);
  4259         if (U_SUCCESS(localStatus) && !set->isEmpty()) {
  4260             *fStatus = U_ZERO_ERROR;
  4261             if (usetFlags & USET_CASE_INSENSITIVE) {
  4262                 set->closeOver(USET_CASE_INSENSITIVE);
  4264             if (negated) {
  4265                 set->complement();
  4267             return set;
  4269         delete set;
  4270         set = NULL;
  4272     error(*fStatus);
  4273     return NULL; 
  4278 //
  4279 //  SetEval   Part of the evaluation of [set expressions].
  4280 //            Perform any pending (stacked) operations with precedence
  4281 //            equal or greater to that of the next operator encountered
  4282 //            in the expression.
  4283 //
  4284 void RegexCompile::setEval(int32_t nextOp) {
  4285     UnicodeSet *rightOperand = NULL;
  4286     UnicodeSet *leftOperand  = NULL;
  4287     for (;;) {
  4288         U_ASSERT(fSetOpStack.empty()==FALSE);
  4289         int32_t pendingSetOperation = fSetOpStack.peeki();
  4290         if ((pendingSetOperation&0xffff0000) < (nextOp&0xffff0000)) {
  4291             break;
  4293         fSetOpStack.popi();
  4294         U_ASSERT(fSetStack.empty() == FALSE);
  4295         rightOperand = (UnicodeSet *)fSetStack.peek();
  4296         switch (pendingSetOperation) {
  4297             case setNegation:
  4298                 rightOperand->complement();
  4299                 break;
  4300             case setCaseClose:
  4301                 // TODO: need a simple close function.  Ticket 6065
  4302                 rightOperand->closeOver(USET_CASE_INSENSITIVE);
  4303                 rightOperand->removeAllStrings();
  4304                 break;
  4305             case setDifference1:
  4306             case setDifference2:
  4307                 fSetStack.pop();
  4308                 leftOperand = (UnicodeSet *)fSetStack.peek();
  4309                 leftOperand->removeAll(*rightOperand);
  4310                 delete rightOperand;
  4311                 break;
  4312             case setIntersection1:
  4313             case setIntersection2:
  4314                 fSetStack.pop();
  4315                 leftOperand = (UnicodeSet *)fSetStack.peek();
  4316                 leftOperand->retainAll(*rightOperand);
  4317                 delete rightOperand;
  4318                 break;
  4319             case setUnion:
  4320                 fSetStack.pop();
  4321                 leftOperand = (UnicodeSet *)fSetStack.peek();
  4322                 leftOperand->addAll(*rightOperand);
  4323                 delete rightOperand;
  4324                 break;
  4325             default:
  4326                 U_ASSERT(FALSE);
  4327                 break;
  4332 void RegexCompile::setPushOp(int32_t op) {
  4333     setEval(op);
  4334     fSetOpStack.push(op, *fStatus);
  4335     fSetStack.push(new UnicodeSet(), *fStatus);
  4338 U_NAMESPACE_END
  4339 #endif  // !UCONFIG_NO_REGULAR_EXPRESSIONS

mercurial