1 /* 2 * Permission is hereby granted, free of charge, to any person obtaining a copy of 3 * this software and associated documentation files (the "Software"), to deal in 4 * the Software without restriction, including without limitation the rights to 5 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 6 * of the Software, and to permit persons to whom the Software is furnished to do 7 * so, subject to the following conditions: 8 * 9 * The above copyright notice and this permission notice shall be included in all 10 * copies or substantial portions of the Software. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 * SOFTWARE. 19 */ 20 package jdk.nashorn.internal.runtime.regexp.joni; 21 22 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt; 23 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindCondition; 24 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindLongest; 25 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindNotEmpty; 26 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isNotBol; 27 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isNotEol; 28 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isPosixRegion; 29 import static jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper.isCrnl; 30 import static jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper.isNewLine; 31 32 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode; 33 import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode; 34 import jdk.nashorn.internal.runtime.regexp.joni.constants.OPSize; 35 import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder; 36 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages; 37 import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException; 38 39 class ByteCodeMachine extends StackMachine { 40 private int bestLen; // return value 41 private int s = 0; // current char 42 43 private int range; // right range 44 private int sprev; 45 private int sstart; 46 private int sbegin; 47 48 private final int[]code; // byte code 49 private int ip; // instruction pointer 50 51 ByteCodeMachine(Regex regex, char[] chars, int p, int end) { 52 super(regex, chars, p, end); 53 this.code = regex.code; 54 } 55 56 protected int stkp; // a temporary 57 private boolean makeCaptureHistoryTree(CaptureTreeNode node) { 58 //CaptureTreeNode child; 59 int k = stkp; 60 //int k = kp; 61 62 while (k < stk) { 63 StackEntry e = stack[k]; 64 if (e.type == MEM_START) { 65 int n = e.getMemNum(); 66 if (n <= Config.MAX_CAPTURE_HISTORY_GROUP && bsAt(regex.captureHistory, n)) { 67 CaptureTreeNode child = new CaptureTreeNode(); 68 child.group = n; 69 child.beg = e.getMemPStr() - str; 70 node.addChild(child); 71 stkp = k + 1; 72 if (makeCaptureHistoryTree(child)) return true; 73 74 k = stkp; 75 child.end = e.getMemPStr() - str; 76 } 77 } else if (e.type == MEM_END) { 78 if (e.getMemNum() == node.group) { 79 node.end = e.getMemPStr() - str; 80 stkp = k; 81 return false; 82 } 83 } 84 } 85 return true; /* 1: root node ending. */ 86 } 87 88 private void checkCaptureHistory(Region region) { 89 CaptureTreeNode node; 90 if (region.historyRoot == null) { 91 node = region.historyRoot = new CaptureTreeNode(); 92 } else { 93 node = region.historyRoot; 94 node.clear(); 95 } 96 97 // was clear ??? 98 node.group = 0; 99 node.beg = sstart - str; 100 node.end = s - str; 101 102 stkp = 0; 103 makeCaptureHistoryTree(region.historyRoot); 104 } 105 106 private boolean stringCmpIC(int caseFlodFlag, int s1, IntHolder ps2, int mbLen, int textEnd) { 107 108 int s2 = ps2.value; 109 int end1 = s1 + mbLen; 110 111 while (s1 < end1) { 112 char c1 = Character.toLowerCase(chars[s1++]); 113 char c2 = Character.toLowerCase(chars[s2++]); 114 115 if (c1 != c2) { 116 return false; 117 } 118 } 119 ps2.value = s2; 120 return true; 121 } 122 123 private void debugMatchBegin() { 124 Config.log.println("match_at: " + 125 "str: " + str + 126 ", end: " + end + 127 ", start: " + this.sstart + 128 ", sprev: " + this.sprev); 129 Config.log.println("size: " + (end - str) + ", start offset: " + (this.sstart - str)); 130 } 131 132 private void debugMatchLoop() { 133 if (Config.DEBUG_MATCH) { 134 Config.log.printf("%4d", (s - str)).print("> \""); 135 int q, i; 136 for (i=0, q=s; i<7 && q<end && s>=0; i++) { 137 if (q < end) Config.log.print(new String(new char[]{chars[q++]})); 138 } 139 String str = q < end ? "...\"" : "\""; 140 q += str.length(); 141 Config.log.print(str); 142 for (i=0; i<20-(q-s);i++) Config.log.print(" "); 143 StringBuilder sb = new StringBuilder(); 144 new ByteCodePrinter(regex).compiledByteCodeToString(sb, ip); 145 Config.log.println(sb.toString()); 146 } 147 } 148 149 protected final int matchAt(int range, int sstart, int sprev) { 150 this.range = range; 151 this.sstart = sstart; 152 this.sprev = sprev; 153 154 stk = 0; 155 ip = 0; 156 157 if (Config.DEBUG_MATCH) debugMatchBegin(); 158 159 init(); 160 161 bestLen = -1; 162 s = sstart; 163 164 final int[]code = this.code; 165 while (true) { 166 if (Config.DEBUG_MATCH) debugMatchLoop(); 167 168 sbegin = s; 169 switch (code[ip++]) { 170 case OPCode.END: if (opEnd()) return finish(); break; 171 case OPCode.EXACT1: opExact1(); break; 172 case OPCode.EXACT2: opExact2(); continue; 173 case OPCode.EXACT3: opExact3(); continue; 174 case OPCode.EXACT4: opExact4(); continue; 175 case OPCode.EXACT5: opExact5(); continue; 176 case OPCode.EXACTN: opExactN(); continue; 177 178 case OPCode.EXACTMB2N1: opExactMB2N1(); break; 179 case OPCode.EXACTMB2N2: opExactMB2N2(); continue; 180 case OPCode.EXACTMB2N3: opExactMB2N3(); continue; 181 case OPCode.EXACTMB2N: opExactMB2N(); continue; 182 case OPCode.EXACTMB3N: opExactMB3N(); continue; 183 case OPCode.EXACTMBN: opExactMBN(); continue; 184 185 case OPCode.EXACT1_IC: opExact1IC(); break; 186 case OPCode.EXACTN_IC: opExactNIC(); continue; 187 188 case OPCode.CCLASS: opCClass(); break; 189 case OPCode.CCLASS_MB: opCClassMB(); break; 190 case OPCode.CCLASS_MIX: opCClassMIX(); break; 191 case OPCode.CCLASS_NOT: opCClassNot(); break; 192 case OPCode.CCLASS_MB_NOT: opCClassMBNot(); break; 193 case OPCode.CCLASS_MIX_NOT: opCClassMIXNot(); break; 194 case OPCode.CCLASS_NODE: opCClassNode(); break; 195 196 case OPCode.ANYCHAR: opAnyChar(); break; 197 case OPCode.ANYCHAR_ML: opAnyCharML(); break; 198 case OPCode.ANYCHAR_STAR: opAnyCharStar(); break; 199 case OPCode.ANYCHAR_ML_STAR: opAnyCharMLStar(); break; 200 case OPCode.ANYCHAR_STAR_PEEK_NEXT: opAnyCharStarPeekNext(); break; 201 case OPCode.ANYCHAR_ML_STAR_PEEK_NEXT: opAnyCharMLStarPeekNext(); break; 202 case OPCode.STATE_CHECK_ANYCHAR_STAR: opStateCheckAnyCharStar(); break; 203 case OPCode.STATE_CHECK_ANYCHAR_ML_STAR:opStateCheckAnyCharMLStar();break; 204 205 case OPCode.WORD: opWord(); break; 206 case OPCode.NOT_WORD: opNotWord(); break; 207 case OPCode.WORD_BOUND: opWordBound(); continue; 208 case OPCode.NOT_WORD_BOUND: opNotWordBound(); continue; 209 case OPCode.WORD_BEGIN: opWordBegin(); continue; 210 case OPCode.WORD_END: opWordEnd(); continue; 211 212 case OPCode.BEGIN_BUF: opBeginBuf(); continue; 213 case OPCode.END_BUF: opEndBuf(); continue; 214 case OPCode.BEGIN_LINE: opBeginLine(); continue; 215 case OPCode.END_LINE: opEndLine(); continue; 216 case OPCode.SEMI_END_BUF: opSemiEndBuf(); continue; 217 case OPCode.BEGIN_POSITION: opBeginPosition(); continue; 218 219 case OPCode.MEMORY_START_PUSH: opMemoryStartPush(); continue; 220 case OPCode.MEMORY_START: opMemoryStart(); continue; 221 case OPCode.MEMORY_END_PUSH: opMemoryEndPush(); continue; 222 case OPCode.MEMORY_END: opMemoryEnd(); continue; 223 case OPCode.MEMORY_END_PUSH_REC: opMemoryEndPushRec(); continue; 224 case OPCode.MEMORY_END_REC: opMemoryEndRec(); continue; 225 226 case OPCode.BACKREF1: opBackRef1(); continue; 227 case OPCode.BACKREF2: opBackRef2(); continue; 228 case OPCode.BACKREFN: opBackRefN(); continue; 229 case OPCode.BACKREFN_IC: opBackRefNIC(); continue; 230 case OPCode.BACKREF_MULTI: opBackRefMulti(); continue; 231 case OPCode.BACKREF_MULTI_IC: opBackRefMultiIC(); continue; 232 case OPCode.BACKREF_WITH_LEVEL: opBackRefAtLevel(); continue; 233 234 case OPCode.NULL_CHECK_START: opNullCheckStart(); continue; 235 case OPCode.NULL_CHECK_END: opNullCheckEnd(); continue; 236 case OPCode.NULL_CHECK_END_MEMST: opNullCheckEndMemST(); continue; 237 case OPCode.NULL_CHECK_END_MEMST_PUSH: opNullCheckEndMemSTPush(); continue; 238 239 case OPCode.JUMP: opJump(); continue; 240 case OPCode.PUSH: opPush(); continue; 241 242 // CEC 243 case OPCode.STATE_CHECK_PUSH: opStateCheckPush(); continue; 244 case OPCode.STATE_CHECK_PUSH_OR_JUMP: opStateCheckPushOrJump(); continue; 245 case OPCode.STATE_CHECK: opStateCheck(); continue; 246 247 case OPCode.POP: opPop(); continue; 248 case OPCode.PUSH_OR_JUMP_EXACT1: opPushOrJumpExact1(); continue; 249 case OPCode.PUSH_IF_PEEK_NEXT: opPushIfPeekNext(); continue; 250 251 case OPCode.REPEAT: opRepeat(); continue; 252 case OPCode.REPEAT_NG: opRepeatNG(); continue; 253 case OPCode.REPEAT_INC: opRepeatInc(); continue; 254 case OPCode.REPEAT_INC_SG: opRepeatIncSG(); continue; 255 case OPCode.REPEAT_INC_NG: opRepeatIncNG(); continue; 256 case OPCode.REPEAT_INC_NG_SG: opRepeatIncNGSG(); continue; 257 258 case OPCode.PUSH_POS: opPushPos(); continue; 259 case OPCode.POP_POS: opPopPos(); continue; 260 case OPCode.PUSH_POS_NOT: opPushPosNot(); continue; 261 case OPCode.FAIL_POS: opFailPos(); continue; 262 case OPCode.PUSH_STOP_BT: opPushStopBT(); continue; 263 case OPCode.POP_STOP_BT: opPopStopBT(); continue; 264 265 case OPCode.LOOK_BEHIND: opLookBehind(); continue; 266 case OPCode.PUSH_LOOK_BEHIND_NOT: opPushLookBehindNot(); continue; 267 case OPCode.FAIL_LOOK_BEHIND_NOT: opFailLookBehindNot(); continue; 268 269 // USE_SUBEXP_CALL 270 case OPCode.CALL: opCall(); continue; 271 case OPCode.RETURN: opReturn(); continue; 272 273 case OPCode.FINISH: 274 return finish(); 275 276 case OPCode.FAIL: opFail(); continue; 277 278 default: 279 throw new InternalException(ErrorMessages.ERR_UNDEFINED_BYTECODE); 280 281 } // main switch 282 } // main while 283 } 284 285 private boolean opEnd() { 286 int n = s - sstart; 287 288 if (n > bestLen) { 289 if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) { 290 if (isFindLongest(regex.options)) { 291 if (n > msaBestLen) { 292 msaBestLen = n; 293 msaBestS = sstart; 294 } else { 295 // goto end_best_len; 296 return endBestLength(); 297 } 298 } 299 } // USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE 300 301 bestLen = n; 302 final Region region = msaRegion; 303 if (region != null) { 304 // USE_POSIX_REGION_OPTION ... else ... 305 region.beg[0] = msaBegin = sstart - str; 306 region.end[0] = msaEnd = s - str; 307 for (int i = 1; i <= regex.numMem; i++) { 308 // opt! 309 if (repeatStk[memEndStk + i] != INVALID_INDEX) { 310 region.beg[i] = bsAt(regex.btMemStart, i) ? 311 stack[repeatStk[memStartStk + i]].getMemPStr() - str : 312 repeatStk[memStartStk + i] - str; 313 314 315 region.end[i] = bsAt(regex.btMemEnd, i) ? 316 stack[repeatStk[memEndStk + i]].getMemPStr() : 317 repeatStk[memEndStk + i] - str; 318 319 } else { 320 region.beg[i] = region.end[i] = Region.REGION_NOTPOS; 321 } 322 323 } 324 325 if (Config.USE_CAPTURE_HISTORY) { 326 if (regex.captureHistory != 0) checkCaptureHistory(region); 327 } 328 } else { 329 msaBegin = sstart - str; 330 msaEnd = s - str; 331 } 332 } else { 333 Region region = msaRegion; 334 if (Config.USE_POSIX_API_REGION_OPTION) { 335 if (!isPosixRegion(regex.options)) { 336 if (region != null) { 337 region.clear(); 338 } else { 339 msaBegin = msaEnd = 0; 340 } 341 } 342 } else { 343 if (region != null) { 344 region.clear(); 345 } else { 346 msaBegin = msaEnd = 0; 347 } 348 } // USE_POSIX_REGION_OPTION 349 } 350 // end_best_len: 351 /* default behavior: return first-matching result. */ 352 return endBestLength(); 353 } 354 355 private boolean endBestLength() { 356 if (isFindCondition(regex.options)) { 357 if (isFindNotEmpty(regex.options) && s == sstart) { 358 bestLen = -1; 359 {opFail(); return false;} /* for retry */ 360 } 361 if (isFindLongest(regex.options) && s < range) { 362 {opFail(); return false;} /* for retry */ 363 } 364 } 365 // goto finish; 366 return true; 367 } 368 369 private void opExact1() { 370 if (s >= range || code[ip] != chars[s++]) {opFail(); return;} 371 //if (s > range) {opFail(); return;} 372 ip++; 373 sprev = sbegin; // break; 374 } 375 376 private void opExact2() { 377 if (s + 2 > range) {opFail(); return;} 378 if (code[ip] != chars[s]) {opFail(); return;} 379 ip++; s++; 380 if (code[ip] != chars[s]) {opFail(); return;} 381 sprev = s; 382 ip++; s++; 383 } 384 385 private void opExact3() { 386 if (s + 3 > range) {opFail(); return;} 387 if (code[ip] != chars[s]) {opFail(); return;} 388 ip++; s++; 389 if (code[ip] != chars[s]) {opFail(); return;} 390 ip++; s++; 391 if (code[ip] != chars[s]) {opFail(); return;} 392 sprev = s; 393 ip++; s++; 394 } 395 396 private void opExact4() { 397 if (s + 4 > range) {opFail(); return;} 398 if (code[ip] != chars[s]) {opFail(); return;} 399 ip++; s++; 400 if (code[ip] != chars[s]) {opFail(); return;} 401 ip++; s++; 402 if (code[ip] != chars[s]) {opFail(); return;} 403 ip++; s++; 404 if (code[ip] != chars[s]) {opFail(); return;} 405 sprev = s; 406 ip++; s++; 407 } 408 409 private void opExact5() { 410 if (s + 5 > range) {opFail(); return;} 411 if (code[ip] != chars[s]) {opFail(); return;} 412 ip++; s++; 413 if (code[ip] != chars[s]) {opFail(); return;} 414 ip++; s++; 415 if (code[ip] != chars[s]) {opFail(); return;} 416 ip++; s++; 417 if (code[ip] != chars[s]) {opFail(); return;} 418 ip++; s++; 419 if (code[ip] != chars[s]) {opFail(); return;} 420 sprev = s; 421 ip++; s++; 422 } 423 424 private void opExactN() { 425 int tlen = code[ip++]; 426 if (s + tlen > range) {opFail(); return;} 427 428 if (Config.USE_STRING_TEMPLATES) { 429 char[] bs = regex.templates[code[ip++]]; 430 int ps = code[ip++]; 431 432 while (tlen-- > 0) if (bs[ps++] != chars[s++]) {opFail(); return;} 433 434 } else { 435 while (tlen-- > 0) if (code[ip++] != chars[s++]) {opFail(); return;} 436 } 437 sprev = s - 1; 438 } 439 440 private void opExactMB2N1() { 441 if (s + 2 > range) {opFail(); return;} 442 if (code[ip] != chars[s]) {opFail(); return;} 443 ip++; s++; 444 if (code[ip] != chars[s]) {opFail(); return;} 445 ip++; s++; 446 sprev = sbegin; // break; 447 } 448 449 private void opExactMB2N2() { 450 if (s + 4 > range) {opFail(); return;} 451 if (code[ip] != chars[s]) {opFail(); return;} 452 ip++; s++; 453 if (code[ip] != chars[s]) {opFail(); return;} 454 ip++; s++; 455 sprev = s; 456 if (code[ip] != chars[s]) {opFail(); return;} 457 ip++; s++; 458 if (code[ip] != chars[s]) {opFail(); return;} 459 ip++; s++; 460 } 461 462 private void opExactMB2N3() { 463 if (s + 6 > range) {opFail(); return;} 464 if (code[ip] != chars[s]) {opFail(); return;} 465 ip++; s++; 466 if (code[ip] != chars[s]) {opFail(); return;} 467 ip++; s++; 468 if (code[ip] != chars[s]) {opFail(); return;} 469 ip++; s++; 470 if (code[ip] != chars[s]) {opFail(); return;} 471 ip++; s++; 472 sprev = s; 473 if (code[ip] != chars[s]) {opFail(); return;} 474 ip++; s++; 475 if (code[ip] != chars[s]) {opFail(); return;} 476 ip++; s++; 477 } 478 479 private void opExactMB2N() { 480 int tlen = code[ip++]; 481 if (s + tlen * 2 > range) {opFail(); return;} 482 483 if (Config.USE_STRING_TEMPLATES) { 484 char[] bs = regex.templates[code[ip++]]; 485 int ps = code[ip++]; 486 487 while(tlen-- > 0) { 488 if (bs[ps] != chars[s]) {opFail(); return;} 489 ps++; s++; 490 if (bs[ps] != chars[s]) {opFail(); return;} 491 ps++; s++; 492 } 493 } else { 494 while(tlen-- > 0) { 495 if (code[ip] != chars[s]) {opFail(); return;} 496 ip++; s++; 497 if (code[ip] != chars[s]) {opFail(); return;} 498 ip++; s++; 499 } 500 } 501 sprev = s - 2; 502 } 503 504 private void opExactMB3N() { 505 int tlen = code[ip++]; 506 if (s + tlen * 3 > range) {opFail(); return;} 507 508 if (Config.USE_STRING_TEMPLATES) { 509 char[] bs = regex.templates[code[ip++]]; 510 int ps = code[ip++]; 511 512 while (tlen-- > 0) { 513 if (bs[ps] != chars[s]) {opFail(); return;} 514 ps++; s++; 515 if (bs[ps] != chars[s]) {opFail(); return;} 516 ps++; s++; 517 if (bs[ps] != chars[s]) {opFail(); return;} 518 ps++; s++; 519 } 520 } else { 521 while (tlen-- > 0) { 522 if (code[ip] != chars[s]) {opFail(); return;} 523 ip++; s++; 524 if (code[ip] != chars[s]) {opFail(); return;} 525 ip++; s++; 526 if (code[ip] != chars[s]) {opFail(); return;} 527 ip++; s++; 528 } 529 } 530 531 sprev = s - 3; 532 } 533 534 private void opExactMBN() { 535 int tlen = code[ip++]; /* mb-len */ 536 int tlen2= code[ip++]; /* string len */ 537 538 tlen2 *= tlen; 539 if (s + tlen2 > range) {opFail(); return;} 540 541 if (Config.USE_STRING_TEMPLATES) { 542 char[] bs = regex.templates[code[ip++]]; 543 int ps = code[ip++]; 544 545 while (tlen2-- > 0) { 546 if (bs[ps] != chars[s]) {opFail(); return;} 547 ps++; s++; 548 } 549 } else { 550 while (tlen2-- > 0) { 551 if (code[ip] != chars[s]) {opFail(); return;} 552 ip++; s++; 553 } 554 } 555 556 sprev = s - tlen; 557 } 558 559 private void opExact1IC() { 560 if (s >= range || code[ip] != Character.toLowerCase(chars[s++])) {opFail(); return;} 561 ip++; 562 sprev = sbegin; // break; 563 } 564 565 private void opExactNIC() { 566 int tlen = code[ip++]; 567 if (s + tlen > range) {opFail(); return;} 568 569 if (Config.USE_STRING_TEMPLATES) { 570 char[] bs = regex.templates[code[ip++]]; 571 int ps = code[ip++]; 572 573 while (tlen-- > 0) if (bs[ps++] != Character.toLowerCase(chars[s++])) {opFail(); return;} 574 } else { 575 576 while (tlen-- > 0) if (code[ip++] != Character.toLowerCase(chars[s++])) {opFail(); return;} 577 } 578 sprev = s - 1; 579 } 580 581 private boolean isInBitSet() { 582 int c = chars[s]; 583 return (c <= 0xff && (code[ip + (c >>> BitSet.ROOM_SHIFT)] & (1 << c)) != 0); 584 } 585 586 private void opCClass() { 587 if (s >= range || !isInBitSet()) {opFail(); return;} 588 ip += BitSet.BITSET_SIZE; 589 s++; 590 sprev = sbegin; // break; 591 } 592 593 private boolean isInClassMB() { 594 int tlen = code[ip++]; 595 if (s >= range) return false; 596 int ss = s; 597 s++; 598 int c = chars[ss]; 599 if (!EncodingHelper.isInCodeRange(code, ip, c)) return false; 600 ip += tlen; 601 return true; 602 } 603 604 private void opCClassMB() { 605 // beyond string check 606 if (s >= range || chars[s] <= 0xff) {opFail(); return;} 607 if (!isInClassMB()) {opFail(); return;} // not!!! 608 sprev = sbegin; // break; 609 } 610 611 private void opCClassMIX() { 612 if (s >= range) {opFail(); return;} 613 if (chars[s] > 0xff) { 614 ip += BitSet.BITSET_SIZE; 615 if (!isInClassMB()) {opFail(); return;} 616 } else { 617 if (!isInBitSet()) {opFail(); return;} 618 ip += BitSet.BITSET_SIZE; 619 int tlen = code[ip++]; // by code range length 620 ip += tlen; 621 s++; 622 } 623 sprev = sbegin; // break; 624 } 625 626 private void opCClassNot() { 627 if (s >= range || isInBitSet()) {opFail(); return;} 628 ip += BitSet.BITSET_SIZE; 629 s++; 630 sprev = sbegin; // break; 631 } 632 633 private boolean isNotInClassMB() { 634 int tlen = code[ip++]; 635 636 if (!(s + 1 <= range)) { 637 if (s >= range) return false; 638 s = end; 639 ip += tlen; 640 return true; 641 } 642 643 int ss = s; 644 s++; 645 int c = chars[ss]; 646 647 if (EncodingHelper.isInCodeRange(code, ip, c)) return false; 648 ip += tlen; 649 return true; 650 } 651 652 private void opCClassMBNot() { 653 if (s >= range) {opFail(); return;} 654 if (chars[s] <= 0xff) { 655 s++; 656 int tlen = code[ip++]; 657 ip += tlen; 658 sprev = sbegin; // break; 659 return; 660 } 661 if (!isNotInClassMB()) {opFail(); return;} 662 sprev = sbegin; // break; 663 } 664 665 private void opCClassMIXNot() { 666 if (s >= range) {opFail(); return;} 667 if (chars[s] > 0xff) { 668 ip += BitSet.BITSET_SIZE; 669 if (!isNotInClassMB()) {opFail(); return;} 670 } else { 671 if (isInBitSet()) {opFail(); return;} 672 ip += BitSet.BITSET_SIZE; 673 int tlen = code[ip++]; 674 ip += tlen; 675 s++; 676 } 677 sprev = sbegin; // break; 678 } 679 680 private void opCClassNode() { 681 if (s >= range) {opFail(); return;} 682 CClassNode cc = (CClassNode)regex.operands[code[ip++]]; 683 int ss = s; 684 s++; 685 int c = chars[ss]; 686 if (!cc.isCodeInCCLength(c)) {opFail(); return;} 687 sprev = sbegin; // break; 688 } 689 690 private void opAnyChar() { 691 if (s >= range) {opFail(); return;} 692 if (chars[s] == EncodingHelper.NEW_LINE) {opFail(); return;} 693 s++; 694 sprev = sbegin; // break; 695 } 696 697 private void opAnyCharML() { 698 if (s >= range) {opFail(); return;} 699 s++; 700 sprev = sbegin; // break; 701 } 702 703 private void opAnyCharStar() { 704 final char[] chars = this.chars; 705 while (s < range) { 706 pushAlt(ip, s, sprev); 707 if (isNewLine(chars, s, end)) {opFail(); return;} 708 sprev = s; 709 s++; 710 } 711 sprev = sbegin; // break; 712 } 713 714 private void opAnyCharMLStar() { 715 while (s < range) { 716 pushAlt(ip, s, sprev); 717 sprev = s; 718 s++; 719 } 720 sprev = sbegin; // break; 721 } 722 723 private void opAnyCharStarPeekNext() { 724 final char c = (char)code[ip]; 725 final char[] chars = this.chars; 726 727 while (s < range) { 728 char b = chars[s]; 729 if (c == b) pushAlt(ip + 1, s, sprev); 730 if (b == EncodingHelper.NEW_LINE) {opFail(); return;} 731 sprev = s; 732 s++; 733 } 734 ip++; 735 sprev = sbegin; // break; 736 } 737 738 private void opAnyCharMLStarPeekNext() { 739 final char c = (char)code[ip]; 740 final char[] chars = this.chars; 741 742 while (s < range) { 743 if (c == chars[s]) pushAlt(ip + 1, s, sprev); 744 sprev = s; 745 s++; 746 } 747 ip++; 748 sprev = sbegin; // break; 749 } 750 751 // CEC 752 private void opStateCheckAnyCharStar() { 753 int mem = code[ip++]; 754 final char[] chars = this.chars; 755 756 while (s < range) { 757 if (stateCheckVal(s, mem)) {opFail(); return;} 758 pushAltWithStateCheck(ip, s, sprev, mem); 759 if (chars[s] == EncodingHelper.NEW_LINE) {opFail(); return;} 760 sprev = s; 761 s++; 762 } 763 sprev = sbegin; // break; 764 } 765 766 // CEC 767 private void opStateCheckAnyCharMLStar() { 768 int mem = code[ip++]; 769 770 while (s < range) { 771 if (stateCheckVal(s, mem)) {opFail(); return;} 772 pushAltWithStateCheck(ip, s, sprev, mem); 773 sprev = s; 774 s++; 775 } 776 sprev = sbegin; // break; 777 } 778 779 private void opWord() { 780 if (s >= range || !EncodingHelper.isWord(chars[s])) {opFail(); return;} 781 s++; 782 sprev = sbegin; // break; 783 } 784 785 private void opNotWord() { 786 if (s >= range || EncodingHelper.isWord(chars[s])) {opFail(); return;} 787 s++; 788 sprev = sbegin; // break; 789 } 790 791 private void opWordBound() { 792 if (s == str) { 793 if (s >= range || !EncodingHelper.isWord(chars[s])) {opFail(); return;} 794 } else if (s == end) { 795 if (sprev >= end || !EncodingHelper.isWord(chars[sprev])) {opFail(); return;} 796 } else { 797 if (EncodingHelper.isWord(chars[s]) == EncodingHelper.isWord(chars[sprev])) {opFail(); return;} 798 } 799 } 800 801 private void opNotWordBound() { 802 if (s == str) { 803 if (s < range && EncodingHelper.isWord(chars[s])) {opFail(); return;} 804 } else if (s == end) { 805 if (sprev < end && EncodingHelper.isWord(chars[sprev])) {opFail(); return;} 806 } else { 807 if (EncodingHelper.isWord(chars[s]) != EncodingHelper.isWord(chars[sprev])) {opFail(); return;} 808 } 809 } 810 811 private void opWordBegin() { 812 if (s < range && EncodingHelper.isWord(chars[s])) { 813 if (s == str || !EncodingHelper.isWord(chars[sprev])) return; 814 } 815 opFail(); 816 } 817 818 private void opWordEnd() { 819 if (s != str && EncodingHelper.isWord(chars[sprev])) { 820 if (s == end || !EncodingHelper.isWord(chars[s])) return; 821 } 822 opFail(); 823 } 824 825 private void opBeginBuf() { 826 if (s != str) opFail(); 827 } 828 829 private void opEndBuf() { 830 if (s != end) opFail(); 831 } 832 833 private void opBeginLine() { 834 if (s == str) { 835 if (isNotBol(msaOptions)) opFail(); 836 return; 837 } else if (EncodingHelper.isNewLine(chars, sprev, end) && s != end) { 838 return; 839 } 840 opFail(); 841 } 842 843 private void opEndLine() { 844 if (s == end) { 845 if (Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) { 846 if (str == end || !EncodingHelper.isNewLine(chars, sprev, end)) { 847 if (isNotEol(msaOptions)) opFail(); 848 } 849 return; 850 } else { 851 if (isNotEol(msaOptions)) opFail(); 852 return; 853 } 854 } else if (isNewLine(chars, s, end) || (Config.USE_CRNL_AS_LINE_TERMINATOR && isCrnl(chars, s, end))) { 855 return; 856 } 857 opFail(); 858 } 859 860 private void opSemiEndBuf() { 861 if (s == end) { 862 if (Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) { 863 if (str == end || !isNewLine(chars, sprev, end)) { 864 if (isNotEol(msaOptions)) opFail(); 865 } 866 return; 867 } else { 868 if (isNotEol(msaOptions)) opFail(); 869 return; 870 } 871 } else if (isNewLine(chars, s, end) && s + 1 == end) { 872 return; 873 } else if (Config.USE_CRNL_AS_LINE_TERMINATOR && isCrnl(chars, s, end)) { 874 int ss = s + 2; 875 if (ss == end) return; 876 } 877 opFail(); 878 } 879 880 private void opBeginPosition() { 881 if (s != msaStart) opFail(); 882 } 883 884 private void opMemoryStartPush() { 885 int mem = code[ip++]; 886 pushMemStart(mem, s); 887 } 888 889 private void opMemoryStart() { 890 int mem = code[ip++]; 891 repeatStk[memStartStk + mem] = s; 892 } 893 894 private void opMemoryEndPush() { 895 int mem = code[ip++]; 896 pushMemEnd(mem, s); 897 } 898 899 private void opMemoryEnd() { 900 int mem = code[ip++]; 901 repeatStk[memEndStk + mem] = s; 902 } 903 904 private void opMemoryEndPushRec() { 905 int mem = code[ip++]; 906 int stkp = getMemStart(mem); /* should be before push mem-end. */ 907 pushMemEnd(mem, s); 908 repeatStk[memStartStk + mem] = stkp; 909 } 910 911 private void opMemoryEndRec() { 912 int mem = code[ip++]; 913 repeatStk[memEndStk + mem] = s; 914 int stkp = getMemStart(mem); 915 916 if (BitStatus.bsAt(regex.btMemStart, mem)) { 917 repeatStk[memStartStk + mem] = stkp; 918 } else { 919 repeatStk[memStartStk + mem] = stack[stkp].getMemPStr(); 920 } 921 922 pushMemEndMark(mem); 923 } 924 925 private boolean backrefInvalid(int mem) { 926 return repeatStk[memEndStk + mem] == INVALID_INDEX || repeatStk[memStartStk + mem] == INVALID_INDEX; 927 } 928 929 private int backrefStart(int mem) { 930 return bsAt(regex.btMemStart, mem) ? stack[repeatStk[memStartStk + mem]].getMemPStr() : repeatStk[memStartStk + mem]; 931 } 932 933 private int backrefEnd(int mem) { 934 return bsAt(regex.btMemEnd, mem) ? stack[repeatStk[memEndStk + mem]].getMemPStr() : repeatStk[memEndStk + mem]; 935 } 936 937 private void backref(int mem) { 938 /* if you want to remove following line, 939 you should check in parse and compile time. (numMem) */ 940 if (mem > regex.numMem || backrefInvalid(mem)) {opFail(); return;} 941 942 int pstart = backrefStart(mem); 943 int pend = backrefEnd(mem); 944 945 int n = pend - pstart; 946 if (s + n > range) {opFail(); return;} 947 sprev = s; 948 949 // STRING_CMP 950 while(n-- > 0) if (chars[pstart++] != chars[s++]) {opFail(); return;} 951 952 int len; 953 954 // beyond string check 955 if (sprev < range) { 956 while (sprev + 1 < s) sprev++; 957 } 958 } 959 960 private void opBackRef1() { 961 backref(1); 962 } 963 964 private void opBackRef2() { 965 backref(2); 966 } 967 968 private void opBackRefN() { 969 backref(code[ip++]); 970 } 971 972 private void opBackRefNIC() { 973 int mem = code[ip++]; 974 /* if you want to remove following line, 975 you should check in parse and compile time. (numMem) */ 976 if (mem > regex.numMem || backrefInvalid(mem)) {opFail(); return;} 977 978 int pstart = backrefStart(mem); 979 int pend = backrefEnd(mem); 980 981 int n = pend - pstart; 982 if (s + n > range) {opFail(); return;} 983 sprev = s; 984 985 value = s; 986 if (!stringCmpIC(regex.caseFoldFlag, pstart, this, n, end)) {opFail(); return;} 987 s = value; 988 989 int len; 990 // if (sprev < chars.length) 991 while (sprev + 1 < s) sprev++; 992 } 993 994 private void opBackRefMulti() { 995 int tlen = code[ip++]; 996 997 int i; 998 loop:for (i=0; i<tlen; i++) { 999 int mem = code[ip++]; 1000 if (backrefInvalid(mem)) continue; 1001 1002 int pstart = backrefStart(mem); 1003 int pend = backrefEnd(mem); 1004 1005 int n = pend - pstart; 1006 if (s + n > range) {opFail(); return;} 1007 1008 sprev = s; 1009 int swork = s; 1010 1011 while (n-- > 0) { 1012 if (chars[pstart++] != chars[swork++]) continue loop; 1013 } 1014 1015 s = swork; 1016 1017 int len; 1018 1019 // beyond string check 1020 if (sprev < range) { 1021 while (sprev + 1 < s) sprev++; 1022 } 1023 1024 ip += tlen - i - 1; // * SIZE_MEMNUM (1) 1025 break; /* success */ 1026 } 1027 if (i == tlen) {opFail(); return;} 1028 } 1029 1030 private void opBackRefMultiIC() { 1031 int tlen = code[ip++]; 1032 1033 int i; 1034 loop:for (i=0; i<tlen; i++) { 1035 int mem = code[ip++]; 1036 if (backrefInvalid(mem)) continue; 1037 1038 int pstart = backrefStart(mem); 1039 int pend = backrefEnd(mem); 1040 1041 int n = pend - pstart; 1042 if (s + n > range) {opFail(); return;} 1043 1044 sprev = s; 1045 1046 value = s; 1047 if (!stringCmpIC(regex.caseFoldFlag, pstart, this, n, end)) continue loop; // STRING_CMP_VALUE_IC 1048 s = value; 1049 1050 int len; 1051 // if (sprev < chars.length) 1052 while (sprev + 1 < s) sprev++; 1053 1054 ip += tlen - i - 1; // * SIZE_MEMNUM (1) 1055 break; /* success */ 1056 } 1057 if (i == tlen) {opFail(); return;} 1058 } 1059 1060 private boolean memIsInMemp(int mem, int num, int memp) { 1061 for (int i=0; i<num; i++) { 1062 int m = code[memp++]; 1063 if (mem == m) return true; 1064 } 1065 return false; 1066 } 1067 1068 // USE_BACKREF_AT_LEVEL // (s) and (end) implicit 1069 private boolean backrefMatchAtNestedLevel(boolean ignoreCase, int caseFoldFlag, 1070 int nest, int memNum, int memp) { 1071 int pend = -1; 1072 int level = 0; 1073 int k = stk - 1; 1074 1075 while (k >= 0) { 1076 StackEntry e = stack[k]; 1077 1078 if (e.type == CALL_FRAME) { 1079 level--; 1080 } else if (e.type == RETURN) { 1081 level++; 1082 } else if (level == nest) { 1083 if (e.type == MEM_START) { 1084 if (memIsInMemp(e.getMemNum(), memNum, memp)) { 1085 int pstart = e.getMemPStr(); 1086 if (pend != -1) { 1087 if (pend - pstart > end - s) return false; /* or goto next_mem; */ 1088 int p = pstart; 1089 1090 value = s; 1091 if (ignoreCase) { 1092 if (!stringCmpIC(caseFoldFlag, pstart, this, pend - pstart, end)) { 1093 return false; /* or goto next_mem; */ 1094 } 1095 } else { 1096 while (p < pend) { 1097 if (chars[p++] != chars[value++]) return false; /* or goto next_mem; */ 1098 } 1099 } 1100 s = value; 1101 1102 return true; 1103 } 1104 } 1105 } else if (e.type == MEM_END) { 1106 if (memIsInMemp(e.getMemNum(), memNum, memp)) { 1107 pend = e.getMemPStr(); 1108 } 1109 } 1110 } 1111 k--; 1112 } 1113 return false; 1114 } 1115 1116 private void opBackRefAtLevel() { 1117 int ic = code[ip++]; 1118 int level = code[ip++]; 1119 int tlen = code[ip++]; 1120 1121 sprev = s; 1122 if (backrefMatchAtNestedLevel(ic != 0, regex.caseFoldFlag, level, tlen, ip)) { // (s) and (end) implicit 1123 int len; 1124 while (sprev + 1 < s) sprev++; 1125 ip += tlen; // * SIZE_MEMNUM 1126 } else { 1127 {opFail(); return;} 1128 } 1129 } 1130 1131 /* no need: IS_DYNAMIC_OPTION() == 0 */ 1132 private void opSetOptionPush() { 1133 // option = code[ip++]; // final for now 1134 pushAlt(ip, s, sprev); 1135 ip += OPSize.SET_OPTION + OPSize.FAIL; 1136 } 1137 1138 private void opSetOption() { 1139 // option = code[ip++]; // final for now 1140 } 1141 1142 private void opNullCheckStart() { 1143 int mem = code[ip++]; 1144 pushNullCheckStart(mem, s); 1145 } 1146 1147 private void nullCheckFound() { 1148 // null_check_found: 1149 /* empty loop founded, skip next instruction */ 1150 switch(code[ip++]) { 1151 case OPCode.JUMP: 1152 case OPCode.PUSH: 1153 ip++; // p += SIZE_RELADDR; 1154 break; 1155 case OPCode.REPEAT_INC: 1156 case OPCode.REPEAT_INC_NG: 1157 case OPCode.REPEAT_INC_SG: 1158 case OPCode.REPEAT_INC_NG_SG: 1159 ip++; // p += SIZE_MEMNUM; 1160 break; 1161 default: 1162 throw new InternalException(ErrorMessages.ERR_UNEXPECTED_BYTECODE); 1163 } // switch 1164 } 1165 1166 private void opNullCheckEnd() { 1167 int mem = code[ip++]; 1168 int isNull = nullCheck(mem, s); /* mem: null check id */ 1169 1170 if (isNull != 0) { 1171 if (Config.DEBUG_MATCH) { 1172 Config.log.println("NULL_CHECK_END: skip id:" + mem + ", s:" + s); 1173 } 1174 1175 nullCheckFound(); 1176 } 1177 } 1178 1179 // USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK 1180 private void opNullCheckEndMemST() { 1181 int mem = code[ip++]; /* mem: null check id */ 1182 int isNull = nullCheckMemSt(mem, s); 1183 1184 if (isNull != 0) { 1185 if (Config.DEBUG_MATCH) { 1186 Config.log.println("NULL_CHECK_END_MEMST: skip id:" + mem + ", s:" + s); 1187 } 1188 1189 if (isNull == -1) {opFail(); return;} 1190 nullCheckFound(); 1191 } 1192 } 1193 1194 // USE_SUBEXP_CALL 1195 private void opNullCheckEndMemSTPush() { 1196 int mem = code[ip++]; /* mem: null check id */ 1197 1198 int isNull; 1199 if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) { 1200 isNull = nullCheckMemStRec(mem, s); 1201 } else { 1202 isNull = nullCheckRec(mem, s); 1203 } 1204 1205 if (isNull != 0) { 1206 if (Config.DEBUG_MATCH) { 1207 Config.log.println("NULL_CHECK_END_MEMST_PUSH: skip id:" + mem + ", s:" + s); 1208 } 1209 1210 if (isNull == -1) {opFail(); return;} 1211 nullCheckFound(); 1212 } else { 1213 pushNullCheckEnd(mem); 1214 } 1215 } 1216 1217 private void opJump() { 1218 ip += code[ip] + 1; 1219 } 1220 1221 private void opPush() { 1222 int addr = code[ip++]; 1223 pushAlt(ip + addr, s, sprev); 1224 } 1225 1226 // CEC 1227 private void opStateCheckPush() { 1228 int mem = code[ip++]; 1229 if (stateCheckVal(s, mem)) {opFail(); return;} 1230 int addr = code[ip++]; 1231 pushAltWithStateCheck(ip + addr, s, sprev, mem); 1232 } 1233 1234 // CEC 1235 private void opStateCheckPushOrJump() { 1236 int mem = code[ip++]; 1237 int addr= code[ip++]; 1238 1239 if (stateCheckVal(s, mem)) { 1240 ip += addr; 1241 } else { 1242 pushAltWithStateCheck(ip + addr, s, sprev, mem); 1243 } 1244 } 1245 1246 // CEC 1247 private void opStateCheck() { 1248 int mem = code[ip++]; 1249 if (stateCheckVal(s, mem)) {opFail(); return;} 1250 pushStateCheck(s, mem); 1251 } 1252 1253 private void opPop() { 1254 popOne(); 1255 } 1256 1257 private void opPushOrJumpExact1() { 1258 int addr = code[ip++]; 1259 // beyond string check 1260 if (s < range && code[ip] == chars[s]) { 1261 ip++; 1262 pushAlt(ip + addr, s, sprev); 1263 return; 1264 } 1265 ip += addr + 1; 1266 } 1267 1268 private void opPushIfPeekNext() { 1269 int addr = code[ip++]; 1270 // beyond string check 1271 if (s < range && code[ip] == chars[s]) { 1272 ip++; 1273 pushAlt(ip + addr, s, sprev); 1274 return; 1275 } 1276 ip++; 1277 } 1278 1279 private void opRepeat() { 1280 int mem = code[ip++]; /* mem: OP_REPEAT ID */ 1281 int addr= code[ip++]; 1282 1283 // ensure1(); 1284 repeatStk[mem] = stk; 1285 pushRepeat(mem, ip); 1286 1287 if (regex.repeatRangeLo[mem] == 0) { // lower 1288 pushAlt(ip + addr, s, sprev); 1289 } 1290 } 1291 1292 private void opRepeatNG() { 1293 int mem = code[ip++]; /* mem: OP_REPEAT ID */ 1294 int addr= code[ip++]; 1295 1296 // ensure1(); 1297 repeatStk[mem] = stk; 1298 pushRepeat(mem, ip); 1299 1300 if (regex.repeatRangeLo[mem] == 0) { 1301 pushAlt(ip, s, sprev); 1302 ip += addr; 1303 } 1304 } 1305 1306 private void repeatInc(int mem, int si) { 1307 StackEntry e = stack[si]; 1308 1309 e.increaseRepeatCount(); 1310 1311 if (e.getRepeatCount() >= regex.repeatRangeHi[mem]) { 1312 /* end of repeat. Nothing to do. */ 1313 } else if (e.getRepeatCount() >= regex.repeatRangeLo[mem]) { 1314 pushAlt(ip, s, sprev); 1315 ip = e.getRepeatPCode(); /* Don't use stkp after PUSH. */ 1316 } else { 1317 ip = e.getRepeatPCode(); 1318 } 1319 pushRepeatInc(si); 1320 } 1321 1322 private void opRepeatInc() { 1323 int mem = code[ip++]; /* mem: OP_REPEAT ID */ 1324 int si = repeatStk[mem]; 1325 repeatInc(mem, si); 1326 } 1327 1328 private void opRepeatIncSG() { 1329 int mem = code[ip++]; /* mem: OP_REPEAT ID */ 1330 int si = getRepeat(mem); 1331 repeatInc(mem, si); 1332 } 1333 1334 private void repeatIncNG(int mem, int si) { 1335 StackEntry e = stack[si]; 1336 1337 e.increaseRepeatCount(); 1338 1339 if (e.getRepeatCount() < regex.repeatRangeHi[mem]) { 1340 if (e.getRepeatCount() >= regex.repeatRangeLo[mem]) { 1341 int pcode = e.getRepeatPCode(); 1342 pushRepeatInc(si); 1343 pushAlt(pcode, s, sprev); 1344 } else { 1345 ip = e.getRepeatPCode(); 1346 pushRepeatInc(si); 1347 } 1348 } else if (e.getRepeatCount() == regex.repeatRangeHi[mem]) { 1349 pushRepeatInc(si); 1350 } 1351 } 1352 1353 private void opRepeatIncNG() { 1354 int mem = code[ip++]; 1355 int si = repeatStk[mem]; 1356 repeatIncNG(mem, si); 1357 } 1358 1359 private void opRepeatIncNGSG() { 1360 int mem = code[ip++]; 1361 int si = getRepeat(mem); 1362 repeatIncNG(mem, si); 1363 } 1364 1365 private void opPushPos() { 1366 pushPos(s, sprev); 1367 } 1368 1369 private void opPopPos() { 1370 StackEntry e = stack[posEnd()]; 1371 s = e.getStatePStr(); 1372 sprev= e.getStatePStrPrev(); 1373 } 1374 1375 private void opPushPosNot() { 1376 int addr = code[ip++]; 1377 pushPosNot(ip + addr, s, sprev); 1378 } 1379 1380 private void opFailPos() { 1381 popTilPosNot(); 1382 opFail(); 1383 } 1384 1385 private void opPushStopBT() { 1386 pushStopBT(); 1387 } 1388 1389 private void opPopStopBT() { 1390 stopBtEnd(); 1391 } 1392 1393 private void opLookBehind() { 1394 int tlen = code[ip++]; 1395 s = EncodingHelper.stepBack(str, s, tlen); 1396 if (s == -1) {opFail(); return;} 1397 sprev = EncodingHelper.prevCharHead(str, s); 1398 } 1399 1400 private void opLookBehindSb() { 1401 int tlen = code[ip++]; 1402 s -= tlen; 1403 if (s < str) {opFail(); return;} 1404 sprev = s == str ? -1 : s - 1; 1405 } 1406 1407 private void opPushLookBehindNot() { 1408 int addr = code[ip++]; 1409 int tlen = code[ip++]; 1410 int q = EncodingHelper.stepBack(str, s, tlen); 1411 if (q == -1) { 1412 /* too short case -> success. ex. /(?<!XXX)a/.match("a") 1413 If you want to change to fail, replace following line. */ 1414 ip += addr; 1415 // return FAIL; 1416 } else { 1417 pushLookBehindNot(ip + addr, s, sprev); 1418 s = q; 1419 sprev = EncodingHelper.prevCharHead(str, s); 1420 } 1421 } 1422 1423 private void opFailLookBehindNot() { 1424 popTilLookBehindNot(); 1425 opFail(); 1426 } 1427 1428 private void opCall() { 1429 int addr = code[ip++]; 1430 pushCallFrame(ip); 1431 ip = addr; // absolute address 1432 } 1433 1434 private void opReturn() { 1435 ip = sreturn(); 1436 pushReturn(); 1437 } 1438 1439 private void opFail() { 1440 if (stack == null) { 1441 ip = regex.codeLength - 1; 1442 return; 1443 } 1444 1445 1446 StackEntry e = pop(); 1447 ip = e.getStatePCode(); 1448 s = e.getStatePStr(); 1449 sprev = e.getStatePStrPrev(); 1450 1451 if (Config.USE_COMBINATION_EXPLOSION_CHECK) { 1452 if (e.getStateCheck() != 0) { 1453 e.type = STATE_CHECK_MARK; 1454 stk++; 1455 } 1456 } 1457 } 1458 1459 private int finish() { 1460 return bestLen; 1461 } 1462 }