00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 #include "config.h"
00046 
00047 #include "pcre_internal.h"
00048 
00049 #include "ASCIICType.h"
00050 
00051 #include <ctype.h>
00052 #include <limits.h>
00053 #include <string.h> 
00054 
00055 #ifdef __GNUC__
00056 #define USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
00057 
00058 #endif
00059 
00060 
00061 #undef min
00062 #undef max
00063 
00064 #ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
00065 typedef int ReturnLocation;
00066 #else
00067 typedef void* ReturnLocation;
00068 #endif
00069 
00070 
00071 
00072  
00073 struct BracketChainNode {
00074     BracketChainNode* previousBracket;
00075     const UChar* bracketStart;
00076 };
00077 
00078 struct MatchFrame {
00079     ReturnLocation returnLocation;
00080     struct MatchFrame* previousFrame;
00081     
00082     
00083     struct {
00084         const UChar* subjectPtr;
00085         const unsigned char* instructionPtr;
00086         int offsetTop;
00087         BracketChainNode* bracketChain;
00088     } args;
00089     
00090     
00091     
00092 
00093 
00094     struct {
00095         const unsigned char* data;
00096         const unsigned char* startOfRepeatingBracket;
00097         const UChar* subjectPtrAtStartOfInstruction; 
00098         const unsigned char* instructionPtrAtStartOfOnce;
00099         
00100         int repeatOthercase;
00101         
00102         int ctype;
00103         int fc;
00104         int fi;
00105         int length;
00106         int max;
00107         int number;
00108         int offset;
00109         int saveOffset1;
00110         int saveOffset2;
00111         int saveOffset3;
00112         
00113         BracketChainNode bracketChainNode;
00114     } locals;
00115 };
00116 
00117 
00118 
00119 
00120 struct MatchData {
00121   int*   offsetVector;         
00122   int    offsetEnd;            
00123   int    offsetMax;            
00124   bool   offsetOverflow;       
00125   const UChar*  startSubject;         
00126   const UChar*  endSubject;           
00127   const UChar*  endMatchPtr;         
00128   int    endOffsetTop;        
00129   bool   multiline;
00130   bool   ignoreCase;
00131 };
00132 
00133 
00134 
00135 
00136 #define REQ_BYTE_MAX 1000
00137 
00138 
00139 
00140 
00141 static const unsigned matchLimit = 100000;
00142 
00143 #ifdef DEBUG
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 static void pchars(const UChar* p, int length, bool isSubject, const MatchData& md)
00159 {
00160     if (isSubject && length > md.endSubject - p)
00161         length = md.endSubject - p;
00162     while (length-- > 0) {
00163         int c;
00164         if (isprint(c = *(p++)))
00165             printf("%c", c);
00166         else if (c < 256)
00167             printf("\\x%02x", c);
00168         else
00169             printf("\\x{%x}", c);
00170     }
00171 }
00172 #endif
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 
00189 
00190 static bool matchRef(int offset, const UChar* subjectPtr, int length, const MatchData& md)
00191 {
00192     const UChar* p = md.startSubject + md.offsetVector[offset];
00193     
00194 #ifdef DEBUG
00195     if (subjectPtr >= md.endSubject)
00196         printf("matching subject <null>");
00197     else {
00198         printf("matching subject ");
00199         pchars(subjectPtr, length, true, md);
00200     }
00201     printf(" against backref ");
00202     pchars(p, length, false, md);
00203     printf("\n");
00204 #endif
00205     
00206     
00207     
00208     if (length > md.endSubject - subjectPtr)
00209         return false;
00210     
00211     
00212     
00213     if (md.ignoreCase) {
00214         while (length-- > 0) {
00215             UChar c = *p++;
00216             int othercase = kjs_pcre_ucp_othercase(c);
00217             UChar d = *subjectPtr++;
00218             if (c != d && othercase != d)
00219                 return false;
00220         }
00221     }
00222     else {
00223         while (length-- > 0)
00224             if (*p++ != *subjectPtr++)
00225                 return false;
00226     }
00227     
00228     return true;
00229 }
00230 
00231 #ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
00232 
00233 
00234 
00235 #define RMATCH_WHERE(num) num
00236 #define RRETURN_LABEL RRETURN_SWITCH
00237 
00238 #else
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 #define RMATCH_WHERE(num) &&RRETURN_##num
00248 #define RRETURN_LABEL *stack.currentFrame->returnLocation
00249 
00250 #endif
00251 
00252 #define RECURSIVE_MATCH_COMMON(num) \
00253     goto RECURSE;\
00254     RRETURN_##num: \
00255     stack.popCurrentFrame();
00256 
00257 #define RECURSIVE_MATCH(num, ra, rb) \
00258     do { \
00259         stack.pushNewFrame((ra), (rb), RMATCH_WHERE(num)); \
00260         RECURSIVE_MATCH_COMMON(num) \
00261     } while (0)
00262 
00263 #define RECURSIVE_MATCH_STARTNG_NEW_GROUP(num, ra, rb) \
00264     do { \
00265         stack.pushNewFrame((ra), (rb), RMATCH_WHERE(num)); \
00266         startNewGroup(stack.currentFrame); \
00267         RECURSIVE_MATCH_COMMON(num) \
00268     } while (0)
00269 
00270 #define RRETURN goto RRETURN_LABEL
00271 
00272 #define RRETURN_NO_MATCH do { isMatch = false; RRETURN; } while (0)
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 static const unsigned FRAMES_ON_STACK = 16;
00298 
00299 struct MatchStack {
00300     MatchStack()
00301         : framesEnd(frames + FRAMES_ON_STACK)
00302         , currentFrame(frames)
00303         , size(1) 
00304     {
00305         ASSERT((sizeof(frames) / sizeof(frames[0])) == FRAMES_ON_STACK);
00306     }
00307     
00308     MatchFrame frames[FRAMES_ON_STACK];
00309     MatchFrame* framesEnd;
00310     MatchFrame* currentFrame;
00311     unsigned size;
00312     
00313     inline bool canUseStackBufferForNextFrame()
00314     {
00315         return size < FRAMES_ON_STACK;
00316     }
00317     
00318     inline MatchFrame* allocateNextFrame()
00319     {
00320         if (canUseStackBufferForNextFrame())
00321             return currentFrame + 1;
00322         return new MatchFrame;
00323     }
00324     
00325     inline void pushNewFrame(const unsigned char* instructionPtr, BracketChainNode* bracketChain, ReturnLocation returnLocation)
00326     {
00327         MatchFrame* newframe = allocateNextFrame();
00328         newframe->previousFrame = currentFrame;
00329 
00330         newframe->args.subjectPtr = currentFrame->args.subjectPtr;
00331         newframe->args.offsetTop = currentFrame->args.offsetTop;
00332         newframe->args.instructionPtr = instructionPtr;
00333         newframe->args.bracketChain = bracketChain;
00334         newframe->returnLocation = returnLocation;
00335         size++;
00336 
00337         currentFrame = newframe;
00338     }
00339     
00340     inline void popCurrentFrame()
00341     {
00342         MatchFrame* oldFrame = currentFrame;
00343         currentFrame = currentFrame->previousFrame;
00344         if (size > FRAMES_ON_STACK)
00345             delete oldFrame;
00346         size--;
00347     }
00348 
00349     void popAllFrames()
00350     {
00351         while (size)
00352             popCurrentFrame();
00353     }
00354 };
00355 
00356 static int matchError(int errorCode, MatchStack& stack)
00357 {
00358     stack.popAllFrames();
00359     return errorCode;
00360 }
00361 
00362 
00363 
00364 
00365 static inline void getUTF8CharAndIncrementLength(int& c, const unsigned char* subjectPtr, int& len)
00366 {
00367     c = *subjectPtr;
00368     if ((c & 0xc0) == 0xc0) {
00369         int gcaa = kjs_pcre_utf8_table4[c & 0x3f];  
00370         int gcss = 6 * gcaa;
00371         c = (c & kjs_pcre_utf8_table3[gcaa]) << gcss;
00372         for (int gcii = 1; gcii <= gcaa; gcii++) {
00373             gcss -= 6;
00374             c |= (subjectPtr[gcii] & 0x3f) << gcss;
00375         }
00376         len += gcaa;
00377     }
00378 }
00379 
00380 static inline void startNewGroup(MatchFrame* currentFrame)
00381 {
00382     
00383 
00384 
00385 
00386     
00387     currentFrame->locals.bracketChainNode.previousBracket = currentFrame->args.bracketChain;
00388     currentFrame->locals.bracketChainNode.bracketStart = currentFrame->args.subjectPtr;
00389     currentFrame->args.bracketChain = ¤tFrame->locals.bracketChainNode;
00390 }
00391 
00392 
00393 static inline void repeatInformationFromInstructionOffset(short instructionOffset, bool& minimize, int& minimumRepeats, int& maximumRepeats)
00394 {
00395     
00396     static const char minimumRepeatsFromInstructionOffset[] = { 0, 0, 1, 1, 0, 0 };
00397     static const int maximumRepeatsFromInstructionOffset[] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX, 1, 1 };
00398 
00399     ASSERT(instructionOffset >= 0);
00400     ASSERT(instructionOffset <= (OP_CRMINQUERY - OP_CRSTAR));
00401 
00402     minimize = (instructionOffset & 1); 
00403     minimumRepeats = minimumRepeatsFromInstructionOffset[instructionOffset];
00404     maximumRepeats = maximumRepeatsFromInstructionOffset[instructionOffset];
00405 }
00406 
00407 static int match(const UChar* subjectPtr, const unsigned char* instructionPtr, int offsetTop, MatchData& md)
00408 {
00409     bool isMatch = false;
00410     int min;
00411     bool minimize = false; 
00412     unsigned matchCount = 0;
00413     
00414     MatchStack stack;
00415 
00416     
00417 #ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
00418 #define EMIT_JUMP_TABLE_ENTRY(opcode) &&LABEL_OP_##opcode,
00419     static void* opcodeJumpTable[256] = { FOR_EACH_OPCODE(EMIT_JUMP_TABLE_ENTRY) };
00420 #undef EMIT_JUMP_TABLE_ENTRY
00421 #endif
00422     
00423     
00424 #ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
00425     for (int i = 255; !opcodeJumpTable[i]; i--)
00426         opcodeJumpTable[i] = &&CAPTURING_BRACKET;
00427 #endif
00428     
00429 #ifdef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
00430     
00431     
00432     stack.currentFrame->returnLocation = &&RETURN;
00433 #else
00434     stack.currentFrame->returnLocation = 0;
00435 #endif
00436     stack.currentFrame->args.subjectPtr = subjectPtr;
00437     stack.currentFrame->args.instructionPtr = instructionPtr;
00438     stack.currentFrame->args.offsetTop = offsetTop;
00439     stack.currentFrame->args.bracketChain = 0;
00440     startNewGroup(stack.currentFrame);
00441     
00442     
00443     
00444 RECURSE:
00445     if (++matchCount > matchLimit)
00446         return matchError(JSRegExpErrorHitLimit, stack);
00447 
00448     
00449     
00450 #ifndef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
00451     while (true)
00452 #endif
00453     {
00454         
00455 #ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
00456 #define BEGIN_OPCODE(opcode) LABEL_OP_##opcode
00457 #define NEXT_OPCODE goto *opcodeJumpTable[*stack.currentFrame->args.instructionPtr]
00458 #else
00459 #define BEGIN_OPCODE(opcode) case OP_##opcode
00460 #define NEXT_OPCODE continue
00461 #endif
00462         
00463 #ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
00464         NEXT_OPCODE;
00465 #else
00466         switch (*stack.currentFrame->args.instructionPtr)
00467 #endif
00468         {
00469             
00470                 
00471             BEGIN_OPCODE(BRA):
00472             NON_CAPTURING_BRACKET:
00473                 DPRINTF(("start bracket 0\n"));
00474                 do {
00475                     RECURSIVE_MATCH_STARTNG_NEW_GROUP(2, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
00476                     if (isMatch)
00477                         RRETURN;
00478                     stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
00479                 } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
00480                 DPRINTF(("bracket 0 failed\n"));
00481                 RRETURN;
00482                 
00483             
00484                 
00485             BEGIN_OPCODE(BRANUMBER):
00486                 stack.currentFrame->args.instructionPtr += 3;
00487                 NEXT_OPCODE;
00488                 
00489             
00490                 
00491             BEGIN_OPCODE(END):
00492                 md.endMatchPtr = stack.currentFrame->args.subjectPtr;          
00493                 md.endOffsetTop = stack.currentFrame->args.offsetTop;   
00494                 isMatch = true;
00495                 RRETURN;
00496                 
00497             
00498 
00499 
00500 
00501 
00502                 
00503             BEGIN_OPCODE(ASSERT):
00504                 do {
00505                     RECURSIVE_MATCH_STARTNG_NEW_GROUP(6, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
00506                     if (isMatch)
00507                         break;
00508                     stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
00509                 } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
00510                 if (*stack.currentFrame->args.instructionPtr == OP_KET)
00511                     RRETURN_NO_MATCH;
00512                 
00513                 
00514 
00515                 
00516                 advanceToEndOfBracket(stack.currentFrame->args.instructionPtr);
00517                 stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
00518                 stack.currentFrame->args.offsetTop = md.endOffsetTop;
00519                 NEXT_OPCODE;
00520                 
00521             
00522                 
00523             BEGIN_OPCODE(ASSERT_NOT):
00524                 do {
00525                     RECURSIVE_MATCH_STARTNG_NEW_GROUP(7, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
00526                     if (isMatch)
00527                         RRETURN_NO_MATCH;
00528                     stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
00529                 } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
00530                 
00531                 stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
00532                 NEXT_OPCODE;
00533                 
00534             
00535 
00536                 
00537             BEGIN_OPCODE(ALT):
00538                 advanceToEndOfBracket(stack.currentFrame->args.instructionPtr);
00539                 NEXT_OPCODE;
00540                 
00541             
00542 
00543 
00544 
00545 
00546                 
00547             BEGIN_OPCODE(BRAZERO): {
00548                 stack.currentFrame->locals.startOfRepeatingBracket = stack.currentFrame->args.instructionPtr + 1;
00549                 RECURSIVE_MATCH_STARTNG_NEW_GROUP(14, stack.currentFrame->locals.startOfRepeatingBracket, stack.currentFrame->args.bracketChain);
00550                 if (isMatch)
00551                     RRETURN;
00552                 advanceToEndOfBracket(stack.currentFrame->locals.startOfRepeatingBracket);
00553                 stack.currentFrame->args.instructionPtr = stack.currentFrame->locals.startOfRepeatingBracket + 1 + LINK_SIZE;
00554                 NEXT_OPCODE;
00555             }
00556                 
00557             BEGIN_OPCODE(BRAMINZERO): {
00558                 stack.currentFrame->locals.startOfRepeatingBracket = stack.currentFrame->args.instructionPtr + 1;
00559                 advanceToEndOfBracket(stack.currentFrame->locals.startOfRepeatingBracket);
00560                 RECURSIVE_MATCH_STARTNG_NEW_GROUP(15, stack.currentFrame->locals.startOfRepeatingBracket + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
00561                 if (isMatch)
00562                     RRETURN;
00563                 stack.currentFrame->args.instructionPtr++;
00564                 NEXT_OPCODE;
00565             }
00566                 
00567             
00568 
00569 
00570 
00571                 
00572             BEGIN_OPCODE(KET):
00573             BEGIN_OPCODE(KETRMIN):
00574             BEGIN_OPCODE(KETRMAX):
00575                 stack.currentFrame->locals.instructionPtrAtStartOfOnce = stack.currentFrame->args.instructionPtr - getLinkValue(stack.currentFrame->args.instructionPtr + 1);
00576                 stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.bracketChain->bracketStart;
00577 
00578                 
00579 
00580                 stack.currentFrame->args.bracketChain = stack.currentFrame->args.bracketChain->previousBracket;
00581 
00582                 if (*stack.currentFrame->locals.instructionPtrAtStartOfOnce == OP_ASSERT || *stack.currentFrame->locals.instructionPtrAtStartOfOnce == OP_ASSERT_NOT) {
00583                     md.endOffsetTop = stack.currentFrame->args.offsetTop;
00584                     isMatch = true;
00585                     RRETURN;
00586                 }
00587                 
00588                 
00589 
00590 
00591                 
00592                 stack.currentFrame->locals.number = *stack.currentFrame->locals.instructionPtrAtStartOfOnce - OP_BRA;
00593                 
00594                 
00595 
00596                 
00597                 if (stack.currentFrame->locals.number > EXTRACT_BASIC_MAX)
00598                     stack.currentFrame->locals.number = get2ByteValue(stack.currentFrame->locals.instructionPtrAtStartOfOnce + 2 + LINK_SIZE);
00599                 stack.currentFrame->locals.offset = stack.currentFrame->locals.number << 1;
00600                 
00601 #ifdef DEBUG
00602                 printf("end bracket %d", stack.currentFrame->locals.number);
00603                 printf("\n");
00604 #endif
00605                 
00606                 
00607 
00608 
00609 
00610                 
00611                 if (stack.currentFrame->locals.number > 0) {
00612                     if (stack.currentFrame->locals.offset >= md.offsetMax)
00613                         md.offsetOverflow = true;
00614                     else {
00615                         md.offsetVector[stack.currentFrame->locals.offset] =
00616                         md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number];
00617                         md.offsetVector[stack.currentFrame->locals.offset+1] = stack.currentFrame->args.subjectPtr - md.startSubject;
00618                         if (stack.currentFrame->args.offsetTop <= stack.currentFrame->locals.offset)
00619                             stack.currentFrame->args.offsetTop = stack.currentFrame->locals.offset + 2;
00620                     }
00621                 }
00622                 
00623                 
00624 
00625 
00626 
00627 
00628                 
00629                 if (*stack.currentFrame->args.instructionPtr == OP_KET || stack.currentFrame->args.subjectPtr == stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
00630                     stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
00631                     NEXT_OPCODE;
00632                 }
00633                 
00634                 
00635 
00636                 
00637                 if (*stack.currentFrame->args.instructionPtr == OP_KETRMIN) {
00638                     RECURSIVE_MATCH(16, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
00639                     if (isMatch)
00640                         RRETURN;
00641                     RECURSIVE_MATCH_STARTNG_NEW_GROUP(17, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
00642                     if (isMatch)
00643                         RRETURN;
00644                 } else { 
00645                     RECURSIVE_MATCH_STARTNG_NEW_GROUP(18, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
00646                     if (isMatch)
00647                         RRETURN;
00648                     RECURSIVE_MATCH(19, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
00649                     if (isMatch)
00650                         RRETURN;
00651                 }
00652                 RRETURN;
00653                 
00654             
00655 
00656             BEGIN_OPCODE(CIRC):
00657                 if (stack.currentFrame->args.subjectPtr != md.startSubject)
00658                     RRETURN_NO_MATCH;
00659                 stack.currentFrame->args.instructionPtr++;
00660                 NEXT_OPCODE;
00661 
00662             
00663 
00664             BEGIN_OPCODE(BOL):
00665                 if (stack.currentFrame->args.subjectPtr != md.startSubject && !isNewline(stack.currentFrame->args.subjectPtr[-1]))
00666                     RRETURN_NO_MATCH;
00667                 stack.currentFrame->args.instructionPtr++;
00668                 NEXT_OPCODE;
00669 
00670             
00671 
00672             BEGIN_OPCODE(DOLL):
00673                 if (stack.currentFrame->args.subjectPtr < md.endSubject)
00674                     RRETURN_NO_MATCH;
00675                 stack.currentFrame->args.instructionPtr++;
00676                 NEXT_OPCODE;
00677 
00678             
00679 
00680             BEGIN_OPCODE(EOL):
00681                 if (stack.currentFrame->args.subjectPtr < md.endSubject && !isNewline(*stack.currentFrame->args.subjectPtr))
00682                     RRETURN_NO_MATCH;
00683                 stack.currentFrame->args.instructionPtr++;
00684                 NEXT_OPCODE;
00685                 
00686             
00687                 
00688             BEGIN_OPCODE(NOT_WORD_BOUNDARY):
00689             BEGIN_OPCODE(WORD_BOUNDARY): {
00690                 bool currentCharIsWordChar = false;
00691                 bool previousCharIsWordChar = false;
00692                 
00693                 if (stack.currentFrame->args.subjectPtr > md.startSubject)
00694                     previousCharIsWordChar = isWordChar(stack.currentFrame->args.subjectPtr[-1]);
00695                 if (stack.currentFrame->args.subjectPtr < md.endSubject)
00696                     currentCharIsWordChar = isWordChar(*stack.currentFrame->args.subjectPtr);
00697                 
00698                 
00699                 bool wordBoundaryDesired = (*stack.currentFrame->args.instructionPtr++ == OP_WORD_BOUNDARY);
00700                 if (wordBoundaryDesired ? currentCharIsWordChar == previousCharIsWordChar : currentCharIsWordChar != previousCharIsWordChar)
00701                     RRETURN_NO_MATCH;
00702                 NEXT_OPCODE;
00703             }
00704                 
00705             
00706                 
00707             BEGIN_OPCODE(NOT_NEWLINE):
00708                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00709                     RRETURN_NO_MATCH;
00710                 if (isNewline(*stack.currentFrame->args.subjectPtr++))
00711                     RRETURN_NO_MATCH;
00712                 stack.currentFrame->args.instructionPtr++;
00713                 NEXT_OPCODE;
00714 
00715             BEGIN_OPCODE(NOT_DIGIT):
00716                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00717                     RRETURN_NO_MATCH;
00718                 if (isASCIIDigit(*stack.currentFrame->args.subjectPtr++))
00719                     RRETURN_NO_MATCH;
00720                 stack.currentFrame->args.instructionPtr++;
00721                 NEXT_OPCODE;
00722 
00723             BEGIN_OPCODE(DIGIT):
00724                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00725                     RRETURN_NO_MATCH;
00726                 if (!isASCIIDigit(*stack.currentFrame->args.subjectPtr++))
00727                     RRETURN_NO_MATCH;
00728                 stack.currentFrame->args.instructionPtr++;
00729                 NEXT_OPCODE;
00730 
00731             BEGIN_OPCODE(NOT_WHITESPACE):
00732                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00733                     RRETURN_NO_MATCH;
00734                 if (isSpaceChar(*stack.currentFrame->args.subjectPtr++))
00735                     RRETURN_NO_MATCH;
00736                 stack.currentFrame->args.instructionPtr++;
00737                 NEXT_OPCODE;
00738 
00739             BEGIN_OPCODE(WHITESPACE):
00740                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00741                     RRETURN_NO_MATCH;
00742                 if (!isSpaceChar(*stack.currentFrame->args.subjectPtr++))
00743                     RRETURN_NO_MATCH;
00744                 stack.currentFrame->args.instructionPtr++;
00745                 NEXT_OPCODE;
00746                 
00747             BEGIN_OPCODE(NOT_WORDCHAR):
00748                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00749                     RRETURN_NO_MATCH;
00750                 if (isWordChar(*stack.currentFrame->args.subjectPtr++))
00751                     RRETURN_NO_MATCH;
00752                 stack.currentFrame->args.instructionPtr++;
00753                 NEXT_OPCODE;
00754                 
00755             BEGIN_OPCODE(WORDCHAR):
00756                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00757                     RRETURN_NO_MATCH;
00758                 if (!isWordChar(*stack.currentFrame->args.subjectPtr++))
00759                     RRETURN_NO_MATCH;
00760                 stack.currentFrame->args.instructionPtr++;
00761                 NEXT_OPCODE;
00762                 
00763             
00764 
00765 
00766 
00767 
00768 
00769 
00770                 
00771             BEGIN_OPCODE(REF):
00772                 stack.currentFrame->locals.offset = get2ByteValue(stack.currentFrame->args.instructionPtr + 1) << 1;               
00773                 stack.currentFrame->args.instructionPtr += 3;                                 
00774                 
00775                 
00776 
00777 
00778 
00779                 
00780                 if (stack.currentFrame->locals.offset >= stack.currentFrame->args.offsetTop || md.offsetVector[stack.currentFrame->locals.offset] < 0)
00781                     stack.currentFrame->locals.length = 0;
00782                 else
00783                     stack.currentFrame->locals.length = md.offsetVector[stack.currentFrame->locals.offset+1] - md.offsetVector[stack.currentFrame->locals.offset];
00784                 
00785                 
00786                 
00787                 switch (*stack.currentFrame->args.instructionPtr) {
00788                     case OP_CRSTAR:
00789                     case OP_CRMINSTAR:
00790                     case OP_CRPLUS:
00791                     case OP_CRMINPLUS:
00792                     case OP_CRQUERY:
00793                     case OP_CRMINQUERY:
00794                         repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
00795                         break;
00796                         
00797                     case OP_CRRANGE:
00798                     case OP_CRMINRANGE:
00799                         minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
00800                         min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
00801                         stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
00802                         if (stack.currentFrame->locals.max == 0)
00803                             stack.currentFrame->locals.max = INT_MAX;
00804                         stack.currentFrame->args.instructionPtr += 5;
00805                         break;
00806                     
00807                     default:               
00808                         if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
00809                             RRETURN_NO_MATCH;
00810                         stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
00811                         NEXT_OPCODE;
00812                 }
00813                 
00814                 
00815 
00816                 
00817                 if (stack.currentFrame->locals.length == 0)
00818                     NEXT_OPCODE;
00819                 
00820                 
00821                 
00822                 for (int i = 1; i <= min; i++) {
00823                     if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
00824                         RRETURN_NO_MATCH;
00825                     stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
00826                 }
00827                 
00828                 
00829 
00830                 
00831                 if (min == stack.currentFrame->locals.max)
00832                     NEXT_OPCODE;
00833                 
00834                 
00835                 
00836                 if (minimize) {
00837                     for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
00838                         RECURSIVE_MATCH(20, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
00839                         if (isMatch)
00840                             RRETURN;
00841                         if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || !matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
00842                             RRETURN;
00843                         stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
00844                     }
00845                     
00846                 }
00847                 
00848                 
00849                 
00850                 else {
00851                     stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
00852                     for (int i = min; i < stack.currentFrame->locals.max; i++) {
00853                         if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
00854                             break;
00855                         stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
00856                     }
00857                     while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
00858                         RECURSIVE_MATCH(21, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
00859                         if (isMatch)
00860                             RRETURN;
00861                         stack.currentFrame->args.subjectPtr -= stack.currentFrame->locals.length;
00862                     }
00863                     RRETURN_NO_MATCH;
00864                 }
00865                 
00866                 
00867             
00868 
00869 
00870 
00871 
00872 
00873 
00874 
00875 
00876 
00877                 
00878             BEGIN_OPCODE(NCLASS):
00879             BEGIN_OPCODE(CLASS):
00880                 stack.currentFrame->locals.data = stack.currentFrame->args.instructionPtr + 1;                
00881                 stack.currentFrame->args.instructionPtr += 33;                     
00882                 
00883                 switch (*stack.currentFrame->args.instructionPtr) {
00884                     case OP_CRSTAR:
00885                     case OP_CRMINSTAR:
00886                     case OP_CRPLUS:
00887                     case OP_CRMINPLUS:
00888                     case OP_CRQUERY:
00889                     case OP_CRMINQUERY:
00890                         repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
00891                         break;
00892                         
00893                     case OP_CRRANGE:
00894                     case OP_CRMINRANGE:
00895                         minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
00896                         min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
00897                         stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
00898                         if (stack.currentFrame->locals.max == 0)
00899                             stack.currentFrame->locals.max = INT_MAX;
00900                         stack.currentFrame->args.instructionPtr += 5;
00901                         break;
00902                         
00903                     default:               
00904                         min = stack.currentFrame->locals.max = 1;
00905                         break;
00906                 }
00907                 
00908                 
00909                 
00910                 for (int i = 1; i <= min; i++) {
00911                     if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00912                         RRETURN_NO_MATCH;
00913                     int c = *stack.currentFrame->args.subjectPtr++;
00914                     if (c > 255) {
00915                         if (stack.currentFrame->locals.data[-1] == OP_CLASS)
00916                             RRETURN_NO_MATCH;
00917                     } else {
00918                         if (!(stack.currentFrame->locals.data[c / 8] & (1 << (c & 7))))
00919                             RRETURN_NO_MATCH;
00920                     }
00921                 }
00922                 
00923                 
00924 
00925                 
00926                 if (min == stack.currentFrame->locals.max)
00927                     NEXT_OPCODE;      
00928                 
00929                 
00930 
00931                 if (minimize) {
00932                     for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
00933                         RECURSIVE_MATCH(22, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
00934                         if (isMatch)
00935                             RRETURN;
00936                         if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
00937                             RRETURN;
00938                         int c = *stack.currentFrame->args.subjectPtr++;
00939                         if (c > 255) {
00940                             if (stack.currentFrame->locals.data[-1] == OP_CLASS)
00941                                 RRETURN;
00942                         } else {
00943                             if ((stack.currentFrame->locals.data[c/8] & (1 << (c&7))) == 0)
00944                                 RRETURN;
00945                         }
00946                     }
00947                     
00948                 }
00949                 
00950                 else {
00951                     stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
00952                     
00953                     for (int i = min; i < stack.currentFrame->locals.max; i++) {
00954                         if (stack.currentFrame->args.subjectPtr >= md.endSubject)
00955                             break;
00956                         int c = *stack.currentFrame->args.subjectPtr;
00957                         if (c > 255) {
00958                             if (stack.currentFrame->locals.data[-1] == OP_CLASS)
00959                                 break;
00960                         } else {
00961                             if (!(stack.currentFrame->locals.data[c / 8] & (1 << (c & 7))))
00962                                 break;
00963                         }
00964                         ++stack.currentFrame->args.subjectPtr;
00965                     }
00966                     for (;;) {
00967                         RECURSIVE_MATCH(24, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
00968                         if (isMatch)
00969                             RRETURN;
00970                         if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
00971                             break;        
00972                     }
00973                     
00974                     RRETURN;
00975                 }
00976                 
00977                 
00978             
00979                 
00980             BEGIN_OPCODE(XCLASS):
00981                 stack.currentFrame->locals.data = stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE;                
00982                 stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);                      
00983                 
00984                 switch (*stack.currentFrame->args.instructionPtr) {
00985                     case OP_CRSTAR:
00986                     case OP_CRMINSTAR:
00987                     case OP_CRPLUS:
00988                     case OP_CRMINPLUS:
00989                     case OP_CRQUERY:
00990                     case OP_CRMINQUERY:
00991                         repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
00992                         break;
00993                         
00994                     case OP_CRRANGE:
00995                     case OP_CRMINRANGE:
00996                         minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
00997                         min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
00998                         stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
00999                         if (stack.currentFrame->locals.max == 0)
01000                             stack.currentFrame->locals.max = INT_MAX;
01001                         stack.currentFrame->args.instructionPtr += 5;
01002                         break;
01003                         
01004                     default:               
01005                         min = stack.currentFrame->locals.max = 1;
01006                 }
01007                 
01008                 
01009                 
01010                 for (int i = 1; i <= min; i++) {
01011                     if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01012                         RRETURN_NO_MATCH;
01013                     int c = *stack.currentFrame->args.subjectPtr++;
01014                     if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
01015                         RRETURN_NO_MATCH;
01016                 }
01017                 
01018                 
01019 
01020                 
01021                 if (min == stack.currentFrame->locals.max)
01022                     NEXT_OPCODE;
01023                 
01024                 
01025 
01026                 
01027                 if (minimize) {
01028                     for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
01029                         RECURSIVE_MATCH(26, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01030                         if (isMatch)
01031                             RRETURN;
01032                         if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
01033                             RRETURN;
01034                         int c = *stack.currentFrame->args.subjectPtr++;
01035                         if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
01036                             RRETURN;
01037                     }
01038                     
01039                 }
01040                 
01041                 
01042                 
01043                 else {
01044                     stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
01045                     for (int i = min; i < stack.currentFrame->locals.max; i++) {
01046                         if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01047                             break;
01048                         int c = *stack.currentFrame->args.subjectPtr;
01049                         if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
01050                             break;
01051                         ++stack.currentFrame->args.subjectPtr;
01052                     }
01053                     for(;;) {
01054                         RECURSIVE_MATCH(27, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01055                         if (isMatch)
01056                             RRETURN;
01057                         if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
01058                             break;        
01059                     }
01060                     RRETURN;
01061                 }
01062                 
01063                 
01064                 
01065             
01066                 
01067             BEGIN_OPCODE(CHAR):
01068                 stack.currentFrame->locals.length = 1;
01069                 stack.currentFrame->args.instructionPtr++;
01070                 getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
01071                 stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
01072                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01073                     RRETURN_NO_MATCH;
01074                 if (stack.currentFrame->locals.fc != *stack.currentFrame->args.subjectPtr++)
01075                     RRETURN_NO_MATCH;
01076                 NEXT_OPCODE;
01077                 
01078             
01079                 
01080             BEGIN_OPCODE(CHAR_IGNORING_CASE): {
01081                 stack.currentFrame->locals.length = 1;
01082                 stack.currentFrame->args.instructionPtr++;
01083                 getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
01084                 stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
01085                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01086                     RRETURN_NO_MATCH;
01087                 int dc = *stack.currentFrame->args.subjectPtr++;
01088                 if (stack.currentFrame->locals.fc != dc && kjs_pcre_ucp_othercase(stack.currentFrame->locals.fc) != dc)
01089                     RRETURN_NO_MATCH;
01090                 NEXT_OPCODE;
01091             }
01092                 
01093             
01094                 
01095             BEGIN_OPCODE(ASCII_CHAR):
01096                 if (md.endSubject == stack.currentFrame->args.subjectPtr)
01097                     RRETURN_NO_MATCH;
01098                 if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->args.instructionPtr[1])
01099                     RRETURN_NO_MATCH;
01100                 ++stack.currentFrame->args.subjectPtr;
01101                 stack.currentFrame->args.instructionPtr += 2;
01102                 NEXT_OPCODE;
01103                 
01104             
01105                 
01106             BEGIN_OPCODE(ASCII_LETTER_IGNORING_CASE):
01107                 if (md.endSubject == stack.currentFrame->args.subjectPtr)
01108                     RRETURN_NO_MATCH;
01109                 if ((*stack.currentFrame->args.subjectPtr | 0x20) != stack.currentFrame->args.instructionPtr[1])
01110                     RRETURN_NO_MATCH;
01111                 ++stack.currentFrame->args.subjectPtr;
01112                 stack.currentFrame->args.instructionPtr += 2;
01113                 NEXT_OPCODE;
01114                 
01115             
01116                 
01117             BEGIN_OPCODE(EXACT):
01118                 min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
01119                 minimize = false;
01120                 stack.currentFrame->args.instructionPtr += 3;
01121                 goto REPEATCHAR;
01122                 
01123             BEGIN_OPCODE(UPTO):
01124             BEGIN_OPCODE(MINUPTO):
01125                 min = 0;
01126                 stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
01127                 minimize = *stack.currentFrame->args.instructionPtr == OP_MINUPTO;
01128                 stack.currentFrame->args.instructionPtr += 3;
01129                 goto REPEATCHAR;
01130                 
01131             BEGIN_OPCODE(STAR):
01132             BEGIN_OPCODE(MINSTAR):
01133             BEGIN_OPCODE(PLUS):
01134             BEGIN_OPCODE(MINPLUS):
01135             BEGIN_OPCODE(QUERY):
01136             BEGIN_OPCODE(MINQUERY):
01137                 repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_STAR, minimize, min, stack.currentFrame->locals.max);
01138                 
01139                 
01140 
01141 
01142                 
01143             REPEATCHAR:
01144                 
01145                 stack.currentFrame->locals.length = 1;
01146                 getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
01147                 if (min * (stack.currentFrame->locals.fc > 0xFFFF ? 2 : 1) > md.endSubject - stack.currentFrame->args.subjectPtr)
01148                     RRETURN_NO_MATCH;
01149                 stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
01150                 
01151                 if (stack.currentFrame->locals.fc <= 0xFFFF) {
01152                     int othercase = md.ignoreCase ? kjs_pcre_ucp_othercase(stack.currentFrame->locals.fc) : -1;
01153                     
01154                     for (int i = 1; i <= min; i++) {
01155                         if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != othercase)
01156                             RRETURN_NO_MATCH;
01157                         ++stack.currentFrame->args.subjectPtr;
01158                     }
01159                     
01160                     if (min == stack.currentFrame->locals.max)
01161                         NEXT_OPCODE;
01162                     
01163                     if (minimize) {
01164                         stack.currentFrame->locals.repeatOthercase = othercase;
01165                         for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
01166                             RECURSIVE_MATCH(28, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01167                             if (isMatch)
01168                                 RRETURN;
01169                             if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
01170                                 RRETURN;
01171                             if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.repeatOthercase)
01172                                 RRETURN;
01173                             ++stack.currentFrame->args.subjectPtr;
01174                         }
01175                         
01176                     } else {
01177                         stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
01178                         for (int i = min; i < stack.currentFrame->locals.max; i++) {
01179                             if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01180                                 break;
01181                             if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != othercase)
01182                                 break;
01183                             ++stack.currentFrame->args.subjectPtr;
01184                         }
01185                         while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
01186                             RECURSIVE_MATCH(29, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01187                             if (isMatch)
01188                                 RRETURN;
01189                             --stack.currentFrame->args.subjectPtr;
01190                         }
01191                         RRETURN_NO_MATCH;
01192                     }
01193                     
01194                 } else {
01195                     
01196                     
01197                     for (int i = 1; i <= min; i++) {
01198                         if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
01199                             RRETURN_NO_MATCH;
01200                         stack.currentFrame->args.subjectPtr += 2;
01201                     }
01202                     
01203                     if (min == stack.currentFrame->locals.max)
01204                         NEXT_OPCODE;
01205                     
01206                     if (minimize) {
01207                         for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
01208                             RECURSIVE_MATCH(30, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01209                             if (isMatch)
01210                                 RRETURN;
01211                             if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
01212                                 RRETURN;
01213                             if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
01214                                 RRETURN;
01215                             stack.currentFrame->args.subjectPtr += 2;
01216                         }
01217                         
01218                     } else {
01219                         stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
01220                         for (int i = min; i < stack.currentFrame->locals.max; i++) {
01221                             if (stack.currentFrame->args.subjectPtr > md.endSubject - 2)
01222                                 break;
01223                             if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
01224                                 break;
01225                             stack.currentFrame->args.subjectPtr += 2;
01226                         }
01227                         while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
01228                             RECURSIVE_MATCH(31, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01229                             if (isMatch)
01230                                 RRETURN;
01231                             stack.currentFrame->args.subjectPtr -= 2;
01232                         }
01233                         RRETURN_NO_MATCH;
01234                     }
01235                     
01236                 }
01237                 
01238                 
01239             
01240                 
01241             BEGIN_OPCODE(NOT): {
01242                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01243                     RRETURN_NO_MATCH;
01244                 stack.currentFrame->args.instructionPtr++;
01245                 int c = *stack.currentFrame->args.subjectPtr++;
01246                 if (md.ignoreCase) {
01247                     if (c < 128)
01248                         c = toLowerCase(c);
01249                     if (toLowerCase(*stack.currentFrame->args.instructionPtr++) == c)
01250                         RRETURN_NO_MATCH;
01251                 } else {
01252                     if (*stack.currentFrame->args.instructionPtr++ == c)
01253                         RRETURN_NO_MATCH;
01254                 }
01255                 NEXT_OPCODE;
01256             }
01257                 
01258             
01259 
01260 
01261 
01262 
01263 
01264                 
01265             BEGIN_OPCODE(NOTEXACT):
01266                 min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
01267                 minimize = false;
01268                 stack.currentFrame->args.instructionPtr += 3;
01269                 goto REPEATNOTCHAR;
01270                 
01271             BEGIN_OPCODE(NOTUPTO):
01272             BEGIN_OPCODE(NOTMINUPTO):
01273                 min = 0;
01274                 stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
01275                 minimize = *stack.currentFrame->args.instructionPtr == OP_NOTMINUPTO;
01276                 stack.currentFrame->args.instructionPtr += 3;
01277                 goto REPEATNOTCHAR;
01278                 
01279             BEGIN_OPCODE(NOTSTAR):
01280             BEGIN_OPCODE(NOTMINSTAR):
01281             BEGIN_OPCODE(NOTPLUS):
01282             BEGIN_OPCODE(NOTMINPLUS):
01283             BEGIN_OPCODE(NOTQUERY):
01284             BEGIN_OPCODE(NOTMINQUERY):
01285                 repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_NOTSTAR, minimize, min, stack.currentFrame->locals.max);
01286                 
01287             
01288 
01289 
01290                 
01291             REPEATNOTCHAR:
01292                 if (min > md.endSubject - stack.currentFrame->args.subjectPtr)
01293                     RRETURN_NO_MATCH;
01294                 stack.currentFrame->locals.fc = *stack.currentFrame->args.instructionPtr++;
01295                 
01296                 
01297 
01298 
01299 
01300 
01301 
01302 
01303                 
01304                 DPRINTF(("negative matching %c{%d,%d}\n", stack.currentFrame->locals.fc, min, stack.currentFrame->locals.max));
01305                 
01306                 if (md.ignoreCase) {
01307                     if (stack.currentFrame->locals.fc < 128)
01308                         stack.currentFrame->locals.fc = toLowerCase(stack.currentFrame->locals.fc);
01309                     
01310                     for (int i = 1; i <= min; i++) {
01311                         int d = *stack.currentFrame->args.subjectPtr++;
01312                         if (d < 128)
01313                             d = toLowerCase(d);
01314                         if (stack.currentFrame->locals.fc == d)
01315                             RRETURN_NO_MATCH;
01316                     }
01317                     
01318                     if (min == stack.currentFrame->locals.max)
01319                         NEXT_OPCODE;      
01320                     
01321                     if (minimize) {
01322                         for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
01323                             RECURSIVE_MATCH(38, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01324                             if (isMatch)
01325                                 RRETURN;
01326                             int d = *stack.currentFrame->args.subjectPtr++;
01327                             if (d < 128)
01328                                 d = toLowerCase(d);
01329                             if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject || stack.currentFrame->locals.fc == d)
01330                                 RRETURN;
01331                         }
01332                         
01333                     }
01334                     
01335                     
01336                     
01337                     else {
01338                         stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
01339                         
01340                         for (int i = min; i < stack.currentFrame->locals.max; i++) {
01341                             if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01342                                 break;
01343                             int d = *stack.currentFrame->args.subjectPtr;
01344                             if (d < 128)
01345                                 d = toLowerCase(d);
01346                             if (stack.currentFrame->locals.fc == d)
01347                                 break;
01348                             ++stack.currentFrame->args.subjectPtr;
01349                         }
01350                         for (;;) {
01351                             RECURSIVE_MATCH(40, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01352                             if (isMatch)
01353                                 RRETURN;
01354                             if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
01355                                 break;        
01356                         }
01357                         
01358                         RRETURN;
01359                     }
01360                     
01361                 }
01362                 
01363                 
01364                 
01365                 else {
01366                     for (int i = 1; i <= min; i++) {
01367                         int d = *stack.currentFrame->args.subjectPtr++;
01368                         if (stack.currentFrame->locals.fc == d)
01369                             RRETURN_NO_MATCH;
01370                     }
01371 
01372                     if (min == stack.currentFrame->locals.max)
01373                         NEXT_OPCODE;
01374                     
01375                     if (minimize) {
01376                         for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
01377                             RECURSIVE_MATCH(42, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01378                             if (isMatch)
01379                                 RRETURN;
01380                             int d = *stack.currentFrame->args.subjectPtr++;
01381                             if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject || stack.currentFrame->locals.fc == d)
01382                                 RRETURN;
01383                         }
01384                         
01385                     }
01386                     
01387                     
01388                     
01389                     else {
01390                         stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
01391                         
01392                         for (int i = min; i < stack.currentFrame->locals.max; i++) {
01393                             if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01394                                 break;
01395                             int d = *stack.currentFrame->args.subjectPtr;
01396                             if (stack.currentFrame->locals.fc == d)
01397                                 break;
01398                             ++stack.currentFrame->args.subjectPtr;
01399                         }
01400                         for (;;) {
01401                             RECURSIVE_MATCH(44, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01402                             if (isMatch)
01403                                 RRETURN;
01404                             if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
01405                                 break;        
01406                         }
01407 
01408                         RRETURN;
01409                     }
01410                 }
01411                 
01412                 
01413             
01414 
01415 
01416                 
01417             BEGIN_OPCODE(TYPEEXACT):
01418                 min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
01419                 minimize = true;
01420                 stack.currentFrame->args.instructionPtr += 3;
01421                 goto REPEATTYPE;
01422                 
01423             BEGIN_OPCODE(TYPEUPTO):
01424             BEGIN_OPCODE(TYPEMINUPTO):
01425                 min = 0;
01426                 stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
01427                 minimize = *stack.currentFrame->args.instructionPtr == OP_TYPEMINUPTO;
01428                 stack.currentFrame->args.instructionPtr += 3;
01429                 goto REPEATTYPE;
01430                 
01431             BEGIN_OPCODE(TYPESTAR):
01432             BEGIN_OPCODE(TYPEMINSTAR):
01433             BEGIN_OPCODE(TYPEPLUS):
01434             BEGIN_OPCODE(TYPEMINPLUS):
01435             BEGIN_OPCODE(TYPEQUERY):
01436             BEGIN_OPCODE(TYPEMINQUERY):
01437                 repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_TYPESTAR, minimize, min, stack.currentFrame->locals.max);
01438                 
01439                 
01440 
01441 
01442                 
01443             REPEATTYPE:
01444                 stack.currentFrame->locals.ctype = *stack.currentFrame->args.instructionPtr++;      
01445                 
01446                 
01447 
01448 
01449 
01450                 
01451                 if (min > md.endSubject - stack.currentFrame->args.subjectPtr)
01452                     RRETURN_NO_MATCH;
01453                 if (min > 0) {
01454                     switch (stack.currentFrame->locals.ctype) {
01455                         case OP_NOT_NEWLINE:
01456                             for (int i = 1; i <= min; i++) {
01457                                 if (isNewline(*stack.currentFrame->args.subjectPtr))
01458                                     RRETURN_NO_MATCH;
01459                                 ++stack.currentFrame->args.subjectPtr;
01460                             }
01461                             break;
01462                             
01463                         case OP_NOT_DIGIT:
01464                             for (int i = 1; i <= min; i++) {
01465                                 if (isASCIIDigit(*stack.currentFrame->args.subjectPtr))
01466                                     RRETURN_NO_MATCH;
01467                                 ++stack.currentFrame->args.subjectPtr;
01468                             }
01469                             break;
01470                             
01471                         case OP_DIGIT:
01472                             for (int i = 1; i <= min; i++) {
01473                                 if (!isASCIIDigit(*stack.currentFrame->args.subjectPtr))
01474                                     RRETURN_NO_MATCH;
01475                                 ++stack.currentFrame->args.subjectPtr;
01476                             }
01477                             break;
01478                             
01479                         case OP_NOT_WHITESPACE:
01480                             for (int i = 1; i <= min; i++) {
01481                                 if (isSpaceChar(*stack.currentFrame->args.subjectPtr))
01482                                     RRETURN_NO_MATCH;
01483                                 ++stack.currentFrame->args.subjectPtr;
01484                             }
01485                             break;
01486                             
01487                         case OP_WHITESPACE:
01488                             for (int i = 1; i <= min; i++) {
01489                                 if (!isSpaceChar(*stack.currentFrame->args.subjectPtr))
01490                                     RRETURN_NO_MATCH;
01491                                 ++stack.currentFrame->args.subjectPtr;
01492                             }
01493                             break;
01494                             
01495                         case OP_NOT_WORDCHAR:
01496                             for (int i = 1; i <= min; i++) {
01497                                 if (isWordChar(*stack.currentFrame->args.subjectPtr))
01498                                     RRETURN_NO_MATCH;
01499                                 ++stack.currentFrame->args.subjectPtr;
01500                             }
01501                             break;
01502                             
01503                         case OP_WORDCHAR:
01504                             for (int i = 1; i <= min; i++) {
01505                                 if (!isWordChar(*stack.currentFrame->args.subjectPtr))
01506                                     RRETURN_NO_MATCH;
01507                                 ++stack.currentFrame->args.subjectPtr;
01508                             }
01509                             break;
01510                             
01511                         default:
01512                             ASSERT_NOT_REACHED();
01513                             return matchError(JSRegExpErrorInternal, stack);
01514                     }  
01515                 }
01516                 
01517                 
01518                 
01519                 if (min == stack.currentFrame->locals.max)
01520                     NEXT_OPCODE;    
01521                 
01522                 
01523 
01524                 
01525                 if (minimize) {
01526                     for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
01527                         RECURSIVE_MATCH(48, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01528                         if (isMatch)
01529                             RRETURN;
01530                         if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
01531                             RRETURN;
01532                         
01533                         int c = *stack.currentFrame->args.subjectPtr++;
01534                         switch (stack.currentFrame->locals.ctype) {
01535                             case OP_NOT_NEWLINE:
01536                                 if (isNewline(c))
01537                                     RRETURN;
01538                                 break;
01539                                 
01540                             case OP_NOT_DIGIT:
01541                                 if (isASCIIDigit(c))
01542                                     RRETURN;
01543                                 break;
01544                                 
01545                             case OP_DIGIT:
01546                                 if (!isASCIIDigit(c))
01547                                     RRETURN;
01548                                 break;
01549                                 
01550                             case OP_NOT_WHITESPACE:
01551                                 if (isSpaceChar(c))
01552                                     RRETURN;
01553                                 break;
01554                                 
01555                             case OP_WHITESPACE:
01556                                 if (!isSpaceChar(c))
01557                                     RRETURN;
01558                                 break;
01559                                 
01560                             case OP_NOT_WORDCHAR:
01561                                 if (isWordChar(c))
01562                                     RRETURN;
01563                                 break;
01564                                 
01565                             case OP_WORDCHAR:
01566                                 if (!isWordChar(c))
01567                                     RRETURN;
01568                                 break;
01569                                 
01570                             default:
01571                                 ASSERT_NOT_REACHED();
01572                                 return matchError(JSRegExpErrorInternal, stack);
01573                         }
01574                     }
01575                     
01576                 }
01577                 
01578                 
01579 
01580                 
01581                 else {
01582                     stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;  
01583                     
01584                     switch (stack.currentFrame->locals.ctype) {
01585                         case OP_NOT_NEWLINE:
01586                             for (int i = min; i < stack.currentFrame->locals.max; i++) {
01587                                 if (stack.currentFrame->args.subjectPtr >= md.endSubject || isNewline(*stack.currentFrame->args.subjectPtr))
01588                                     break;
01589                                 stack.currentFrame->args.subjectPtr++;
01590                             }
01591                             break;
01592                             
01593                         case OP_NOT_DIGIT:
01594                             for (int i = min; i < stack.currentFrame->locals.max; i++) {
01595                                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01596                                     break;
01597                                 int c = *stack.currentFrame->args.subjectPtr;
01598                                 if (isASCIIDigit(c))
01599                                     break;
01600                                 ++stack.currentFrame->args.subjectPtr;
01601                             }
01602                             break;
01603                             
01604                         case OP_DIGIT:
01605                             for (int i = min; i < stack.currentFrame->locals.max; i++) {
01606                                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01607                                     break;
01608                                 int c = *stack.currentFrame->args.subjectPtr;
01609                                 if (!isASCIIDigit(c))
01610                                     break;
01611                                 ++stack.currentFrame->args.subjectPtr;
01612                             }
01613                             break;
01614                             
01615                         case OP_NOT_WHITESPACE:
01616                             for (int i = min; i < stack.currentFrame->locals.max; i++) {
01617                                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01618                                     break;
01619                                 int c = *stack.currentFrame->args.subjectPtr;
01620                                 if (isSpaceChar(c))
01621                                     break;
01622                                 ++stack.currentFrame->args.subjectPtr;
01623                             }
01624                             break;
01625                             
01626                         case OP_WHITESPACE:
01627                             for (int i = min; i < stack.currentFrame->locals.max; i++) {
01628                                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01629                                     break;
01630                                 int c = *stack.currentFrame->args.subjectPtr;
01631                                 if (!isSpaceChar(c))
01632                                     break;
01633                                 ++stack.currentFrame->args.subjectPtr;
01634                             }
01635                             break;
01636                             
01637                         case OP_NOT_WORDCHAR:
01638                             for (int i = min; i < stack.currentFrame->locals.max; i++) {
01639                                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01640                                     break;
01641                                 int c = *stack.currentFrame->args.subjectPtr;
01642                                 if (isWordChar(c))
01643                                     break;
01644                                 ++stack.currentFrame->args.subjectPtr;
01645                             }
01646                             break;
01647                             
01648                         case OP_WORDCHAR:
01649                             for (int i = min; i < stack.currentFrame->locals.max; i++) {
01650                                 if (stack.currentFrame->args.subjectPtr >= md.endSubject)
01651                                     break;
01652                                 int c = *stack.currentFrame->args.subjectPtr;
01653                                 if (!isWordChar(c))
01654                                     break;
01655                                 ++stack.currentFrame->args.subjectPtr;
01656                             }
01657                             break;
01658                             
01659                         default:
01660                             ASSERT_NOT_REACHED();
01661                             return matchError(JSRegExpErrorInternal, stack);
01662                     }
01663                     
01664                     
01665                     
01666                     for (;;) {
01667                         RECURSIVE_MATCH(52, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
01668                         if (isMatch)
01669                             RRETURN;
01670                         if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
01671                             break;        
01672                     }
01673                     
01674                     
01675                     
01676                     RRETURN;
01677                 }
01678                 
01679                 
01680             BEGIN_OPCODE(CRMINPLUS):
01681             BEGIN_OPCODE(CRMINQUERY):
01682             BEGIN_OPCODE(CRMINRANGE):
01683             BEGIN_OPCODE(CRMINSTAR):
01684             BEGIN_OPCODE(CRPLUS):
01685             BEGIN_OPCODE(CRQUERY):
01686             BEGIN_OPCODE(CRRANGE):
01687             BEGIN_OPCODE(CRSTAR):
01688                 ASSERT_NOT_REACHED();
01689                 return matchError(JSRegExpErrorInternal, stack);
01690                 
01691 #ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
01692             CAPTURING_BRACKET:
01693 #else
01694             default:
01695 #endif
01696                 
01697 
01698 
01699 
01700 
01701 
01702 
01703 
01704 
01705 
01706 
01707 
01708 
01709                 
01710                 ASSERT(*stack.currentFrame->args.instructionPtr > OP_BRA);
01711                 
01712                 stack.currentFrame->locals.number = *stack.currentFrame->args.instructionPtr - OP_BRA;
01713                 
01714                 
01715 
01716                 
01717                 if (stack.currentFrame->locals.number > EXTRACT_BASIC_MAX)
01718                     stack.currentFrame->locals.number = get2ByteValue(stack.currentFrame->args.instructionPtr + 2 + LINK_SIZE);
01719                 stack.currentFrame->locals.offset = stack.currentFrame->locals.number << 1;
01720                 
01721 #ifdef DEBUG
01722                 printf("start bracket %d subject=", stack.currentFrame->locals.number);
01723                 pchars(stack.currentFrame->args.subjectPtr, 16, true, md);
01724                 printf("\n");
01725 #endif
01726                 
01727                 if (stack.currentFrame->locals.offset < md.offsetMax) {
01728                     stack.currentFrame->locals.saveOffset1 = md.offsetVector[stack.currentFrame->locals.offset];
01729                     stack.currentFrame->locals.saveOffset2 = md.offsetVector[stack.currentFrame->locals.offset + 1];
01730                     stack.currentFrame->locals.saveOffset3 = md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number];
01731                     
01732                     DPRINTF(("saving %d %d %d\n", stack.currentFrame->locals.saveOffset1, stack.currentFrame->locals.saveOffset2, stack.currentFrame->locals.saveOffset3));
01733                     md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number] = stack.currentFrame->args.subjectPtr - md.startSubject;
01734                     
01735                     do {
01736                         RECURSIVE_MATCH_STARTNG_NEW_GROUP(1, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
01737                         if (isMatch)
01738                             RRETURN;
01739                         stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
01740                     } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
01741                     
01742                     DPRINTF(("bracket %d failed\n", stack.currentFrame->locals.number));
01743                     
01744                     md.offsetVector[stack.currentFrame->locals.offset] = stack.currentFrame->locals.saveOffset1;
01745                     md.offsetVector[stack.currentFrame->locals.offset + 1] = stack.currentFrame->locals.saveOffset2;
01746                     md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number] = stack.currentFrame->locals.saveOffset3;
01747                     
01748                     RRETURN;
01749                 }
01750                 
01751                 
01752                 
01753                 goto NON_CAPTURING_BRACKET;
01754         }
01755         
01756         
01757 
01758 
01759         
01760     } 
01761     
01762     ASSERT_NOT_REACHED();
01763     
01764 #ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
01765     
01766 RRETURN_SWITCH:
01767     switch (stack.currentFrame->returnLocation) {
01768         case 0: goto RETURN;
01769         case 1: goto RRETURN_1;
01770         case 2: goto RRETURN_2;
01771         case 6: goto RRETURN_6;
01772         case 7: goto RRETURN_7;
01773         case 14: goto RRETURN_14;
01774         case 15: goto RRETURN_15;
01775         case 16: goto RRETURN_16;
01776         case 17: goto RRETURN_17;
01777         case 18: goto RRETURN_18;
01778         case 19: goto RRETURN_19;
01779         case 20: goto RRETURN_20;
01780         case 21: goto RRETURN_21;
01781         case 22: goto RRETURN_22;
01782         case 24: goto RRETURN_24;
01783         case 26: goto RRETURN_26;
01784         case 27: goto RRETURN_27;
01785         case 28: goto RRETURN_28;
01786         case 29: goto RRETURN_29;
01787         case 30: goto RRETURN_30;
01788         case 31: goto RRETURN_31;
01789         case 38: goto RRETURN_38;
01790         case 40: goto RRETURN_40;
01791         case 42: goto RRETURN_42;
01792         case 44: goto RRETURN_44;
01793         case 48: goto RRETURN_48;
01794         case 52: goto RRETURN_52;
01795     }
01796     
01797     ASSERT_NOT_REACHED();
01798     return matchError(JSRegExpErrorInternal, stack);
01799     
01800 #endif
01801     
01802 RETURN:
01803     return isMatch;
01804 }
01805 
01806 
01807 
01808 
01809 
01810 
01811 
01812 
01813 
01814 
01815 
01816 
01817 
01818 
01819 
01820 
01821 
01822 
01823 
01824 
01825 
01826 
01827 
01828 
01829 
01830 
01831 static void tryFirstByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int first_byte, bool first_byte_caseless, bool useMultiLineFirstCharOptimization, const UChar* originalSubjectStart)
01832 {
01833     
01834     
01835     if (first_byte >= 0) {
01836         UChar first_char = first_byte;
01837         if (first_byte_caseless)
01838             while (subjectPtr < endSubject) {
01839                 int c = *subjectPtr;
01840                 if (c > 127)
01841                     break;
01842                 if (toLowerCase(c) == first_char)
01843                     break;
01844                 subjectPtr++;
01845             }
01846         else {
01847             while (subjectPtr < endSubject && *subjectPtr != first_char)
01848                 subjectPtr++;
01849         }
01850     } else if (useMultiLineFirstCharOptimization) {
01851         
01852         
01853         if (subjectPtr > originalSubjectStart) {
01854             while (subjectPtr < endSubject && !isNewline(subjectPtr[-1]))
01855                 subjectPtr++;
01856         }
01857     }
01858 }
01859 
01860 static bool tryRequiredByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int req_byte, int req_byte2, bool req_byte_caseless, bool hasFirstByte, const UChar*& reqBytePtr)
01861 {
01862     
01863 
01864 
01865 
01866 
01867 
01868 
01869 
01870 
01871 
01872 
01873 
01874 
01875 
01876     if (req_byte >= 0 && endSubject - subjectPtr < REQ_BYTE_MAX) {
01877         const UChar* p = subjectPtr + (hasFirstByte ? 1 : 0);
01878 
01879         
01880 
01881 
01882         if (p > reqBytePtr) {
01883             if (req_byte_caseless) {
01884                 while (p < endSubject) {
01885                     int pp = *p++;
01886                     if (pp == req_byte || pp == req_byte2) {
01887                         p--;
01888                         break;
01889                     }
01890                 }
01891             } else {
01892                 while (p < endSubject) {
01893                     if (*p++ == req_byte) {
01894                         p--;
01895                         break;
01896                     }
01897                 }
01898             }
01899 
01900             
01901 
01902             if (p >= endSubject)
01903                 return true;
01904 
01905             
01906 
01907 
01908 
01909             reqBytePtr = p;
01910         }
01911     }
01912     return false;
01913 }
01914 
01915 int jsRegExpExecute(const JSRegExp* re,
01916                     const UChar* subject, int length, int start_offset, int* offsets,
01917                     int offsetcount)
01918 {
01919     ASSERT(re);
01920     ASSERT(subject);
01921     ASSERT(offsetcount >= 0);
01922     ASSERT(offsets || offsetcount == 0);
01923     
01924     MatchData matchBlock;
01925     matchBlock.startSubject = subject;
01926     matchBlock.endSubject = matchBlock.startSubject + length;
01927     const UChar* endSubject = matchBlock.endSubject;
01928     
01929     matchBlock.multiline = (re->options & MatchAcrossMultipleLinesOption);
01930     matchBlock.ignoreCase = (re->options & IgnoreCaseOption);
01931     
01932     
01933 
01934 
01935 
01936     
01937     int ocount = offsetcount - (offsetcount % 3);
01938     
01939     
01940     
01941     
01942     bool using_temporary_offsets = false;
01943     if (re->top_backref > 0 && re->top_backref >= ocount/3) {
01944         ocount = re->top_backref * 3 + 3;
01945         matchBlock.offsetVector = new int[ocount];
01946         if (!matchBlock.offsetVector)
01947             return JSRegExpErrorNoMemory;
01948         using_temporary_offsets = true;
01949     } else
01950         matchBlock.offsetVector = offsets;
01951     
01952     matchBlock.offsetEnd = ocount;
01953     matchBlock.offsetMax = (2*ocount)/3;
01954     matchBlock.offsetOverflow = false;
01955     
01956     
01957 
01958 
01959     
01960     int resetcount = 2 + re->top_bracket * 2;
01961     if (resetcount > offsetcount)
01962         resetcount = ocount;
01963     
01964     
01965 
01966 
01967     
01968     if (matchBlock.offsetVector) {
01969         int* iptr = matchBlock.offsetVector + ocount;
01970         int* iend = iptr - resetcount/2 + 1;
01971         while (--iptr >= iend)
01972             *iptr = -1;
01973     }
01974     
01975     
01976 
01977 
01978 
01979 
01980     
01981     bool first_byte_caseless = false;
01982     int first_byte = -1;
01983     if (re->options & UseFirstByteOptimizationOption) {
01984         first_byte = re->first_byte & 255;
01985         if ((first_byte_caseless = (re->first_byte & REQ_IGNORE_CASE)))
01986             first_byte = toLowerCase(first_byte);
01987     }
01988     
01989     
01990 
01991     
01992     bool req_byte_caseless = false;
01993     int req_byte = -1;
01994     int req_byte2 = -1;
01995     if (re->options & UseRequiredByteOptimizationOption) {
01996         req_byte = re->req_byte & 255; 
01997         req_byte_caseless = (re->req_byte & REQ_IGNORE_CASE);
01998         req_byte2 = flipCase(req_byte);
01999     }
02000     
02001     
02002 
02003     
02004     const UChar* startMatch = subject + start_offset;
02005     const UChar* reqBytePtr = startMatch - 1;
02006     bool useMultiLineFirstCharOptimization = re->options & UseMultiLineFirstByteOptimizationOption;
02007     
02008     do {
02009         
02010         if (matchBlock.offsetVector) {
02011             int* iptr = matchBlock.offsetVector;
02012             int* iend = iptr + resetcount;
02013             while (iptr < iend)
02014                 *iptr++ = -1;
02015         }
02016         
02017         tryFirstByteOptimization(startMatch, endSubject, first_byte, first_byte_caseless, useMultiLineFirstCharOptimization, matchBlock.startSubject + start_offset);
02018         if (tryRequiredByteOptimization(startMatch, endSubject, req_byte, req_byte2, req_byte_caseless, first_byte >= 0, reqBytePtr))
02019             break;
02020                 
02021         
02022 
02023 
02024 
02025 
02026 
02027         
02028         
02029         const unsigned char* start_code = (const unsigned char*)(re + 1);
02030         
02031         int returnCode = match(startMatch, start_code, 2, matchBlock);
02032         
02033         
02034 
02035         if (returnCode == 0) {
02036             startMatch++;
02037             continue;
02038         }
02039 
02040         if (returnCode != 1) {
02041             ASSERT(returnCode == JSRegExpErrorHitLimit || returnCode == JSRegExpErrorNoMemory);
02042             DPRINTF((">>>> error: returning %d\n", returnCode));
02043             return returnCode;
02044         }
02045         
02046         
02047 
02048         
02049         if (using_temporary_offsets) {
02050             if (offsetcount >= 4) {
02051                 memcpy(offsets + 2, matchBlock.offsetVector + 2, (offsetcount - 2) * sizeof(int));
02052                 DPRINTF(("Copied offsets from temporary memory\n"));
02053             }
02054             if (matchBlock.endOffsetTop > offsetcount)
02055                 matchBlock.offsetOverflow = true;
02056             
02057             DPRINTF(("Freeing temporary memory\n"));
02058             delete [] matchBlock.offsetVector;
02059         }
02060         
02061         returnCode = matchBlock.offsetOverflow ? 0 : matchBlock.endOffsetTop / 2;
02062         
02063         if (offsetcount < 2)
02064             returnCode = 0;
02065         else {
02066             offsets[0] = startMatch - matchBlock.startSubject;
02067             offsets[1] = matchBlock.endMatchPtr - matchBlock.startSubject;
02068         }
02069         
02070         DPRINTF((">>>> returning %d\n", returnCode));
02071         return returnCode;
02072     } while (!(re->options & IsAnchoredOption) && startMatch <= endSubject);
02073     
02074     if (using_temporary_offsets) {
02075         DPRINTF(("Freeing temporary memory\n"));
02076         delete [] matchBlock.offsetVector;
02077     }
02078     
02079     DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
02080     return JSRegExpErrorNoMatch;
02081 }