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 }