Annotation of win32/pcre/pcre_jit_compile.c, revision 1.4

1.1       misha       1: /*************************************************
                      2: *      Perl-Compatible Regular Expressions       *
                      3: *************************************************/
                      4: 
                      5: /* PCRE is a library of functions to support regular expressions whose syntax
                      6: and semantics are as close as possible to those of the Perl 5 language.
                      7: 
                      8:                        Written by Philip Hazel
1.2       misha       9:            Copyright (c) 1997-2013 University of Cambridge
1.1       misha      10: 
                     11:   The machine code generator part (this module) was written by Zoltan Herczeg
1.2       misha      12:                       Copyright (c) 2010-2013
1.1       misha      13: 
                     14: -----------------------------------------------------------------------------
                     15: Redistribution and use in source and binary forms, with or without
                     16: modification, are permitted provided that the following conditions are met:
                     17: 
                     18:     * Redistributions of source code must retain the above copyright notice,
                     19:       this list of conditions and the following disclaimer.
                     20: 
                     21:     * Redistributions in binary form must reproduce the above copyright
                     22:       notice, this list of conditions and the following disclaimer in the
                     23:       documentation and/or other materials provided with the distribution.
                     24: 
                     25:     * Neither the name of the University of Cambridge nor the names of its
                     26:       contributors may be used to endorse or promote products derived from
                     27:       this software without specific prior written permission.
                     28: 
                     29: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                     30: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     31: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     32: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
                     33: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     34: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     35: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     36: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     37: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     38: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     39: POSSIBILITY OF SUCH DAMAGE.
                     40: -----------------------------------------------------------------------------
                     41: */
                     42: 
                     43: #ifdef HAVE_CONFIG_H
                     44: #include "config.h"
                     45: #endif
                     46: 
                     47: #include "pcre_internal.h"
                     48: 
1.2       misha      49: #if defined SUPPORT_JIT
1.1       misha      50: 
                     51: /* All-in-one: Since we use the JIT compiler only from here,
                     52: we just include it. This way we don't need to touch the build
                     53: system files. */
                     54: 
1.3       moko       55: #define SLJIT_MALLOC(size, allocator_data) (PUBL(malloc))(size)
                     56: #define SLJIT_FREE(ptr, allocator_data) (PUBL(free))(ptr)
1.1       misha      57: #define SLJIT_CONFIG_AUTO 1
                     58: #define SLJIT_CONFIG_STATIC 1
                     59: #define SLJIT_VERBOSE 0
                     60: #define SLJIT_DEBUG 0
                     61: 
                     62: #include "sljit/sljitLir.c"
                     63: 
                     64: #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
                     65: #error Unsupported architecture
                     66: #endif
                     67: 
1.2       misha      68: /* Defines for debugging purposes. */
1.1       misha      69: 
1.2       misha      70: /* 1 - Use unoptimized capturing brackets.
                     71:    2 - Enable capture_last_ptr (includes option 1). */
                     72: /* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */
                     73: 
                     74: /* 1 - Always have a control head. */
                     75: /* #define DEBUG_FORCE_CONTROL_HEAD 1 */
                     76: 
                     77: /* Allocate memory for the regex stack on the real machine stack.
                     78: Fast, but limited size. */
                     79: #define MACHINE_STACK_SIZE 32768
                     80: 
                     81: /* Growth rate for stack allocated by the OS. Should be the multiply
                     82: of page size. */
1.1       misha      83: #define STACK_GROWTH_RATE 8192
                     84: 
                     85: /* Enable to check that the allocation could destroy temporaries. */
                     86: #if defined SLJIT_DEBUG && SLJIT_DEBUG
                     87: #define DESTROY_REGISTERS 1
                     88: #endif
                     89: 
                     90: /*
                     91: Short summary about the backtracking mechanism empolyed by the jit code generator:
                     92: 
                     93: The code generator follows the recursive nature of the PERL compatible regular
                     94: expressions. The basic blocks of regular expressions are condition checkers
                     95: whose execute different commands depending on the result of the condition check.
                     96: The relationship between the operators can be horizontal (concatenation) and
1.2       misha      97: vertical (sub-expression) (See struct backtrack_common for more details).
1.1       misha      98: 
                     99:   'ab' - 'a' and 'b' regexps are concatenated
                    100:   'a+' - 'a' is the sub-expression of the '+' operator
                    101: 
                    102: The condition checkers are boolean (true/false) checkers. Machine code is generated
                    103: for the checker itself and for the actions depending on the result of the checker.
1.2       misha     104: The 'true' case is called as the matching path (expected path), and the other is called as
                    105: the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken
                    106: branches on the matching path.
1.1       misha     107: 
                    108:  Greedy star operator (*) :
1.2       misha     109:    Matching path: match happens.
                    110:    Backtrack path: match failed.
1.1       misha     111:  Non-greedy star operator (*?) :
1.2       misha     112:    Matching path: no need to perform a match.
                    113:    Backtrack path: match is required.
1.1       misha     114: 
                    115: The following example shows how the code generated for a capturing bracket
                    116: with two alternatives. Let A, B, C, D are arbirary regular expressions, and
                    117: we have the following regular expression:
                    118: 
                    119:    A(B|C)D
                    120: 
                    121: The generated code will be the following:
                    122: 
1.2       misha     123:  A matching path
                    124:  '(' matching path (pushing arguments to the stack)
                    125:  B matching path
                    126:  ')' matching path (pushing arguments to the stack)
                    127:  D matching path
1.1       misha     128:  return with successful match
                    129: 
1.2       misha     130:  D backtrack path
                    131:  ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")
                    132:  B backtrack path
1.1       misha     133:  C expected path
1.2       misha     134:  jump to D matching path
                    135:  C backtrack path
                    136:  A backtrack path
1.1       misha     137: 
1.2       misha     138:  Notice, that the order of backtrack code paths are the opposite of the fast
1.1       misha     139:  code paths. In this way the topmost value on the stack is always belong
1.2       misha     140:  to the current backtrack code path. The backtrack path must check
1.1       misha     141:  whether there is a next alternative. If so, it needs to jump back to
1.2       misha     142:  the matching path eventually. Otherwise it needs to clear out its own stack
                    143:  frame and continue the execution on the backtrack code paths.
1.1       misha     144: */
                    145: 
                    146: /*
                    147: Saved stack frames:
                    148: 
1.2       misha     149: Atomic blocks and asserts require reloading the values of private data
                    150: when the backtrack mechanism performed. Because of OP_RECURSE, the data
1.1       misha     151: are not necessarly known in compile time, thus we need a dynamic restore
                    152: mechanism.
                    153: 
                    154: The stack frames are stored in a chain list, and have the following format:
                    155: ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
                    156: 
1.2       misha     157: Thus we can restore the private data to a particular point in the stack.
1.1       misha     158: */
                    159: 
                    160: typedef struct jit_arguments {
                    161:   /* Pointers first. */
                    162:   struct sljit_stack *stack;
                    163:   const pcre_uchar *str;
                    164:   const pcre_uchar *begin;
                    165:   const pcre_uchar *end;
                    166:   int *offsets;
1.2       misha     167:   pcre_uchar *mark_ptr;
                    168:   void *callout_data;
1.1       misha     169:   /* Everything else after. */
1.4     ! moko      170:   sljit_u32 limit_match;
1.2       misha     171:   int real_offset_count;
                    172:   int offset_count;
1.4     ! moko      173:   sljit_u8 notbol;
        !           174:   sljit_u8 noteol;
        !           175:   sljit_u8 notempty;
        !           176:   sljit_u8 notempty_atstart;
1.1       misha     177: } jit_arguments;
                    178: 
1.2       misha     179: typedef struct executable_functions {
                    180:   void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];
1.3       moko      181:   void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES];
                    182:   sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
1.1       misha     183:   PUBL(jit_callback) callback;
                    184:   void *userdata;
1.4     ! moko      185:   sljit_u32 top_bracket;
        !           186:   sljit_u32 limit_match;
1.2       misha     187: } executable_functions;
1.1       misha     188: 
                    189: typedef struct jump_list {
                    190:   struct sljit_jump *jump;
                    191:   struct jump_list *next;
                    192: } jump_list;
                    193: 
                    194: typedef struct stub_list {
                    195:   struct sljit_jump *start;
1.2       misha     196:   struct sljit_label *quit;
1.1       misha     197:   struct stub_list *next;
                    198: } stub_list;
                    199: 
1.3       moko      200: typedef struct label_addr_list {
                    201:   struct sljit_label *label;
                    202:   sljit_uw *update_addr;
                    203:   struct label_addr_list *next;
                    204: } label_addr_list;
                    205: 
1.2       misha     206: enum frame_types {
                    207:   no_frame = -1,
                    208:   no_stack = -2
                    209: };
                    210: 
                    211: enum control_types {
                    212:   type_mark = 0,
                    213:   type_then_trap = 1
                    214: };
                    215: 
1.4     ! moko      216: typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args);
1.1       misha     217: 
                    218: /* The following structure is the key data type for the recursive
1.2       misha     219: code generator. It is allocated by compile_matchingpath, and contains
                    220: the arguments for compile_backtrackingpath. Must be the first member
1.1       misha     221: of its descendants. */
1.2       misha     222: typedef struct backtrack_common {
1.1       misha     223:   /* Concatenation stack. */
1.2       misha     224:   struct backtrack_common *prev;
                    225:   jump_list *nextbacktracks;
1.1       misha     226:   /* Internal stack (for component operators). */
1.2       misha     227:   struct backtrack_common *top;
                    228:   jump_list *topbacktracks;
1.1       misha     229:   /* Opcode pointer. */
                    230:   pcre_uchar *cc;
1.2       misha     231: } backtrack_common;
1.1       misha     232: 
1.2       misha     233: typedef struct assert_backtrack {
                    234:   backtrack_common common;
1.1       misha     235:   jump_list *condfailed;
1.2       misha     236:   /* Less than 0 if a frame is not needed. */
1.1       misha     237:   int framesize;
                    238:   /* Points to our private memory word on the stack. */
1.2       misha     239:   int private_data_ptr;
1.1       misha     240:   /* For iterators. */
1.2       misha     241:   struct sljit_label *matchingpath;
                    242: } assert_backtrack;
1.1       misha     243: 
1.2       misha     244: typedef struct bracket_backtrack {
                    245:   backtrack_common common;
1.1       misha     246:   /* Where to coninue if an alternative is successfully matched. */
1.2       misha     247:   struct sljit_label *alternative_matchingpath;
1.1       misha     248:   /* For rmin and rmax iterators. */
1.2       misha     249:   struct sljit_label *recursive_matchingpath;
1.1       misha     250:   /* For greedy ? operator. */
1.2       misha     251:   struct sljit_label *zero_matchingpath;
1.1       misha     252:   /* Contains the branches of a failed condition. */
                    253:   union {
                    254:     /* Both for OP_COND, OP_SCOND. */
                    255:     jump_list *condfailed;
1.2       misha     256:     assert_backtrack *assert;
                    257:     /* For OP_ONCE. Less than 0 if not needed. */
1.1       misha     258:     int framesize;
                    259:   } u;
                    260:   /* Points to our private memory word on the stack. */
1.2       misha     261:   int private_data_ptr;
                    262: } bracket_backtrack;
1.1       misha     263: 
1.2       misha     264: typedef struct bracketpos_backtrack {
                    265:   backtrack_common common;
1.1       misha     266:   /* Points to our private memory word on the stack. */
1.2       misha     267:   int private_data_ptr;
1.1       misha     268:   /* Reverting stack is needed. */
                    269:   int framesize;
                    270:   /* Allocated stack size. */
                    271:   int stacksize;
1.2       misha     272: } bracketpos_backtrack;
1.1       misha     273: 
1.2       misha     274: typedef struct braminzero_backtrack {
                    275:   backtrack_common common;
                    276:   struct sljit_label *matchingpath;
                    277: } braminzero_backtrack;
1.1       misha     278: 
1.4     ! moko      279: typedef struct char_iterator_backtrack {
1.2       misha     280:   backtrack_common common;
1.1       misha     281:   /* Next iteration. */
1.2       misha     282:   struct sljit_label *matchingpath;
1.4     ! moko      283:   union {
        !           284:     jump_list *backtracks;
        !           285:     struct {
        !           286:       unsigned int othercasebit;
        !           287:       pcre_uchar chr;
        !           288:       BOOL enabled;
        !           289:     } charpos;
        !           290:   } u;
        !           291: } char_iterator_backtrack;
        !           292: 
        !           293: typedef struct ref_iterator_backtrack {
        !           294:   backtrack_common common;
        !           295:   /* Next iteration. */
        !           296:   struct sljit_label *matchingpath;
        !           297: } ref_iterator_backtrack;
1.1       misha     298: 
                    299: typedef struct recurse_entry {
                    300:   struct recurse_entry *next;
                    301:   /* Contains the function entry. */
                    302:   struct sljit_label *entry;
                    303:   /* Collects the calls until the function is not created. */
                    304:   jump_list *calls;
                    305:   /* Points to the starting opcode. */
1.2       misha     306:   sljit_sw start;
1.1       misha     307: } recurse_entry;
                    308: 
1.2       misha     309: typedef struct recurse_backtrack {
                    310:   backtrack_common common;
                    311:   BOOL inlined_pattern;
                    312: } recurse_backtrack;
                    313: 
                    314: #define OP_THEN_TRAP OP_TABLE_LENGTH
                    315: 
                    316: typedef struct then_trap_backtrack {
                    317:   backtrack_common common;
                    318:   /* If then_trap is not NULL, this structure contains the real
                    319:   then_trap for the backtracking path. */
                    320:   struct then_trap_backtrack *then_trap;
                    321:   /* Points to the starting opcode. */
                    322:   sljit_sw start;
                    323:   /* Exit point for the then opcodes of this alternative. */
                    324:   jump_list *quit;
                    325:   /* Frame size of the current alternative. */
                    326:   int framesize;
                    327: } then_trap_backtrack;
                    328: 
1.3       moko      329: #define MAX_RANGE_SIZE 4
1.1       misha     330: 
                    331: typedef struct compiler_common {
1.2       misha     332:   /* The sljit ceneric compiler. */
1.1       misha     333:   struct sljit_compiler *compiler;
1.2       misha     334:   /* First byte code. */
1.1       misha     335:   pcre_uchar *start;
1.2       misha     336:   /* Maps private data offset to each opcode. */
1.4     ! moko      337:   sljit_s32 *private_data_ptrs;
1.3       moko      338:   /* Chain list of read-only data ptrs. */
                    339:   void *read_only_data_head;
1.2       misha     340:   /* Tells whether the capturing bracket is optimized. */
1.4     ! moko      341:   sljit_u8 *optimized_cbracket;
1.2       misha     342:   /* Tells whether the starting offset is a target of then. */
1.4     ! moko      343:   sljit_u8 *then_offsets;
1.2       misha     344:   /* Current position where a THEN must jump. */
                    345:   then_trap_backtrack *then_trap;
                    346:   /* Starting offset of private data for capturing brackets. */
1.4     ! moko      347:   sljit_s32 cbra_ptr;
1.2       misha     348:   /* Output vector starting point. Must be divisible by 2. */
1.4     ! moko      349:   sljit_s32 ovector_start;
        !           350:   /* Points to the starting character of the current match. */
        !           351:   sljit_s32 start_ptr;
1.2       misha     352:   /* Last known position of the requested byte. */
1.4     ! moko      353:   sljit_s32 req_char_ptr;
1.2       misha     354:   /* Head of the last recursion. */
1.4     ! moko      355:   sljit_s32 recursive_head_ptr;
        !           356:   /* First inspected character for partial matching.
        !           357:      (Needed for avoiding zero length partial matches.) */
        !           358:   sljit_s32 start_used_ptr;
1.2       misha     359:   /* Starting pointer for partial soft matches. */
1.4     ! moko      360:   sljit_s32 hit_start;
        !           361:   /* Pointer of the match end position. */
        !           362:   sljit_s32 match_end_ptr;
1.2       misha     363:   /* Points to the marked string. */
1.4     ! moko      364:   sljit_s32 mark_ptr;
1.2       misha     365:   /* Recursive control verb management chain. */
1.4     ! moko      366:   sljit_s32 control_head_ptr;
1.2       misha     367:   /* Points to the last matched capture block index. */
1.4     ! moko      368:   sljit_s32 capture_last_ptr;
        !           369:   /* Fast forward skipping byte code pointer. */
        !           370:   pcre_uchar *fast_forward_bc_ptr;
        !           371:   /* Locals used by fast fail optimization. */
        !           372:   sljit_s32 fast_fail_start_ptr;
        !           373:   sljit_s32 fast_fail_end_ptr;
1.2       misha     374: 
                    375:   /* Flipped and lower case tables. */
1.4     ! moko      376:   const sljit_u8 *fcc;
1.2       misha     377:   sljit_sw lcc;
                    378:   /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */
                    379:   int mode;
1.3       moko      380:   /* TRUE, when minlength is greater than 0. */
                    381:   BOOL might_be_empty;
1.2       misha     382:   /* \K is found in the pattern. */
                    383:   BOOL has_set_som;
                    384:   /* (*SKIP:arg) is found in the pattern. */
                    385:   BOOL has_skip_arg;
                    386:   /* (*THEN) is found in the pattern. */
                    387:   BOOL has_then;
1.4     ! moko      388:   /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */
        !           389:   BOOL has_skip_in_assert_back;
1.2       misha     390:   /* Currently in recurse or negative assert. */
                    391:   BOOL local_exit;
                    392:   /* Currently in a positive assert. */
                    393:   BOOL positive_assert;
                    394:   /* Newline control. */
1.1       misha     395:   int nltype;
1.4     ! moko      396:   sljit_u32 nlmax;
        !           397:   sljit_u32 nlmin;
1.1       misha     398:   int newline;
                    399:   int bsr_nltype;
1.4     ! moko      400:   sljit_u32 bsr_nlmax;
        !           401:   sljit_u32 bsr_nlmin;
1.2       misha     402:   /* Dollar endonly. */
1.1       misha     403:   int endonly;
1.2       misha     404:   /* Tables. */
                    405:   sljit_sw ctypes;
                    406:   /* Named capturing brackets. */
1.3       moko      407:   pcre_uchar *name_table;
1.2       misha     408:   sljit_sw name_count;
                    409:   sljit_sw name_entry_size;
                    410: 
                    411:   /* Labels and jump lists. */
                    412:   struct sljit_label *partialmatchlabel;
                    413:   struct sljit_label *quit_label;
                    414:   struct sljit_label *forced_quit_label;
                    415:   struct sljit_label *accept_label;
1.3       moko      416:   struct sljit_label *ff_newline_shortcut;
1.1       misha     417:   stub_list *stubs;
1.3       moko      418:   label_addr_list *label_addrs;
1.1       misha     419:   recurse_entry *entries;
                    420:   recurse_entry *currententry;
1.2       misha     421:   jump_list *partialmatch;
                    422:   jump_list *quit;
                    423:   jump_list *positive_assert_quit;
                    424:   jump_list *forced_quit;
1.1       misha     425:   jump_list *accept;
                    426:   jump_list *calllimit;
                    427:   jump_list *stackalloc;
                    428:   jump_list *revertframes;
                    429:   jump_list *wordboundary;
                    430:   jump_list *anynewline;
                    431:   jump_list *hspace;
                    432:   jump_list *vspace;
                    433:   jump_list *casefulcmp;
                    434:   jump_list *caselesscmp;
1.2       misha     435:   jump_list *reset_match;
1.1       misha     436:   BOOL jscript_compat;
                    437: #ifdef SUPPORT_UTF
                    438:   BOOL utf;
                    439: #ifdef SUPPORT_UCP
                    440:   BOOL use_ucp;
1.4     ! moko      441:   jump_list *getucd;
1.1       misha     442: #endif
1.3       moko      443: #ifdef COMPILE_PCRE8
1.1       misha     444:   jump_list *utfreadchar;
1.3       moko      445:   jump_list *utfreadchar16;
1.1       misha     446:   jump_list *utfreadtype8;
                    447: #endif
                    448: #endif /* SUPPORT_UTF */
                    449: } compiler_common;
                    450: 
                    451: /* For byte_sequence_compare. */
                    452: 
                    453: typedef struct compare_context {
                    454:   int length;
                    455:   int sourcereg;
                    456: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
                    457:   int ucharptr;
                    458:   union {
1.4     ! moko      459:     sljit_s32 asint;
        !           460:     sljit_u16 asushort;
1.2       misha     461: #if defined COMPILE_PCRE8
1.4     ! moko      462:     sljit_u8 asbyte;
        !           463:     sljit_u8 asuchars[4];
1.2       misha     464: #elif defined COMPILE_PCRE16
1.4     ! moko      465:     sljit_u16 asuchars[2];
1.2       misha     466: #elif defined COMPILE_PCRE32
1.4     ! moko      467:     sljit_u32 asuchars[1];
1.1       misha     468: #endif
                    469:   } c;
                    470:   union {
1.4     ! moko      471:     sljit_s32 asint;
        !           472:     sljit_u16 asushort;
1.2       misha     473: #if defined COMPILE_PCRE8
1.4     ! moko      474:     sljit_u8 asbyte;
        !           475:     sljit_u8 asuchars[4];
1.2       misha     476: #elif defined COMPILE_PCRE16
1.4     ! moko      477:     sljit_u16 asuchars[2];
1.2       misha     478: #elif defined COMPILE_PCRE32
1.4     ! moko      479:     sljit_u32 asuchars[1];
1.1       misha     480: #endif
                    481:   } oc;
                    482: #endif
                    483: } compare_context;
                    484: 
                    485: /* Undefine sljit macros. */
                    486: #undef CMP
                    487: 
                    488: /* Used for accessing the elements of the stack. */
1.4     ! moko      489: #define STACK(i)      ((i) * (int)sizeof(sljit_sw))
        !           490: 
        !           491: #ifdef SLJIT_PREF_SHIFT_REG
        !           492: #if SLJIT_PREF_SHIFT_REG == SLJIT_R2
        !           493: /* Nothing. */
        !           494: #elif SLJIT_PREF_SHIFT_REG == SLJIT_R3
        !           495: #define SHIFT_REG_IS_R3
        !           496: #else
        !           497: #error "Unsupported shift register"
        !           498: #endif
        !           499: #endif
1.1       misha     500: 
1.3       moko      501: #define TMP1          SLJIT_R0
1.4     ! moko      502: #ifdef SHIFT_REG_IS_R3
        !           503: #define TMP2          SLJIT_R3
        !           504: #define TMP3          SLJIT_R2
        !           505: #else
1.3       moko      506: #define TMP2          SLJIT_R2
                    507: #define TMP3          SLJIT_R3
1.4     ! moko      508: #endif
1.3       moko      509: #define STR_PTR       SLJIT_S0
                    510: #define STR_END       SLJIT_S1
                    511: #define STACK_TOP     SLJIT_R1
                    512: #define STACK_LIMIT   SLJIT_S2
                    513: #define COUNT_MATCH   SLJIT_S3
                    514: #define ARGUMENTS     SLJIT_S4
                    515: #define RETURN_ADDR   SLJIT_R4
1.1       misha     516: 
1.2       misha     517: /* Local space layout. */
1.1       misha     518: /* These two locals can be used by the current opcode. */
1.2       misha     519: #define LOCALS0          (0 * sizeof(sljit_sw))
                    520: #define LOCALS1          (1 * sizeof(sljit_sw))
1.1       misha     521: /* Two local variables for possessive quantifiers (char1 cannot use them). */
1.2       misha     522: #define POSSESSIVE0      (2 * sizeof(sljit_sw))
                    523: #define POSSESSIVE1      (3 * sizeof(sljit_sw))
1.1       misha     524: /* Max limit of recursions. */
1.2       misha     525: #define LIMIT_MATCH      (4 * sizeof(sljit_sw))
1.1       misha     526: /* The output vector is stored on the stack, and contains pointers
                    527: to characters. The vector data is divided into two groups: the first
                    528: group contains the start / end character pointers, and the second is
                    529: the start pointers when the end of the capturing group has not yet reached. */
1.2       misha     530: #define OVECTOR_START    (common->ovector_start)
1.3       moko      531: #define OVECTOR(i)       (OVECTOR_START + (i) * (sljit_sw)sizeof(sljit_sw))
                    532: #define OVECTOR_PRIV(i)  (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw))
1.2       misha     533: #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])
1.1       misha     534: 
1.2       misha     535: #if defined COMPILE_PCRE8
1.4     ! moko      536: #define MOV_UCHAR  SLJIT_MOV_U8
1.2       misha     537: #elif defined COMPILE_PCRE16
1.4     ! moko      538: #define MOV_UCHAR  SLJIT_MOV_U16
1.2       misha     539: #elif defined COMPILE_PCRE32
1.4     ! moko      540: #define MOV_UCHAR  SLJIT_MOV_U32
1.1       misha     541: #else
                    542: #error Unsupported compiling mode
                    543: #endif
                    544: 
                    545: /* Shortcuts. */
                    546: #define DEFINE_COMPILER \
                    547:   struct sljit_compiler *compiler = common->compiler
                    548: #define OP1(op, dst, dstw, src, srcw) \
                    549:   sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
                    550: #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
                    551:   sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
                    552: #define LABEL() \
                    553:   sljit_emit_label(compiler)
                    554: #define JUMP(type) \
                    555:   sljit_emit_jump(compiler, (type))
                    556: #define JUMPTO(type, label) \
                    557:   sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
                    558: #define JUMPHERE(jump) \
                    559:   sljit_set_label((jump), sljit_emit_label(compiler))
1.2       misha     560: #define SET_LABEL(jump, label) \
                    561:   sljit_set_label((jump), (label))
1.1       misha     562: #define CMP(type, src1, src1w, src2, src2w) \
                    563:   sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
                    564: #define CMPTO(type, src1, src1w, src2, src2w, label) \
                    565:   sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
1.4     ! moko      566: #define OP_FLAGS(op, dst, dstw, type) \
        !           567:   sljit_emit_op_flags(compiler, (op), (dst), (dstw), (type))
1.2       misha     568: #define GET_LOCAL_BASE(dst, dstw, offset) \
                    569:   sljit_get_local_base(compiler, (dst), (dstw), (offset))
1.1       misha     570: 
1.3       moko      571: #define READ_CHAR_MAX 0x7fffffff
                    572: 
1.4     ! moko      573: #define INVALID_UTF_CHAR 888
        !           574: 
1.3       moko      575: static pcre_uchar *bracketend(pcre_uchar *cc)
1.1       misha     576: {
                    577: SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
                    578: do cc += GET(cc, 1); while (*cc == OP_ALT);
                    579: SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
                    580: cc += 1 + LINK_SIZE;
                    581: return cc;
                    582: }
                    583: 
1.3       moko      584: static int no_alternatives(pcre_uchar *cc)
                    585: {
                    586: int count = 0;
                    587: SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
                    588: do
                    589:   {
                    590:   cc += GET(cc, 1);
                    591:   count++;
                    592:   }
                    593: while (*cc == OP_ALT);
                    594: SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
                    595: return count;
                    596: }
                    597: 
1.1       misha     598: /* Functions whose might need modification for all new supported opcodes:
                    599:  next_opcode
1.2       misha     600:  check_opcode_types
                    601:  set_private_data_ptrs
1.1       misha     602:  get_framesize
                    603:  init_frame
1.2       misha     604:  get_private_data_copy_length
                    605:  copy_private_data
                    606:  compile_matchingpath
                    607:  compile_backtrackingpath
1.1       misha     608: */
                    609: 
                    610: static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc)
                    611: {
                    612: SLJIT_UNUSED_ARG(common);
                    613: switch(*cc)
                    614:   {
                    615:   case OP_SOD:
                    616:   case OP_SOM:
                    617:   case OP_SET_SOM:
                    618:   case OP_NOT_WORD_BOUNDARY:
                    619:   case OP_WORD_BOUNDARY:
                    620:   case OP_NOT_DIGIT:
                    621:   case OP_DIGIT:
                    622:   case OP_NOT_WHITESPACE:
                    623:   case OP_WHITESPACE:
                    624:   case OP_NOT_WORDCHAR:
                    625:   case OP_WORDCHAR:
                    626:   case OP_ANY:
                    627:   case OP_ALLANY:
1.2       misha     628:   case OP_NOTPROP:
                    629:   case OP_PROP:
1.1       misha     630:   case OP_ANYNL:
                    631:   case OP_NOT_HSPACE:
                    632:   case OP_HSPACE:
                    633:   case OP_NOT_VSPACE:
                    634:   case OP_VSPACE:
                    635:   case OP_EXTUNI:
                    636:   case OP_EODN:
                    637:   case OP_EOD:
                    638:   case OP_CIRC:
                    639:   case OP_CIRCM:
                    640:   case OP_DOLL:
                    641:   case OP_DOLLM:
                    642:   case OP_CRSTAR:
                    643:   case OP_CRMINSTAR:
                    644:   case OP_CRPLUS:
                    645:   case OP_CRMINPLUS:
                    646:   case OP_CRQUERY:
                    647:   case OP_CRMINQUERY:
1.2       misha     648:   case OP_CRRANGE:
                    649:   case OP_CRMINRANGE:
1.3       moko      650:   case OP_CRPOSSTAR:
                    651:   case OP_CRPOSPLUS:
                    652:   case OP_CRPOSQUERY:
                    653:   case OP_CRPOSRANGE:
1.2       misha     654:   case OP_CLASS:
                    655:   case OP_NCLASS:
                    656:   case OP_REF:
                    657:   case OP_REFI:
1.3       moko      658:   case OP_DNREF:
                    659:   case OP_DNREFI:
1.2       misha     660:   case OP_RECURSE:
                    661:   case OP_CALLOUT:
                    662:   case OP_ALT:
                    663:   case OP_KET:
                    664:   case OP_KETRMAX:
                    665:   case OP_KETRMIN:
                    666:   case OP_KETRPOS:
                    667:   case OP_REVERSE:
                    668:   case OP_ASSERT:
                    669:   case OP_ASSERT_NOT:
                    670:   case OP_ASSERTBACK:
                    671:   case OP_ASSERTBACK_NOT:
                    672:   case OP_ONCE:
                    673:   case OP_ONCE_NC:
                    674:   case OP_BRA:
                    675:   case OP_BRAPOS:
                    676:   case OP_CBRA:
                    677:   case OP_CBRAPOS:
                    678:   case OP_COND:
                    679:   case OP_SBRA:
                    680:   case OP_SBRAPOS:
                    681:   case OP_SCBRA:
                    682:   case OP_SCBRAPOS:
                    683:   case OP_SCOND:
                    684:   case OP_CREF:
1.3       moko      685:   case OP_DNCREF:
1.2       misha     686:   case OP_RREF:
1.3       moko      687:   case OP_DNRREF:
1.1       misha     688:   case OP_DEF:
                    689:   case OP_BRAZERO:
                    690:   case OP_BRAMINZERO:
                    691:   case OP_BRAPOSZERO:
1.2       misha     692:   case OP_PRUNE:
                    693:   case OP_SKIP:
                    694:   case OP_THEN:
                    695:   case OP_COMMIT:
1.1       misha     696:   case OP_FAIL:
                    697:   case OP_ACCEPT:
                    698:   case OP_ASSERT_ACCEPT:
1.2       misha     699:   case OP_CLOSE:
1.1       misha     700:   case OP_SKIPZERO:
1.2       misha     701:   return cc + PRIV(OP_lengths)[*cc];
1.1       misha     702: 
                    703:   case OP_CHAR:
                    704:   case OP_CHARI:
                    705:   case OP_NOT:
                    706:   case OP_NOTI:
                    707:   case OP_STAR:
                    708:   case OP_MINSTAR:
                    709:   case OP_PLUS:
                    710:   case OP_MINPLUS:
                    711:   case OP_QUERY:
                    712:   case OP_MINQUERY:
1.2       misha     713:   case OP_UPTO:
                    714:   case OP_MINUPTO:
                    715:   case OP_EXACT:
1.1       misha     716:   case OP_POSSTAR:
                    717:   case OP_POSPLUS:
                    718:   case OP_POSQUERY:
1.2       misha     719:   case OP_POSUPTO:
1.1       misha     720:   case OP_STARI:
                    721:   case OP_MINSTARI:
                    722:   case OP_PLUSI:
                    723:   case OP_MINPLUSI:
                    724:   case OP_QUERYI:
                    725:   case OP_MINQUERYI:
1.2       misha     726:   case OP_UPTOI:
                    727:   case OP_MINUPTOI:
                    728:   case OP_EXACTI:
1.1       misha     729:   case OP_POSSTARI:
                    730:   case OP_POSPLUSI:
                    731:   case OP_POSQUERYI:
1.2       misha     732:   case OP_POSUPTOI:
1.1       misha     733:   case OP_NOTSTAR:
                    734:   case OP_NOTMINSTAR:
                    735:   case OP_NOTPLUS:
                    736:   case OP_NOTMINPLUS:
                    737:   case OP_NOTQUERY:
                    738:   case OP_NOTMINQUERY:
1.2       misha     739:   case OP_NOTUPTO:
                    740:   case OP_NOTMINUPTO:
                    741:   case OP_NOTEXACT:
1.1       misha     742:   case OP_NOTPOSSTAR:
                    743:   case OP_NOTPOSPLUS:
                    744:   case OP_NOTPOSQUERY:
1.2       misha     745:   case OP_NOTPOSUPTO:
1.1       misha     746:   case OP_NOTSTARI:
                    747:   case OP_NOTMINSTARI:
                    748:   case OP_NOTPLUSI:
                    749:   case OP_NOTMINPLUSI:
                    750:   case OP_NOTQUERYI:
                    751:   case OP_NOTMINQUERYI:
1.2       misha     752:   case OP_NOTUPTOI:
                    753:   case OP_NOTMINUPTOI:
                    754:   case OP_NOTEXACTI:
1.1       misha     755:   case OP_NOTPOSSTARI:
                    756:   case OP_NOTPOSPLUSI:
                    757:   case OP_NOTPOSQUERYI:
                    758:   case OP_NOTPOSUPTOI:
1.2       misha     759:   cc += PRIV(OP_lengths)[*cc];
1.1       misha     760: #ifdef SUPPORT_UTF
                    761:   if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
                    762: #endif
                    763:   return cc;
                    764: 
1.2       misha     765:   /* Special cases. */
                    766:   case OP_TYPESTAR:
                    767:   case OP_TYPEMINSTAR:
                    768:   case OP_TYPEPLUS:
                    769:   case OP_TYPEMINPLUS:
                    770:   case OP_TYPEQUERY:
                    771:   case OP_TYPEMINQUERY:
1.1       misha     772:   case OP_TYPEUPTO:
                    773:   case OP_TYPEMINUPTO:
                    774:   case OP_TYPEEXACT:
1.2       misha     775:   case OP_TYPEPOSSTAR:
                    776:   case OP_TYPEPOSPLUS:
                    777:   case OP_TYPEPOSQUERY:
1.1       misha     778:   case OP_TYPEPOSUPTO:
1.2       misha     779:   return cc + PRIV(OP_lengths)[*cc] - 1;
1.1       misha     780: 
1.2       misha     781:   case OP_ANYBYTE:
                    782: #ifdef SUPPORT_UTF
                    783:   if (common->utf) return NULL;
                    784: #endif
                    785:   return cc + 1;
1.1       misha     786: 
                    787: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
                    788:   case OP_XCLASS:
                    789:   return cc + GET(cc, 1);
                    790: #endif
                    791: 
1.2       misha     792:   case OP_MARK:
                    793:   case OP_PRUNE_ARG:
                    794:   case OP_SKIP_ARG:
                    795:   case OP_THEN_ARG:
                    796:   return cc + 1 + 2 + cc[1];
1.1       misha     797: 
                    798:   default:
1.2       misha     799:   /* All opcodes are supported now! */
1.4     ! moko      800:   SLJIT_UNREACHABLE();
1.1       misha     801:   return NULL;
                    802:   }
                    803: }
                    804: 
1.2       misha     805: static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
1.1       misha     806: {
1.3       moko      807: int count;
                    808: pcre_uchar *slot;
1.4     ! moko      809: pcre_uchar *assert_back_end = cc - 1;
1.2       misha     810: 
1.1       misha     811: /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
                    812: while (cc < ccend)
                    813:   {
                    814:   switch(*cc)
                    815:     {
1.2       misha     816:     case OP_SET_SOM:
                    817:     common->has_set_som = TRUE;
1.3       moko      818:     common->might_be_empty = TRUE;
1.2       misha     819:     cc += 1;
                    820:     break;
                    821: 
                    822:     case OP_REF:
                    823:     case OP_REFI:
                    824:     common->optimized_cbracket[GET2(cc, 1)] = 0;
                    825:     cc += 1 + IMM2_SIZE;
1.1       misha     826:     break;
                    827: 
                    828:     case OP_CBRAPOS:
                    829:     case OP_SCBRAPOS:
1.2       misha     830:     common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;
1.1       misha     831:     cc += 1 + LINK_SIZE + IMM2_SIZE;
                    832:     break;
                    833: 
                    834:     case OP_COND:
1.2       misha     835:     case OP_SCOND:
                    836:     /* Only AUTO_CALLOUT can insert this opcode. We do
                    837:        not intend to support this case. */
                    838:     if (cc[1 + LINK_SIZE] == OP_CALLOUT)
                    839:       return FALSE;
                    840:     cc += 1 + LINK_SIZE;
                    841:     break;
                    842: 
                    843:     case OP_CREF:
1.3       moko      844:     common->optimized_cbracket[GET2(cc, 1)] = 0;
1.2       misha     845:     cc += 1 + IMM2_SIZE;
                    846:     break;
                    847: 
1.3       moko      848:     case OP_DNREF:
                    849:     case OP_DNREFI:
                    850:     case OP_DNCREF:
                    851:     count = GET2(cc, 1 + IMM2_SIZE);
                    852:     slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
                    853:     while (count-- > 0)
                    854:       {
                    855:       common->optimized_cbracket[GET2(slot, 0)] = 0;
                    856:       slot += common->name_entry_size;
1.2       misha     857:       }
1.3       moko      858:     cc += 1 + 2 * IMM2_SIZE;
1.2       misha     859:     break;
                    860: 
                    861:     case OP_RECURSE:
                    862:     /* Set its value only once. */
                    863:     if (common->recursive_head_ptr == 0)
                    864:       {
                    865:       common->recursive_head_ptr = common->ovector_start;
                    866:       common->ovector_start += sizeof(sljit_sw);
                    867:       }
1.1       misha     868:     cc += 1 + LINK_SIZE;
                    869:     break;
                    870: 
1.2       misha     871:     case OP_CALLOUT:
                    872:     if (common->capture_last_ptr == 0)
                    873:       {
                    874:       common->capture_last_ptr = common->ovector_start;
                    875:       common->ovector_start += sizeof(sljit_sw);
                    876:       }
                    877:     cc += 2 + 2 * LINK_SIZE;
                    878:     break;
                    879: 
1.4     ! moko      880:     case OP_ASSERTBACK:
        !           881:     slot = bracketend(cc);
        !           882:     if (slot > assert_back_end)
        !           883:       assert_back_end = slot;
        !           884:     cc += 1 + LINK_SIZE;
        !           885:     break;
        !           886: 
1.2       misha     887:     case OP_THEN_ARG:
                    888:     common->has_then = TRUE;
                    889:     common->control_head_ptr = 1;
                    890:     /* Fall through. */
                    891: 
                    892:     case OP_PRUNE_ARG:
                    893:     case OP_MARK:
                    894:     if (common->mark_ptr == 0)
                    895:       {
                    896:       common->mark_ptr = common->ovector_start;
                    897:       common->ovector_start += sizeof(sljit_sw);
                    898:       }
                    899:     cc += 1 + 2 + cc[1];
                    900:     break;
                    901: 
                    902:     case OP_THEN:
                    903:     common->has_then = TRUE;
                    904:     common->control_head_ptr = 1;
1.4     ! moko      905:     cc += 1;
        !           906:     break;
1.2       misha     907: 
                    908:     case OP_SKIP:
1.4     ! moko      909:     if (cc < assert_back_end)
        !           910:       common->has_skip_in_assert_back = TRUE;
1.2       misha     911:     cc += 1;
                    912:     break;
                    913: 
                    914:     case OP_SKIP_ARG:
                    915:     common->control_head_ptr = 1;
                    916:     common->has_skip_arg = TRUE;
1.4     ! moko      917:     if (cc < assert_back_end)
        !           918:       common->has_skip_in_assert_back = TRUE;
1.2       misha     919:     cc += 1 + 2 + cc[1];
                    920:     break;
                    921: 
1.1       misha     922:     default:
                    923:     cc = next_opcode(common, cc);
                    924:     if (cc == NULL)
1.2       misha     925:       return FALSE;
1.1       misha     926:     break;
                    927:     }
                    928:   }
1.2       misha     929: return TRUE;
1.1       misha     930: }
                    931: 
1.4     ! moko      932: static BOOL is_accelerated_repeat(pcre_uchar *cc)
        !           933: {
        !           934: switch(*cc)
        !           935:   {
        !           936:   case OP_TYPESTAR:
        !           937:   case OP_TYPEMINSTAR:
        !           938:   case OP_TYPEPLUS:
        !           939:   case OP_TYPEMINPLUS:
        !           940:   case OP_TYPEPOSSTAR:
        !           941:   case OP_TYPEPOSPLUS:
        !           942:   return (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI);
        !           943: 
        !           944:   case OP_STAR:
        !           945:   case OP_MINSTAR:
        !           946:   case OP_PLUS:
        !           947:   case OP_MINPLUS:
        !           948:   case OP_POSSTAR:
        !           949:   case OP_POSPLUS:
        !           950: 
        !           951:   case OP_STARI:
        !           952:   case OP_MINSTARI:
        !           953:   case OP_PLUSI:
        !           954:   case OP_MINPLUSI:
        !           955:   case OP_POSSTARI:
        !           956:   case OP_POSPLUSI:
        !           957: 
        !           958:   case OP_NOTSTAR:
        !           959:   case OP_NOTMINSTAR:
        !           960:   case OP_NOTPLUS:
        !           961:   case OP_NOTMINPLUS:
        !           962:   case OP_NOTPOSSTAR:
        !           963:   case OP_NOTPOSPLUS:
        !           964: 
        !           965:   case OP_NOTSTARI:
        !           966:   case OP_NOTMINSTARI:
        !           967:   case OP_NOTPLUSI:
        !           968:   case OP_NOTMINPLUSI:
        !           969:   case OP_NOTPOSSTARI:
        !           970:   case OP_NOTPOSPLUSI:
        !           971:   return TRUE;
        !           972: 
        !           973:   case OP_CLASS:
        !           974:   case OP_NCLASS:
        !           975: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
        !           976:   case OP_XCLASS:
        !           977:   cc += (*cc == OP_XCLASS) ? GET(cc, 1) : (int)(1 + (32 / sizeof(pcre_uchar)));
        !           978: #else
        !           979:   cc += (1 + (32 / sizeof(pcre_uchar)));
        !           980: #endif
        !           981: 
        !           982:   switch(*cc)
        !           983:     {
        !           984:     case OP_CRSTAR:
        !           985:     case OP_CRMINSTAR:
        !           986:     case OP_CRPLUS:
        !           987:     case OP_CRMINPLUS:
        !           988:     case OP_CRPOSSTAR:
        !           989:     case OP_CRPOSPLUS:
        !           990:     return TRUE;
        !           991:     }
        !           992:   break;
        !           993:   }
        !           994: return FALSE;
        !           995: }
        !           996: 
        !           997: static SLJIT_INLINE BOOL detect_fast_forward_skip(compiler_common *common, int *private_data_start)
        !           998: {
        !           999: pcre_uchar *cc = common->start;
        !          1000: pcre_uchar *end;
        !          1001: 
        !          1002: /* Skip not repeated brackets. */
        !          1003: while (TRUE)
        !          1004:   {
        !          1005:   switch(*cc)
        !          1006:     {
        !          1007:     case OP_SOD:
        !          1008:     case OP_SOM:
        !          1009:     case OP_SET_SOM:
        !          1010:     case OP_NOT_WORD_BOUNDARY:
        !          1011:     case OP_WORD_BOUNDARY:
        !          1012:     case OP_EODN:
        !          1013:     case OP_EOD:
        !          1014:     case OP_CIRC:
        !          1015:     case OP_CIRCM:
        !          1016:     case OP_DOLL:
        !          1017:     case OP_DOLLM:
        !          1018:     /* Zero width assertions. */
        !          1019:     cc++;
        !          1020:     continue;
        !          1021:     }
        !          1022: 
        !          1023:   if (*cc != OP_BRA && *cc != OP_CBRA)
        !          1024:     break;
        !          1025: 
        !          1026:   end = cc + GET(cc, 1);
        !          1027:   if (*end != OP_KET || PRIVATE_DATA(end) != 0)
        !          1028:     return FALSE;
        !          1029:   if (*cc == OP_CBRA)
        !          1030:     {
        !          1031:     if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
        !          1032:       return FALSE;
        !          1033:     cc += IMM2_SIZE;
        !          1034:     }
        !          1035:   cc += 1 + LINK_SIZE;
        !          1036:   }
        !          1037: 
        !          1038: if (is_accelerated_repeat(cc))
        !          1039:   {
        !          1040:   common->fast_forward_bc_ptr = cc;
        !          1041:   common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start;
        !          1042:   *private_data_start += sizeof(sljit_sw);
        !          1043:   return TRUE;
        !          1044:   }
        !          1045: return FALSE;
        !          1046: }
        !          1047: 
        !          1048: static SLJIT_INLINE void detect_fast_fail(compiler_common *common, pcre_uchar *cc, int *private_data_start, sljit_s32 depth)
        !          1049: {
        !          1050:   pcre_uchar *next_alt;
        !          1051: 
        !          1052:   SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA);
        !          1053: 
        !          1054:   if (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
        !          1055:     return;
        !          1056: 
        !          1057:   next_alt = bracketend(cc) - (1 + LINK_SIZE);
        !          1058:   if (*next_alt != OP_KET || PRIVATE_DATA(next_alt) != 0)
        !          1059:     return;
        !          1060: 
        !          1061:   do
        !          1062:     {
        !          1063:     next_alt = cc + GET(cc, 1);
        !          1064: 
        !          1065:     cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0);
        !          1066: 
        !          1067:     while (TRUE)
        !          1068:       {
        !          1069:       switch(*cc)
        !          1070:         {
        !          1071:         case OP_SOD:
        !          1072:         case OP_SOM:
        !          1073:         case OP_SET_SOM:
        !          1074:         case OP_NOT_WORD_BOUNDARY:
        !          1075:         case OP_WORD_BOUNDARY:
        !          1076:         case OP_EODN:
        !          1077:         case OP_EOD:
        !          1078:         case OP_CIRC:
        !          1079:         case OP_CIRCM:
        !          1080:         case OP_DOLL:
        !          1081:         case OP_DOLLM:
        !          1082:         /* Zero width assertions. */
        !          1083:         cc++;
        !          1084:         continue;
        !          1085:         }
        !          1086:       break;
        !          1087:       }
        !          1088: 
        !          1089:     if (depth > 0 && (*cc == OP_BRA || *cc == OP_CBRA))
        !          1090:       detect_fast_fail(common, cc, private_data_start, depth - 1);
        !          1091: 
        !          1092:     if (is_accelerated_repeat(cc))
        !          1093:       {
        !          1094:       common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start;
        !          1095: 
        !          1096:       if (common->fast_fail_start_ptr == 0)
        !          1097:         common->fast_fail_start_ptr = *private_data_start;
        !          1098: 
        !          1099:       *private_data_start += sizeof(sljit_sw);
        !          1100:       common->fast_fail_end_ptr = *private_data_start;
        !          1101: 
        !          1102:       if (*private_data_start > SLJIT_MAX_LOCAL_SIZE)
        !          1103:         return;
        !          1104:       }
        !          1105: 
        !          1106:     cc = next_alt;
        !          1107:     }
        !          1108:   while (*cc == OP_ALT);
        !          1109: }
        !          1110: 
1.2       misha    1111: static int get_class_iterator_size(pcre_uchar *cc)
                   1112: {
1.4     ! moko     1113: sljit_u32 min;
        !          1114: sljit_u32 max;
1.2       misha    1115: switch(*cc)
                   1116:   {
                   1117:   case OP_CRSTAR:
                   1118:   case OP_CRPLUS:
                   1119:   return 2;
                   1120: 
                   1121:   case OP_CRMINSTAR:
                   1122:   case OP_CRMINPLUS:
                   1123:   case OP_CRQUERY:
                   1124:   case OP_CRMINQUERY:
                   1125:   return 1;
                   1126: 
                   1127:   case OP_CRRANGE:
                   1128:   case OP_CRMINRANGE:
1.4     ! moko     1129:   min = GET2(cc, 1);
        !          1130:   max = GET2(cc, 1 + IMM2_SIZE);
        !          1131:   if (max == 0)
        !          1132:     return (*cc == OP_CRRANGE) ? 2 : 1;
        !          1133:   max -= min;
        !          1134:   if (max > 2)
        !          1135:     max = 2;
        !          1136:   return max;
1.2       misha    1137: 
                   1138:   default:
                   1139:   return 0;
                   1140:   }
                   1141: }
                   1142: 
                   1143: static BOOL detect_repeat(compiler_common *common, pcre_uchar *begin)
                   1144: {
                   1145: pcre_uchar *end = bracketend(begin);
                   1146: pcre_uchar *next;
                   1147: pcre_uchar *next_end;
                   1148: pcre_uchar *max_end;
                   1149: pcre_uchar type;
                   1150: sljit_sw length = end - begin;
                   1151: int min, max, i;
                   1152: 
                   1153: /* Detect fixed iterations first. */
                   1154: if (end[-(1 + LINK_SIZE)] != OP_KET)
                   1155:   return FALSE;
                   1156: 
                   1157: /* Already detected repeat. */
                   1158: if (common->private_data_ptrs[end - common->start - LINK_SIZE] != 0)
                   1159:   return TRUE;
                   1160: 
                   1161: next = end;
                   1162: min = 1;
                   1163: while (1)
                   1164:   {
                   1165:   if (*next != *begin)
                   1166:     break;
                   1167:   next_end = bracketend(next);
                   1168:   if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0)
                   1169:     break;
                   1170:   next = next_end;
                   1171:   min++;
                   1172:   }
                   1173: 
                   1174: if (min == 2)
                   1175:   return FALSE;
                   1176: 
                   1177: max = 0;
                   1178: max_end = next;
                   1179: if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)
                   1180:   {
                   1181:   type = *next;
                   1182:   while (1)
                   1183:     {
                   1184:     if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin)
                   1185:       break;
                   1186:     next_end = bracketend(next + 2 + LINK_SIZE);
                   1187:     if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0)
                   1188:       break;
                   1189:     next = next_end;
                   1190:     max++;
                   1191:     }
                   1192: 
                   1193:   if (next[0] == type && next[1] == *begin && max >= 1)
                   1194:     {
                   1195:     next_end = bracketend(next + 1);
                   1196:     if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0)
                   1197:       {
                   1198:       for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE)
                   1199:         if (*next_end != OP_KET)
                   1200:           break;
                   1201: 
                   1202:       if (i == max)
                   1203:         {
                   1204:         common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end;
                   1205:         common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO;
                   1206:         /* +2 the original and the last. */
                   1207:         common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2;
                   1208:         if (min == 1)
                   1209:           return TRUE;
                   1210:         min--;
                   1211:         max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE);
                   1212:         }
                   1213:       }
                   1214:     }
                   1215:   }
                   1216: 
                   1217: if (min >= 3)
                   1218:   {
                   1219:   common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end;
                   1220:   common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT;
                   1221:   common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min;
                   1222:   return TRUE;
                   1223:   }
                   1224: 
                   1225: return FALSE;
                   1226: }
                   1227: 
                   1228: #define CASE_ITERATOR_PRIVATE_DATA_1 \
                   1229:     case OP_MINSTAR: \
                   1230:     case OP_MINPLUS: \
                   1231:     case OP_QUERY: \
                   1232:     case OP_MINQUERY: \
                   1233:     case OP_MINSTARI: \
                   1234:     case OP_MINPLUSI: \
                   1235:     case OP_QUERYI: \
                   1236:     case OP_MINQUERYI: \
                   1237:     case OP_NOTMINSTAR: \
                   1238:     case OP_NOTMINPLUS: \
                   1239:     case OP_NOTQUERY: \
                   1240:     case OP_NOTMINQUERY: \
                   1241:     case OP_NOTMINSTARI: \
                   1242:     case OP_NOTMINPLUSI: \
                   1243:     case OP_NOTQUERYI: \
                   1244:     case OP_NOTMINQUERYI:
                   1245: 
                   1246: #define CASE_ITERATOR_PRIVATE_DATA_2A \
                   1247:     case OP_STAR: \
                   1248:     case OP_PLUS: \
                   1249:     case OP_STARI: \
                   1250:     case OP_PLUSI: \
                   1251:     case OP_NOTSTAR: \
                   1252:     case OP_NOTPLUS: \
                   1253:     case OP_NOTSTARI: \
                   1254:     case OP_NOTPLUSI:
                   1255: 
                   1256: #define CASE_ITERATOR_PRIVATE_DATA_2B \
                   1257:     case OP_UPTO: \
                   1258:     case OP_MINUPTO: \
                   1259:     case OP_UPTOI: \
                   1260:     case OP_MINUPTOI: \
                   1261:     case OP_NOTUPTO: \
                   1262:     case OP_NOTMINUPTO: \
                   1263:     case OP_NOTUPTOI: \
                   1264:     case OP_NOTMINUPTOI:
                   1265: 
                   1266: #define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \
                   1267:     case OP_TYPEMINSTAR: \
                   1268:     case OP_TYPEMINPLUS: \
                   1269:     case OP_TYPEQUERY: \
                   1270:     case OP_TYPEMINQUERY:
                   1271: 
                   1272: #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \
                   1273:     case OP_TYPESTAR: \
                   1274:     case OP_TYPEPLUS:
                   1275: 
                   1276: #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \
                   1277:     case OP_TYPEUPTO: \
                   1278:     case OP_TYPEMINUPTO:
                   1279: 
                   1280: static void set_private_data_ptrs(compiler_common *common, int *private_data_start, pcre_uchar *ccend)
1.1       misha    1281: {
                   1282: pcre_uchar *cc = common->start;
                   1283: pcre_uchar *alternative;
1.2       misha    1284: pcre_uchar *end = NULL;
                   1285: int private_data_ptr = *private_data_start;
                   1286: int space, size, bracketlen;
1.4     ! moko     1287: BOOL repeat_check = TRUE;
1.2       misha    1288: 
1.1       misha    1289: while (cc < ccend)
                   1290:   {
1.2       misha    1291:   space = 0;
                   1292:   size = 0;
                   1293:   bracketlen = 0;
                   1294:   if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)
1.4     ! moko     1295:     break;
1.2       misha    1296: 
1.4     ! moko     1297:   if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND))
        !          1298:     {
1.2       misha    1299:     if (detect_repeat(common, cc))
                   1300:       {
                   1301:       /* These brackets are converted to repeats, so no global
                   1302:       based single character repeat is allowed. */
                   1303:       if (cc >= end)
                   1304:         end = bracketend(cc);
                   1305:       }
1.4     ! moko     1306:     }
        !          1307:   repeat_check = TRUE;
1.2       misha    1308: 
1.1       misha    1309:   switch(*cc)
                   1310:     {
1.2       misha    1311:     case OP_KET:
                   1312:     if (common->private_data_ptrs[cc + 1 - common->start] != 0)
                   1313:       {
                   1314:       common->private_data_ptrs[cc - common->start] = private_data_ptr;
                   1315:       private_data_ptr += sizeof(sljit_sw);
                   1316:       cc += common->private_data_ptrs[cc + 1 - common->start];
                   1317:       }
                   1318:     cc += 1 + LINK_SIZE;
                   1319:     break;
                   1320: 
1.1       misha    1321:     case OP_ASSERT:
                   1322:     case OP_ASSERT_NOT:
                   1323:     case OP_ASSERTBACK:
                   1324:     case OP_ASSERTBACK_NOT:
                   1325:     case OP_ONCE:
                   1326:     case OP_ONCE_NC:
                   1327:     case OP_BRAPOS:
                   1328:     case OP_SBRA:
                   1329:     case OP_SBRAPOS:
                   1330:     case OP_SCOND:
1.2       misha    1331:     common->private_data_ptrs[cc - common->start] = private_data_ptr;
                   1332:     private_data_ptr += sizeof(sljit_sw);
                   1333:     bracketlen = 1 + LINK_SIZE;
1.1       misha    1334:     break;
                   1335: 
                   1336:     case OP_CBRAPOS:
                   1337:     case OP_SCBRAPOS:
1.2       misha    1338:     common->private_data_ptrs[cc - common->start] = private_data_ptr;
                   1339:     private_data_ptr += sizeof(sljit_sw);
                   1340:     bracketlen = 1 + LINK_SIZE + IMM2_SIZE;
1.1       misha    1341:     break;
                   1342: 
                   1343:     case OP_COND:
                   1344:     /* Might be a hidden SCOND. */
                   1345:     alternative = cc + GET(cc, 1);
                   1346:     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
                   1347:       {
1.2       misha    1348:       common->private_data_ptrs[cc - common->start] = private_data_ptr;
                   1349:       private_data_ptr += sizeof(sljit_sw);
1.1       misha    1350:       }
1.2       misha    1351:     bracketlen = 1 + LINK_SIZE;
                   1352:     break;
                   1353: 
                   1354:     case OP_BRA:
                   1355:     bracketlen = 1 + LINK_SIZE;
                   1356:     break;
                   1357: 
                   1358:     case OP_CBRA:
                   1359:     case OP_SCBRA:
                   1360:     bracketlen = 1 + LINK_SIZE + IMM2_SIZE;
                   1361:     break;
                   1362: 
1.4     ! moko     1363:     case OP_BRAZERO:
        !          1364:     case OP_BRAMINZERO:
        !          1365:     case OP_BRAPOSZERO:
        !          1366:     repeat_check = FALSE;
        !          1367:     size = 1;
        !          1368:     break;
        !          1369: 
1.2       misha    1370:     CASE_ITERATOR_PRIVATE_DATA_1
                   1371:     space = 1;
                   1372:     size = -2;
                   1373:     break;
                   1374: 
                   1375:     CASE_ITERATOR_PRIVATE_DATA_2A
                   1376:     space = 2;
                   1377:     size = -2;
                   1378:     break;
                   1379: 
                   1380:     CASE_ITERATOR_PRIVATE_DATA_2B
                   1381:     space = 2;
                   1382:     size = -(2 + IMM2_SIZE);
                   1383:     break;
                   1384: 
                   1385:     CASE_ITERATOR_TYPE_PRIVATE_DATA_1
                   1386:     space = 1;
                   1387:     size = 1;
                   1388:     break;
                   1389: 
                   1390:     CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
                   1391:     if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI)
                   1392:       space = 2;
                   1393:     size = 1;
                   1394:     break;
                   1395: 
1.4     ! moko     1396:     case OP_TYPEUPTO:
1.2       misha    1397:     if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)
                   1398:       space = 2;
                   1399:     size = 1 + IMM2_SIZE;
                   1400:     break;
                   1401: 
1.4     ! moko     1402:     case OP_TYPEMINUPTO:
        !          1403:     space = 2;
        !          1404:     size = 1 + IMM2_SIZE;
        !          1405:     break;
        !          1406: 
1.2       misha    1407:     case OP_CLASS:
                   1408:     case OP_NCLASS:
                   1409:     space = get_class_iterator_size(cc + size);
1.4     ! moko     1410:     size = 1 + 32 / sizeof(pcre_uchar);
1.2       misha    1411:     break;
                   1412: 
                   1413: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
                   1414:     case OP_XCLASS:
1.4     ! moko     1415:     space = get_class_iterator_size(cc + size);
1.2       misha    1416:     size = GET(cc, 1);
1.1       misha    1417:     break;
1.2       misha    1418: #endif
1.1       misha    1419: 
                   1420:     default:
                   1421:     cc = next_opcode(common, cc);
1.2       misha    1422:     SLJIT_ASSERT(cc != NULL);
                   1423:     break;
                   1424:     }
                   1425: 
                   1426:   /* Character iterators, which are not inside a repeated bracket,
                   1427:      gets a private slot instead of allocating it on the stack. */
                   1428:   if (space > 0 && cc >= end)
                   1429:     {
                   1430:     common->private_data_ptrs[cc - common->start] = private_data_ptr;
                   1431:     private_data_ptr += sizeof(sljit_sw) * space;
                   1432:     }
                   1433: 
                   1434:   if (size != 0)
                   1435:     {
                   1436:     if (size < 0)
                   1437:       {
                   1438:       cc += -size;
                   1439: #ifdef SUPPORT_UTF
                   1440:       if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
                   1441: #endif
                   1442:       }
                   1443:     else
                   1444:       cc += size;
                   1445:     }
                   1446: 
                   1447:   if (bracketlen > 0)
                   1448:     {
                   1449:     if (cc >= end)
                   1450:       {
                   1451:       end = bracketend(cc);
                   1452:       if (end[-1 - LINK_SIZE] == OP_KET)
                   1453:         end = NULL;
                   1454:       }
                   1455:     cc += bracketlen;
1.1       misha    1456:     }
                   1457:   }
1.2       misha    1458: *private_data_start = private_data_ptr;
1.1       misha    1459: }
                   1460: 
1.2       misha    1461: /* Returns with a frame_types (always < 0) if no need for frame. */
1.3       moko     1462: static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL *needs_control_head)
1.1       misha    1463: {
                   1464: int length = 0;
1.2       misha    1465: int possessive = 0;
                   1466: BOOL stack_restore = FALSE;
                   1467: BOOL setsom_found = recursive;
                   1468: BOOL setmark_found = recursive;
                   1469: /* The last capture is a local variable even for recursions. */
                   1470: BOOL capture_last_found = FALSE;
                   1471: 
                   1472: #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
                   1473: SLJIT_ASSERT(common->control_head_ptr != 0);
                   1474: *needs_control_head = TRUE;
                   1475: #else
                   1476: *needs_control_head = FALSE;
                   1477: #endif
1.1       misha    1478: 
1.2       misha    1479: if (ccend == NULL)
1.1       misha    1480:   {
1.2       misha    1481:   ccend = bracketend(cc) - (1 + LINK_SIZE);
                   1482:   if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
                   1483:     {
                   1484:     possessive = length = (common->capture_last_ptr != 0) ? 5 : 3;
                   1485:     /* This is correct regardless of common->capture_last_ptr. */
                   1486:     capture_last_found = TRUE;
                   1487:     }
                   1488:   cc = next_opcode(common, cc);
1.1       misha    1489:   }
                   1490: 
                   1491: SLJIT_ASSERT(cc != NULL);
                   1492: while (cc < ccend)
                   1493:   switch(*cc)
                   1494:     {
                   1495:     case OP_SET_SOM:
1.2       misha    1496:     SLJIT_ASSERT(common->has_set_som);
                   1497:     stack_restore = TRUE;
                   1498:     if (!setsom_found)
                   1499:       {
                   1500:       length += 2;
                   1501:       setsom_found = TRUE;
                   1502:       }
                   1503:     cc += 1;
                   1504:     break;
                   1505: 
                   1506:     case OP_MARK:
                   1507:     case OP_PRUNE_ARG:
                   1508:     case OP_THEN_ARG:
                   1509:     SLJIT_ASSERT(common->mark_ptr != 0);
                   1510:     stack_restore = TRUE;
                   1511:     if (!setmark_found)
                   1512:       {
                   1513:       length += 2;
                   1514:       setmark_found = TRUE;
                   1515:       }
                   1516:     if (common->control_head_ptr != 0)
                   1517:       *needs_control_head = TRUE;
                   1518:     cc += 1 + 2 + cc[1];
                   1519:     break;
                   1520: 
1.1       misha    1521:     case OP_RECURSE:
1.2       misha    1522:     stack_restore = TRUE;
                   1523:     if (common->has_set_som && !setsom_found)
1.1       misha    1524:       {
                   1525:       length += 2;
                   1526:       setsom_found = TRUE;
                   1527:       }
1.2       misha    1528:     if (common->mark_ptr != 0 && !setmark_found)
                   1529:       {
                   1530:       length += 2;
                   1531:       setmark_found = TRUE;
                   1532:       }
                   1533:     if (common->capture_last_ptr != 0 && !capture_last_found)
                   1534:       {
                   1535:       length += 2;
                   1536:       capture_last_found = TRUE;
                   1537:       }
                   1538:     cc += 1 + LINK_SIZE;
1.1       misha    1539:     break;
                   1540: 
                   1541:     case OP_CBRA:
                   1542:     case OP_CBRAPOS:
                   1543:     case OP_SCBRA:
                   1544:     case OP_SCBRAPOS:
1.2       misha    1545:     stack_restore = TRUE;
                   1546:     if (common->capture_last_ptr != 0 && !capture_last_found)
                   1547:       {
                   1548:       length += 2;
                   1549:       capture_last_found = TRUE;
                   1550:       }
1.1       misha    1551:     length += 3;
                   1552:     cc += 1 + LINK_SIZE + IMM2_SIZE;
                   1553:     break;
                   1554: 
1.4     ! moko     1555:     case OP_THEN:
        !          1556:     stack_restore = TRUE;
        !          1557:     if (common->control_head_ptr != 0)
        !          1558:       *needs_control_head = TRUE;
        !          1559:     cc ++;
        !          1560:     break;
        !          1561: 
1.1       misha    1562:     default:
1.2       misha    1563:     stack_restore = TRUE;
                   1564:     /* Fall through. */
                   1565: 
                   1566:     case OP_NOT_WORD_BOUNDARY:
                   1567:     case OP_WORD_BOUNDARY:
                   1568:     case OP_NOT_DIGIT:
                   1569:     case OP_DIGIT:
                   1570:     case OP_NOT_WHITESPACE:
                   1571:     case OP_WHITESPACE:
                   1572:     case OP_NOT_WORDCHAR:
                   1573:     case OP_WORDCHAR:
                   1574:     case OP_ANY:
                   1575:     case OP_ALLANY:
                   1576:     case OP_ANYBYTE:
                   1577:     case OP_NOTPROP:
                   1578:     case OP_PROP:
                   1579:     case OP_ANYNL:
                   1580:     case OP_NOT_HSPACE:
                   1581:     case OP_HSPACE:
                   1582:     case OP_NOT_VSPACE:
                   1583:     case OP_VSPACE:
                   1584:     case OP_EXTUNI:
                   1585:     case OP_EODN:
                   1586:     case OP_EOD:
                   1587:     case OP_CIRC:
                   1588:     case OP_CIRCM:
                   1589:     case OP_DOLL:
                   1590:     case OP_DOLLM:
                   1591:     case OP_CHAR:
                   1592:     case OP_CHARI:
                   1593:     case OP_NOT:
                   1594:     case OP_NOTI:
                   1595: 
                   1596:     case OP_EXACT:
                   1597:     case OP_POSSTAR:
                   1598:     case OP_POSPLUS:
                   1599:     case OP_POSQUERY:
                   1600:     case OP_POSUPTO:
                   1601: 
                   1602:     case OP_EXACTI:
                   1603:     case OP_POSSTARI:
                   1604:     case OP_POSPLUSI:
                   1605:     case OP_POSQUERYI:
                   1606:     case OP_POSUPTOI:
                   1607: 
                   1608:     case OP_NOTEXACT:
                   1609:     case OP_NOTPOSSTAR:
                   1610:     case OP_NOTPOSPLUS:
                   1611:     case OP_NOTPOSQUERY:
                   1612:     case OP_NOTPOSUPTO:
                   1613: 
                   1614:     case OP_NOTEXACTI:
                   1615:     case OP_NOTPOSSTARI:
                   1616:     case OP_NOTPOSPLUSI:
                   1617:     case OP_NOTPOSQUERYI:
                   1618:     case OP_NOTPOSUPTOI:
                   1619: 
                   1620:     case OP_TYPEEXACT:
                   1621:     case OP_TYPEPOSSTAR:
                   1622:     case OP_TYPEPOSPLUS:
                   1623:     case OP_TYPEPOSQUERY:
                   1624:     case OP_TYPEPOSUPTO:
                   1625: 
                   1626:     case OP_CLASS:
                   1627:     case OP_NCLASS:
                   1628:     case OP_XCLASS:
1.4     ! moko     1629:     case OP_CALLOUT:
1.2       misha    1630: 
1.1       misha    1631:     cc = next_opcode(common, cc);
                   1632:     SLJIT_ASSERT(cc != NULL);
                   1633:     break;
                   1634:     }
                   1635: 
                   1636: /* Possessive quantifiers can use a special case. */
1.2       misha    1637: if (SLJIT_UNLIKELY(possessive == length))
                   1638:   return stack_restore ? no_frame : no_stack;
1.1       misha    1639: 
                   1640: if (length > 0)
                   1641:   return length + 1;
1.2       misha    1642: return stack_restore ? no_frame : no_stack;
1.1       misha    1643: }
                   1644: 
1.2       misha    1645: static void init_frame(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, int stackpos, int stacktop, BOOL recursive)
1.1       misha    1646: {
                   1647: DEFINE_COMPILER;
1.2       misha    1648: BOOL setsom_found = recursive;
                   1649: BOOL setmark_found = recursive;
                   1650: /* The last capture is a local variable even for recursions. */
                   1651: BOOL capture_last_found = FALSE;
1.1       misha    1652: int offset;
                   1653: 
                   1654: /* >= 1 + shortest item size (2) */
                   1655: SLJIT_UNUSED_ARG(stacktop);
                   1656: SLJIT_ASSERT(stackpos >= stacktop + 2);
                   1657: 
                   1658: stackpos = STACK(stackpos);
1.2       misha    1659: if (ccend == NULL)
                   1660:   {
                   1661:   ccend = bracketend(cc) - (1 + LINK_SIZE);
                   1662:   if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS))
                   1663:     cc = next_opcode(common, cc);
                   1664:   }
                   1665: 
1.1       misha    1666: SLJIT_ASSERT(cc != NULL);
                   1667: while (cc < ccend)
                   1668:   switch(*cc)
                   1669:     {
                   1670:     case OP_SET_SOM:
1.2       misha    1671:     SLJIT_ASSERT(common->has_set_som);
                   1672:     if (!setsom_found)
                   1673:       {
1.3       moko     1674:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
1.2       misha    1675:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));
1.4     ! moko     1676:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1677:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
1.4     ! moko     1678:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1679:       setsom_found = TRUE;
                   1680:       }
                   1681:     cc += 1;
                   1682:     break;
                   1683: 
                   1684:     case OP_MARK:
                   1685:     case OP_PRUNE_ARG:
                   1686:     case OP_THEN_ARG:
                   1687:     SLJIT_ASSERT(common->mark_ptr != 0);
                   1688:     if (!setmark_found)
                   1689:       {
1.3       moko     1690:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
1.2       misha    1691:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);
1.4     ! moko     1692:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1693:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
1.4     ! moko     1694:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1695:       setmark_found = TRUE;
                   1696:       }
                   1697:     cc += 1 + 2 + cc[1];
                   1698:     break;
                   1699: 
1.1       misha    1700:     case OP_RECURSE:
1.2       misha    1701:     if (common->has_set_som && !setsom_found)
1.1       misha    1702:       {
1.3       moko     1703:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
1.2       misha    1704:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));
1.4     ! moko     1705:       stackpos -= (int)sizeof(sljit_sw);
1.1       misha    1706:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
1.4     ! moko     1707:       stackpos -= (int)sizeof(sljit_sw);
1.1       misha    1708:       setsom_found = TRUE;
                   1709:       }
1.2       misha    1710:     if (common->mark_ptr != 0 && !setmark_found)
                   1711:       {
1.3       moko     1712:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
1.2       misha    1713:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);
1.4     ! moko     1714:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1715:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
1.4     ! moko     1716:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1717:       setmark_found = TRUE;
                   1718:       }
                   1719:     if (common->capture_last_ptr != 0 && !capture_last_found)
                   1720:       {
1.3       moko     1721:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
1.2       misha    1722:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);
1.4     ! moko     1723:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1724:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
1.4     ! moko     1725:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1726:       capture_last_found = TRUE;
                   1727:       }
                   1728:     cc += 1 + LINK_SIZE;
1.1       misha    1729:     break;
                   1730: 
                   1731:     case OP_CBRA:
                   1732:     case OP_CBRAPOS:
                   1733:     case OP_SCBRA:
                   1734:     case OP_SCBRAPOS:
1.2       misha    1735:     if (common->capture_last_ptr != 0 && !capture_last_found)
                   1736:       {
1.3       moko     1737:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
1.2       misha    1738:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);
1.4     ! moko     1739:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1740:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
1.4     ! moko     1741:       stackpos -= (int)sizeof(sljit_sw);
1.2       misha    1742:       capture_last_found = TRUE;
                   1743:       }
1.1       misha    1744:     offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
                   1745:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
1.4     ! moko     1746:     stackpos -= (int)sizeof(sljit_sw);
1.3       moko     1747:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
                   1748:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
1.1       misha    1749:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
1.4     ! moko     1750:     stackpos -= (int)sizeof(sljit_sw);
1.1       misha    1751:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
1.4     ! moko     1752:     stackpos -= (int)sizeof(sljit_sw);
1.1       misha    1753: 
                   1754:     cc += 1 + LINK_SIZE + IMM2_SIZE;
                   1755:     break;
                   1756: 
                   1757:     default:
                   1758:     cc = next_opcode(common, cc);
                   1759:     SLJIT_ASSERT(cc != NULL);
                   1760:     break;
                   1761:     }
                   1762: 
1.2       misha    1763: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0);
1.1       misha    1764: SLJIT_ASSERT(stackpos == STACK(stacktop));
                   1765: }
                   1766: 
1.2       misha    1767: static SLJIT_INLINE int get_private_data_copy_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL needs_control_head)
1.1       misha    1768: {
1.2       misha    1769: int private_data_length = needs_control_head ? 3 : 2;
                   1770: int size;
1.1       misha    1771: pcre_uchar *alternative;
1.2       misha    1772: /* Calculate the sum of the private machine words. */
1.1       misha    1773: while (cc < ccend)
                   1774:   {
1.2       misha    1775:   size = 0;
1.1       misha    1776:   switch(*cc)
                   1777:     {
1.2       misha    1778:     case OP_KET:
                   1779:     if (PRIVATE_DATA(cc) != 0)
1.3       moko     1780:       {
1.2       misha    1781:       private_data_length++;
1.3       moko     1782:       SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
                   1783:       cc += PRIVATE_DATA(cc + 1);
                   1784:       }
1.2       misha    1785:     cc += 1 + LINK_SIZE;
                   1786:     break;
                   1787: 
1.1       misha    1788:     case OP_ASSERT:
                   1789:     case OP_ASSERT_NOT:
                   1790:     case OP_ASSERTBACK:
                   1791:     case OP_ASSERTBACK_NOT:
                   1792:     case OP_ONCE:
                   1793:     case OP_ONCE_NC:
                   1794:     case OP_BRAPOS:
                   1795:     case OP_SBRA:
                   1796:     case OP_SBRAPOS:
                   1797:     case OP_SCOND:
1.2       misha    1798:     private_data_length++;
1.3       moko     1799:     SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);
1.1       misha    1800:     cc += 1 + LINK_SIZE;
                   1801:     break;
                   1802: 
                   1803:     case OP_CBRA:
                   1804:     case OP_SCBRA:
1.2       misha    1805:     if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
                   1806:       private_data_length++;
1.1       misha    1807:     cc += 1 + LINK_SIZE + IMM2_SIZE;
                   1808:     break;
                   1809: 
                   1810:     case OP_CBRAPOS:
                   1811:     case OP_SCBRAPOS:
1.2       misha    1812:     private_data_length += 2;
1.1       misha    1813:     cc += 1 + LINK_SIZE + IMM2_SIZE;
                   1814:     break;
                   1815: 
                   1816:     case OP_COND:
                   1817:     /* Might be a hidden SCOND. */
                   1818:     alternative = cc + GET(cc, 1);
                   1819:     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
1.2       misha    1820:       private_data_length++;
1.1       misha    1821:     cc += 1 + LINK_SIZE;
                   1822:     break;
                   1823: 
1.2       misha    1824:     CASE_ITERATOR_PRIVATE_DATA_1
                   1825:     if (PRIVATE_DATA(cc))
                   1826:       private_data_length++;
                   1827:     cc += 2;
                   1828: #ifdef SUPPORT_UTF
                   1829:     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
                   1830: #endif
                   1831:     break;
                   1832: 
                   1833:     CASE_ITERATOR_PRIVATE_DATA_2A
                   1834:     if (PRIVATE_DATA(cc))
                   1835:       private_data_length += 2;
                   1836:     cc += 2;
                   1837: #ifdef SUPPORT_UTF
                   1838:     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
                   1839: #endif
                   1840:     break;
                   1841: 
                   1842:     CASE_ITERATOR_PRIVATE_DATA_2B
                   1843:     if (PRIVATE_DATA(cc))
                   1844:       private_data_length += 2;
                   1845:     cc += 2 + IMM2_SIZE;
                   1846: #ifdef SUPPORT_UTF
                   1847:     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
                   1848: #endif
                   1849:     break;
                   1850: 
                   1851:     CASE_ITERATOR_TYPE_PRIVATE_DATA_1
                   1852:     if (PRIVATE_DATA(cc))
                   1853:       private_data_length++;
                   1854:     cc += 1;
                   1855:     break;
                   1856: 
                   1857:     CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
                   1858:     if (PRIVATE_DATA(cc))
                   1859:       private_data_length += 2;
                   1860:     cc += 1;
                   1861:     break;
                   1862: 
                   1863:     CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
                   1864:     if (PRIVATE_DATA(cc))
                   1865:       private_data_length += 2;
                   1866:     cc += 1 + IMM2_SIZE;
                   1867:     break;
                   1868: 
                   1869:     case OP_CLASS:
                   1870:     case OP_NCLASS:
                   1871: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
                   1872:     case OP_XCLASS:
                   1873:     size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
                   1874: #else
                   1875:     size = 1 + 32 / (int)sizeof(pcre_uchar);
                   1876: #endif
                   1877:     if (PRIVATE_DATA(cc))
                   1878:       private_data_length += get_class_iterator_size(cc + size);
                   1879:     cc += size;
                   1880:     break;
                   1881: 
1.1       misha    1882:     default:
                   1883:     cc = next_opcode(common, cc);
                   1884:     SLJIT_ASSERT(cc != NULL);
                   1885:     break;
                   1886:     }
                   1887:   }
                   1888: SLJIT_ASSERT(cc == ccend);
1.2       misha    1889: return private_data_length;
1.1       misha    1890: }
                   1891: 
1.2       misha    1892: static void copy_private_data(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend,
                   1893:   BOOL save, int stackptr, int stacktop, BOOL needs_control_head)
1.1       misha    1894: {
                   1895: DEFINE_COMPILER;
                   1896: int srcw[2];
1.2       misha    1897: int count, size;
1.1       misha    1898: BOOL tmp1next = TRUE;
                   1899: BOOL tmp1empty = TRUE;
                   1900: BOOL tmp2empty = TRUE;
                   1901: pcre_uchar *alternative;
                   1902: enum {
                   1903:   loop,
                   1904:   end
                   1905: } status;
                   1906: 
1.4     ! moko     1907: status = loop;
        !          1908: stackptr = STACK(stackptr);
1.1       misha    1909: stacktop = STACK(stacktop - 1);
                   1910: 
                   1911: if (!save)
                   1912:   {
1.4     ! moko     1913:   stacktop -= (needs_control_head ? 2 : 1) * sizeof(sljit_sw);
1.1       misha    1914:   if (stackptr < stacktop)
                   1915:     {
                   1916:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1.2       misha    1917:     stackptr += sizeof(sljit_sw);
1.1       misha    1918:     tmp1empty = FALSE;
                   1919:     }
                   1920:   if (stackptr < stacktop)
                   1921:     {
                   1922:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1.2       misha    1923:     stackptr += sizeof(sljit_sw);
1.1       misha    1924:     tmp2empty = FALSE;
                   1925:     }
                   1926:   /* The tmp1next must be TRUE in either way. */
                   1927:   }
                   1928: 
1.4     ! moko     1929: SLJIT_ASSERT(common->recursive_head_ptr != 0);
        !          1930: 
1.2       misha    1931: do
1.1       misha    1932:   {
                   1933:   count = 0;
1.4     ! moko     1934:   if (cc >= ccend)
1.1       misha    1935:     {
1.4     ! moko     1936:     if (!save)
        !          1937:       break;
        !          1938: 
1.1       misha    1939:     count = 1;
1.2       misha    1940:     srcw[0] = common->recursive_head_ptr;
                   1941:     if (needs_control_head)
                   1942:       {
                   1943:       SLJIT_ASSERT(common->control_head_ptr != 0);
                   1944:       count = 2;
1.4     ! moko     1945:       srcw[0] = common->control_head_ptr;
        !          1946:       srcw[1] = common->recursive_head_ptr;
        !          1947:       }
        !          1948:     status = end;
        !          1949:     }
        !          1950:   else switch(*cc)
        !          1951:     {
        !          1952:     case OP_KET:
        !          1953:     if (PRIVATE_DATA(cc) != 0)
        !          1954:       {
        !          1955:       count = 1;
        !          1956:       srcw[0] = PRIVATE_DATA(cc);
        !          1957:       SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
        !          1958:       cc += PRIVATE_DATA(cc + 1);
1.2       misha    1959:       }
1.4     ! moko     1960:     cc += 1 + LINK_SIZE;
        !          1961:     break;
        !          1962: 
        !          1963:     case OP_ASSERT:
        !          1964:     case OP_ASSERT_NOT:
        !          1965:     case OP_ASSERTBACK:
        !          1966:     case OP_ASSERTBACK_NOT:
        !          1967:     case OP_ONCE:
        !          1968:     case OP_ONCE_NC:
        !          1969:     case OP_BRAPOS:
        !          1970:     case OP_SBRA:
        !          1971:     case OP_SBRAPOS:
        !          1972:     case OP_SCOND:
        !          1973:     count = 1;
        !          1974:     srcw[0] = PRIVATE_DATA(cc);
        !          1975:     SLJIT_ASSERT(srcw[0] != 0);
        !          1976:     cc += 1 + LINK_SIZE;
1.1       misha    1977:     break;
                   1978: 
1.4     ! moko     1979:     case OP_CBRA:
        !          1980:     case OP_SCBRA:
        !          1981:     if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
1.1       misha    1982:       {
1.4     ! moko     1983:       count = 1;
        !          1984:       srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
1.1       misha    1985:       }
1.4     ! moko     1986:     cc += 1 + LINK_SIZE + IMM2_SIZE;
        !          1987:     break;
        !          1988: 
        !          1989:     case OP_CBRAPOS:
        !          1990:     case OP_SCBRAPOS:
        !          1991:     count = 2;
        !          1992:     srcw[0] = PRIVATE_DATA(cc);
        !          1993:     srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
        !          1994:     SLJIT_ASSERT(srcw[0] != 0 && srcw[1] != 0);
        !          1995:     cc += 1 + LINK_SIZE + IMM2_SIZE;
        !          1996:     break;
1.1       misha    1997: 
1.4     ! moko     1998:     case OP_COND:
        !          1999:     /* Might be a hidden SCOND. */
        !          2000:     alternative = cc + GET(cc, 1);
        !          2001:     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
1.1       misha    2002:       {
                   2003:       count = 1;
1.2       misha    2004:       srcw[0] = PRIVATE_DATA(cc);
1.1       misha    2005:       SLJIT_ASSERT(srcw[0] != 0);
1.4     ! moko     2006:       }
        !          2007:     cc += 1 + LINK_SIZE;
        !          2008:     break;
1.1       misha    2009: 
1.4     ! moko     2010:     CASE_ITERATOR_PRIVATE_DATA_1
        !          2011:     if (PRIVATE_DATA(cc))
        !          2012:       {
        !          2013:       count = 1;
1.2       misha    2014:       srcw[0] = PRIVATE_DATA(cc);
1.4     ! moko     2015:       }
        !          2016:     cc += 2;
        !          2017: #ifdef SUPPORT_UTF
        !          2018:     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
        !          2019: #endif
        !          2020:     break;
1.1       misha    2021: 
1.4     ! moko     2022:     CASE_ITERATOR_PRIVATE_DATA_2A
        !          2023:     if (PRIVATE_DATA(cc))
        !          2024:       {
        !          2025:       count = 2;
        !          2026:       srcw[0] = PRIVATE_DATA(cc);
        !          2027:       srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
        !          2028:       }
        !          2029:     cc += 2;
1.2       misha    2030: #ifdef SUPPORT_UTF
1.4     ! moko     2031:     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.2       misha    2032: #endif
1.4     ! moko     2033:     break;
1.2       misha    2034: 
1.4     ! moko     2035:     CASE_ITERATOR_PRIVATE_DATA_2B
        !          2036:     if (PRIVATE_DATA(cc))
        !          2037:       {
        !          2038:       count = 2;
        !          2039:       srcw[0] = PRIVATE_DATA(cc);
        !          2040:       srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
        !          2041:       }
        !          2042:     cc += 2 + IMM2_SIZE;
1.2       misha    2043: #ifdef SUPPORT_UTF
1.4     ! moko     2044:     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.2       misha    2045: #endif
1.4     ! moko     2046:     break;
        !          2047: 
        !          2048:     CASE_ITERATOR_TYPE_PRIVATE_DATA_1
        !          2049:     if (PRIVATE_DATA(cc))
        !          2050:       {
        !          2051:       count = 1;
        !          2052:       srcw[0] = PRIVATE_DATA(cc);
        !          2053:       }
        !          2054:     cc += 1;
        !          2055:     break;
        !          2056: 
        !          2057:     CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
        !          2058:     if (PRIVATE_DATA(cc))
        !          2059:       {
        !          2060:       count = 2;
        !          2061:       srcw[0] = PRIVATE_DATA(cc);
        !          2062:       srcw[1] = srcw[0] + sizeof(sljit_sw);
        !          2063:       }
        !          2064:     cc += 1;
        !          2065:     break;
        !          2066: 
        !          2067:     CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
        !          2068:     if (PRIVATE_DATA(cc))
        !          2069:       {
        !          2070:       count = 2;
        !          2071:       srcw[0] = PRIVATE_DATA(cc);
        !          2072:       srcw[1] = srcw[0] + sizeof(sljit_sw);
        !          2073:       }
        !          2074:     cc += 1 + IMM2_SIZE;
        !          2075:     break;
1.2       misha    2076: 
1.4     ! moko     2077:     case OP_CLASS:
        !          2078:     case OP_NCLASS:
        !          2079: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
        !          2080:     case OP_XCLASS:
        !          2081:     size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
        !          2082: #else
        !          2083:     size = 1 + 32 / (int)sizeof(pcre_uchar);
1.2       misha    2084: #endif
1.4     ! moko     2085:     if (PRIVATE_DATA(cc))
        !          2086:       switch(get_class_iterator_size(cc + size))
1.2       misha    2087:         {
1.4     ! moko     2088:         case 1:
1.2       misha    2089:         count = 1;
                   2090:         srcw[0] = PRIVATE_DATA(cc);
1.4     ! moko     2091:         break;
1.2       misha    2092: 
1.4     ! moko     2093:         case 2:
1.2       misha    2094:         count = 2;
                   2095:         srcw[0] = PRIVATE_DATA(cc);
                   2096:         srcw[1] = srcw[0] + sizeof(sljit_sw);
1.4     ! moko     2097:         break;
1.2       misha    2098: 
1.4     ! moko     2099:         default:
        !          2100:         SLJIT_UNREACHABLE();
        !          2101:         break;
1.2       misha    2102:         }
1.4     ! moko     2103:     cc += size;
1.1       misha    2104:     break;
                   2105: 
1.4     ! moko     2106:     default:
        !          2107:     cc = next_opcode(common, cc);
        !          2108:     SLJIT_ASSERT(cc != NULL);
1.1       misha    2109:     break;
                   2110:     }
                   2111: 
                   2112:   while (count > 0)
                   2113:     {
                   2114:     count--;
                   2115:     if (save)
                   2116:       {
                   2117:       if (tmp1next)
                   2118:         {
                   2119:         if (!tmp1empty)
                   2120:           {
                   2121:           OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1.2       misha    2122:           stackptr += sizeof(sljit_sw);
1.1       misha    2123:           }
1.3       moko     2124:         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]);
1.1       misha    2125:         tmp1empty = FALSE;
                   2126:         tmp1next = FALSE;
                   2127:         }
                   2128:       else
                   2129:         {
                   2130:         if (!tmp2empty)
                   2131:           {
                   2132:           OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1.2       misha    2133:           stackptr += sizeof(sljit_sw);
1.1       misha    2134:           }
1.3       moko     2135:         OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]);
1.1       misha    2136:         tmp2empty = FALSE;
                   2137:         tmp1next = TRUE;
                   2138:         }
                   2139:       }
                   2140:     else
                   2141:       {
                   2142:       if (tmp1next)
                   2143:         {
                   2144:         SLJIT_ASSERT(!tmp1empty);
1.3       moko     2145:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP1, 0);
1.1       misha    2146:         tmp1empty = stackptr >= stacktop;
                   2147:         if (!tmp1empty)
                   2148:           {
                   2149:           OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1.2       misha    2150:           stackptr += sizeof(sljit_sw);
1.1       misha    2151:           }
                   2152:         tmp1next = FALSE;
                   2153:         }
                   2154:       else
                   2155:         {
                   2156:         SLJIT_ASSERT(!tmp2empty);
1.3       moko     2157:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP2, 0);
1.1       misha    2158:         tmp2empty = stackptr >= stacktop;
                   2159:         if (!tmp2empty)
                   2160:           {
                   2161:           OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1.2       misha    2162:           stackptr += sizeof(sljit_sw);
1.1       misha    2163:           }
                   2164:         tmp1next = TRUE;
                   2165:         }
                   2166:       }
                   2167:     }
                   2168:   }
1.2       misha    2169: while (status != end);
1.1       misha    2170: 
                   2171: if (save)
                   2172:   {
                   2173:   if (tmp1next)
                   2174:     {
                   2175:     if (!tmp1empty)
                   2176:       {
                   2177:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1.2       misha    2178:       stackptr += sizeof(sljit_sw);
1.1       misha    2179:       }
                   2180:     if (!tmp2empty)
                   2181:       {
                   2182:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1.2       misha    2183:       stackptr += sizeof(sljit_sw);
1.1       misha    2184:       }
                   2185:     }
                   2186:   else
                   2187:     {
                   2188:     if (!tmp2empty)
                   2189:       {
                   2190:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1.2       misha    2191:       stackptr += sizeof(sljit_sw);
1.1       misha    2192:       }
                   2193:     if (!tmp1empty)
                   2194:       {
                   2195:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1.2       misha    2196:       stackptr += sizeof(sljit_sw);
1.1       misha    2197:       }
                   2198:     }
                   2199:   }
                   2200: SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
                   2201: }
                   2202: 
1.4     ! moko     2203: static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, sljit_u8 *current_offset)
1.2       misha    2204: {
                   2205: pcre_uchar *end = bracketend(cc);
                   2206: BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT;
                   2207: 
                   2208: /* Assert captures then. */
                   2209: if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT)
                   2210:   current_offset = NULL;
                   2211: /* Conditional block does not. */
                   2212: if (*cc == OP_COND || *cc == OP_SCOND)
                   2213:   has_alternatives = FALSE;
                   2214: 
                   2215: cc = next_opcode(common, cc);
                   2216: if (has_alternatives)
                   2217:   current_offset = common->then_offsets + (cc - common->start);
                   2218: 
                   2219: while (cc < end)
                   2220:   {
                   2221:   if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND))
                   2222:     cc = set_then_offsets(common, cc, current_offset);
                   2223:   else
                   2224:     {
                   2225:     if (*cc == OP_ALT && has_alternatives)
                   2226:       current_offset = common->then_offsets + (cc + 1 + LINK_SIZE - common->start);
                   2227:     if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL)
                   2228:       *current_offset = 1;
                   2229:     cc = next_opcode(common, cc);
                   2230:     }
                   2231:   }
                   2232: 
                   2233: return end;
                   2234: }
                   2235: 
                   2236: #undef CASE_ITERATOR_PRIVATE_DATA_1
                   2237: #undef CASE_ITERATOR_PRIVATE_DATA_2A
                   2238: #undef CASE_ITERATOR_PRIVATE_DATA_2B
                   2239: #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_1
                   2240: #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
                   2241: #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
                   2242: 
                   2243: static SLJIT_INLINE BOOL is_powerof2(unsigned int value)
1.1       misha    2244: {
                   2245: return (value & (value - 1)) == 0;
                   2246: }
                   2247: 
                   2248: static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)
                   2249: {
                   2250: while (list)
                   2251:   {
                   2252:   /* sljit_set_label is clever enough to do nothing
1.2       misha    2253:   if either the jump or the label is NULL. */
                   2254:   SET_LABEL(list->jump, label);
1.1       misha    2255:   list = list->next;
                   2256:   }
                   2257: }
                   2258: 
1.3       moko     2259: static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump *jump)
1.1       misha    2260: {
                   2261: jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));
                   2262: if (list_item)
                   2263:   {
                   2264:   list_item->next = *list;
                   2265:   list_item->jump = jump;
                   2266:   *list = list_item;
                   2267:   }
                   2268: }
                   2269: 
1.2       misha    2270: static void add_stub(compiler_common *common, struct sljit_jump *start)
1.1       misha    2271: {
                   2272: DEFINE_COMPILER;
1.3       moko     2273: stub_list *list_item = sljit_alloc_memory(compiler, sizeof(stub_list));
1.1       misha    2274: 
                   2275: if (list_item)
                   2276:   {
                   2277:   list_item->start = start;
1.2       misha    2278:   list_item->quit = LABEL();
1.1       misha    2279:   list_item->next = common->stubs;
                   2280:   common->stubs = list_item;
                   2281:   }
                   2282: }
                   2283: 
                   2284: static void flush_stubs(compiler_common *common)
                   2285: {
                   2286: DEFINE_COMPILER;
1.3       moko     2287: stub_list *list_item = common->stubs;
1.1       misha    2288: 
                   2289: while (list_item)
                   2290:   {
                   2291:   JUMPHERE(list_item->start);
1.2       misha    2292:   add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
                   2293:   JUMPTO(SLJIT_JUMP, list_item->quit);
1.1       misha    2294:   list_item = list_item->next;
                   2295:   }
                   2296: common->stubs = NULL;
                   2297: }
                   2298: 
1.3       moko     2299: static void add_label_addr(compiler_common *common, sljit_uw *update_addr)
                   2300: {
                   2301: DEFINE_COMPILER;
                   2302: label_addr_list *label_addr;
                   2303: 
                   2304: label_addr = sljit_alloc_memory(compiler, sizeof(label_addr_list));
                   2305: if (label_addr == NULL)
                   2306:   return;
                   2307: label_addr->label = LABEL();
                   2308: label_addr->update_addr = update_addr;
                   2309: label_addr->next = common->label_addrs;
                   2310: common->label_addrs = label_addr;
                   2311: }
                   2312: 
1.2       misha    2313: static SLJIT_INLINE void count_match(compiler_common *common)
1.1       misha    2314: {
                   2315: DEFINE_COMPILER;
                   2316: 
1.4     ! moko     2317: OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);
1.3       moko     2318: add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO));
1.1       misha    2319: }
                   2320: 
                   2321: static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
                   2322: {
                   2323: /* May destroy all locals and registers except TMP2. */
                   2324: DEFINE_COMPILER;
                   2325: 
1.4     ! moko     2326: SLJIT_ASSERT(size > 0);
        !          2327: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
1.1       misha    2328: #ifdef DESTROY_REGISTERS
                   2329: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
                   2330: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
                   2331: OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
1.3       moko     2332: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0);
                   2333: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0);
1.1       misha    2334: #endif
1.4     ! moko     2335: add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0));
1.1       misha    2336: }
                   2337: 
                   2338: static SLJIT_INLINE void free_stack(compiler_common *common, int size)
                   2339: {
                   2340: DEFINE_COMPILER;
1.4     ! moko     2341: 
        !          2342: SLJIT_ASSERT(size > 0);
        !          2343: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
1.1       misha    2344: }
                   2345: 
1.3       moko     2346: static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size)
                   2347: {
                   2348: DEFINE_COMPILER;
                   2349: sljit_uw *result;
                   2350: 
                   2351: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   2352:   return NULL;
                   2353: 
                   2354: result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), compiler->allocator_data);
                   2355: if (SLJIT_UNLIKELY(result == NULL))
                   2356:   {
                   2357:   sljit_set_compiler_memory_error(compiler);
                   2358:   return NULL;
                   2359:   }
                   2360: 
                   2361: *(void**)result = common->read_only_data_head;
                   2362: common->read_only_data_head = (void *)result;
                   2363: return result + 1;
                   2364: }
                   2365: 
                   2366: static void free_read_only_data(void *current, void *allocator_data)
                   2367: {
                   2368: void *next;
                   2369: 
                   2370: SLJIT_UNUSED_ARG(allocator_data);
                   2371: 
                   2372: while (current != NULL)
                   2373:   {
                   2374:   next = *(void**)current;
                   2375:   SLJIT_FREE(current, allocator_data);
                   2376:   current = next;
                   2377:   }
                   2378: }
                   2379: 
1.1       misha    2380: static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
                   2381: {
                   2382: DEFINE_COMPILER;
                   2383: struct sljit_label *loop;
                   2384: int i;
1.2       misha    2385: 
1.1       misha    2386: /* At this point we can freely use all temporary registers. */
1.2       misha    2387: SLJIT_ASSERT(length > 1);
1.1       misha    2388: /* TMP1 returns with begin - 1. */
1.3       moko     2389: OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));
1.2       misha    2390: if (length < 8)
                   2391:   {
                   2392:   for (i = 1; i < length; i++)
1.3       moko     2393:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), SLJIT_R0, 0);
1.2       misha    2394:   }
                   2395: else
                   2396:   {
1.4     ! moko     2397:   if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS)
        !          2398:     {
        !          2399:     GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);
        !          2400:     OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
        !          2401:     loop = LABEL();
        !          2402:     sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw));
        !          2403:     OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
        !          2404:     JUMPTO(SLJIT_NOT_ZERO, loop);
        !          2405:     }
        !          2406:   else
        !          2407:     {
        !          2408:     GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw));
        !          2409:     OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
        !          2410:     loop = LABEL();
        !          2411:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);
        !          2412:     OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));
        !          2413:     OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
        !          2414:     JUMPTO(SLJIT_NOT_ZERO, loop);
        !          2415:     }
1.2       misha    2416:   }
                   2417: }
                   2418: 
1.4     ! moko     2419: static SLJIT_INLINE void reset_fast_fail(compiler_common *common)
        !          2420: {
        !          2421: DEFINE_COMPILER;
        !          2422: sljit_s32 i;
        !          2423: 
        !          2424: SLJIT_ASSERT(common->fast_fail_start_ptr < common->fast_fail_end_ptr);
        !          2425: 
        !          2426: OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          2427: for (i = common->fast_fail_start_ptr; i < common->fast_fail_end_ptr; i += sizeof(sljit_sw))
        !          2428:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, TMP1, 0);
        !          2429: }
        !          2430: 
1.2       misha    2431: static SLJIT_INLINE void do_reset_match(compiler_common *common, int length)
                   2432: {
                   2433: DEFINE_COMPILER;
                   2434: struct sljit_label *loop;
                   2435: int i;
                   2436: 
                   2437: SLJIT_ASSERT(length > 1);
                   2438: /* OVECTOR(1) contains the "string begin - 1" constant. */
                   2439: if (length > 2)
1.3       moko     2440:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
1.1       misha    2441: if (length < 8)
                   2442:   {
1.2       misha    2443:   for (i = 2; i < length; i++)
1.3       moko     2444:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), TMP1, 0);
1.1       misha    2445:   }
                   2446: else
                   2447:   {
1.4     ! moko     2448:   if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS)
        !          2449:     {
        !          2450:     GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));
        !          2451:     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
        !          2452:     loop = LABEL();
        !          2453:     sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
        !          2454:     OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
        !          2455:     JUMPTO(SLJIT_NOT_ZERO, loop);
        !          2456:     }
        !          2457:   else
        !          2458:     {
        !          2459:     GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw));
        !          2460:     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
        !          2461:     loop = LABEL();
        !          2462:     OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);
        !          2463:     OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw));
        !          2464:     OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
        !          2465:     JUMPTO(SLJIT_NOT_ZERO, loop);
        !          2466:     }
1.2       misha    2467:   }
                   2468: 
                   2469: OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
                   2470: if (common->mark_ptr != 0)
1.3       moko     2471:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);
1.2       misha    2472: if (common->control_head_ptr != 0)
1.3       moko     2473:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
1.2       misha    2474: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
1.3       moko     2475: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
1.4     ! moko     2476: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end));
1.2       misha    2477: }
                   2478: 
1.4     ! moko     2479: static sljit_sw SLJIT_FUNC do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg)
1.2       misha    2480: {
                   2481: while (current != NULL)
                   2482:   {
1.4     ! moko     2483:   switch (current[1])
1.2       misha    2484:     {
                   2485:     case type_then_trap:
                   2486:     break;
                   2487: 
                   2488:     case type_mark:
1.4     ! moko     2489:     if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[2]) == 0)
        !          2490:       return current[3];
1.2       misha    2491:     break;
                   2492: 
                   2493:     default:
1.4     ! moko     2494:     SLJIT_UNREACHABLE();
1.2       misha    2495:     break;
                   2496:     }
1.4     ! moko     2497:   SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]);
        !          2498:   current = (sljit_sw*)current[0];
1.1       misha    2499:   }
1.4     ! moko     2500: return 0;
1.1       misha    2501: }
                   2502: 
                   2503: static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
                   2504: {
                   2505: DEFINE_COMPILER;
                   2506: struct sljit_label *loop;
1.2       misha    2507: struct sljit_jump *early_quit;
1.4     ! moko     2508: BOOL has_pre;
1.1       misha    2509: 
                   2510: /* At this point we can freely use all registers. */
1.3       moko     2511: OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
                   2512: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0);
1.1       misha    2513: 
1.3       moko     2514: OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
1.2       misha    2515: if (common->mark_ptr != 0)
1.3       moko     2516:   OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
1.4     ! moko     2517: OP1(SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offset_count));
1.2       misha    2518: if (common->mark_ptr != 0)
1.3       moko     2519:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);
                   2520: OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
                   2521: OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin));
1.4     ! moko     2522: 
        !          2523: has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;
        !          2524: GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));
        !          2525: 
1.1       misha    2526: /* Unlikely, but possible */
1.3       moko     2527: early_quit = CMP(SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0);
1.1       misha    2528: loop = LABEL();
1.4     ! moko     2529: 
        !          2530: if (has_pre)
        !          2531:   sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));
        !          2532: else
        !          2533:   {
        !          2534:   OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0);
        !          2535:   OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
        !          2536:   }
        !          2537: 
        !          2538: OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(int));
        !          2539: OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0);
1.1       misha    2540: /* Copy the integer value to the output buffer */
1.2       misha    2541: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.3       moko     2542: OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
1.1       misha    2543: #endif
1.4     ! moko     2544: 
        !          2545: OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0);
        !          2546: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
1.3       moko     2547: JUMPTO(SLJIT_NOT_ZERO, loop);
1.2       misha    2548: JUMPHERE(early_quit);
1.1       misha    2549: 
                   2550: /* Calculate the return value, which is the maximum ovector value. */
                   2551: if (topbracket > 1)
                   2552:   {
1.4     ! moko     2553:   if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS)
        !          2554:     {
        !          2555:     GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));
        !          2556:     OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
        !          2557: 
        !          2558:     /* OVECTOR(0) is never equal to SLJIT_S2. */
        !          2559:     loop = LABEL();
        !          2560:     sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw)));
        !          2561:     OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
        !          2562:     CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
        !          2563:     }
        !          2564:   else
        !          2565:     {
        !          2566:     GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw));
        !          2567:     OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
1.1       misha    2568: 
1.4     ! moko     2569:     /* OVECTOR(0) is never equal to SLJIT_S2. */
        !          2570:     loop = LABEL();
        !          2571:     OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0);
        !          2572:     OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw));
        !          2573:     OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
        !          2574:     CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
        !          2575:     }
1.3       moko     2576:   OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);
1.1       misha    2577:   }
                   2578: else
                   2579:   OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
                   2580: }
                   2581: 
1.2       misha    2582: static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit)
                   2583: {
                   2584: DEFINE_COMPILER;
                   2585: struct sljit_jump *jump;
                   2586: 
1.3       moko     2587: SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S1, str_end_must_be_saved_reg2);
1.2       misha    2588: SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0
                   2589:   && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0));
                   2590: 
1.3       moko     2591: OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0);
1.2       misha    2592: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL);
1.4     ! moko     2593: OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, real_offset_count));
1.3       moko     2594: CMPTO(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 2, quit);
1.2       misha    2595: 
                   2596: /* Store match begin and end. */
1.3       moko     2597: OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin));
                   2598: OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, offsets));
1.2       misha    2599: 
1.3       moko     2600: jump = CMP(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 3);
                   2601: OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_S0, 0);
1.2       misha    2602: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.3       moko     2603: OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);
1.2       misha    2604: #endif
1.4     ! moko     2605: OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(int), SLJIT_R2, 0);
1.2       misha    2606: JUMPHERE(jump);
                   2607: 
1.3       moko     2608: OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start);
                   2609: OP2(SLJIT_SUB, SLJIT_S1, 0, STR_END, 0, SLJIT_S0, 0);
1.2       misha    2610: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.3       moko     2611: OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
1.2       misha    2612: #endif
1.4     ! moko     2613: OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), sizeof(int), SLJIT_S1, 0);
1.2       misha    2614: 
1.3       moko     2615: OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S0, 0);
1.2       misha    2616: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.3       moko     2617: OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);
1.2       misha    2618: #endif
1.4     ! moko     2619: OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
1.2       misha    2620: 
                   2621: JUMPTO(SLJIT_JUMP, quit);
                   2622: }
                   2623: 
                   2624: static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)
                   2625: {
                   2626: /* May destroy TMP1. */
                   2627: DEFINE_COMPILER;
                   2628: struct sljit_jump *jump;
                   2629: 
                   2630: if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
                   2631:   {
                   2632:   /* The value of -1 must be kept for start_used_ptr! */
1.3       moko     2633:   OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, 1);
1.2       misha    2634:   /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting
                   2635:   is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */
1.3       moko     2636:   jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, STR_PTR, 0);
                   2637:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
1.2       misha    2638:   JUMPHERE(jump);
                   2639:   }
                   2640: else if (common->mode == JIT_PARTIAL_HARD_COMPILE)
                   2641:   {
1.3       moko     2642:   jump = CMP(SLJIT_LESS_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
                   2643:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
1.2       misha    2644:   JUMPHERE(jump);
                   2645:   }
                   2646: }
                   2647: 
1.3       moko     2648: static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar *cc)
1.1       misha    2649: {
                   2650: /* Detects if the character has an othercase. */
                   2651: unsigned int c;
                   2652: 
                   2653: #ifdef SUPPORT_UTF
                   2654: if (common->utf)
                   2655:   {
                   2656:   GETCHAR(c, cc);
                   2657:   if (c > 127)
                   2658:     {
                   2659: #ifdef SUPPORT_UCP
                   2660:     return c != UCD_OTHERCASE(c);
                   2661: #else
                   2662:     return FALSE;
                   2663: #endif
                   2664:     }
                   2665: #ifndef COMPILE_PCRE8
                   2666:   return common->fcc[c] != c;
                   2667: #endif
                   2668:   }
                   2669: else
                   2670: #endif
                   2671:   c = *cc;
                   2672: return MAX_255(c) ? common->fcc[c] != c : FALSE;
                   2673: }
                   2674: 
                   2675: static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)
                   2676: {
                   2677: /* Returns with the othercase. */
                   2678: #ifdef SUPPORT_UTF
                   2679: if (common->utf && c > 127)
                   2680:   {
                   2681: #ifdef SUPPORT_UCP
                   2682:   return UCD_OTHERCASE(c);
                   2683: #else
                   2684:   return c;
                   2685: #endif
                   2686:   }
                   2687: #endif
                   2688: return TABLE_GET(c, common->fcc, c);
                   2689: }
                   2690: 
1.3       moko     2691: static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar *cc)
1.1       misha    2692: {
                   2693: /* Detects if the character and its othercase has only 1 bit difference. */
                   2694: unsigned int c, oc, bit;
                   2695: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
                   2696: int n;
                   2697: #endif
                   2698: 
                   2699: #ifdef SUPPORT_UTF
                   2700: if (common->utf)
                   2701:   {
                   2702:   GETCHAR(c, cc);
                   2703:   if (c <= 127)
                   2704:     oc = common->fcc[c];
                   2705:   else
                   2706:     {
                   2707: #ifdef SUPPORT_UCP
                   2708:     oc = UCD_OTHERCASE(c);
                   2709: #else
                   2710:     oc = c;
                   2711: #endif
                   2712:     }
                   2713:   }
                   2714: else
                   2715:   {
                   2716:   c = *cc;
                   2717:   oc = TABLE_GET(c, common->fcc, c);
                   2718:   }
                   2719: #else
                   2720: c = *cc;
                   2721: oc = TABLE_GET(c, common->fcc, c);
                   2722: #endif
                   2723: 
                   2724: SLJIT_ASSERT(c != oc);
                   2725: 
                   2726: bit = c ^ oc;
                   2727: /* Optimized for English alphabet. */
                   2728: if (c <= 127 && bit == 0x20)
                   2729:   return (0 << 8) | 0x20;
                   2730: 
                   2731: /* Since c != oc, they must have at least 1 bit difference. */
1.2       misha    2732: if (!is_powerof2(bit))
1.1       misha    2733:   return 0;
                   2734: 
1.2       misha    2735: #if defined COMPILE_PCRE8
1.1       misha    2736: 
                   2737: #ifdef SUPPORT_UTF
                   2738: if (common->utf && c > 127)
                   2739:   {
                   2740:   n = GET_EXTRALEN(*cc);
                   2741:   while ((bit & 0x3f) == 0)
                   2742:     {
                   2743:     n--;
                   2744:     bit >>= 6;
                   2745:     }
                   2746:   return (n << 8) | bit;
                   2747:   }
                   2748: #endif /* SUPPORT_UTF */
                   2749: return (0 << 8) | bit;
                   2750: 
1.2       misha    2751: #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.1       misha    2752: 
                   2753: #ifdef SUPPORT_UTF
                   2754: if (common->utf && c > 65535)
                   2755:   {
                   2756:   if (bit >= (1 << 10))
                   2757:     bit >>= 10;
                   2758:   else
                   2759:     return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));
                   2760:   }
                   2761: #endif /* SUPPORT_UTF */
                   2762: return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8));
                   2763: 
1.2       misha    2764: #endif /* COMPILE_PCRE[8|16|32] */
                   2765: }
                   2766: 
                   2767: static void check_partial(compiler_common *common, BOOL force)
                   2768: {
                   2769: /* Checks whether a partial matching is occurred. Does not modify registers. */
                   2770: DEFINE_COMPILER;
                   2771: struct sljit_jump *jump = NULL;
                   2772: 
                   2773: SLJIT_ASSERT(!force || common->mode != JIT_COMPILE);
                   2774: 
                   2775: if (common->mode == JIT_COMPILE)
                   2776:   return;
                   2777: 
                   2778: if (!force)
1.3       moko     2779:   jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
1.2       misha    2780: else if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
1.3       moko     2781:   jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);
1.2       misha    2782: 
                   2783: if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
1.3       moko     2784:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
1.2       misha    2785: else
                   2786:   {
                   2787:   if (common->partialmatchlabel != NULL)
                   2788:     JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
                   2789:   else
                   2790:     add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
                   2791:   }
                   2792: 
                   2793: if (jump != NULL)
                   2794:   JUMPHERE(jump);
                   2795: }
                   2796: 
                   2797: static void check_str_end(compiler_common *common, jump_list **end_reached)
                   2798: {
                   2799: /* Does not affect registers. Usually used in a tight spot. */
                   2800: DEFINE_COMPILER;
                   2801: struct sljit_jump *jump;
                   2802: 
                   2803: if (common->mode == JIT_COMPILE)
                   2804:   {
1.3       moko     2805:   add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1.2       misha    2806:   return;
                   2807:   }
                   2808: 
1.3       moko     2809: jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
1.2       misha    2810: if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
                   2811:   {
1.3       moko     2812:   add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
                   2813:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
1.2       misha    2814:   add_jump(compiler, end_reached, JUMP(SLJIT_JUMP));
                   2815:   }
                   2816: else
                   2817:   {
1.3       moko     2818:   add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
1.2       misha    2819:   if (common->partialmatchlabel != NULL)
                   2820:     JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
                   2821:   else
                   2822:     add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
                   2823:   }
                   2824: JUMPHERE(jump);
1.1       misha    2825: }
                   2826: 
1.2       misha    2827: static void detect_partial_match(compiler_common *common, jump_list **backtracks)
1.1       misha    2828: {
                   2829: DEFINE_COMPILER;
1.2       misha    2830: struct sljit_jump *jump;
                   2831: 
                   2832: if (common->mode == JIT_COMPILE)
                   2833:   {
1.3       moko     2834:   add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1.2       misha    2835:   return;
                   2836:   }
                   2837: 
                   2838: /* Partial matching mode. */
1.3       moko     2839: jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
                   2840: add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
1.2       misha    2841: if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
                   2842:   {
1.3       moko     2843:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
1.2       misha    2844:   add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
                   2845:   }
                   2846: else
                   2847:   {
                   2848:   if (common->partialmatchlabel != NULL)
                   2849:     JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
                   2850:   else
                   2851:     add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
                   2852:   }
                   2853: JUMPHERE(jump);
1.1       misha    2854: }
                   2855: 
1.4     ! moko     2856: static void peek_char(compiler_common *common, sljit_u32 max)
1.1       misha    2857: {
1.3       moko     2858: /* Reads the character into TMP1, keeps STR_PTR.
1.1       misha    2859: Does not check STR_END. TMP2 Destroyed. */
                   2860: DEFINE_COMPILER;
1.2       misha    2861: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
1.1       misha    2862: struct sljit_jump *jump;
                   2863: #endif
                   2864: 
1.3       moko     2865: SLJIT_UNUSED_ARG(max);
                   2866: 
1.1       misha    2867: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.3       moko     2868: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.1       misha    2869: if (common->utf)
                   2870:   {
1.3       moko     2871:   if (max < 128) return;
                   2872: 
                   2873:   jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
                   2874:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1       misha    2875:   add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
1.3       moko     2876:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1.1       misha    2877:   JUMPHERE(jump);
                   2878:   }
1.2       misha    2879: #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
1.3       moko     2880: 
                   2881: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
                   2882: if (common->utf)
                   2883:   {
                   2884:   if (max < 0xd800) return;
                   2885: 
                   2886:   OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
                   2887:   jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
                   2888:   /* TMP2 contains the high surrogate. */
                   2889:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   2890:   OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40);
                   2891:   OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
                   2892:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
                   2893:   OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   2894:   JUMPHERE(jump);
                   2895:   }
                   2896: #endif
                   2897: }
                   2898: 
                   2899: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
                   2900: 
1.4     ! moko     2901: static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass)
1.3       moko     2902: {
                   2903: /* Tells whether the character codes below 128 are enough
                   2904: to determine a match. */
1.4     ! moko     2905: const sljit_u8 value = nclass ? 0xff : 0;
        !          2906: const sljit_u8 *end = bitset + 32;
1.3       moko     2907: 
                   2908: bitset += 16;
                   2909: do
                   2910:   {
                   2911:   if (*bitset++ != value)
                   2912:     return FALSE;
                   2913:   }
                   2914: while (bitset < end);
                   2915: return TRUE;
                   2916: }
                   2917: 
                   2918: static void read_char7_type(compiler_common *common, BOOL full_read)
                   2919: {
                   2920: /* Reads the precise character type of a character into TMP1, if the character
                   2921: is less than 128. Otherwise it returns with zero. Does not check STR_END. The
                   2922: full_read argument tells whether characters above max are accepted or not. */
                   2923: DEFINE_COMPILER;
                   2924: struct sljit_jump *jump;
                   2925: 
                   2926: SLJIT_ASSERT(common->utf);
                   2927: 
                   2928: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1.1       misha    2929: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.3       moko     2930: 
1.4     ! moko     2931: OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1.3       moko     2932: 
                   2933: if (full_read)
                   2934:   {
                   2935:   jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
1.4     ! moko     2936:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.3       moko     2937:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
                   2938:   JUMPHERE(jump);
                   2939:   }
1.1       misha    2940: }
                   2941: 
1.3       moko     2942: #endif /* SUPPORT_UTF && COMPILE_PCRE8 */
                   2943: 
1.4     ! moko     2944: static void read_char_range(compiler_common *common, sljit_u32 min, sljit_u32 max, BOOL update_str_ptr)
1.1       misha    2945: {
1.3       moko     2946: /* Reads the precise value of a character into TMP1, if the character is
                   2947: between min and max (c >= min && c <= max). Otherwise it returns with a value
                   2948: outside the range. Does not check STR_END. */
1.1       misha    2949: DEFINE_COMPILER;
1.2       misha    2950: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
1.1       misha    2951: struct sljit_jump *jump;
                   2952: #endif
1.3       moko     2953: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
                   2954: struct sljit_jump *jump2;
                   2955: #endif
                   2956: 
                   2957: SLJIT_UNUSED_ARG(update_str_ptr);
                   2958: SLJIT_UNUSED_ARG(min);
                   2959: SLJIT_UNUSED_ARG(max);
                   2960: SLJIT_ASSERT(min <= max);
                   2961: 
                   2962: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   2963: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   2964: 
                   2965: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
                   2966: if (common->utf)
                   2967:   {
                   2968:   if (max < 128 && !update_str_ptr) return;
                   2969: 
                   2970:   jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
                   2971:   if (min >= 0x10000)
                   2972:     {
                   2973:     OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0);
                   2974:     if (update_str_ptr)
1.4     ! moko     2975:       OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.3       moko     2976:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   2977:     jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x7);
                   2978:     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
                   2979:     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
                   2980:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   2981:     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
                   2982:     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
                   2983:     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   2984:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   2985:     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
                   2986:     if (!update_str_ptr)
                   2987:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
                   2988:     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
                   2989:     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   2990:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   2991:     JUMPHERE(jump2);
                   2992:     if (update_str_ptr)
                   2993:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
                   2994:     }
                   2995:   else if (min >= 0x800 && max <= 0xffff)
                   2996:     {
                   2997:     OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0);
                   2998:     if (update_str_ptr)
1.4     ! moko     2999:       OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.3       moko     3000:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   3001:     jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xf);
                   3002:     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
                   3003:     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
                   3004:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   3005:     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
                   3006:     if (!update_str_ptr)
                   3007:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
                   3008:     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
                   3009:     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   3010:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   3011:     JUMPHERE(jump2);
                   3012:     if (update_str_ptr)
                   3013:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
                   3014:     }
                   3015:   else if (max >= 0x800)
                   3016:     add_jump(compiler, (max < 0x10000) ? &common->utfreadchar16 : &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
                   3017:   else if (max < 128)
                   3018:     {
1.4     ! moko     3019:     OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.3       moko     3020:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
                   3021:     }
                   3022:   else
                   3023:     {
                   3024:     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   3025:     if (!update_str_ptr)
                   3026:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3027:     else
1.4     ! moko     3028:       OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.3       moko     3029:     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
                   3030:     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
                   3031:     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   3032:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   3033:     if (update_str_ptr)
                   3034:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
                   3035:     }
                   3036:   JUMPHERE(jump);
                   3037:   }
                   3038: #endif
1.1       misha    3039: 
1.3       moko     3040: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
1.1       misha    3041: if (common->utf)
                   3042:   {
1.3       moko     3043:   if (max >= 0x10000)
                   3044:     {
                   3045:     OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
                   3046:     jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
                   3047:     /* TMP2 contains the high surrogate. */
                   3048:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   3049:     OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40);
                   3050:     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
                   3051:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3052:     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
                   3053:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   3054:     JUMPHERE(jump);
                   3055:     return;
                   3056:     }
                   3057: 
                   3058:   if (max < 0xd800 && !update_str_ptr) return;
                   3059: 
                   3060:   /* Skip low surrogate if necessary. */
                   3061:   OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
                   3062:   jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
                   3063:   if (update_str_ptr)
                   3064:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3065:   if (max >= 0xd800)
                   3066:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);
1.1       misha    3067:   JUMPHERE(jump);
                   3068:   }
1.3       moko     3069: #endif
                   3070: }
                   3071: 
                   3072: static SLJIT_INLINE void read_char(compiler_common *common)
                   3073: {
                   3074: read_char_range(common, 0, READ_CHAR_MAX, TRUE);
1.1       misha    3075: }
                   3076: 
1.3       moko     3077: static void read_char8_type(compiler_common *common, BOOL update_str_ptr)
1.1       misha    3078: {
                   3079: /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
                   3080: DEFINE_COMPILER;
1.3       moko     3081: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1       misha    3082: struct sljit_jump *jump;
                   3083: #endif
1.3       moko     3084: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
                   3085: struct sljit_jump *jump2;
                   3086: #endif
                   3087: 
                   3088: SLJIT_UNUSED_ARG(update_str_ptr);
                   3089: 
                   3090: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
                   3091: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1       misha    3092: 
1.3       moko     3093: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.1       misha    3094: if (common->utf)
                   3095:   {
                   3096:   /* This can be an extra read in some situations, but hopefully
                   3097:   it is needed in most cases. */
1.4     ! moko     3098:   OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1.3       moko     3099:   jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
                   3100:   if (!update_str_ptr)
                   3101:     {
                   3102:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   3103:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3104:     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   3105:     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
                   3106:     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
                   3107:     OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
                   3108:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
                   3109:     jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);
1.4     ! moko     3110:     OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1.3       moko     3111:     JUMPHERE(jump2);
                   3112:     }
                   3113:   else
                   3114:     add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
1.2       misha    3115:   JUMPHERE(jump);
1.1       misha    3116:   return;
                   3117:   }
1.3       moko     3118: #endif /* SUPPORT_UTF && COMPILE_PCRE8 */
                   3119: 
                   3120: #if !defined COMPILE_PCRE8
1.1       misha    3121: /* The ctypes array contains only 256 values. */
                   3122: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1.3       moko     3123: jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);
1.1       misha    3124: #endif
1.4     ! moko     3125: OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1.3       moko     3126: #if !defined COMPILE_PCRE8
1.1       misha    3127: JUMPHERE(jump);
                   3128: #endif
1.3       moko     3129: 
                   3130: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
                   3131: if (common->utf && update_str_ptr)
                   3132:   {
                   3133:   /* Skip low surrogate if necessary. */
                   3134:   OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);
                   3135:   jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
                   3136:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3137:   JUMPHERE(jump);
                   3138:   }
                   3139: #endif /* SUPPORT_UTF && COMPILE_PCRE16 */
1.1       misha    3140: }
                   3141: 
                   3142: static void skip_char_back(compiler_common *common)
                   3143: {
                   3144: /* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
                   3145: DEFINE_COMPILER;
1.2       misha    3146: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
                   3147: #if defined COMPILE_PCRE8
1.1       misha    3148: struct sljit_label *label;
                   3149: 
                   3150: if (common->utf)
                   3151:   {
                   3152:   label = LABEL();
                   3153:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
                   3154:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3155:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
1.3       moko     3156:   CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
1.1       misha    3157:   return;
                   3158:   }
1.2       misha    3159: #elif defined COMPILE_PCRE16
1.1       misha    3160: if (common->utf)
                   3161:   {
                   3162:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
                   3163:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3164:   /* Skip low surrogate if necessary. */
                   3165:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
1.4     ! moko     3166:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
        !          3167:   OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
1.1       misha    3168:   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
                   3169:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
                   3170:   return;
                   3171:   }
1.2       misha    3172: #endif /* COMPILE_PCRE[8|16] */
                   3173: #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
1.1       misha    3174: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3175: }
                   3176: 
1.3       moko     3177: static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpifmatch)
1.1       misha    3178: {
                   3179: /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
                   3180: DEFINE_COMPILER;
1.3       moko     3181: struct sljit_jump *jump;
1.1       misha    3182: 
                   3183: if (nltype == NLTYPE_ANY)
                   3184:   {
                   3185:   add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
1.4     ! moko     3186:   sljit_set_current_flags(compiler, SLJIT_SET_Z);
1.3       moko     3187:   add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_NOT_ZERO : SLJIT_ZERO));
1.1       misha    3188:   }
                   3189: else if (nltype == NLTYPE_ANYCRLF)
                   3190:   {
1.3       moko     3191:   if (jumpifmatch)
                   3192:     {
                   3193:     add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR));
                   3194:     add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
                   3195:     }
                   3196:   else
                   3197:     {
                   3198:     jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
                   3199:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
                   3200:     JUMPHERE(jump);
                   3201:     }
1.1       misha    3202:   }
                   3203: else
                   3204:   {
                   3205:   SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);
1.3       moko     3206:   add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
1.1       misha    3207:   }
                   3208: }
                   3209: 
                   3210: #ifdef SUPPORT_UTF
                   3211: 
1.2       misha    3212: #if defined COMPILE_PCRE8
1.1       misha    3213: static void do_utfreadchar(compiler_common *common)
                   3214: {
                   3215: /* Fast decoding a UTF-8 character. TMP1 contains the first byte
1.3       moko     3216: of the character (>= 0xc0). Return char value in TMP1, length in TMP2. */
1.1       misha    3217: DEFINE_COMPILER;
                   3218: struct sljit_jump *jump;
                   3219: 
1.2       misha    3220: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.3       moko     3221: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   3222: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
                   3223: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
                   3224: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   3225: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   3226: 
1.1       misha    3227: /* Searching for the first zero. */
1.4     ! moko     3228: OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
1.3       moko     3229: jump = JUMP(SLJIT_NOT_ZERO);
1.1       misha    3230: /* Two byte sequence. */
1.3       moko     3231: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3232: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2));
                   3233: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3234: 
                   3235: JUMPHERE(jump);
1.1       misha    3236: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.3       moko     3237: OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800);
1.1       misha    3238: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
                   3239: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   3240: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
                   3241: 
1.4     ! moko     3242: OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
1.3       moko     3243: jump = JUMP(SLJIT_NOT_ZERO);
1.1       misha    3244: /* Three byte sequence. */
                   3245: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.3       moko     3246: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));
1.1       misha    3247: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3248: 
                   3249: /* Four byte sequence. */
1.3       moko     3250: JUMPHERE(jump);
                   3251: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
                   3252: OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
                   3253: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
                   3254: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
1.1       misha    3255: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   3256: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.3       moko     3257: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(4));
                   3258: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3259: }
                   3260: 
                   3261: static void do_utfreadchar16(compiler_common *common)
                   3262: {
                   3263: /* Fast decoding a UTF-8 character. TMP1 contains the first byte
                   3264: of the character (>= 0xc0). Return value in TMP1. */
                   3265: DEFINE_COMPILER;
                   3266: struct sljit_jump *jump;
                   3267: 
                   3268: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
                   3269: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   3270: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
                   3271: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
1.1       misha    3272: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   3273: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.3       moko     3274: 
                   3275: /* Searching for the first zero. */
1.4     ! moko     3276: OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
1.3       moko     3277: jump = JUMP(SLJIT_NOT_ZERO);
                   3278: /* Two byte sequence. */
                   3279: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3280: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3281: 
                   3282: JUMPHERE(jump);
1.4     ! moko     3283: OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
        !          3284: OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO);
1.3       moko     3285: /* This code runs only in 8 bit mode. No need to shift the value. */
                   3286: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
                   3287: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
                   3288: OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800);
                   3289: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
1.1       misha    3290: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
                   3291: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.3       moko     3292: /* Three byte sequence. */
                   3293: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.1       misha    3294: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3295: }
                   3296: 
                   3297: static void do_utfreadtype8(compiler_common *common)
                   3298: {
                   3299: /* Fast decoding a UTF-8 character type. TMP2 contains the first byte
                   3300: of the character (>= 0xc0). Return value in TMP1. */
                   3301: DEFINE_COMPILER;
                   3302: struct sljit_jump *jump;
                   3303: struct sljit_jump *compare;
                   3304: 
1.2       misha    3305: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1       misha    3306: 
1.4     ! moko     3307: OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
1.3       moko     3308: jump = JUMP(SLJIT_NOT_ZERO);
1.1       misha    3309: /* Two byte sequence. */
                   3310: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
                   3311: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3312: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);
1.3       moko     3313: /* The upper 5 bits are known at this point. */
                   3314: compare = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x3);
1.1       misha    3315: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
                   3316: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
                   3317: OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
1.4     ! moko     3318: OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1.1       misha    3319: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3320: 
                   3321: JUMPHERE(compare);
                   3322: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
                   3323: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3324: 
                   3325: /* We only have types for characters less than 256. */
1.3       moko     3326: JUMPHERE(jump);
1.4     ! moko     3327: OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.1       misha    3328: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1.3       moko     3329: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1.1       misha    3330: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3331: }
                   3332: 
1.3       moko     3333: #endif /* COMPILE_PCRE8 */
1.1       misha    3334: 
1.3       moko     3335: #endif /* SUPPORT_UTF */
1.1       misha    3336: 
1.3       moko     3337: #ifdef SUPPORT_UCP
1.1       misha    3338: 
                   3339: /* UCD_BLOCK_SIZE must be 128 (see the assert below). */
                   3340: #define UCD_BLOCK_MASK 127
                   3341: #define UCD_BLOCK_SHIFT 7
                   3342: 
                   3343: static void do_getucd(compiler_common *common)
                   3344: {
                   3345: /* Search the UCD record for the character comes in TMP1.
                   3346: Returns chartype in TMP1 and UCD offset in TMP2. */
                   3347: DEFINE_COMPILER;
1.4     ! moko     3348: #ifdef COMPILE_PCRE32
        !          3349: struct sljit_jump *jump;
        !          3350: #endif
        !          3351: 
        !          3352: #if defined SLJIT_DEBUG && SLJIT_DEBUG
        !          3353: /* dummy_ucd_record */
        !          3354: const ucd_record *record = GET_UCD(INVALID_UTF_CHAR);
        !          3355: SLJIT_ASSERT(record->script == ucp_Common && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther);
        !          3356: SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0);
        !          3357: #endif
1.1       misha    3358: 
                   3359: SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
                   3360: 
1.2       misha    3361: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.4     ! moko     3362: 
        !          3363: #ifdef COMPILE_PCRE32
        !          3364: if (!common->utf)
        !          3365:   {
        !          3366:   jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10ffff + 1);
        !          3367:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
        !          3368:   JUMPHERE(jump);
        !          3369:   }
        !          3370: #endif
        !          3371: 
1.1       misha    3372: OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1.4     ! moko     3373: OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
1.1       misha    3374: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
                   3375: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
                   3376: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
1.2       misha    3377: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
1.4     ! moko     3378: OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
1.2       misha    3379: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
1.4     ! moko     3380: OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1.1       misha    3381: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   3382: }
                   3383: #endif
                   3384: 
1.4     ! moko     3385: static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf)
1.1       misha    3386: {
                   3387: DEFINE_COMPILER;
                   3388: struct sljit_label *mainloop;
                   3389: struct sljit_label *newlinelabel = NULL;
                   3390: struct sljit_jump *start;
                   3391: struct sljit_jump *end = NULL;
1.4     ! moko     3392: struct sljit_jump *end2 = NULL;
1.2       misha    3393: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
1.1       misha    3394: struct sljit_jump *singlechar;
                   3395: #endif
                   3396: jump_list *newline = NULL;
                   3397: BOOL newlinecheck = FALSE;
                   3398: BOOL readuchar = FALSE;
                   3399: 
1.4     ! moko     3400: if (!(hascrorlf || (common->match_end_ptr != 0)) &&
        !          3401:     (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
1.1       misha    3402:   newlinecheck = TRUE;
                   3403: 
1.4     ! moko     3404: if (common->match_end_ptr != 0)
1.2       misha    3405:   {
                   3406:   /* Search for the end of the first line. */
                   3407:   OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
                   3408: 
                   3409:   if (common->nltype == NLTYPE_FIXED && common->newline > 255)
                   3410:     {
                   3411:     mainloop = LABEL();
                   3412:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.3       moko     3413:     end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.2       misha    3414:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
                   3415:     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.3       moko     3416:     CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
                   3417:     CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
1.2       misha    3418:     JUMPHERE(end);
1.4     ! moko     3419:     OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.2       misha    3420:     }
                   3421:   else
                   3422:     {
1.3       moko     3423:     end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.2       misha    3424:     mainloop = LABEL();
                   3425:     /* Continual stores does not cause data dependency. */
1.4     ! moko     3426:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);
1.3       moko     3427:     read_char_range(common, common->nlmin, common->nlmax, TRUE);
1.2       misha    3428:     check_newlinechar(common, common->nltype, &newline, TRUE);
1.3       moko     3429:     CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop);
1.2       misha    3430:     JUMPHERE(end);
1.4     ! moko     3431:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);
1.2       misha    3432:     set_jumps(newline, LABEL());
                   3433:     }
                   3434: 
                   3435:   OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
                   3436:   }
                   3437: 
                   3438: start = JUMP(SLJIT_JUMP);
                   3439: 
                   3440: if (newlinecheck)
                   3441:   {
                   3442:   newlinelabel = LABEL();
                   3443:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.3       moko     3444:   end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.2       misha    3445:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.4     ! moko     3446:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
        !          3447:   OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
1.2       misha    3448: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
                   3449:   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
                   3450: #endif
                   3451:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1.4     ! moko     3452:   end2 = JUMP(SLJIT_JUMP);
1.2       misha    3453:   }
                   3454: 
                   3455: mainloop = LABEL();
                   3456: 
                   3457: /* Increasing the STR_PTR here requires one less jump in the most common case. */
                   3458: #ifdef SUPPORT_UTF
                   3459: if (common->utf) readuchar = TRUE;
                   3460: #endif
                   3461: if (newlinecheck) readuchar = TRUE;
                   3462: 
                   3463: if (readuchar)
                   3464:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
                   3465: 
                   3466: if (newlinecheck)
1.3       moko     3467:   CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);
1.2       misha    3468: 
                   3469: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   3470: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
                   3471: #if defined COMPILE_PCRE8
                   3472: if (common->utf)
                   3473:   {
1.3       moko     3474:   singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.4     ! moko     3475:   OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.2       misha    3476:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
                   3477:   JUMPHERE(singlechar);
                   3478:   }
                   3479: #elif defined COMPILE_PCRE16
                   3480: if (common->utf)
                   3481:   {
1.3       moko     3482:   singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
1.2       misha    3483:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
1.4     ! moko     3484:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
        !          3485:   OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
1.2       misha    3486:   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
                   3487:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
                   3488:   JUMPHERE(singlechar);
                   3489:   }
                   3490: #endif /* COMPILE_PCRE[8|16] */
                   3491: #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
                   3492: JUMPHERE(start);
                   3493: 
                   3494: if (newlinecheck)
                   3495:   {
                   3496:   JUMPHERE(end);
1.4     ! moko     3497:   JUMPHERE(end2);
1.2       misha    3498:   }
                   3499: 
                   3500: return mainloop;
                   3501: }
                   3502: 
1.3       moko     3503: #define MAX_N_CHARS 16
1.4     ! moko     3504: #define MAX_DIFF_CHARS 6
1.2       misha    3505: 
1.4     ! moko     3506: static SLJIT_INLINE void add_prefix_char(pcre_uchar chr, pcre_uchar *chars)
1.2       misha    3507: {
1.4     ! moko     3508: pcre_uchar i, len;
1.3       moko     3509: 
1.4     ! moko     3510: len = chars[0];
1.3       moko     3511: if (len == 255)
                   3512:   return;
                   3513: 
                   3514: if (len == 0)
                   3515:   {
1.4     ! moko     3516:   chars[0] = 1;
        !          3517:   chars[1] = chr;
1.3       moko     3518:   return;
                   3519:   }
                   3520: 
                   3521: for (i = len; i > 0; i--)
1.4     ! moko     3522:   if (chars[i] == chr)
1.3       moko     3523:     return;
                   3524: 
1.4     ! moko     3525: if (len >= MAX_DIFF_CHARS - 1)
1.3       moko     3526:   {
1.4     ! moko     3527:   chars[0] = 255;
1.3       moko     3528:   return;
                   3529:   }
                   3530: 
                   3531: len++;
1.4     ! moko     3532: chars[len] = chr;
        !          3533: chars[0] = len;
1.3       moko     3534: }
1.2       misha    3535: 
1.4     ! moko     3536: static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uchar *chars, int max_chars, sljit_u32 *rec_count)
1.3       moko     3537: {
                   3538: /* Recursive function, which scans prefix literals. */
1.4     ! moko     3539: BOOL last, any, class, caseless;
1.3       moko     3540: int len, repeat, len_save, consumed = 0;
1.4     ! moko     3541: sljit_u32 chr; /* Any unicode character. */
        !          3542: sljit_u8 *bytes, *bytes_end, byte;
1.3       moko     3543: pcre_uchar *alternative, *cc_save, *oc;
                   3544: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
                   3545: pcre_uchar othercase[8];
                   3546: #elif defined SUPPORT_UTF && defined COMPILE_PCRE16
                   3547: pcre_uchar othercase[2];
                   3548: #else
                   3549: pcre_uchar othercase[1];
                   3550: #endif
1.2       misha    3551: 
1.3       moko     3552: repeat = 1;
1.2       misha    3553: while (TRUE)
                   3554:   {
1.4     ! moko     3555:   if (*rec_count == 0)
        !          3556:     return 0;
        !          3557:   (*rec_count)--;
        !          3558: 
1.3       moko     3559:   last = TRUE;
                   3560:   any = FALSE;
1.4     ! moko     3561:   class = FALSE;
1.3       moko     3562:   caseless = FALSE;
1.4     ! moko     3563: 
1.3       moko     3564:   switch (*cc)
1.2       misha    3565:     {
1.3       moko     3566:     case OP_CHARI:
                   3567:     caseless = TRUE;
1.2       misha    3568:     case OP_CHAR:
1.3       moko     3569:     last = FALSE;
1.2       misha    3570:     cc++;
                   3571:     break;
                   3572: 
                   3573:     case OP_SOD:
                   3574:     case OP_SOM:
                   3575:     case OP_SET_SOM:
                   3576:     case OP_NOT_WORD_BOUNDARY:
                   3577:     case OP_WORD_BOUNDARY:
                   3578:     case OP_EODN:
                   3579:     case OP_EOD:
                   3580:     case OP_CIRC:
                   3581:     case OP_CIRCM:
                   3582:     case OP_DOLL:
                   3583:     case OP_DOLLM:
                   3584:     /* Zero width assertions. */
                   3585:     cc++;
                   3586:     continue;
                   3587: 
1.3       moko     3588:     case OP_ASSERT:
                   3589:     case OP_ASSERT_NOT:
                   3590:     case OP_ASSERTBACK:
                   3591:     case OP_ASSERTBACK_NOT:
                   3592:     cc = bracketend(cc);
                   3593:     continue;
                   3594: 
                   3595:     case OP_PLUSI:
                   3596:     case OP_MINPLUSI:
                   3597:     case OP_POSPLUSI:
                   3598:     caseless = TRUE;
1.2       misha    3599:     case OP_PLUS:
                   3600:     case OP_MINPLUS:
                   3601:     case OP_POSPLUS:
                   3602:     cc++;
                   3603:     break;
                   3604: 
1.3       moko     3605:     case OP_EXACTI:
                   3606:     caseless = TRUE;
1.2       misha    3607:     case OP_EXACT:
1.3       moko     3608:     repeat = GET2(cc, 1);
                   3609:     last = FALSE;
1.2       misha    3610:     cc += 1 + IMM2_SIZE;
                   3611:     break;
                   3612: 
1.3       moko     3613:     case OP_QUERYI:
                   3614:     case OP_MINQUERYI:
                   3615:     case OP_POSQUERYI:
                   3616:     caseless = TRUE;
                   3617:     case OP_QUERY:
                   3618:     case OP_MINQUERY:
                   3619:     case OP_POSQUERY:
                   3620:     len = 1;
                   3621:     cc++;
                   3622: #ifdef SUPPORT_UTF
                   3623:     if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
                   3624: #endif
1.4     ! moko     3625:     max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count);
1.3       moko     3626:     if (max_chars == 0)
                   3627:       return consumed;
                   3628:     last = FALSE;
                   3629:     break;
                   3630: 
                   3631:     case OP_KET:
                   3632:     cc += 1 + LINK_SIZE;
                   3633:     continue;
                   3634: 
                   3635:     case OP_ALT:
                   3636:     cc += GET(cc, 1);
                   3637:     continue;
                   3638: 
                   3639:     case OP_ONCE:
                   3640:     case OP_ONCE_NC:
                   3641:     case OP_BRA:
                   3642:     case OP_BRAPOS:
                   3643:     case OP_CBRA:
                   3644:     case OP_CBRAPOS:
                   3645:     alternative = cc + GET(cc, 1);
                   3646:     while (*alternative == OP_ALT)
                   3647:       {
1.4     ! moko     3648:       max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count);
1.3       moko     3649:       if (max_chars == 0)
                   3650:         return consumed;
                   3651:       alternative += GET(alternative, 1);
                   3652:       }
                   3653: 
                   3654:     if (*cc == OP_CBRA || *cc == OP_CBRAPOS)
                   3655:       cc += IMM2_SIZE;
                   3656:     cc += 1 + LINK_SIZE;
                   3657:     continue;
                   3658: 
                   3659:     case OP_CLASS:
                   3660: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.4     ! moko     3661:     if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE))
        !          3662:       return consumed;
1.3       moko     3663: #endif
1.4     ! moko     3664:     class = TRUE;
1.3       moko     3665:     break;
                   3666: 
                   3667:     case OP_NCLASS:
                   3668: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
                   3669:     if (common->utf) return consumed;
                   3670: #endif
1.4     ! moko     3671:     class = TRUE;
1.3       moko     3672:     break;
                   3673: 
                   3674: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
                   3675:     case OP_XCLASS:
                   3676: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
                   3677:     if (common->utf) return consumed;
                   3678: #endif
                   3679:     any = TRUE;
                   3680:     cc += GET(cc, 1);
                   3681:     break;
                   3682: #endif
                   3683: 
                   3684:     case OP_DIGIT:
                   3685: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.4     ! moko     3686:     if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
1.3       moko     3687:       return consumed;
                   3688: #endif
                   3689:     any = TRUE;
                   3690:     cc++;
                   3691:     break;
                   3692: 
                   3693:     case OP_WHITESPACE:
                   3694: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.4     ! moko     3695:     if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))
1.3       moko     3696:       return consumed;
                   3697: #endif
                   3698:     any = TRUE;
                   3699:     cc++;
                   3700:     break;
                   3701: 
                   3702:     case OP_WORDCHAR:
                   3703: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.4     ! moko     3704:     if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))
1.3       moko     3705:       return consumed;
                   3706: #endif
                   3707:     any = TRUE;
                   3708:     cc++;
                   3709:     break;
                   3710: 
                   3711:     case OP_NOT:
                   3712:     case OP_NOTI:
                   3713:     cc++;
                   3714:     /* Fall through. */
                   3715:     case OP_NOT_DIGIT:
                   3716:     case OP_NOT_WHITESPACE:
                   3717:     case OP_NOT_WORDCHAR:
                   3718:     case OP_ANY:
                   3719:     case OP_ALLANY:
                   3720: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
                   3721:     if (common->utf) return consumed;
                   3722: #endif
                   3723:     any = TRUE;
1.2       misha    3724:     cc++;
                   3725:     break;
                   3726: 
1.4     ! moko     3727: #ifdef SUPPORT_UTF
1.3       moko     3728:     case OP_NOTPROP:
                   3729:     case OP_PROP:
1.4     ! moko     3730: #ifndef COMPILE_PCRE32
1.3       moko     3731:     if (common->utf) return consumed;
                   3732: #endif
                   3733:     any = TRUE;
                   3734:     cc += 1 + 2;
                   3735:     break;
                   3736: #endif
                   3737: 
                   3738:     case OP_TYPEEXACT:
                   3739:     repeat = GET2(cc, 1);
1.2       misha    3740:     cc += 1 + IMM2_SIZE;
1.3       moko     3741:     continue;
                   3742: 
                   3743:     case OP_NOTEXACT:
                   3744:     case OP_NOTEXACTI:
                   3745: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
                   3746:     if (common->utf) return consumed;
                   3747: #endif
                   3748:     any = TRUE;
                   3749:     repeat = GET2(cc, 1);
                   3750:     cc += 1 + IMM2_SIZE + 1;
1.2       misha    3751:     break;
                   3752: 
                   3753:     default:
1.3       moko     3754:     return consumed;
1.2       misha    3755:     }
                   3756: 
1.3       moko     3757:   if (any)
                   3758:     {
1.4     ! moko     3759:     do
        !          3760:       {
        !          3761:       chars[0] = 255;
        !          3762: 
        !          3763:       consumed++;
        !          3764:       if (--max_chars == 0)
        !          3765:         return consumed;
        !          3766:       chars += MAX_DIFF_CHARS;
        !          3767:       }
        !          3768:     while (--repeat > 0);
        !          3769: 
        !          3770:     repeat = 1;
        !          3771:     continue;
        !          3772:     }
        !          3773: 
        !          3774:   if (class)
        !          3775:     {
        !          3776:     bytes = (sljit_u8*) (cc + 1);
        !          3777:     cc += 1 + 32 / sizeof(pcre_uchar);
        !          3778: 
        !          3779:     switch (*cc)
        !          3780:       {
        !          3781:       case OP_CRSTAR:
        !          3782:       case OP_CRMINSTAR:
        !          3783:       case OP_CRPOSSTAR:
        !          3784:       case OP_CRQUERY:
        !          3785:       case OP_CRMINQUERY:
        !          3786:       case OP_CRPOSQUERY:
        !          3787:       max_chars = scan_prefix(common, cc + 1, chars, max_chars, rec_count);
        !          3788:       if (max_chars == 0)
        !          3789:         return consumed;
        !          3790:       break;
        !          3791: 
        !          3792:       default:
        !          3793:       case OP_CRPLUS:
        !          3794:       case OP_CRMINPLUS:
        !          3795:       case OP_CRPOSPLUS:
        !          3796:       break;
        !          3797: 
        !          3798:       case OP_CRRANGE:
        !          3799:       case OP_CRMINRANGE:
        !          3800:       case OP_CRPOSRANGE:
        !          3801:       repeat = GET2(cc, 1);
        !          3802:       if (repeat <= 0)
        !          3803:         return consumed;
        !          3804:       break;
        !          3805:       }
1.3       moko     3806: 
                   3807:     do
                   3808:       {
1.4     ! moko     3809:       if (bytes[31] & 0x80)
        !          3810:         chars[0] = 255;
        !          3811:       else if (chars[0] != 255)
        !          3812:         {
        !          3813:         bytes_end = bytes + 32;
        !          3814:         chr = 0;
        !          3815:         do
        !          3816:           {
        !          3817:           byte = *bytes++;
        !          3818:           SLJIT_ASSERT((chr & 0x7) == 0);
        !          3819:           if (byte == 0)
        !          3820:             chr += 8;
        !          3821:           else
        !          3822:             {
        !          3823:             do
        !          3824:               {
        !          3825:               if ((byte & 0x1) != 0)
        !          3826:                 add_prefix_char(chr, chars);
        !          3827:               byte >>= 1;
        !          3828:               chr++;
        !          3829:               }
        !          3830:             while (byte != 0);
        !          3831:             chr = (chr + 7) & ~7;
        !          3832:             }
        !          3833:           }
        !          3834:         while (chars[0] != 255 && bytes < bytes_end);
        !          3835:         bytes = bytes_end - 32;
        !          3836:         }
1.3       moko     3837: 
                   3838:       consumed++;
                   3839:       if (--max_chars == 0)
                   3840:         return consumed;
1.4     ! moko     3841:       chars += MAX_DIFF_CHARS;
1.3       moko     3842:       }
                   3843:     while (--repeat > 0);
                   3844: 
1.4     ! moko     3845:     switch (*cc)
        !          3846:       {
        !          3847:       case OP_CRSTAR:
        !          3848:       case OP_CRMINSTAR:
        !          3849:       case OP_CRPOSSTAR:
        !          3850:       return consumed;
        !          3851: 
        !          3852:       case OP_CRQUERY:
        !          3853:       case OP_CRMINQUERY:
        !          3854:       case OP_CRPOSQUERY:
        !          3855:       cc++;
        !          3856:       break;
        !          3857: 
        !          3858:       case OP_CRRANGE:
        !          3859:       case OP_CRMINRANGE:
        !          3860:       case OP_CRPOSRANGE:
        !          3861:       if (GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE))
        !          3862:         return consumed;
        !          3863:       cc += 1 + 2 * IMM2_SIZE;
        !          3864:       break;
        !          3865:       }
        !          3866: 
1.3       moko     3867:     repeat = 1;
                   3868:     continue;
                   3869:     }
1.2       misha    3870: 
                   3871:   len = 1;
                   3872: #ifdef SUPPORT_UTF
1.3       moko     3873:   if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
1.2       misha    3874: #endif
                   3875: 
                   3876:   if (caseless && char_has_othercase(common, cc))
1.1       misha    3877:     {
1.3       moko     3878: #ifdef SUPPORT_UTF
                   3879:     if (common->utf)
                   3880:       {
                   3881:       GETCHAR(chr, cc);
                   3882:       if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len)
                   3883:         return consumed;
                   3884:       }
1.2       misha    3885:     else
                   3886: #endif
1.3       moko     3887:       {
                   3888:       chr = *cc;
                   3889:       othercase[0] = TABLE_GET(chr, common->fcc, chr);
                   3890:       }
1.1       misha    3891:     }
                   3892:   else
1.4     ! moko     3893:     {
1.3       moko     3894:     caseless = FALSE;
1.4     ! moko     3895:     othercase[0] = 0; /* Stops compiler warning - PH */
        !          3896:     }
1.3       moko     3897: 
                   3898:   len_save = len;
                   3899:   cc_save = cc;
                   3900:   while (TRUE)
                   3901:     {
                   3902:     oc = othercase;
                   3903:     do
                   3904:       {
                   3905:       chr = *cc;
1.4     ! moko     3906:       add_prefix_char(*cc, chars);
1.3       moko     3907: 
                   3908:       if (caseless)
1.4     ! moko     3909:         add_prefix_char(*oc, chars);
1.3       moko     3910: 
                   3911:       len--;
                   3912:       consumed++;
                   3913:       if (--max_chars == 0)
                   3914:         return consumed;
1.4     ! moko     3915:       chars += MAX_DIFF_CHARS;
1.3       moko     3916:       cc++;
                   3917:       oc++;
                   3918:       }
                   3919:     while (len > 0);
                   3920: 
                   3921:     if (--repeat == 0)
                   3922:       break;
                   3923: 
                   3924:     len = len_save;
                   3925:     cc = cc_save;
                   3926:     }
                   3927: 
                   3928:   repeat = 1;
                   3929:   if (last)
                   3930:     return consumed;
                   3931:   }
                   3932: }
                   3933: 
1.4     ! moko     3934: #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
        !          3935: 
        !          3936: static sljit_s32 character_to_int32(pcre_uchar chr)
        !          3937: {
        !          3938: sljit_s32 value = (sljit_s32)chr;
        !          3939: #if defined COMPILE_PCRE8
        !          3940: #define SSE2_COMPARE_TYPE_INDEX 0
        !          3941: return (value << 24) | (value << 16) | (value << 8) | value;
        !          3942: #elif defined COMPILE_PCRE16
        !          3943: #define SSE2_COMPARE_TYPE_INDEX 1
        !          3944: return (value << 16) | value;
        !          3945: #elif defined COMPILE_PCRE32
        !          3946: #define SSE2_COMPARE_TYPE_INDEX 2
        !          3947: return value;
        !          3948: #else
        !          3949: #error "Unsupported unit width"
        !          3950: #endif
        !          3951: }
        !          3952: 
        !          3953: static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, pcre_uchar char1, pcre_uchar char2)
        !          3954: {
        !          3955: DEFINE_COMPILER;
        !          3956: struct sljit_label *start;
        !          3957: struct sljit_jump *quit[3];
        !          3958: struct sljit_jump *nomatch;
        !          3959: sljit_u8 instruction[8];
        !          3960: sljit_s32 tmp1_ind = sljit_get_register_index(TMP1);
        !          3961: sljit_s32 tmp2_ind = sljit_get_register_index(TMP2);
        !          3962: sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR);
        !          3963: BOOL load_twice = FALSE;
        !          3964: pcre_uchar bit;
        !          3965: 
        !          3966: bit = char1 ^ char2;
        !          3967: if (!is_powerof2(bit))
        !          3968:   bit = 0;
        !          3969: 
        !          3970: if ((char1 != char2) && bit == 0)
        !          3971:   load_twice = TRUE;
        !          3972: 
        !          3973: quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
        !          3974: 
        !          3975: /* First part (unaligned start) */
        !          3976: 
        !          3977: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
        !          3978: 
        !          3979: SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1);
        !          3980: 
        !          3981: /* MOVD xmm, r/m32 */
        !          3982: instruction[0] = 0x66;
        !          3983: instruction[1] = 0x0f;
        !          3984: instruction[2] = 0x6e;
        !          3985: instruction[3] = 0xc0 | (2 << 3) | tmp1_ind;
        !          3986: sljit_emit_op_custom(compiler, instruction, 4);
        !          3987: 
        !          3988: if (char1 != char2)
        !          3989:   {
        !          3990:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
        !          3991: 
        !          3992:   /* MOVD xmm, r/m32 */
        !          3993:   instruction[3] = 0xc0 | (3 << 3) | tmp1_ind;
        !          3994:   sljit_emit_op_custom(compiler, instruction, 4);
        !          3995:   }
        !          3996: 
        !          3997: /* PSHUFD xmm1, xmm2/m128, imm8 */
        !          3998: instruction[2] = 0x70;
        !          3999: instruction[3] = 0xc0 | (2 << 3) | 2;
        !          4000: instruction[4] = 0;
        !          4001: sljit_emit_op_custom(compiler, instruction, 5);
        !          4002: 
        !          4003: if (char1 != char2)
        !          4004:   {
        !          4005:   /* PSHUFD xmm1, xmm2/m128, imm8 */
        !          4006:   instruction[3] = 0xc0 | (3 << 3) | 3;
        !          4007:   instruction[4] = 0;
        !          4008:   sljit_emit_op_custom(compiler, instruction, 5);
        !          4009:   }
        !          4010: 
        !          4011: OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 0xf);
        !          4012: OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
        !          4013: 
        !          4014: /* MOVDQA xmm1, xmm2/m128 */
        !          4015: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        !          4016: 
        !          4017: if (str_ptr_ind < 8)
        !          4018:   {
        !          4019:   instruction[2] = 0x6f;
        !          4020:   instruction[3] = (0 << 3) | str_ptr_ind;
        !          4021:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4022: 
        !          4023:   if (load_twice)
        !          4024:     {
        !          4025:     instruction[3] = (1 << 3) | str_ptr_ind;
        !          4026:     sljit_emit_op_custom(compiler, instruction, 4);
        !          4027:     }
        !          4028:   }
        !          4029: else
        !          4030:   {
        !          4031:   instruction[1] = 0x41;
        !          4032:   instruction[2] = 0x0f;
        !          4033:   instruction[3] = 0x6f;
        !          4034:   instruction[4] = (0 << 3) | (str_ptr_ind & 0x7);
        !          4035:   sljit_emit_op_custom(compiler, instruction, 5);
        !          4036: 
        !          4037:   if (load_twice)
        !          4038:     {
        !          4039:     instruction[4] = (1 << 3) | str_ptr_ind;
        !          4040:     sljit_emit_op_custom(compiler, instruction, 5);
        !          4041:     }
        !          4042:   instruction[1] = 0x0f;
        !          4043:   }
        !          4044: 
        !          4045: #else
        !          4046: 
        !          4047: instruction[2] = 0x6f;
        !          4048: instruction[3] = (0 << 3) | str_ptr_ind;
        !          4049: sljit_emit_op_custom(compiler, instruction, 4);
        !          4050: 
        !          4051: if (load_twice)
        !          4052:   {
        !          4053:   instruction[3] = (1 << 3) | str_ptr_ind;
        !          4054:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4055:   }
        !          4056: 
        !          4057: #endif
        !          4058: 
        !          4059: if (bit != 0)
        !          4060:   {
        !          4061:   /* POR xmm1, xmm2/m128 */
        !          4062:   instruction[2] = 0xeb;
        !          4063:   instruction[3] = 0xc0 | (0 << 3) | 3;
        !          4064:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4065:   }
        !          4066: 
        !          4067: /* PCMPEQB/W/D xmm1, xmm2/m128 */
        !          4068: instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
        !          4069: instruction[3] = 0xc0 | (0 << 3) | 2;
        !          4070: sljit_emit_op_custom(compiler, instruction, 4);
        !          4071: 
        !          4072: if (load_twice)
        !          4073:   {
        !          4074:   instruction[3] = 0xc0 | (1 << 3) | 3;
        !          4075:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4076:   }
        !          4077: 
        !          4078: /* PMOVMSKB reg, xmm */
        !          4079: instruction[2] = 0xd7;
        !          4080: instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
        !          4081: sljit_emit_op_custom(compiler, instruction, 4);
        !          4082: 
        !          4083: if (load_twice)
        !          4084:   {
        !          4085:   OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0);
        !          4086:   instruction[3] = 0xc0 | (tmp2_ind << 3) | 1;
        !          4087:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4088: 
        !          4089:   OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
        !          4090:   OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0);
        !          4091:   }
        !          4092: 
        !          4093: OP2(SLJIT_ASHR, TMP1, 0, TMP1, 0, TMP2, 0);
        !          4094: 
        !          4095: /* BSF r32, r/m32 */
        !          4096: instruction[0] = 0x0f;
        !          4097: instruction[1] = 0xbc;
        !          4098: instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
        !          4099: sljit_emit_op_custom(compiler, instruction, 3);
        !          4100: sljit_set_current_flags(compiler, SLJIT_SET_Z);
        !          4101: 
        !          4102: nomatch = JUMP(SLJIT_ZERO);
        !          4103: 
        !          4104: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
        !          4105: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
        !          4106: quit[1] = JUMP(SLJIT_JUMP);
        !          4107: 
        !          4108: JUMPHERE(nomatch);
        !          4109: 
        !          4110: start = LABEL();
        !          4111: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
        !          4112: quit[2] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
        !          4113: 
        !          4114: /* Second part (aligned) */
        !          4115: 
        !          4116: instruction[0] = 0x66;
        !          4117: instruction[1] = 0x0f;
        !          4118: 
        !          4119: /* MOVDQA xmm1, xmm2/m128 */
        !          4120: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        !          4121: 
        !          4122: if (str_ptr_ind < 8)
        !          4123:   {
        !          4124:   instruction[2] = 0x6f;
        !          4125:   instruction[3] = (0 << 3) | str_ptr_ind;
        !          4126:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4127: 
        !          4128:   if (load_twice)
        !          4129:     {
        !          4130:     instruction[3] = (1 << 3) | str_ptr_ind;
        !          4131:     sljit_emit_op_custom(compiler, instruction, 4);
        !          4132:     }
        !          4133:   }
        !          4134: else
        !          4135:   {
        !          4136:   instruction[1] = 0x41;
        !          4137:   instruction[2] = 0x0f;
        !          4138:   instruction[3] = 0x6f;
        !          4139:   instruction[4] = (0 << 3) | (str_ptr_ind & 0x7);
        !          4140:   sljit_emit_op_custom(compiler, instruction, 5);
        !          4141: 
        !          4142:   if (load_twice)
        !          4143:     {
        !          4144:     instruction[4] = (1 << 3) | str_ptr_ind;
        !          4145:     sljit_emit_op_custom(compiler, instruction, 5);
        !          4146:     }
        !          4147:   instruction[1] = 0x0f;
        !          4148:   }
        !          4149: 
        !          4150: #else
        !          4151: 
        !          4152: instruction[2] = 0x6f;
        !          4153: instruction[3] = (0 << 3) | str_ptr_ind;
        !          4154: sljit_emit_op_custom(compiler, instruction, 4);
        !          4155: 
        !          4156: if (load_twice)
        !          4157:   {
        !          4158:   instruction[3] = (1 << 3) | str_ptr_ind;
        !          4159:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4160:   }
        !          4161: 
        !          4162: #endif
        !          4163: 
        !          4164: if (bit != 0)
        !          4165:   {
        !          4166:   /* POR xmm1, xmm2/m128 */
        !          4167:   instruction[2] = 0xeb;
        !          4168:   instruction[3] = 0xc0 | (0 << 3) | 3;
        !          4169:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4170:   }
        !          4171: 
        !          4172: /* PCMPEQB/W/D xmm1, xmm2/m128 */
        !          4173: instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
        !          4174: instruction[3] = 0xc0 | (0 << 3) | 2;
        !          4175: sljit_emit_op_custom(compiler, instruction, 4);
        !          4176: 
        !          4177: if (load_twice)
        !          4178:   {
        !          4179:   instruction[3] = 0xc0 | (1 << 3) | 3;
        !          4180:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4181:   }
        !          4182: 
        !          4183: /* PMOVMSKB reg, xmm */
        !          4184: instruction[2] = 0xd7;
        !          4185: instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
        !          4186: sljit_emit_op_custom(compiler, instruction, 4);
        !          4187: 
        !          4188: if (load_twice)
        !          4189:   {
        !          4190:   instruction[3] = 0xc0 | (tmp2_ind << 3) | 1;
        !          4191:   sljit_emit_op_custom(compiler, instruction, 4);
        !          4192: 
        !          4193:   OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
        !          4194:   }
        !          4195: 
        !          4196: /* BSF r32, r/m32 */
        !          4197: instruction[0] = 0x0f;
        !          4198: instruction[1] = 0xbc;
        !          4199: instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
        !          4200: sljit_emit_op_custom(compiler, instruction, 3);
        !          4201: sljit_set_current_flags(compiler, SLJIT_SET_Z);
        !          4202: 
        !          4203: JUMPTO(SLJIT_ZERO, start);
        !          4204: 
        !          4205: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
        !          4206: 
        !          4207: start = LABEL();
        !          4208: SET_LABEL(quit[0], start);
        !          4209: SET_LABEL(quit[1], start);
        !          4210: SET_LABEL(quit[2], start);
        !          4211: }
        !          4212: 
        !          4213: #undef SSE2_COMPARE_TYPE_INDEX
        !          4214: 
        !          4215: #endif
        !          4216: 
        !          4217: static void fast_forward_first_char2(compiler_common *common, pcre_uchar char1, pcre_uchar char2, sljit_s32 offset)
1.3       moko     4218: {
                   4219: DEFINE_COMPILER;
                   4220: struct sljit_label *start;
                   4221: struct sljit_jump *quit;
1.4     ! moko     4222: struct sljit_jump *found;
        !          4223: pcre_uchar mask;
        !          4224: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          4225: struct sljit_label *utf_start = NULL;
        !          4226: struct sljit_jump *utf_quit = NULL;
        !          4227: #endif
        !          4228: BOOL has_match_end = (common->match_end_ptr != 0);
        !          4229: 
        !          4230: if (offset > 0)
        !          4231:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
        !          4232: 
        !          4233: if (has_match_end)
        !          4234:   {
        !          4235:   OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
        !          4236: 
        !          4237:   OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1));
        !          4238:   OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0);
        !          4239:   sljit_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0);
        !          4240:   }
        !          4241: 
        !          4242: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          4243: if (common->utf && offset > 0)
        !          4244:   utf_start = LABEL();
        !          4245: #endif
        !          4246: 
        !          4247: #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
        !          4248: 
        !          4249: /* SSE2 accelerated first character search. */
1.3       moko     4250: 
1.4     ! moko     4251: if (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
1.3       moko     4252:   {
1.4     ! moko     4253:   fast_forward_first_char2_sse2(common, char1, char2);
        !          4254: 
        !          4255:   SLJIT_ASSERT(common->mode == JIT_COMPILE || offset == 0);
        !          4256:   if (common->mode == JIT_COMPILE)
        !          4257:     {
        !          4258:     /* In complete mode, we don't need to run a match when STR_PTR == STR_END. */
        !          4259:     SLJIT_ASSERT(common->forced_quit_label == NULL);
        !          4260:     OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
        !          4261:     add_jump(compiler, &common->forced_quit, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
        !          4262: 
        !          4263: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          4264:     if (common->utf && offset > 0)
        !          4265:       {
        !          4266:       SLJIT_ASSERT(common->mode == JIT_COMPILE);
        !          4267: 
        !          4268:       OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
        !          4269:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          4270: #if defined COMPILE_PCRE8
        !          4271:       OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
        !          4272:       CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start);
        !          4273: #elif defined COMPILE_PCRE16
        !          4274:       OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
        !          4275:       CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start);
        !          4276: #else
        !          4277: #error "Unknown code width"
        !          4278: #endif
        !          4279:       OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          4280:       }
        !          4281: #endif
        !          4282: 
        !          4283:     if (offset > 0)
        !          4284:       OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
        !          4285:     }
        !          4286:   else
        !          4287:     {
        !          4288:     OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
        !          4289:     if (has_match_end)
        !          4290:       {
        !          4291:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
        !          4292:       sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, TMP1, 0);
        !          4293:       }
        !          4294:     else
        !          4295:       sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, STR_END, 0);
        !          4296:     }
        !          4297: 
        !          4298:   if (has_match_end)
        !          4299:     OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
        !          4300:   return;
1.3       moko     4301:   }
1.2       misha    4302: 
1.4     ! moko     4303: #endif
1.3       moko     4304: 
1.4     ! moko     4305: quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
        !          4306: 
        !          4307: start = LABEL();
        !          4308: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.3       moko     4309: 
1.4     ! moko     4310: if (char1 == char2)
        !          4311:   found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1);
        !          4312: else
1.3       moko     4313:   {
1.4     ! moko     4314:   mask = char1 ^ char2;
        !          4315:   if (is_powerof2(mask))
        !          4316:     {
        !          4317:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);
        !          4318:     found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask);
        !          4319:     }
        !          4320:   else
1.1       misha    4321:     {
1.4     ! moko     4322:     OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1);
        !          4323:     OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
        !          4324:     OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2);
        !          4325:     OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
        !          4326:     found = JUMP(SLJIT_NOT_ZERO);
1.3       moko     4327:     }
                   4328:   }
                   4329: 
1.4     ! moko     4330: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          4331: CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, start);
        !          4332: 
        !          4333: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          4334: if (common->utf && offset > 0)
        !          4335:   utf_quit = JUMP(SLJIT_JUMP);
        !          4336: #endif
        !          4337: 
        !          4338: JUMPHERE(found);
        !          4339: 
        !          4340: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          4341: if (common->utf && offset > 0)
        !          4342:   {
        !          4343:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
        !          4344:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          4345: #if defined COMPILE_PCRE8
        !          4346:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
        !          4347:   CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start);
        !          4348: #elif defined COMPILE_PCRE16
        !          4349:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
        !          4350:   CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start);
        !          4351: #else
        !          4352: #error "Unknown code width"
        !          4353: #endif
        !          4354:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          4355:   JUMPHERE(utf_quit);
        !          4356:   }
        !          4357: #endif
        !          4358: 
        !          4359: JUMPHERE(quit);
        !          4360: 
        !          4361: if (has_match_end)
        !          4362:   {
        !          4363:   quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
        !          4364:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
        !          4365:   if (offset > 0)
        !          4366:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
        !          4367:   JUMPHERE(quit);
        !          4368:   OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
        !          4369:   }
        !          4370: 
        !          4371: if (offset > 0)
        !          4372:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
        !          4373: }
        !          4374: 
        !          4375: static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common)
        !          4376: {
        !          4377: DEFINE_COMPILER;
        !          4378: struct sljit_label *start;
        !          4379: struct sljit_jump *quit;
        !          4380: struct sljit_jump *match;
        !          4381: /* bytes[0] represent the number of characters between 0
        !          4382: and MAX_N_BYTES - 1, 255 represents any character. */
        !          4383: pcre_uchar chars[MAX_N_CHARS * MAX_DIFF_CHARS];
        !          4384: sljit_s32 offset;
        !          4385: pcre_uchar mask;
        !          4386: pcre_uchar *char_set, *char_set_end;
        !          4387: int i, max, from;
        !          4388: int range_right = -1, range_len;
        !          4389: sljit_u8 *update_table = NULL;
        !          4390: BOOL in_range;
        !          4391: sljit_u32 rec_count;
        !          4392: 
        !          4393: for (i = 0; i < MAX_N_CHARS; i++)
        !          4394:   chars[i * MAX_DIFF_CHARS] = 0;
        !          4395: 
        !          4396: rec_count = 10000;
        !          4397: max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count);
        !          4398: 
        !          4399: if (max < 1)
        !          4400:   return FALSE;
        !          4401: 
1.3       moko     4402: in_range = FALSE;
1.4     ! moko     4403: /* Prevent compiler "uninitialized" warning */
        !          4404: from = 0;
        !          4405: range_len = 4 /* minimum length */ - 1;
1.3       moko     4406: for (i = 0; i <= max; i++)
                   4407:   {
1.4     ! moko     4408:   if (in_range && (i - from) > range_len && (chars[(i - 1) * MAX_DIFF_CHARS] < 255))
1.3       moko     4409:     {
                   4410:     range_len = i - from;
                   4411:     range_right = i - 1;
                   4412:     }
                   4413: 
1.4     ! moko     4414:   if (i < max && chars[i * MAX_DIFF_CHARS] < 255)
1.3       moko     4415:     {
1.4     ! moko     4416:     SLJIT_ASSERT(chars[i * MAX_DIFF_CHARS] > 0);
1.3       moko     4417:     if (!in_range)
1.2       misha    4418:       {
1.3       moko     4419:       in_range = TRUE;
                   4420:       from = i;
1.2       misha    4421:       }
1.3       moko     4422:     }
1.4     ! moko     4423:   else
1.3       moko     4424:     in_range = FALSE;
                   4425:   }
1.2       misha    4426: 
1.3       moko     4427: if (range_right >= 0)
                   4428:   {
1.4     ! moko     4429:   update_table = (sljit_u8 *)allocate_read_only_data(common, 256);
1.3       moko     4430:   if (update_table == NULL)
                   4431:     return TRUE;
                   4432:   memset(update_table, IN_UCHARS(range_len), 256);
1.2       misha    4433: 
1.3       moko     4434:   for (i = 0; i < range_len; i++)
                   4435:     {
1.4     ! moko     4436:     char_set = chars + ((range_right - i) * MAX_DIFF_CHARS);
        !          4437:     SLJIT_ASSERT(char_set[0] > 0 && char_set[0] < 255);
        !          4438:     char_set_end = char_set + char_set[0];
        !          4439:     char_set++;
        !          4440:     while (char_set <= char_set_end)
1.3       moko     4441:       {
1.4     ! moko     4442:       if (update_table[(*char_set) & 0xff] > IN_UCHARS(i))
        !          4443:         update_table[(*char_set) & 0xff] = IN_UCHARS(i);
        !          4444:       char_set++;
1.3       moko     4445:       }
1.1       misha    4446:     }
1.3       moko     4447:   }
1.1       misha    4448: 
1.4     ! moko     4449: offset = -1;
1.3       moko     4450: /* Scan forward. */
                   4451: for (i = 0; i < max; i++)
                   4452:   {
1.4     ! moko     4453:   if (offset == -1)
        !          4454:     {
        !          4455:     if (chars[i * MAX_DIFF_CHARS] <= 2)
        !          4456:       offset = i;
        !          4457:     }
        !          4458:   else if (chars[offset * MAX_DIFF_CHARS] == 2 && chars[i * MAX_DIFF_CHARS] <= 2)
        !          4459:     {
        !          4460:     if (chars[i * MAX_DIFF_CHARS] == 1)
        !          4461:       offset = i;
        !          4462:     else
1.3       moko     4463:       {
1.4     ! moko     4464:       mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2];
        !          4465:       if (!is_powerof2(mask))
1.3       moko     4466:         {
1.4     ! moko     4467:         mask = chars[i * MAX_DIFF_CHARS + 1] ^ chars[i * MAX_DIFF_CHARS + 2];
        !          4468:         if (is_powerof2(mask))
        !          4469:           offset = i;
1.3       moko     4470:         }
                   4471:       }
                   4472:     }
1.4     ! moko     4473:   }
1.3       moko     4474: 
1.4     ! moko     4475: if (range_right < 0)
        !          4476:   {
        !          4477:   if (offset < 0)
        !          4478:     return FALSE;
        !          4479:   SLJIT_ASSERT(chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2);
        !          4480:   /* Works regardless the value is 1 or 2. */
        !          4481:   mask = chars[offset * MAX_DIFF_CHARS + chars[offset * MAX_DIFF_CHARS]];
        !          4482:   fast_forward_first_char2(common, chars[offset * MAX_DIFF_CHARS + 1], mask, offset);
        !          4483:   return TRUE;
        !          4484:   }
1.3       moko     4485: 
1.4     ! moko     4486: if (range_right == offset)
        !          4487:   offset = -1;
        !          4488: 
        !          4489: SLJIT_ASSERT(offset == -1 || (chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2));
1.3       moko     4490: 
                   4491: max -= 1;
1.4     ! moko     4492: SLJIT_ASSERT(max > 0);
        !          4493: if (common->match_end_ptr != 0)
1.1       misha    4494:   {
1.4     ! moko     4495:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
1.2       misha    4496:   OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
1.3       moko     4497:   OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
                   4498:   quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP1, 0);
                   4499:   OP1(SLJIT_MOV, STR_END, 0, TMP1, 0);
                   4500:   JUMPHERE(quit);
1.1       misha    4501:   }
1.2       misha    4502: else
1.3       moko     4503:   OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
                   4504: 
1.4     ! moko     4505: SLJIT_ASSERT(range_right >= 0);
        !          4506: 
1.3       moko     4507: #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.4     ! moko     4508: OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
1.3       moko     4509: #endif
1.1       misha    4510: 
1.2       misha    4511: start = LABEL();
1.3       moko     4512: quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
                   4513: 
                   4514: #if defined COMPILE_PCRE8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
1.4     ! moko     4515: OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));
1.3       moko     4516: #else
1.4     ! moko     4517: OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);
1.3       moko     4518: #endif
                   4519: 
                   4520: #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.4     ! moko     4521: OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
1.3       moko     4522: #else
1.4     ! moko     4523: OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
1.3       moko     4524: #endif
1.4     ! moko     4525: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
        !          4526: CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);
1.3       moko     4527: 
1.4     ! moko     4528: if (offset >= 0)
1.3       moko     4529:   {
1.4     ! moko     4530:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offset));
1.3       moko     4531:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   4532: 
1.4     ! moko     4533:   if (chars[offset * MAX_DIFF_CHARS] == 1)
        !          4534:     CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1], start);
        !          4535:   else
1.3       moko     4536:     {
1.4     ! moko     4537:     mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2];
        !          4538:     if (is_powerof2(mask))
        !          4539:       {
        !          4540:       OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);
        !          4541:       CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1] | mask, start);
        !          4542:       }
        !          4543:     else
        !          4544:       {
        !          4545:       match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1]);
        !          4546:       CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 2], start);
        !          4547:       JUMPHERE(match);
        !          4548:       }
1.3       moko     4549:     }
1.4     ! moko     4550:   }
1.3       moko     4551: 
1.4     ! moko     4552: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          4553: if (common->utf && offset != 0)
        !          4554:   {
        !          4555:   if (offset < 0)
1.3       moko     4556:     {
1.4     ! moko     4557:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
        !          4558:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.3       moko     4559:     }
1.4     ! moko     4560:   else
        !          4561:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
        !          4562: #if defined COMPILE_PCRE8
        !          4563:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
        !          4564:   CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, start);
        !          4565: #elif defined COMPILE_PCRE16
        !          4566:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
        !          4567:   CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, start);
        !          4568: #else
        !          4569: #error "Unknown code width"
        !          4570: #endif
        !          4571:   if (offset < 0)
        !          4572:     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          4573:   }
        !          4574: #endif
        !          4575: 
        !          4576: if (offset >= 0)
1.3       moko     4577:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1       misha    4578: 
1.2       misha    4579: JUMPHERE(quit);
1.1       misha    4580: 
1.4     ! moko     4581: if (common->match_end_ptr != 0)
1.3       moko     4582:   {
                   4583:   if (range_right >= 0)
1.4     ! moko     4584:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
1.2       misha    4585:   OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
1.3       moko     4586:   if (range_right >= 0)
                   4587:     {
                   4588:     quit = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
                   4589:     OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
                   4590:     JUMPHERE(quit);
                   4591:     }
                   4592:   }
1.2       misha    4593: else
1.3       moko     4594:   OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
1.2       misha    4595: return TRUE;
1.1       misha    4596: }
                   4597: 
1.2       misha    4598: #undef MAX_N_CHARS
1.4     ! moko     4599: #undef MAX_DIFF_CHARS
1.2       misha    4600: 
1.4     ! moko     4601: static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless)
1.1       misha    4602: {
1.4     ! moko     4603: pcre_uchar oc;
1.1       misha    4604: 
                   4605: oc = first_char;
                   4606: if (caseless)
                   4607:   {
                   4608:   oc = TABLE_GET(first_char, common->fcc, first_char);
1.4     ! moko     4609: #if defined SUPPORT_UCP && !defined COMPILE_PCRE8
1.1       misha    4610:   if (first_char > 127 && common->utf)
                   4611:     oc = UCD_OTHERCASE(first_char);
                   4612: #endif
                   4613:   }
                   4614: 
1.4     ! moko     4615: fast_forward_first_char2(common, first_char, oc, 0);
1.1       misha    4616: }
                   4617: 
1.4     ! moko     4618: static SLJIT_INLINE void fast_forward_newline(compiler_common *common)
1.1       misha    4619: {
                   4620: DEFINE_COMPILER;
                   4621: struct sljit_label *loop;
                   4622: struct sljit_jump *lastchar;
                   4623: struct sljit_jump *firstchar;
1.2       misha    4624: struct sljit_jump *quit;
1.1       misha    4625: struct sljit_jump *foundcr = NULL;
                   4626: struct sljit_jump *notfoundnl;
                   4627: jump_list *newline = NULL;
                   4628: 
1.4     ! moko     4629: if (common->match_end_ptr != 0)
1.1       misha    4630:   {
1.2       misha    4631:   OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
1.4     ! moko     4632:   OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
1.1       misha    4633:   }
                   4634: 
                   4635: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
                   4636:   {
1.3       moko     4637:   lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1       misha    4638:   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
                   4639:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
                   4640:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1.3       moko     4641:   firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1.1       misha    4642: 
                   4643:   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
1.4     ! moko     4644:   OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
        !          4645:   OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL);
1.2       misha    4646: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
                   4647:   OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);
1.1       misha    4648: #endif
                   4649:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
                   4650: 
                   4651:   loop = LABEL();
                   4652:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.3       moko     4653:   quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1       misha    4654:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
                   4655:   OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
1.3       moko     4656:   CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);
                   4657:   CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);
1.1       misha    4658: 
1.2       misha    4659:   JUMPHERE(quit);
1.1       misha    4660:   JUMPHERE(firstchar);
                   4661:   JUMPHERE(lastchar);
                   4662: 
1.4     ! moko     4663:   if (common->match_end_ptr != 0)
1.3       moko     4664:     OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
1.1       misha    4665:   return;
                   4666:   }
                   4667: 
                   4668: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
                   4669: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1.3       moko     4670: firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1.1       misha    4671: skip_char_back(common);
                   4672: 
                   4673: loop = LABEL();
1.3       moko     4674: common->ff_newline_shortcut = loop;
                   4675: 
                   4676: read_char_range(common, common->nlmin, common->nlmax, TRUE);
                   4677: lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1       misha    4678: if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1.3       moko     4679:   foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1.1       misha    4680: check_newlinechar(common, common->nltype, &newline, FALSE);
                   4681: set_jumps(newline, loop);
                   4682: 
                   4683: if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
                   4684:   {
1.2       misha    4685:   quit = JUMP(SLJIT_JUMP);
1.1       misha    4686:   JUMPHERE(foundcr);
1.3       moko     4687:   notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1       misha    4688:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.4     ! moko     4689:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
        !          4690:   OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
1.2       misha    4691: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
                   4692:   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
1.1       misha    4693: #endif
                   4694:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
                   4695:   JUMPHERE(notfoundnl);
1.2       misha    4696:   JUMPHERE(quit);
1.1       misha    4697:   }
                   4698: JUMPHERE(lastchar);
                   4699: JUMPHERE(firstchar);
                   4700: 
1.4     ! moko     4701: if (common->match_end_ptr != 0)
1.2       misha    4702:   OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
1.1       misha    4703: }
                   4704: 
1.4     ! moko     4705: static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks);
1.2       misha    4706: 
1.4     ! moko     4707: static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, const sljit_u8 *start_bits)
1.1       misha    4708: {
                   4709: DEFINE_COMPILER;
                   4710: struct sljit_label *start;
1.2       misha    4711: struct sljit_jump *quit;
                   4712: struct sljit_jump *found = NULL;
                   4713: jump_list *matches = NULL;
1.1       misha    4714: #ifndef COMPILE_PCRE8
                   4715: struct sljit_jump *jump;
                   4716: #endif
                   4717: 
1.4     ! moko     4718: if (common->match_end_ptr != 0)
1.1       misha    4719:   {
1.2       misha    4720:   OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);
1.4     ! moko     4721:   OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
1.1       misha    4722:   }
                   4723: 
                   4724: start = LABEL();
1.3       moko     4725: quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1       misha    4726: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
                   4727: #ifdef SUPPORT_UTF
                   4728: if (common->utf)
                   4729:   OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
                   4730: #endif
1.2       misha    4731: 
1.3       moko     4732: if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE, &matches))
1.2       misha    4733:   {
1.1       misha    4734: #ifndef COMPILE_PCRE8
1.3       moko     4735:   jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 255);
1.2       misha    4736:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255);
                   4737:   JUMPHERE(jump);
1.1       misha    4738: #endif
1.2       misha    4739:   OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
                   4740:   OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
1.4     ! moko     4741:   OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);
1.2       misha    4742:   OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
1.4     ! moko     4743:   OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
1.3       moko     4744:   found = JUMP(SLJIT_NOT_ZERO);
1.2       misha    4745:   }
1.1       misha    4746: 
                   4747: #ifdef SUPPORT_UTF
                   4748: if (common->utf)
                   4749:   OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
                   4750: #endif
                   4751: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.2       misha    4752: #ifdef SUPPORT_UTF
                   4753: #if defined COMPILE_PCRE8
1.1       misha    4754: if (common->utf)
                   4755:   {
1.3       moko     4756:   CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
1.4     ! moko     4757:   OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.1       misha    4758:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
                   4759:   }
1.2       misha    4760: #elif defined COMPILE_PCRE16
1.1       misha    4761: if (common->utf)
                   4762:   {
1.3       moko     4763:   CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
1.1       misha    4764:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
1.4     ! moko     4765:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
        !          4766:   OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
1.1       misha    4767:   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
                   4768:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
                   4769:   }
1.2       misha    4770: #endif /* COMPILE_PCRE[8|16] */
                   4771: #endif /* SUPPORT_UTF */
1.1       misha    4772: JUMPTO(SLJIT_JUMP, start);
1.2       misha    4773: if (found != NULL)
                   4774:   JUMPHERE(found);
                   4775: if (matches != NULL)
                   4776:   set_jumps(matches, LABEL());
                   4777: JUMPHERE(quit);
1.1       misha    4778: 
1.4     ! moko     4779: if (common->match_end_ptr != 0)
1.2       misha    4780:   OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);
1.1       misha    4781: }
                   4782: 
                   4783: static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar)
                   4784: {
                   4785: DEFINE_COMPILER;
                   4786: struct sljit_label *loop;
                   4787: struct sljit_jump *toolong;
                   4788: struct sljit_jump *alreadyfound;
                   4789: struct sljit_jump *found;
                   4790: struct sljit_jump *foundoc = NULL;
                   4791: struct sljit_jump *notfound;
1.4     ! moko     4792: sljit_u32 oc, bit;
1.1       misha    4793: 
1.2       misha    4794: SLJIT_ASSERT(common->req_char_ptr != 0);
1.3       moko     4795: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr);
1.1       misha    4796: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
1.3       moko     4797: toolong = CMP(SLJIT_LESS, TMP1, 0, STR_END, 0);
                   4798: alreadyfound = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);
1.1       misha    4799: 
                   4800: if (has_firstchar)
                   4801:   OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   4802: else
                   4803:   OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);
                   4804: 
                   4805: loop = LABEL();
1.3       moko     4806: notfound = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0);
1.1       misha    4807: 
                   4808: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0);
                   4809: oc = req_char;
                   4810: if (caseless)
                   4811:   {
                   4812:   oc = TABLE_GET(req_char, common->fcc, req_char);
                   4813: #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
                   4814:   if (req_char > 127 && common->utf)
                   4815:     oc = UCD_OTHERCASE(req_char);
                   4816: #endif
                   4817:   }
                   4818: if (req_char == oc)
1.3       moko     4819:   found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
1.1       misha    4820: else
                   4821:   {
                   4822:   bit = req_char ^ oc;
1.2       misha    4823:   if (is_powerof2(bit))
1.1       misha    4824:     {
                   4825:     OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);
1.3       moko     4826:     found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit);
1.1       misha    4827:     }
                   4828:   else
                   4829:     {
1.3       moko     4830:     found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
                   4831:     foundoc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc);
1.1       misha    4832:     }
                   4833:   }
                   4834: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
                   4835: JUMPTO(SLJIT_JUMP, loop);
                   4836: 
                   4837: JUMPHERE(found);
                   4838: if (foundoc)
                   4839:   JUMPHERE(foundoc);
1.3       moko     4840: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, TMP1, 0);
1.1       misha    4841: JUMPHERE(alreadyfound);
                   4842: JUMPHERE(toolong);
                   4843: return notfound;
                   4844: }
                   4845: 
                   4846: static void do_revertframes(compiler_common *common)
                   4847: {
                   4848: DEFINE_COMPILER;
                   4849: struct sljit_jump *jump;
                   4850: struct sljit_label *mainloop;
                   4851: 
1.2       misha    4852: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.4     ! moko     4853: OP1(SLJIT_MOV, TMP3, 0, STACK_TOP, 0);
        !          4854: GET_LOCAL_BASE(TMP1, 0, 0);
1.1       misha    4855: 
                   4856: /* Drop frames until we reach STACK_TOP. */
                   4857: mainloop = LABEL();
1.4     ! moko     4858: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw));
        !          4859: jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0);
        !          4860: 
        !          4861: OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
        !          4862: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -2 * sizeof(sljit_sw));
        !          4863: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -3 * sizeof(sljit_sw));
        !          4864: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));
1.1       misha    4865: JUMPTO(SLJIT_JUMP, mainloop);
                   4866: 
                   4867: JUMPHERE(jump);
1.4     ! moko     4868: jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0);
        !          4869: /* End of reverting values. */
        !          4870: OP1(SLJIT_MOV, STACK_TOP, 0, TMP3, 0);
1.1       misha    4871: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   4872: 
                   4873: JUMPHERE(jump);
1.2       misha    4874: OP1(SLJIT_NEG, TMP2, 0, TMP2, 0);
1.4     ! moko     4875: OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
        !          4876: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -2 * sizeof(sljit_sw));
        !          4877: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
1.1       misha    4878: JUMPTO(SLJIT_JUMP, mainloop);
                   4879: }
                   4880: 
                   4881: static void check_wordboundary(compiler_common *common)
                   4882: {
                   4883: DEFINE_COMPILER;
1.2       misha    4884: struct sljit_jump *skipread;
                   4885: jump_list *skipread_list = NULL;
1.1       misha    4886: #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
                   4887: struct sljit_jump *jump;
                   4888: #endif
                   4889: 
                   4890: SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);
                   4891: 
1.3       moko     4892: sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
1.1       misha    4893: /* Get type of the previous char, and put it to LOCALS1. */
                   4894: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
                   4895: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1.3       moko     4896: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, SLJIT_IMM, 0);
                   4897: skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
1.1       misha    4898: skip_char_back(common);
1.2       misha    4899: check_start_used_ptr(common);
1.1       misha    4900: read_char(common);
                   4901: 
                   4902: /* Testing char type. */
                   4903: #ifdef SUPPORT_UCP
                   4904: if (common->use_ucp)
                   4905:   {
                   4906:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
1.3       moko     4907:   jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
1.1       misha    4908:   add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
                   4909:   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
1.4     ! moko     4910:   OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
        !          4911:   OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
1.1       misha    4912:   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
1.4     ! moko     4913:   OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
        !          4914:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
1.1       misha    4915:   JUMPHERE(jump);
1.3       moko     4916:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0);
1.1       misha    4917:   }
                   4918: else
                   4919: #endif
                   4920:   {
                   4921: #ifndef COMPILE_PCRE8
1.3       moko     4922:   jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.1       misha    4923: #elif defined SUPPORT_UTF
                   4924:   /* Here LOCALS1 has already been zeroed. */
                   4925:   jump = NULL;
                   4926:   if (common->utf)
1.3       moko     4927:     jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.1       misha    4928: #endif /* COMPILE_PCRE8 */
1.4     ! moko     4929:   OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
1.1       misha    4930:   OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
                   4931:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1.3       moko     4932:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0);
1.1       misha    4933: #ifndef COMPILE_PCRE8
                   4934:   JUMPHERE(jump);
                   4935: #elif defined SUPPORT_UTF
                   4936:   if (jump != NULL)
                   4937:     JUMPHERE(jump);
                   4938: #endif /* COMPILE_PCRE8 */
                   4939:   }
1.2       misha    4940: JUMPHERE(skipread);
1.1       misha    4941: 
                   4942: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
1.2       misha    4943: check_str_end(common, &skipread_list);
1.3       moko     4944: peek_char(common, READ_CHAR_MAX);
1.1       misha    4945: 
                   4946: /* Testing char type. This is a code duplication. */
                   4947: #ifdef SUPPORT_UCP
                   4948: if (common->use_ucp)
                   4949:   {
                   4950:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
1.3       moko     4951:   jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
1.1       misha    4952:   add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
                   4953:   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
1.4     ! moko     4954:   OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
        !          4955:   OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
1.1       misha    4956:   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
1.4     ! moko     4957:   OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
        !          4958:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
1.1       misha    4959:   JUMPHERE(jump);
                   4960:   }
                   4961: else
                   4962: #endif
                   4963:   {
                   4964: #ifndef COMPILE_PCRE8
                   4965:   /* TMP2 may be destroyed by peek_char. */
                   4966:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
1.3       moko     4967:   jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.1       misha    4968: #elif defined SUPPORT_UTF
                   4969:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
                   4970:   jump = NULL;
                   4971:   if (common->utf)
1.3       moko     4972:     jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.1       misha    4973: #endif
1.4     ! moko     4974:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
1.1       misha    4975:   OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
                   4976:   OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
                   4977: #ifndef COMPILE_PCRE8
                   4978:   JUMPHERE(jump);
                   4979: #elif defined SUPPORT_UTF
                   4980:   if (jump != NULL)
                   4981:     JUMPHERE(jump);
                   4982: #endif /* COMPILE_PCRE8 */
                   4983:   }
1.2       misha    4984: set_jumps(skipread_list, LABEL());
1.1       misha    4985: 
1.4     ! moko     4986: OP2(SLJIT_XOR | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
1.3       moko     4987: sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
1.2       misha    4988: }
                   4989: 
1.4     ! moko     4990: static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)
1.2       misha    4991: {
1.4     ! moko     4992: /* May destroy TMP1. */
1.3       moko     4993: DEFINE_COMPILER;
                   4994: int ranges[MAX_RANGE_SIZE];
1.4     ! moko     4995: sljit_u8 bit, cbit, all;
1.2       misha    4996: int i, byte, length = 0;
                   4997: 
                   4998: bit = bits[0] & 0x1;
1.3       moko     4999: /* All bits will be zero or one (since bit is zero or one). */
1.2       misha    5000: all = -bit;
                   5001: 
                   5002: for (i = 0; i < 256; )
                   5003:   {
                   5004:   byte = i >> 3;
                   5005:   if ((i & 0x7) == 0 && bits[byte] == all)
                   5006:     i += 8;
                   5007:   else
                   5008:     {
                   5009:     cbit = (bits[byte] >> (i & 0x7)) & 0x1;
                   5010:     if (cbit != bit)
                   5011:       {
                   5012:       if (length >= MAX_RANGE_SIZE)
                   5013:         return FALSE;
1.3       moko     5014:       ranges[length] = i;
1.2       misha    5015:       length++;
                   5016:       bit = cbit;
                   5017:       all = -cbit;
                   5018:       }
                   5019:     i++;
                   5020:     }
                   5021:   }
                   5022: 
                   5023: if (((bit == 0) && nclass) || ((bit == 1) && !nclass))
                   5024:   {
                   5025:   if (length >= MAX_RANGE_SIZE)
                   5026:     return FALSE;
1.3       moko     5027:   ranges[length] = 256;
1.2       misha    5028:   length++;
                   5029:   }
                   5030: 
1.3       moko     5031: if (length < 0 || length > 4)
                   5032:   return FALSE;
                   5033: 
                   5034: bit = bits[0] & 0x1;
                   5035: if (invert) bit ^= 0x1;
                   5036: 
                   5037: /* No character is accepted. */
                   5038: if (length == 0 && bit == 0)
                   5039:   add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
                   5040: 
                   5041: switch(length)
                   5042:   {
                   5043:   case 0:
                   5044:   /* When bit != 0, all characters are accepted. */
                   5045:   return TRUE;
                   5046: 
                   5047:   case 1:
                   5048:   add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
                   5049:   return TRUE;
                   5050: 
                   5051:   case 2:
                   5052:   if (ranges[0] + 1 != ranges[1])
                   5053:     {
                   5054:     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
                   5055:     add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
                   5056:     }
                   5057:   else
                   5058:     add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
                   5059:   return TRUE;
                   5060: 
                   5061:   case 3:
                   5062:   if (bit != 0)
                   5063:     {
                   5064:     add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));
                   5065:     if (ranges[0] + 1 != ranges[1])
                   5066:       {
                   5067:       OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
                   5068:       add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
                   5069:       }
                   5070:     else
                   5071:       add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
                   5072:     return TRUE;
                   5073:     }
                   5074: 
                   5075:   add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[0]));
                   5076:   if (ranges[1] + 1 != ranges[2])
                   5077:     {
                   5078:     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1]);
                   5079:     add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));
                   5080:     }
                   5081:   else
                   5082:     add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1]));
                   5083:   return TRUE;
                   5084: 
                   5085:   case 4:
                   5086:   if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2])
                   5087:       && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2]
1.4     ! moko     5088:       && (ranges[1] & (ranges[2] - ranges[0])) == 0
1.3       moko     5089:       && is_powerof2(ranges[2] - ranges[0]))
                   5090:     {
1.4     ! moko     5091:     SLJIT_ASSERT((ranges[0] & (ranges[2] - ranges[0])) == 0 && (ranges[2] & ranges[3] & (ranges[2] - ranges[0])) != 0);
1.3       moko     5092:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]);
                   5093:     if (ranges[2] + 1 != ranges[3])
                   5094:       {
                   5095:       OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]);
                   5096:       add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));
                   5097:       }
                   5098:     else
                   5099:       add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));
                   5100:     return TRUE;
                   5101:     }
                   5102: 
                   5103:   if (bit != 0)
                   5104:     {
                   5105:     i = 0;
                   5106:     if (ranges[0] + 1 != ranges[1])
                   5107:       {
                   5108:       OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
                   5109:       add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
                   5110:       i = ranges[0];
                   5111:       }
                   5112:     else
                   5113:       add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
                   5114: 
                   5115:     if (ranges[2] + 1 != ranges[3])
                   5116:       {
                   5117:       OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - i);
                   5118:       add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));
                   5119:       }
                   5120:     else
                   5121:       add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i));
                   5122:     return TRUE;
                   5123:     }
                   5124: 
                   5125:   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
                   5126:   add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0]));
                   5127:   if (ranges[1] + 1 != ranges[2])
                   5128:     {
                   5129:     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]);
                   5130:     add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));
                   5131:     }
                   5132:   else
                   5133:     add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
                   5134:   return TRUE;
                   5135: 
                   5136:   default:
1.4     ! moko     5137:   SLJIT_UNREACHABLE();
1.3       moko     5138:   return FALSE;
                   5139:   }
1.2       misha    5140: }
                   5141: 
1.1       misha    5142: static void check_anynewline(compiler_common *common)
                   5143: {
                   5144: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
                   5145: DEFINE_COMPILER;
                   5146: 
1.2       misha    5147: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1       misha    5148: 
                   5149: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
1.4     ! moko     5150: OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
        !          5151: OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
        !          5152: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
1.2       misha    5153: #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.1       misha    5154: #ifdef COMPILE_PCRE8
                   5155: if (common->utf)
                   5156:   {
                   5157: #endif
1.4     ! moko     5158:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
1.1       misha    5159:   OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
1.4     ! moko     5160:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
1.1       misha    5161: #ifdef COMPILE_PCRE8
                   5162:   }
                   5163: #endif
1.2       misha    5164: #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
1.4     ! moko     5165: OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
1.1       misha    5166: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   5167: }
                   5168: 
                   5169: static void check_hspace(compiler_common *common)
                   5170: {
                   5171: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
                   5172: DEFINE_COMPILER;
                   5173: 
1.2       misha    5174: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1       misha    5175: 
1.4     ! moko     5176: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
        !          5177: OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
        !          5178: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
        !          5179: OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          5180: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
1.2       misha    5181: #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.1       misha    5182: #ifdef COMPILE_PCRE8
                   5183: if (common->utf)
                   5184:   {
                   5185: #endif
1.4     ! moko     5186:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          5187:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
        !          5188:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          5189:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
        !          5190:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
1.1       misha    5191:   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
1.4     ! moko     5192:   OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
        !          5193:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
        !          5194:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
        !          5195:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          5196:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
        !          5197:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          5198:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
1.1       misha    5199: #ifdef COMPILE_PCRE8
                   5200:   }
                   5201: #endif
1.2       misha    5202: #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
1.4     ! moko     5203: OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
1.1       misha    5204: 
                   5205: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
                   5206: }
                   5207: 
                   5208: static void check_vspace(compiler_common *common)
                   5209: {
1.4     ! moko     5210: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
        !          5211: DEFINE_COMPILER;
        !          5212: 
        !          5213: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
        !          5214: 
        !          5215: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
        !          5216: OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
        !          5217: OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
        !          5218: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
        !          5219: #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
        !          5220: #ifdef COMPILE_PCRE8
        !          5221: if (common->utf)
        !          5222:   {
        !          5223: #endif
        !          5224:   OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          5225:   OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
        !          5226:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
        !          5227: #ifdef COMPILE_PCRE8
        !          5228:   }
        !          5229: #endif
        !          5230: #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
        !          5231: OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
        !          5232: 
        !          5233: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
        !          5234: }
        !          5235: 
        !          5236: static void do_casefulcmp(compiler_common *common)
        !          5237: {
        !          5238: DEFINE_COMPILER;
        !          5239: struct sljit_jump *jump;
        !          5240: struct sljit_label *label;
        !          5241: int char1_reg;
        !          5242: int char2_reg;
        !          5243: 
        !          5244: if (sljit_get_register_index(TMP3) < 0)
        !          5245:   {
        !          5246:   char1_reg = STR_END;
        !          5247:   char2_reg = STACK_TOP;
        !          5248:   }
        !          5249: else
        !          5250:   {
        !          5251:   char1_reg = TMP3;
        !          5252:   char2_reg = RETURN_ADDR;
        !          5253:   }
        !          5254: 
        !          5255: sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
        !          5256: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
        !          5257: 
        !          5258: if (char1_reg == STR_END)
        !          5259:   {
        !          5260:   OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0);
        !          5261:   OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0);
        !          5262:   }
        !          5263: 
        !          5264: if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
        !          5265:   {
        !          5266:   label = LABEL();
        !          5267:   sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
        !          5268:   sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
        !          5269:   jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
        !          5270:   OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5271:   JUMPTO(SLJIT_NOT_ZERO, label);
        !          5272: 
        !          5273:   JUMPHERE(jump);
        !          5274:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
        !          5275:   }
        !          5276: else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
        !          5277:   {
        !          5278:   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5279:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5280: 
        !          5281:   label = LABEL();
        !          5282:   sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
        !          5283:   sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
        !          5284:   jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
        !          5285:   OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5286:   JUMPTO(SLJIT_NOT_ZERO, label);
        !          5287: 
        !          5288:   JUMPHERE(jump);
        !          5289:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
        !          5290:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5291:   }
        !          5292: else
        !          5293:   {
        !          5294:   label = LABEL();
        !          5295:   OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);
        !          5296:   OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);
        !          5297:   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5298:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5299:   jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
        !          5300:   OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5301:   JUMPTO(SLJIT_NOT_ZERO, label);
1.1       misha    5302: 
1.4     ! moko     5303:   JUMPHERE(jump);
        !          5304:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
        !          5305:   }
1.1       misha    5306: 
1.4     ! moko     5307: if (char1_reg == STR_END)
1.1       misha    5308:   {
1.4     ! moko     5309:   OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0);
        !          5310:   OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0);
1.1       misha    5311:   }
                   5312: 
1.4     ! moko     5313: sljit_emit_fast_return(compiler, TMP1, 0);
1.1       misha    5314: }
                   5315: 
1.4     ! moko     5316: static void do_caselesscmp(compiler_common *common)
1.1       misha    5317: {
                   5318: DEFINE_COMPILER;
                   5319: struct sljit_jump *jump;
                   5320: struct sljit_label *label;
1.4     ! moko     5321: int char1_reg = STR_END;
        !          5322: int char2_reg;
        !          5323: int lcc_table;
        !          5324: int opt_type = 0;
        !          5325: 
        !          5326: if (sljit_get_register_index(TMP3) < 0)
        !          5327:   {
        !          5328:   char2_reg = STACK_TOP;
        !          5329:   lcc_table = STACK_LIMIT;
        !          5330:   }
        !          5331: else
        !          5332:   {
        !          5333:   char2_reg = RETURN_ADDR;
        !          5334:   lcc_table = TMP3;
        !          5335:   }
1.1       misha    5336: 
1.4     ! moko     5337: if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
        !          5338:   opt_type = 1;
        !          5339: else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
        !          5340:   opt_type = 2;
        !          5341: 
        !          5342: sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
1.1       misha    5343: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
                   5344: 
1.4     ! moko     5345: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0);
1.1       misha    5346: 
1.4     ! moko     5347: if (char2_reg == STACK_TOP)
        !          5348:   {
        !          5349:   OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0);
        !          5350:   OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0);
        !          5351:   }
1.1       misha    5352: 
1.4     ! moko     5353: OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc);
1.1       misha    5354: 
1.4     ! moko     5355: if (opt_type == 1)
        !          5356:   {
        !          5357:   label = LABEL();
        !          5358:   sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
        !          5359:   sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
        !          5360:   }
        !          5361: else if (opt_type == 2)
        !          5362:   {
        !          5363:   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5364:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1       misha    5365: 
1.4     ! moko     5366:   label = LABEL();
        !          5367:   sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
        !          5368:   sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
        !          5369:   }
        !          5370: else
        !          5371:   {
        !          5372:   label = LABEL();
        !          5373:   OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);
        !          5374:   OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);
        !          5375:   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5376:   }
1.1       misha    5377: 
                   5378: #ifndef COMPILE_PCRE8
1.4     ! moko     5379: jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255);
1.1       misha    5380: #endif
1.4     ! moko     5381: OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0);
1.1       misha    5382: #ifndef COMPILE_PCRE8
                   5383: JUMPHERE(jump);
1.4     ! moko     5384: jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255);
1.1       misha    5385: #endif
1.4     ! moko     5386: OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0);
1.1       misha    5387: #ifndef COMPILE_PCRE8
                   5388: JUMPHERE(jump);
                   5389: #endif
1.4     ! moko     5390: 
        !          5391: if (opt_type == 0)
        !          5392:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5393: 
        !          5394: jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
        !          5395: OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
1.3       moko     5396: JUMPTO(SLJIT_NOT_ZERO, label);
1.1       misha    5397: 
                   5398: JUMPHERE(jump);
1.4     ! moko     5399: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
        !          5400: 
        !          5401: if (opt_type == 2)
        !          5402:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          5403: 
        !          5404: if (char2_reg == STACK_TOP)
        !          5405:   {
        !          5406:   OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0);
        !          5407:   OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0);
        !          5408:   }
        !          5409: 
        !          5410: OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
        !          5411: sljit_emit_fast_return(compiler, TMP1, 0);
1.1       misha    5412: }
                   5413: 
                   5414: #if defined SUPPORT_UTF && defined SUPPORT_UCP
                   5415: 
1.4     ! moko     5416: static const pcre_uchar * SLJIT_FUNC do_utf_caselesscmp(pcre_uchar *src1, pcre_uchar *src2, pcre_uchar *end1, pcre_uchar *end2)
1.1       misha    5417: {
                   5418: /* This function would be ineffective to do in JIT level. */
1.4     ! moko     5419: sljit_u32 c1, c2;
1.2       misha    5420: const ucd_record *ur;
1.4     ! moko     5421: const sljit_u32 *pp;
1.1       misha    5422: 
                   5423: while (src1 < end1)
                   5424:   {
                   5425:   if (src2 >= end2)
1.2       misha    5426:     return (pcre_uchar*)1;
1.1       misha    5427:   GETCHARINC(c1, src1);
                   5428:   GETCHARINC(c2, src2);
1.2       misha    5429:   ur = GET_UCD(c2);
                   5430:   if (c1 != c2 && c1 != c2 + ur->other_case)
                   5431:     {
                   5432:     pp = PRIV(ucd_caseless_sets) + ur->caseset;
                   5433:     for (;;)
                   5434:       {
                   5435:       if (c1 < *pp) return NULL;
                   5436:       if (c1 == *pp++) break;
                   5437:       }
                   5438:     }
1.1       misha    5439:   }
                   5440: return src2;
                   5441: }
                   5442: 
                   5443: #endif /* SUPPORT_UTF && SUPPORT_UCP */
                   5444: 
                   5445: static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc,
1.3       moko     5446:     compare_context *context, jump_list **backtracks)
1.1       misha    5447: {
                   5448: DEFINE_COMPILER;
                   5449: unsigned int othercasebit = 0;
                   5450: pcre_uchar *othercasechar = NULL;
                   5451: #ifdef SUPPORT_UTF
                   5452: int utflength;
                   5453: #endif
                   5454: 
                   5455: if (caseless && char_has_othercase(common, cc))
                   5456:   {
                   5457:   othercasebit = char_get_othercase_bit(common, cc);
                   5458:   SLJIT_ASSERT(othercasebit);
                   5459:   /* Extracting bit difference info. */
1.2       misha    5460: #if defined COMPILE_PCRE8
1.1       misha    5461:   othercasechar = cc + (othercasebit >> 8);
                   5462:   othercasebit &= 0xff;
1.2       misha    5463: #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
                   5464:   /* Note that this code only handles characters in the BMP. If there
                   5465:   ever are characters outside the BMP whose othercase differs in only one
                   5466:   bit from itself (there currently are none), this code will need to be
                   5467:   revised for COMPILE_PCRE32. */
1.1       misha    5468:   othercasechar = cc + (othercasebit >> 9);
                   5469:   if ((othercasebit & 0x100) != 0)
                   5470:     othercasebit = (othercasebit & 0xff) << 8;
                   5471:   else
                   5472:     othercasebit &= 0xff;
1.2       misha    5473: #endif /* COMPILE_PCRE[8|16|32] */
1.1       misha    5474:   }
                   5475: 
                   5476: if (context->sourcereg == -1)
                   5477:   {
1.2       misha    5478: #if defined COMPILE_PCRE8
1.1       misha    5479: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
                   5480:   if (context->length >= 4)
1.4     ! moko     5481:     OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1       misha    5482:   else if (context->length >= 2)
1.4     ! moko     5483:     OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1       misha    5484:   else
                   5485: #endif
1.4     ! moko     5486:     OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.2       misha    5487: #elif defined COMPILE_PCRE16
1.1       misha    5488: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
                   5489:   if (context->length >= 4)
1.4     ! moko     5490:     OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1       misha    5491:   else
                   5492: #endif
1.2       misha    5493:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
                   5494: #elif defined COMPILE_PCRE32
                   5495:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
                   5496: #endif /* COMPILE_PCRE[8|16|32] */
1.1       misha    5497:   context->sourcereg = TMP2;
                   5498:   }
                   5499: 
                   5500: #ifdef SUPPORT_UTF
                   5501: utflength = 1;
                   5502: if (common->utf && HAS_EXTRALEN(*cc))
                   5503:   utflength += GET_EXTRALEN(*cc);
                   5504: 
                   5505: do
                   5506:   {
                   5507: #endif
                   5508: 
                   5509:   context->length -= IN_UCHARS(1);
1.2       misha    5510: #if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16)
1.1       misha    5511: 
                   5512:   /* Unaligned read is supported. */
                   5513:   if (othercasebit != 0 && othercasechar == cc)
                   5514:     {
                   5515:     context->c.asuchars[context->ucharptr] = *cc | othercasebit;
                   5516:     context->oc.asuchars[context->ucharptr] = othercasebit;
                   5517:     }
                   5518:   else
                   5519:     {
                   5520:     context->c.asuchars[context->ucharptr] = *cc;
                   5521:     context->oc.asuchars[context->ucharptr] = 0;
                   5522:     }
                   5523:   context->ucharptr++;
                   5524: 
1.2       misha    5525: #if defined COMPILE_PCRE8
1.1       misha    5526:   if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))
                   5527: #else
                   5528:   if (context->ucharptr >= 2 || context->length == 0)
                   5529: #endif
                   5530:     {
                   5531:     if (context->length >= 4)
1.4     ! moko     5532:       OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1       misha    5533:     else if (context->length >= 2)
1.4     ! moko     5534:       OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.2       misha    5535: #if defined COMPILE_PCRE8
1.1       misha    5536:     else if (context->length >= 1)
1.4     ! moko     5537:       OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.2       misha    5538: #endif /* COMPILE_PCRE8 */
1.1       misha    5539:     context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
                   5540: 
                   5541:     switch(context->ucharptr)
                   5542:       {
                   5543:       case 4 / sizeof(pcre_uchar):
                   5544:       if (context->oc.asint != 0)
                   5545:         OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
1.3       moko     5546:       add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
1.1       misha    5547:       break;
                   5548: 
                   5549:       case 2 / sizeof(pcre_uchar):
                   5550:       if (context->oc.asushort != 0)
                   5551:         OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);
1.3       moko     5552:       add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));
1.1       misha    5553:       break;
                   5554: 
                   5555: #ifdef COMPILE_PCRE8
                   5556:       case 1:
                   5557:       if (context->oc.asbyte != 0)
                   5558:         OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
1.3       moko     5559:       add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
1.1       misha    5560:       break;
                   5561: #endif
                   5562: 
                   5563:       default:
1.4     ! moko     5564:       SLJIT_UNREACHABLE();
1.1       misha    5565:       break;
                   5566:       }
                   5567:     context->ucharptr = 0;
                   5568:     }
                   5569: 
                   5570: #else
                   5571: 
1.2       misha    5572:   /* Unaligned read is unsupported or in 32 bit mode. */
                   5573:   if (context->length >= 1)
                   5574:     OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
                   5575: 
1.1       misha    5576:   context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
                   5577: 
                   5578:   if (othercasebit != 0 && othercasechar == cc)
                   5579:     {
                   5580:     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
1.3       moko     5581:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
1.1       misha    5582:     }
                   5583:   else
1.3       moko     5584:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));
1.1       misha    5585: 
                   5586: #endif
                   5587: 
                   5588:   cc++;
                   5589: #ifdef SUPPORT_UTF
                   5590:   utflength--;
                   5591:   }
                   5592: while (utflength > 0);
                   5593: #endif
                   5594: 
                   5595: return cc;
                   5596: }
                   5597: 
                   5598: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
                   5599: 
                   5600: #define SET_TYPE_OFFSET(value) \
                   5601:   if ((value) != typeoffset) \
                   5602:     { \
1.3       moko     5603:     if ((value) < typeoffset) \
                   5604:       OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
                   5605:     else \
1.1       misha    5606:       OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
                   5607:     } \
                   5608:   typeoffset = (value);
                   5609: 
                   5610: #define SET_CHAR_OFFSET(value) \
                   5611:   if ((value) != charoffset) \
                   5612:     { \
1.3       moko     5613:     if ((value) < charoffset) \
                   5614:       OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \
1.1       misha    5615:     else \
1.3       moko     5616:       OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \
1.1       misha    5617:     } \
                   5618:   charoffset = (value);
                   5619: 
1.4     ! moko     5620: static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr);
        !          5621: 
1.2       misha    5622: static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
1.1       misha    5623: {
                   5624: DEFINE_COMPILER;
                   5625: jump_list *found = NULL;
1.3       moko     5626: jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks;
                   5627: sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX;
1.1       misha    5628: struct sljit_jump *jump = NULL;
                   5629: pcre_uchar *ccbegin;
1.2       misha    5630: int compares, invertcmp, numberofcmps;
1.3       moko     5631: #if defined SUPPORT_UTF && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16)
                   5632: BOOL utf = common->utf;
                   5633: #endif
                   5634: 
1.1       misha    5635: #ifdef SUPPORT_UCP
                   5636: BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
                   5637: BOOL charsaved = FALSE;
1.4     ! moko     5638: int typereg = TMP1;
        !          5639: const sljit_u32 *other_cases;
1.3       moko     5640: sljit_uw typeoffset;
1.1       misha    5641: #endif
                   5642: 
1.3       moko     5643: /* Scanning the necessary info. */
                   5644: cc++;
                   5645: ccbegin = cc;
                   5646: compares = 0;
                   5647: if (cc[-1] & XCL_MAP)
1.1       misha    5648:   {
1.3       moko     5649:   min = 0;
1.1       misha    5650:   cc += 32 / sizeof(pcre_uchar);
                   5651:   }
                   5652: 
                   5653: while (*cc != XCL_END)
                   5654:   {
                   5655:   compares++;
                   5656:   if (*cc == XCL_SINGLE)
                   5657:     {
1.3       moko     5658:     cc ++;
                   5659:     GETCHARINCTEST(c, cc);
                   5660:     if (c > max) max = c;
                   5661:     if (c < min) min = c;
1.1       misha    5662: #ifdef SUPPORT_UCP
                   5663:     needschar = TRUE;
                   5664: #endif
                   5665:     }
                   5666:   else if (*cc == XCL_RANGE)
                   5667:     {
1.3       moko     5668:     cc ++;
                   5669:     GETCHARINCTEST(c, cc);
                   5670:     if (c < min) min = c;
                   5671:     GETCHARINCTEST(c, cc);
                   5672:     if (c > max) max = c;
1.1       misha    5673: #ifdef SUPPORT_UCP
                   5674:     needschar = TRUE;
                   5675: #endif
                   5676:     }
                   5677: #ifdef SUPPORT_UCP
                   5678:   else
                   5679:     {
                   5680:     SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
                   5681:     cc++;
1.3       moko     5682:     if (*cc == PT_CLIST)
                   5683:       {
                   5684:       other_cases = PRIV(ucd_caseless_sets) + cc[1];
                   5685:       while (*other_cases != NOTACHAR)
                   5686:         {
                   5687:         if (*other_cases > max) max = *other_cases;
                   5688:         if (*other_cases < min) min = *other_cases;
                   5689:         other_cases++;
                   5690:         }
                   5691:       }
                   5692:     else
                   5693:       {
                   5694:       max = READ_CHAR_MAX;
                   5695:       min = 0;
                   5696:       }
                   5697: 
1.1       misha    5698:     switch(*cc)
                   5699:       {
                   5700:       case PT_ANY:
1.4     ! moko     5701:       /* Any either accepts everything or ignored. */
        !          5702:       if (cc[-1] == XCL_PROP)
        !          5703:         {
        !          5704:         compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE);
        !          5705:         if (list == backtracks)
        !          5706:           add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
        !          5707:         return;
        !          5708:         }
1.1       misha    5709:       break;
                   5710: 
                   5711:       case PT_LAMP:
                   5712:       case PT_GC:
                   5713:       case PT_PC:
                   5714:       case PT_ALNUM:
                   5715:       needstype = TRUE;
                   5716:       break;
                   5717: 
                   5718:       case PT_SC:
                   5719:       needsscript = TRUE;
                   5720:       break;
                   5721: 
                   5722:       case PT_SPACE:
                   5723:       case PT_PXSPACE:
                   5724:       case PT_WORD:
1.3       moko     5725:       case PT_PXGRAPH:
                   5726:       case PT_PXPRINT:
                   5727:       case PT_PXPUNCT:
1.1       misha    5728:       needstype = TRUE;
                   5729:       needschar = TRUE;
                   5730:       break;
                   5731: 
1.2       misha    5732:       case PT_CLIST:
                   5733:       case PT_UCNC:
                   5734:       needschar = TRUE;
                   5735:       break;
                   5736: 
1.1       misha    5737:       default:
1.4     ! moko     5738:       SLJIT_UNREACHABLE();
1.1       misha    5739:       break;
                   5740:       }
                   5741:     cc += 2;
                   5742:     }
                   5743: #endif
                   5744:   }
1.4     ! moko     5745: SLJIT_ASSERT(compares > 0);
1.1       misha    5746: 
1.3       moko     5747: /* We are not necessary in utf mode even in 8 bit mode. */
                   5748: cc = ccbegin;
                   5749: read_char_range(common, min, max, (cc[-1] & XCL_NOT) != 0);
                   5750: 
                   5751: if ((cc[-1] & XCL_HASPROP) == 0)
                   5752:   {
                   5753:   if ((cc[-1] & XCL_MAP) != 0)
                   5754:     {
                   5755:     jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.4     ! moko     5756:     if (!check_class_ranges(common, (const sljit_u8 *)cc, (((const sljit_u8 *)cc)[31] & 0x80) != 0, TRUE, &found))
1.3       moko     5757:       {
                   5758:       OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
                   5759:       OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
1.4     ! moko     5760:       OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
1.3       moko     5761:       OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
1.4     ! moko     5762:       OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
1.3       moko     5763:       add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO));
                   5764:       }
                   5765: 
                   5766:     add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
                   5767:     JUMPHERE(jump);
                   5768: 
                   5769:     cc += 32 / sizeof(pcre_uchar);
                   5770:     }
                   5771:   else
                   5772:     {
                   5773:     OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min);
                   5774:     add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, max - min));
                   5775:     }
                   5776:   }
                   5777: else if ((cc[-1] & XCL_MAP) != 0)
                   5778:   {
1.4     ! moko     5779:   OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
1.3       moko     5780: #ifdef SUPPORT_UCP
                   5781:   charsaved = TRUE;
                   5782: #endif
1.4     ! moko     5783:   if (!check_class_ranges(common, (const sljit_u8 *)cc, FALSE, TRUE, list))
1.3       moko     5784:     {
                   5785: #ifdef COMPILE_PCRE8
1.4     ! moko     5786:     jump = NULL;
        !          5787:     if (common->utf)
1.3       moko     5788: #endif
1.4     ! moko     5789:       jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.3       moko     5790: 
                   5791:     OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
                   5792:     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
1.4     ! moko     5793:     OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
1.3       moko     5794:     OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
1.4     ! moko     5795:     OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
1.3       moko     5796:     add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO));
                   5797: 
1.4     ! moko     5798: #ifdef COMPILE_PCRE8
        !          5799:     if (common->utf)
        !          5800: #endif
        !          5801:       JUMPHERE(jump);
1.3       moko     5802:     }
                   5803: 
1.4     ! moko     5804:   OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
1.3       moko     5805:   cc += 32 / sizeof(pcre_uchar);
                   5806:   }
                   5807: 
1.1       misha    5808: #ifdef SUPPORT_UCP
                   5809: if (needstype || needsscript)
                   5810:   {
                   5811:   if (needschar && !charsaved)
1.4     ! moko     5812:     OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
        !          5813: 
        !          5814: #ifdef COMPILE_PCRE32
        !          5815:   if (!common->utf)
        !          5816:     {
        !          5817:     jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10ffff + 1);
        !          5818:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
        !          5819:     JUMPHERE(jump);
        !          5820:     }
        !          5821: #endif
        !          5822: 
        !          5823:   OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
        !          5824:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
        !          5825:   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
        !          5826:   OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
        !          5827:   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
        !          5828:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
        !          5829:   OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
        !          5830: 
        !          5831:   /* Before anything else, we deal with scripts. */
        !          5832:   if (needsscript)
1.1       misha    5833:     {
1.4     ! moko     5834:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
        !          5835:     OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
        !          5836: 
        !          5837:     ccbegin = cc;
        !          5838: 
        !          5839:     while (*cc != XCL_END)
1.1       misha    5840:       {
1.4     ! moko     5841:       if (*cc == XCL_SINGLE)
        !          5842:         {
        !          5843:         cc ++;
        !          5844:         GETCHARINCTEST(c, cc);
        !          5845:         }
        !          5846:       else if (*cc == XCL_RANGE)
        !          5847:         {
        !          5848:         cc ++;
        !          5849:         GETCHARINCTEST(c, cc);
        !          5850:         GETCHARINCTEST(c, cc);
        !          5851:         }
        !          5852:       else
        !          5853:         {
        !          5854:         SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
        !          5855:         cc++;
        !          5856:         if (*cc == PT_SC)
        !          5857:           {
        !          5858:           compares--;
        !          5859:           invertcmp = (compares == 0 && list != backtracks);
        !          5860:           if (cc[-1] == XCL_NOTPROP)
        !          5861:             invertcmp ^= 0x1;
        !          5862:           jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]);
        !          5863:           add_jump(compiler, compares > 0 ? list : backtracks, jump);
        !          5864:           }
        !          5865:         cc += 2;
        !          5866:         }
1.1       misha    5867:       }
                   5868: 
1.4     ! moko     5869:     cc = ccbegin;
        !          5870:     }
        !          5871: 
        !          5872:   if (needschar)
        !          5873:     {
        !          5874:     OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
        !          5875:     }
1.1       misha    5876: 
1.4     ! moko     5877:   if (needstype)
1.1       misha    5878:     {
1.4     ! moko     5879:     if (!needschar)
1.1       misha    5880:       {
1.4     ! moko     5881:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
        !          5882:       OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1.1       misha    5883:       }
                   5884:     else
                   5885:       {
                   5886:       OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
1.4     ! moko     5887:       OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
        !          5888:       typereg = RETURN_ADDR;
1.1       misha    5889:       }
                   5890:     }
                   5891:   }
                   5892: #endif
                   5893: 
                   5894: /* Generating code. */
                   5895: charoffset = 0;
                   5896: numberofcmps = 0;
                   5897: #ifdef SUPPORT_UCP
                   5898: typeoffset = 0;
                   5899: #endif
                   5900: 
                   5901: while (*cc != XCL_END)
                   5902:   {
                   5903:   compares--;
1.2       misha    5904:   invertcmp = (compares == 0 && list != backtracks);
1.1       misha    5905:   jump = NULL;
                   5906: 
                   5907:   if (*cc == XCL_SINGLE)
                   5908:     {
                   5909:     cc ++;
1.3       moko     5910:     GETCHARINCTEST(c, cc);
1.1       misha    5911: 
                   5912:     if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
                   5913:       {
1.4     ! moko     5914:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
        !          5915:       OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
1.1       misha    5916:       numberofcmps++;
                   5917:       }
                   5918:     else if (numberofcmps > 0)
                   5919:       {
1.4     ! moko     5920:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
        !          5921:       OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
1.3       moko     5922:       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
1.1       misha    5923:       numberofcmps = 0;
                   5924:       }
                   5925:     else
                   5926:       {
1.3       moko     5927:       jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
1.1       misha    5928:       numberofcmps = 0;
                   5929:       }
                   5930:     }
                   5931:   else if (*cc == XCL_RANGE)
                   5932:     {
                   5933:     cc ++;
1.3       moko     5934:     GETCHARINCTEST(c, cc);
1.1       misha    5935:     SET_CHAR_OFFSET(c);
1.3       moko     5936:     GETCHARINCTEST(c, cc);
                   5937: 
1.1       misha    5938:     if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
                   5939:       {
1.4     ! moko     5940:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
        !          5941:       OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
1.1       misha    5942:       numberofcmps++;
                   5943:       }
                   5944:     else if (numberofcmps > 0)
                   5945:       {
1.4     ! moko     5946:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
        !          5947:       OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
1.3       moko     5948:       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
1.1       misha    5949:       numberofcmps = 0;
                   5950:       }
                   5951:     else
                   5952:       {
1.3       moko     5953:       jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
1.1       misha    5954:       numberofcmps = 0;
                   5955:       }
                   5956:     }
                   5957: #ifdef SUPPORT_UCP
                   5958:   else
                   5959:     {
1.4     ! moko     5960:     SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
1.1       misha    5961:     if (*cc == XCL_NOTPROP)
                   5962:       invertcmp ^= 0x1;
                   5963:     cc++;
                   5964:     switch(*cc)
                   5965:       {
                   5966:       case PT_ANY:
1.4     ! moko     5967:       if (!invertcmp)
        !          5968:         jump = JUMP(SLJIT_JUMP);
1.1       misha    5969:       break;
                   5970: 
                   5971:       case PT_LAMP:
1.4     ! moko     5972:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
        !          5973:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
        !          5974:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
        !          5975:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          5976:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
        !          5977:       OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
1.3       moko     5978:       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
1.1       misha    5979:       break;
                   5980: 
                   5981:       case PT_GC:
                   5982:       c = PRIV(ucp_typerange)[(int)cc[1] * 2];
                   5983:       SET_TYPE_OFFSET(c);
1.3       moko     5984:       jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c);
1.1       misha    5985:       break;
                   5986: 
                   5987:       case PT_PC:
1.3       moko     5988:       jump = CMP(SLJIT_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);
1.1       misha    5989:       break;
                   5990: 
                   5991:       case PT_SC:
1.4     ! moko     5992:       compares++;
        !          5993:       /* Do nothing. */
1.1       misha    5994:       break;
                   5995: 
                   5996:       case PT_SPACE:
                   5997:       case PT_PXSPACE:
                   5998:       SET_CHAR_OFFSET(9);
1.4     ! moko     5999:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
        !          6000:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
1.3       moko     6001: 
1.4     ! moko     6002:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
        !          6003:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
1.3       moko     6004: 
1.4     ! moko     6005:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
        !          6006:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
1.1       misha    6007: 
                   6008:       SET_TYPE_OFFSET(ucp_Zl);
1.4     ! moko     6009:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
        !          6010:       OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
1.3       moko     6011:       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
1.1       misha    6012:       break;
                   6013: 
                   6014:       case PT_WORD:
1.4     ! moko     6015:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
        !          6016:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
1.2       misha    6017:       /* Fall through. */
1.1       misha    6018: 
                   6019:       case PT_ALNUM:
                   6020:       SET_TYPE_OFFSET(ucp_Ll);
1.4     ! moko     6021:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
        !          6022:       OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
1.1       misha    6023:       SET_TYPE_OFFSET(ucp_Nd);
1.4     ! moko     6024:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
        !          6025:       OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
1.3       moko     6026:       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
1.2       misha    6027:       break;
                   6028: 
                   6029:       case PT_CLIST:
                   6030:       other_cases = PRIV(ucd_caseless_sets) + cc[1];
                   6031: 
                   6032:       /* At least three characters are required.
                   6033:          Otherwise this case would be handled by the normal code path. */
                   6034:       SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR && other_cases[2] != NOTACHAR);
                   6035:       SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]);
                   6036: 
                   6037:       /* Optimizing character pairs, if their difference is power of 2. */
                   6038:       if (is_powerof2(other_cases[1] ^ other_cases[0]))
                   6039:         {
                   6040:         if (charoffset == 0)
                   6041:           OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
                   6042:         else
                   6043:           {
                   6044:           OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
                   6045:           OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
                   6046:           }
1.4     ! moko     6047:         OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]);
        !          6048:         OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
1.2       misha    6049:         other_cases += 2;
                   6050:         }
                   6051:       else if (is_powerof2(other_cases[2] ^ other_cases[1]))
                   6052:         {
                   6053:         if (charoffset == 0)
                   6054:           OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[2] ^ other_cases[1]);
                   6055:         else
                   6056:           {
                   6057:           OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
                   6058:           OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
                   6059:           }
1.4     ! moko     6060:         OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);
        !          6061:         OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
1.2       misha    6062: 
1.4     ! moko     6063:         OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
        !          6064:         OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);
1.2       misha    6065: 
                   6066:         other_cases += 3;
                   6067:         }
                   6068:       else
                   6069:         {
1.4     ! moko     6070:         OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
        !          6071:         OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
1.2       misha    6072:         }
                   6073: 
                   6074:       while (*other_cases != NOTACHAR)
                   6075:         {
1.4     ! moko     6076:         OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
        !          6077:         OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);
1.2       misha    6078:         }
1.3       moko     6079:       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
1.2       misha    6080:       break;
                   6081: 
                   6082:       case PT_UCNC:
1.4     ! moko     6083:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
        !          6084:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
        !          6085:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
        !          6086:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          6087:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
        !          6088:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
1.2       misha    6089: 
                   6090:       SET_CHAR_OFFSET(0xa0);
1.4     ! moko     6091:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
        !          6092:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
1.2       misha    6093:       SET_CHAR_OFFSET(0);
1.4     ! moko     6094:       OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
        !          6095:       OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL);
1.3       moko     6096:       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
                   6097:       break;
                   6098: 
                   6099:       case PT_PXGRAPH:
                   6100:       /* C and Z groups are the farthest two groups. */
                   6101:       SET_TYPE_OFFSET(ucp_Ll);
1.4     ! moko     6102:       OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
        !          6103:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);
1.3       moko     6104: 
                   6105:       jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
                   6106: 
                   6107:       /* In case of ucp_Cf, we overwrite the result. */
                   6108:       SET_CHAR_OFFSET(0x2066);
1.4     ! moko     6109:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
        !          6110:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
        !          6111: 
        !          6112:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
        !          6113:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          6114: 
        !          6115:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);
        !          6116:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
        !          6117: 
        !          6118:       JUMPHERE(jump);
        !          6119:       jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
        !          6120:       break;
        !          6121: 
        !          6122:       case PT_PXPRINT:
        !          6123:       /* C and Z groups are the farthest two groups. */
        !          6124:       SET_TYPE_OFFSET(ucp_Ll);
        !          6125:       OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
        !          6126:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);
        !          6127: 
        !          6128:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);
        !          6129:       OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_NOT_EQUAL);
        !          6130: 
        !          6131:       jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
1.3       moko     6132: 
1.4     ! moko     6133:       /* In case of ucp_Cf, we overwrite the result. */
        !          6134:       SET_CHAR_OFFSET(0x2066);
        !          6135:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
        !          6136:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
1.3       moko     6137: 
1.4     ! moko     6138:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
        !          6139:       OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
1.3       moko     6140: 
                   6141:       JUMPHERE(jump);
1.4     ! moko     6142:       jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
        !          6143:       break;
        !          6144: 
        !          6145:       case PT_PXPUNCT:
        !          6146:       SET_TYPE_OFFSET(ucp_Sc);
        !          6147:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);
        !          6148:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
        !          6149: 
        !          6150:       SET_CHAR_OFFSET(0);
        !          6151:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f);
        !          6152:       OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL);
        !          6153: 
        !          6154:       SET_TYPE_OFFSET(ucp_Pc);
        !          6155:       OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);
        !          6156:       OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
        !          6157:       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
        !          6158:       break;
        !          6159: 
        !          6160:       default:
        !          6161:       SLJIT_UNREACHABLE();
        !          6162:       break;
        !          6163:       }
        !          6164:     cc += 2;
        !          6165:     }
        !          6166: #endif
        !          6167: 
        !          6168:   if (jump != NULL)
        !          6169:     add_jump(compiler, compares > 0 ? list : backtracks, jump);
        !          6170:   }
        !          6171: 
        !          6172: if (found != NULL)
        !          6173:   set_jumps(found, LABEL());
        !          6174: }
        !          6175: 
        !          6176: #undef SET_TYPE_OFFSET
        !          6177: #undef SET_CHAR_OFFSET
        !          6178: 
        !          6179: #endif
        !          6180: 
        !          6181: static pcre_uchar *compile_simple_assertion_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks)
        !          6182: {
        !          6183: DEFINE_COMPILER;
        !          6184: int length;
        !          6185: struct sljit_jump *jump[4];
        !          6186: #ifdef SUPPORT_UTF
        !          6187: struct sljit_label *label;
        !          6188: #endif /* SUPPORT_UTF */
        !          6189: 
        !          6190: switch(type)
        !          6191:   {
        !          6192:   case OP_SOD:
        !          6193:   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
        !          6194:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
        !          6195:   add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
        !          6196:   return cc;
        !          6197: 
        !          6198:   case OP_SOM:
        !          6199:   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
        !          6200:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
        !          6201:   add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
        !          6202:   return cc;
        !          6203: 
        !          6204:   case OP_NOT_WORD_BOUNDARY:
        !          6205:   case OP_WORD_BOUNDARY:
        !          6206:   add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
        !          6207:   sljit_set_current_flags(compiler, SLJIT_SET_Z);
        !          6208:   add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO));
        !          6209:   return cc;
        !          6210: 
        !          6211:   case OP_EODN:
        !          6212:   /* Requires rather complex checks. */
        !          6213:   jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
        !          6214:   if (common->nltype == NLTYPE_FIXED && common->newline > 255)
        !          6215:     {
        !          6216:     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
        !          6217:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
        !          6218:     if (common->mode == JIT_COMPILE)
        !          6219:       add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));
        !          6220:     else
        !          6221:       {
        !          6222:       jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0);
        !          6223:       OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
        !          6224:       OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);
        !          6225:       OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
        !          6226:       OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL);
        !          6227:       add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL));
        !          6228:       check_partial(common, TRUE);
        !          6229:       add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
        !          6230:       JUMPHERE(jump[1]);
        !          6231:       }
        !          6232:     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
        !          6233:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
        !          6234:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
        !          6235:     }
        !          6236:   else if (common->nltype == NLTYPE_FIXED)
        !          6237:     {
        !          6238:     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          6239:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
        !          6240:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));
        !          6241:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
        !          6242:     }
        !          6243:   else
        !          6244:     {
        !          6245:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
        !          6246:     jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
        !          6247:     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
        !          6248:     OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
        !          6249:     jump[2] = JUMP(SLJIT_GREATER);
        !          6250:     add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */);
        !          6251:     /* Equal. */
        !          6252:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
        !          6253:     jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
        !          6254:     add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
        !          6255: 
        !          6256:     JUMPHERE(jump[1]);
        !          6257:     if (common->nltype == NLTYPE_ANYCRLF)
        !          6258:       {
        !          6259:       OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          6260:       add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, STR_END, 0));
        !          6261:       add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
        !          6262:       }
        !          6263:     else
        !          6264:       {
        !          6265:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0);
        !          6266:       read_char_range(common, common->nlmin, common->nlmax, TRUE);
        !          6267:       add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
        !          6268:       add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
        !          6269:       sljit_set_current_flags(compiler, SLJIT_SET_Z);
        !          6270:       add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
        !          6271:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
        !          6272:       }
        !          6273:     JUMPHERE(jump[2]);
        !          6274:     JUMPHERE(jump[3]);
        !          6275:     }
        !          6276:   JUMPHERE(jump[0]);
        !          6277:   check_partial(common, FALSE);
        !          6278:   return cc;
        !          6279: 
        !          6280:   case OP_EOD:
        !          6281:   add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));
        !          6282:   check_partial(common, FALSE);
        !          6283:   return cc;
1.3       moko     6284: 
1.4     ! moko     6285:   case OP_DOLL:
        !          6286:   OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
        !          6287:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
        !          6288:   add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.3       moko     6289: 
1.4     ! moko     6290:   if (!common->endonly)
        !          6291:     compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks);
        !          6292:   else
        !          6293:     {
        !          6294:     add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));
        !          6295:     check_partial(common, FALSE);
        !          6296:     }
        !          6297:   return cc;
1.3       moko     6298: 
1.4     ! moko     6299:   case OP_DOLLM:
        !          6300:   jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
        !          6301:   OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
        !          6302:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
        !          6303:   add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
        !          6304:   check_partial(common, FALSE);
        !          6305:   jump[0] = JUMP(SLJIT_JUMP);
        !          6306:   JUMPHERE(jump[1]);
1.3       moko     6307: 
1.4     ! moko     6308:   if (common->nltype == NLTYPE_FIXED && common->newline > 255)
        !          6309:     {
        !          6310:     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
        !          6311:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
        !          6312:     if (common->mode == JIT_COMPILE)
        !          6313:       add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0));
        !          6314:     else
        !          6315:       {
        !          6316:       jump[1] = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);
        !          6317:       /* STR_PTR = STR_END - IN_UCHARS(1) */
        !          6318:       add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
        !          6319:       check_partial(common, TRUE);
        !          6320:       add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
        !          6321:       JUMPHERE(jump[1]);
        !          6322:       }
1.3       moko     6323: 
1.4     ! moko     6324:     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
        !          6325:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
        !          6326:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
        !          6327:     }
        !          6328:   else
        !          6329:     {
        !          6330:     peek_char(common, common->nlmax);
        !          6331:     check_newlinechar(common, common->nltype, backtracks, FALSE);
        !          6332:     }
        !          6333:   JUMPHERE(jump[0]);
        !          6334:   return cc;
1.3       moko     6335: 
1.4     ! moko     6336:   case OP_CIRC:
        !          6337:   OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
        !          6338:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
        !          6339:   add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
        !          6340:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
        !          6341:   add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
        !          6342:   return cc;
1.3       moko     6343: 
1.4     ! moko     6344:   case OP_CIRCM:
        !          6345:   OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
        !          6346:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
        !          6347:   jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0);
        !          6348:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
        !          6349:   add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
        !          6350:   jump[0] = JUMP(SLJIT_JUMP);
        !          6351:   JUMPHERE(jump[1]);
1.3       moko     6352: 
1.4     ! moko     6353:   add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
        !          6354:   if (common->nltype == NLTYPE_FIXED && common->newline > 255)
        !          6355:     {
        !          6356:     OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
        !          6357:     add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, TMP1, 0));
        !          6358:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
        !          6359:     OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
        !          6360:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
        !          6361:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
        !          6362:     }
        !          6363:   else
        !          6364:     {
        !          6365:     skip_char_back(common);
        !          6366:     read_char_range(common, common->nlmin, common->nlmax, TRUE);
        !          6367:     check_newlinechar(common, common->nltype, backtracks, FALSE);
        !          6368:     }
        !          6369:   JUMPHERE(jump[0]);
        !          6370:   return cc;
1.3       moko     6371: 
1.4     ! moko     6372:   case OP_REVERSE:
        !          6373:   length = GET(cc, 0);
        !          6374:   if (length == 0)
        !          6375:     return cc + LINK_SIZE;
        !          6376:   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
        !          6377: #ifdef SUPPORT_UTF
        !          6378:   if (common->utf)
        !          6379:     {
        !          6380:     OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
        !          6381:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
        !          6382:     label = LABEL();
        !          6383:     add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
        !          6384:     skip_char_back(common);
        !          6385:     OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
        !          6386:     JUMPTO(SLJIT_NOT_ZERO, label);
1.1       misha    6387:     }
1.4     ! moko     6388:   else
1.1       misha    6389: #endif
1.4     ! moko     6390:     {
        !          6391:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
        !          6392:     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
        !          6393:     add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0));
        !          6394:     }
        !          6395:   check_start_used_ptr(common);
        !          6396:   return cc + LINK_SIZE;
1.1       misha    6397:   }
1.4     ! moko     6398: SLJIT_UNREACHABLE();
        !          6399: return cc;
1.1       misha    6400: }
                   6401: 
1.4     ! moko     6402: static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr)
1.1       misha    6403: {
                   6404: DEFINE_COMPILER;
                   6405: int length;
                   6406: unsigned int c, oc, bit;
                   6407: compare_context context;
1.4     ! moko     6408: struct sljit_jump *jump[3];
1.2       misha    6409: jump_list *end_list;
1.1       misha    6410: #ifdef SUPPORT_UTF
                   6411: struct sljit_label *label;
                   6412: #ifdef SUPPORT_UCP
                   6413: pcre_uchar propdata[5];
                   6414: #endif
1.3       moko     6415: #endif /* SUPPORT_UTF */
1.1       misha    6416: 
                   6417: switch(type)
                   6418:   {
                   6419:   case OP_NOT_DIGIT:
                   6420:   case OP_DIGIT:
1.2       misha    6421:   /* Digits are usually 0-9, so it is worth to optimize them. */
1.4     ! moko     6422:   if (check_str_ptr)
        !          6423:     detect_partial_match(common, backtracks);
1.3       moko     6424: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.4     ! moko     6425:   if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
1.3       moko     6426:     read_char7_type(common, type == OP_NOT_DIGIT);
                   6427:   else
                   6428: #endif
                   6429:     read_char8_type(common, type == OP_NOT_DIGIT);
                   6430:     /* Flip the starting bit in the negative case. */
1.4     ! moko     6431:   OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
1.3       moko     6432:   add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO));
1.1       misha    6433:   return cc;
                   6434: 
                   6435:   case OP_NOT_WHITESPACE:
                   6436:   case OP_WHITESPACE:
1.4     ! moko     6437:   if (check_str_ptr)
        !          6438:     detect_partial_match(common, backtracks);
1.3       moko     6439: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.4     ! moko     6440:   if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))
1.3       moko     6441:     read_char7_type(common, type == OP_NOT_WHITESPACE);
                   6442:   else
                   6443: #endif
                   6444:     read_char8_type(common, type == OP_NOT_WHITESPACE);
1.4     ! moko     6445:   OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
1.3       moko     6446:   add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO));
1.1       misha    6447:   return cc;
                   6448: 
                   6449:   case OP_NOT_WORDCHAR:
                   6450:   case OP_WORDCHAR:
1.4     ! moko     6451:   if (check_str_ptr)
        !          6452:     detect_partial_match(common, backtracks);
1.3       moko     6453: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.4     ! moko     6454:   if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))
1.3       moko     6455:     read_char7_type(common, type == OP_NOT_WORDCHAR);
                   6456:   else
                   6457: #endif
                   6458:     read_char8_type(common, type == OP_NOT_WORDCHAR);
1.4     ! moko     6459:   OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
1.3       moko     6460:   add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO));
1.1       misha    6461:   return cc;
                   6462: 
                   6463:   case OP_ANY:
1.4     ! moko     6464:   if (check_str_ptr)
        !          6465:     detect_partial_match(common, backtracks);
1.3       moko     6466:   read_char_range(common, common->nlmin, common->nlmax, TRUE);
1.1       misha    6467:   if (common->nltype == NLTYPE_FIXED && common->newline > 255)
                   6468:     {
1.3       moko     6469:     jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
1.2       misha    6470:     end_list = NULL;
                   6471:     if (common->mode != JIT_PARTIAL_HARD_COMPILE)
1.3       moko     6472:       add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1.2       misha    6473:     else
                   6474:       check_str_end(common, &end_list);
                   6475: 
1.1       misha    6476:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.3       moko     6477:     add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
1.2       misha    6478:     set_jumps(end_list, LABEL());
1.1       misha    6479:     JUMPHERE(jump[0]);
                   6480:     }
                   6481:   else
1.2       misha    6482:     check_newlinechar(common, common->nltype, backtracks, TRUE);
1.1       misha    6483:   return cc;
                   6484: 
                   6485:   case OP_ALLANY:
1.4     ! moko     6486:   if (check_str_ptr)
        !          6487:     detect_partial_match(common, backtracks);
1.1       misha    6488: #ifdef SUPPORT_UTF
                   6489:   if (common->utf)
                   6490:     {
                   6491:     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
                   6492:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.2       misha    6493: #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
                   6494: #if defined COMPILE_PCRE8
1.3       moko     6495:     jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.4     ! moko     6496:     OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.1       misha    6497:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1.2       misha    6498: #elif defined COMPILE_PCRE16
1.3       moko     6499:     jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
1.1       misha    6500:     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
1.4     ! moko     6501:     OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
        !          6502:     OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
1.1       misha    6503:     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
                   6504:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1.2       misha    6505: #endif
1.1       misha    6506:     JUMPHERE(jump[0]);
1.2       misha    6507: #endif /* COMPILE_PCRE[8|16] */
1.1       misha    6508:     return cc;
                   6509:     }
                   6510: #endif
                   6511:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   6512:   return cc;
                   6513: 
                   6514:   case OP_ANYBYTE:
1.4     ! moko     6515:   if (check_str_ptr)
        !          6516:     detect_partial_match(common, backtracks);
1.1       misha    6517:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
                   6518:   return cc;
                   6519: 
                   6520: #ifdef SUPPORT_UTF
                   6521: #ifdef SUPPORT_UCP
                   6522:   case OP_NOTPROP:
                   6523:   case OP_PROP:
1.3       moko     6524:   propdata[0] = XCL_HASPROP;
1.1       misha    6525:   propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
                   6526:   propdata[2] = cc[0];
                   6527:   propdata[3] = cc[1];
                   6528:   propdata[4] = XCL_END;
1.4     ! moko     6529:   if (check_str_ptr)
        !          6530:     detect_partial_match(common, backtracks);
1.2       misha    6531:   compile_xclass_matchingpath(common, propdata, backtracks);
1.1       misha    6532:   return cc + 2;
                   6533: #endif
                   6534: #endif
                   6535: 
                   6536:   case OP_ANYNL:
1.4     ! moko     6537:   if (check_str_ptr)
        !          6538:     detect_partial_match(common, backtracks);
1.3       moko     6539:   read_char_range(common, common->bsr_nlmin, common->bsr_nlmax, FALSE);
                   6540:   jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1.2       misha    6541:   /* We don't need to handle soft partial matching case. */
                   6542:   end_list = NULL;
                   6543:   if (common->mode != JIT_PARTIAL_HARD_COMPILE)
1.3       moko     6544:     add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1.2       misha    6545:   else
                   6546:     check_str_end(common, &end_list);
1.1       misha    6547:   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.3       moko     6548:   jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
1.1       misha    6549:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.2       misha    6550:   jump[2] = JUMP(SLJIT_JUMP);
1.1       misha    6551:   JUMPHERE(jump[0]);
1.2       misha    6552:   check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);
                   6553:   set_jumps(end_list, LABEL());
1.1       misha    6554:   JUMPHERE(jump[1]);
                   6555:   JUMPHERE(jump[2]);
                   6556:   return cc;
                   6557: 
1.4     ! moko     6558:   case OP_NOT_HSPACE:
        !          6559:   case OP_HSPACE:
        !          6560:   if (check_str_ptr)
        !          6561:     detect_partial_match(common, backtracks);
        !          6562:   read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE);
        !          6563:   add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
        !          6564:   sljit_set_current_flags(compiler, SLJIT_SET_Z);
        !          6565:   add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
1.1       misha    6566:   return cc;
                   6567: 
1.4     ! moko     6568:   case OP_NOT_VSPACE:
        !          6569:   case OP_VSPACE:
        !          6570:   if (check_str_ptr)
        !          6571:     detect_partial_match(common, backtracks);
        !          6572:   read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE);
        !          6573:   add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
        !          6574:   sljit_set_current_flags(compiler, SLJIT_SET_Z);
        !          6575:   add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
1.1       misha    6576:   return cc;
                   6577: 
1.4     ! moko     6578: #ifdef SUPPORT_UCP
        !          6579:   case OP_EXTUNI:
        !          6580:   if (check_str_ptr)
        !          6581:     detect_partial_match(common, backtracks);
        !          6582:   read_char(common);
        !          6583:   add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
        !          6584:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
        !          6585:   /* Optimize register allocation: use a real register. */
        !          6586:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
        !          6587:   OP1(SLJIT_MOV_U8, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1.1       misha    6588: 
1.4     ! moko     6589:   label = LABEL();
        !          6590:   jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
        !          6591:   OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
        !          6592:   read_char(common);
        !          6593:   add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
        !          6594:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
        !          6595:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1.1       misha    6596: 
1.4     ! moko     6597:   OP2(SLJIT_SHL, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2);
        !          6598:   OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable));
        !          6599:   OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0);
        !          6600:   OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
        !          6601:   OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
        !          6602:   JUMPTO(SLJIT_NOT_ZERO, label);
1.1       misha    6603: 
1.4     ! moko     6604:   OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
        !          6605:   JUMPHERE(jump[0]);
        !          6606:   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
1.1       misha    6607: 
1.4     ! moko     6608:   if (common->mode == JIT_PARTIAL_HARD_COMPILE)
1.1       misha    6609:     {
1.4     ! moko     6610:     jump[0] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
        !          6611:     /* Since we successfully read a char above, partial matching must occure. */
        !          6612:     check_partial(common, TRUE);
        !          6613:     JUMPHERE(jump[0]);
1.1       misha    6614:     }
                   6615:   return cc;
1.4     ! moko     6616: #endif
1.1       misha    6617: 
                   6618:   case OP_CHAR:
                   6619:   case OP_CHARI:
                   6620:   length = 1;
                   6621: #ifdef SUPPORT_UTF
                   6622:   if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
                   6623: #endif
1.4     ! moko     6624:   if (common->mode == JIT_COMPILE && check_str_ptr
        !          6625:       && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0))
1.1       misha    6626:     {
                   6627:     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
1.3       moko     6628:     add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));
1.1       misha    6629: 
                   6630:     context.length = IN_UCHARS(length);
                   6631:     context.sourcereg = -1;
                   6632: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
                   6633:     context.ucharptr = 0;
                   6634: #endif
1.2       misha    6635:     return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);
1.1       misha    6636:     }
1.3       moko     6637: 
1.4     ! moko     6638:   if (check_str_ptr)
        !          6639:     detect_partial_match(common, backtracks);
1.1       misha    6640: #ifdef SUPPORT_UTF
                   6641:   if (common->utf)
                   6642:     {
                   6643:     GETCHAR(c, cc);
                   6644:     }
                   6645:   else
                   6646: #endif
                   6647:     c = *cc;
1.3       moko     6648: 
1.2       misha    6649:   if (type == OP_CHAR || !char_has_othercase(common, cc))
                   6650:     {
1.3       moko     6651:     read_char_range(common, c, c, FALSE);
                   6652:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));
1.2       misha    6653:     return cc + length;
                   6654:     }
                   6655:   oc = char_othercase(common, c);
1.3       moko     6656:   read_char_range(common, c < oc ? c : oc, c > oc ? c : oc, FALSE);
1.2       misha    6657:   bit = c ^ oc;
                   6658:   if (is_powerof2(bit))
                   6659:     {
                   6660:     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
1.3       moko     6661:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
1.2       misha    6662:     return cc + length;
                   6663:     }
1.3       moko     6664:   jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c);
                   6665:   add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc));
                   6666:   JUMPHERE(jump[0]);
1.1       misha    6667:   return cc + length;
                   6668: 
                   6669:   case OP_NOT:
                   6670:   case OP_NOTI:
1.4     ! moko     6671:   if (check_str_ptr)
        !          6672:     detect_partial_match(common, backtracks);
1.1       misha    6673:   length = 1;
                   6674: #ifdef SUPPORT_UTF
                   6675:   if (common->utf)
                   6676:     {
                   6677: #ifdef COMPILE_PCRE8
                   6678:     c = *cc;
                   6679:     if (c < 128)
                   6680:       {
1.4     ! moko     6681:       OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1       misha    6682:       if (type == OP_NOT || !char_has_othercase(common, cc))
1.3       moko     6683:         add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));
1.1       misha    6684:       else
                   6685:         {
                   6686:         /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
                   6687:         OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);
1.3       moko     6688:         add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));
1.1       misha    6689:         }
                   6690:       /* Skip the variable-length character. */
                   6691:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.3       moko     6692:       jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.2       misha    6693:       OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
1.1       misha    6694:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
                   6695:       JUMPHERE(jump[0]);
                   6696:       return cc + 1;
                   6697:       }
                   6698:     else
                   6699: #endif /* COMPILE_PCRE8 */
                   6700:       {
                   6701:       GETCHARLEN(c, cc, length);
                   6702:       }
                   6703:     }
                   6704:   else
                   6705: #endif /* SUPPORT_UTF */
                   6706:     c = *cc;
                   6707: 
                   6708:   if (type == OP_NOT || !char_has_othercase(common, cc))
1.3       moko     6709:     {
                   6710:     read_char_range(common, c, c, TRUE);
                   6711:     add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));
                   6712:     }
1.1       misha    6713:   else
                   6714:     {
                   6715:     oc = char_othercase(common, c);
1.3       moko     6716:     read_char_range(common, c < oc ? c : oc, c > oc ? c : oc, TRUE);
1.1       misha    6717:     bit = c ^ oc;
1.2       misha    6718:     if (is_powerof2(bit))
1.1       misha    6719:       {
                   6720:       OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
1.3       moko     6721:       add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
1.1       misha    6722:       }
                   6723:     else
                   6724:       {
1.3       moko     6725:       add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));
                   6726:       add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, oc));
1.1       misha    6727:       }
                   6728:     }
1.2       misha    6729:   return cc + length;
1.1       misha    6730: 
                   6731:   case OP_CLASS:
                   6732:   case OP_NCLASS:
1.4     ! moko     6733:   if (check_str_ptr)
        !          6734:     detect_partial_match(common, backtracks);
1.3       moko     6735: 
                   6736: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.4     ! moko     6737:   bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255;
1.3       moko     6738:   read_char_range(common, 0, bit, type == OP_NCLASS);
                   6739: #else
                   6740:   read_char_range(common, 0, 255, type == OP_NCLASS);
                   6741: #endif
                   6742: 
1.4     ! moko     6743:   if (check_class_ranges(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks))
1.2       misha    6744:     return cc + 32 / sizeof(pcre_uchar);
                   6745: 
1.3       moko     6746: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.1       misha    6747:   jump[0] = NULL;
                   6748:   if (common->utf)
                   6749:     {
1.3       moko     6750:     jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, bit);
1.1       misha    6751:     if (type == OP_CLASS)
                   6752:       {
1.2       misha    6753:       add_jump(compiler, backtracks, jump[0]);
1.1       misha    6754:       jump[0] = NULL;
                   6755:       }
                   6756:     }
1.3       moko     6757: #elif !defined COMPILE_PCRE8
                   6758:   jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
                   6759:   if (type == OP_CLASS)
                   6760:     {
                   6761:     add_jump(compiler, backtracks, jump[0]);
                   6762:     jump[0] = NULL;
                   6763:     }
                   6764: #endif /* SUPPORT_UTF && COMPILE_PCRE8 */
                   6765: 
1.1       misha    6766:   OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
                   6767:   OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
1.4     ! moko     6768:   OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
1.1       misha    6769:   OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
1.4     ! moko     6770:   OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
1.3       moko     6771:   add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
                   6772: 
1.1       misha    6773: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
                   6774:   if (jump[0] != NULL)
                   6775:     JUMPHERE(jump[0]);
1.3       moko     6776: #endif
1.1       misha    6777:   return cc + 32 / sizeof(pcre_uchar);
                   6778: 
1.2       misha    6779: #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.1       misha    6780:   case OP_XCLASS:
1.4     ! moko     6781:   if (check_str_ptr)
        !          6782:     detect_partial_match(common, backtracks);
1.2       misha    6783:   compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks);
1.1       misha    6784:   return cc + GET(cc, 0) - 1;
                   6785: #endif
                   6786:   }
1.4     ! moko     6787: SLJIT_UNREACHABLE();
1.1       misha    6788: return cc;
                   6789: }
                   6790: 
1.2       misha    6791: static SLJIT_INLINE pcre_uchar *compile_charn_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks)
1.1       misha    6792: {
                   6793: /* This function consumes at least one input character. */
                   6794: /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
                   6795: DEFINE_COMPILER;
                   6796: pcre_uchar *ccbegin = cc;
                   6797: compare_context context;
                   6798: int size;
                   6799: 
                   6800: context.length = 0;
                   6801: do
                   6802:   {
                   6803:   if (cc >= ccend)
                   6804:     break;
                   6805: 
                   6806:   if (*cc == OP_CHAR)
                   6807:     {
                   6808:     size = 1;
                   6809: #ifdef SUPPORT_UTF
                   6810:     if (common->utf && HAS_EXTRALEN(cc[1]))
                   6811:       size += GET_EXTRALEN(cc[1]);
                   6812: #endif
                   6813:     }
                   6814:   else if (*cc == OP_CHARI)
                   6815:     {
                   6816:     size = 1;
                   6817: #ifdef SUPPORT_UTF
                   6818:     if (common->utf)
                   6819:       {
                   6820:       if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
                   6821:         size = 0;
                   6822:       else if (HAS_EXTRALEN(cc[1]))
                   6823:         size += GET_EXTRALEN(cc[1]);
                   6824:       }
                   6825:     else
                   6826: #endif
                   6827:     if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
                   6828:       size = 0;
                   6829:     }
                   6830:   else
                   6831:     size = 0;
                   6832: 
                   6833:   cc += 1 + size;
                   6834:   context.length += IN_UCHARS(size);
                   6835:   }
                   6836: while (size > 0 && context.length <= 128);
                   6837: 
                   6838: cc = ccbegin;
                   6839: if (context.length > 0)
                   6840:   {
                   6841:   /* We have a fixed-length byte sequence. */
                   6842:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
1.3       moko     6843:   add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));
1.1       misha    6844: 
                   6845:   context.sourcereg = -1;
                   6846: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
                   6847:   context.ucharptr = 0;
                   6848: #endif
1.2       misha    6849:   do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0);
1.1       misha    6850:   return cc;
                   6851:   }
                   6852: 
                   6853: /* A non-fixed length character will be checked if length == 0. */
1.4     ! moko     6854: return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE);
1.1       misha    6855: }
                   6856: 
                   6857: /* Forward definitions. */
1.2       misha    6858: static void compile_matchingpath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *);
                   6859: static void compile_backtrackingpath(compiler_common *, struct backtrack_common *);
1.1       misha    6860: 
1.2       misha    6861: #define PUSH_BACKTRACK(size, ccstart, error) \
1.1       misha    6862:   do \
                   6863:     { \
1.2       misha    6864:     backtrack = sljit_alloc_memory(compiler, (size)); \
1.1       misha    6865:     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
                   6866:       return error; \
1.2       misha    6867:     memset(backtrack, 0, size); \
                   6868:     backtrack->prev = parent->top; \
                   6869:     backtrack->cc = (ccstart); \
                   6870:     parent->top = backtrack; \
1.1       misha    6871:     } \
                   6872:   while (0)
                   6873: 
1.2       misha    6874: #define PUSH_BACKTRACK_NOVALUE(size, ccstart) \
1.1       misha    6875:   do \
                   6876:     { \
1.2       misha    6877:     backtrack = sljit_alloc_memory(compiler, (size)); \
1.1       misha    6878:     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
                   6879:       return; \
1.2       misha    6880:     memset(backtrack, 0, size); \
                   6881:     backtrack->prev = parent->top; \
                   6882:     backtrack->cc = (ccstart); \
                   6883:     parent->top = backtrack; \
1.1       misha    6884:     } \
                   6885:   while (0)
                   6886: 
1.2       misha    6887: #define BACKTRACK_AS(type) ((type *)backtrack)
1.1       misha    6888: 
1.3       moko     6889: static void compile_dnref_search(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
                   6890: {
                   6891: /* The OVECTOR offset goes to TMP2. */
                   6892: DEFINE_COMPILER;
                   6893: int count = GET2(cc, 1 + IMM2_SIZE);
                   6894: pcre_uchar *slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
                   6895: unsigned int offset;
                   6896: jump_list *found = NULL;
                   6897: 
                   6898: SLJIT_ASSERT(*cc == OP_DNREF || *cc == OP_DNREFI);
                   6899: 
                   6900: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
                   6901: 
                   6902: count--;
                   6903: while (count-- > 0)
                   6904:   {
                   6905:   offset = GET2(slot, 0) << 1;
                   6906:   GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));
                   6907:   add_jump(compiler, &found, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));
                   6908:   slot += common->name_entry_size;
                   6909:   }
                   6910: 
                   6911: offset = GET2(slot, 0) << 1;
                   6912: GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));
                   6913: if (backtracks != NULL && !common->jscript_compat)
                   6914:   add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));
                   6915: 
                   6916: set_jumps(found, LABEL());
                   6917: }
                   6918: 
                   6919: static void compile_ref_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)
1.1       misha    6920: {
                   6921: DEFINE_COMPILER;
1.3       moko     6922: BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
                   6923: int offset = 0;
1.1       misha    6924: struct sljit_jump *jump = NULL;
1.2       misha    6925: struct sljit_jump *partial;
                   6926: struct sljit_jump *nopartial;
1.1       misha    6927: 
1.3       moko     6928: if (ref)
                   6929:   {
                   6930:   offset = GET2(cc, 1) << 1;
                   6931:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
                   6932:   /* OVECTOR(1) contains the "string begin - 1" constant. */
                   6933:   if (withchecks && !common->jscript_compat)
                   6934:     add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));
                   6935:   }
                   6936: else
                   6937:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
1.1       misha    6938: 
                   6939: #if defined SUPPORT_UTF && defined SUPPORT_UCP
                   6940: if (common->utf && *cc == OP_REFI)
                   6941:   {
1.4     ! moko     6942:   SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1);
1.3       moko     6943:   if (ref)
1.4     ! moko     6944:     OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
1.3       moko     6945:   else
1.4     ! moko     6946:     OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
1.3       moko     6947: 
1.1       misha    6948:   if (withchecks)
1.4     ! moko     6949:     jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_R2, 0);
1.1       misha    6950: 
1.4     ! moko     6951:   /* No free saved registers so save data on stack. */
1.3       moko     6952:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
1.4     ! moko     6953:   OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0);
        !          6954:   OP1(SLJIT_MOV, SLJIT_R3, 0, STR_END, 0);
        !          6955:   sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
1.3       moko     6956:   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
1.4     ! moko     6957:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
        !          6958: 
1.2       misha    6959:   if (common->mode == JIT_COMPILE)
1.3       moko     6960:     add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
1.2       misha    6961:   else
                   6962:     {
1.4     ! moko     6963:     OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
        !          6964: 
        !          6965:     add_jump(compiler, backtracks, JUMP(SLJIT_LESS));
        !          6966: 
        !          6967:     nopartial = JUMP(SLJIT_NOT_EQUAL);
        !          6968:     OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
1.2       misha    6969:     check_partial(common, FALSE);
                   6970:     add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
                   6971:     JUMPHERE(nopartial);
                   6972:     }
1.1       misha    6973:   }
                   6974: else
                   6975: #endif /* SUPPORT_UTF && SUPPORT_UCP */
                   6976:   {
1.3       moko     6977:   if (ref)
1.4     ! moko     6978:     OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);
1.3       moko     6979:   else
1.4     ! moko     6980:     OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
1.3       moko     6981: 
1.1       misha    6982:   if (withchecks)
1.3       moko     6983:     jump = JUMP(SLJIT_ZERO);
1.2       misha    6984: 
1.1       misha    6985:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1.3       moko     6986:   partial = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);
1.2       misha    6987:   if (common->mode == JIT_COMPILE)
                   6988:     add_jump(compiler, backtracks, partial);
1.1       misha    6989: 
                   6990:   add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
1.3       moko     6991:   add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.2       misha    6992: 
                   6993:   if (common->mode != JIT_COMPILE)
                   6994:     {
                   6995:     nopartial = JUMP(SLJIT_JUMP);
                   6996:     JUMPHERE(partial);
                   6997:     /* TMP2 -= STR_END - STR_PTR */
                   6998:     OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0);
                   6999:     OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0);
1.3       moko     7000:     partial = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0);
1.2       misha    7001:     OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
                   7002:     add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
1.3       moko     7003:     add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.2       misha    7004:     JUMPHERE(partial);
                   7005:     check_partial(common, FALSE);
                   7006:     add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
                   7007:     JUMPHERE(nopartial);
                   7008:     }
1.1       misha    7009:   }
                   7010: 
                   7011: if (jump != NULL)
                   7012:   {
                   7013:   if (emptyfail)
1.2       misha    7014:     add_jump(compiler, backtracks, jump);
1.1       misha    7015:   else
                   7016:     JUMPHERE(jump);
                   7017:   }
                   7018: }
                   7019: 
1.2       misha    7020: static SLJIT_INLINE pcre_uchar *compile_ref_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1       misha    7021: {
                   7022: DEFINE_COMPILER;
1.3       moko     7023: BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
1.2       misha    7024: backtrack_common *backtrack;
1.1       misha    7025: pcre_uchar type;
1.3       moko     7026: int offset = 0;
1.1       misha    7027: struct sljit_label *label;
                   7028: struct sljit_jump *zerolength;
                   7029: struct sljit_jump *jump = NULL;
                   7030: pcre_uchar *ccbegin = cc;
                   7031: int min = 0, max = 0;
                   7032: BOOL minimize;
                   7033: 
1.4     ! moko     7034: PUSH_BACKTRACK(sizeof(ref_iterator_backtrack), cc, NULL);
1.1       misha    7035: 
1.3       moko     7036: if (ref)
                   7037:   offset = GET2(cc, 1) << 1;
                   7038: else
                   7039:   cc += IMM2_SIZE;
1.1       misha    7040: type = cc[1 + IMM2_SIZE];
1.3       moko     7041: 
                   7042: SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even);
1.1       misha    7043: minimize = (type & 0x1) != 0;
                   7044: switch(type)
                   7045:   {
                   7046:   case OP_CRSTAR:
                   7047:   case OP_CRMINSTAR:
                   7048:   min = 0;
                   7049:   max = 0;
                   7050:   cc += 1 + IMM2_SIZE + 1;
                   7051:   break;
                   7052:   case OP_CRPLUS:
                   7053:   case OP_CRMINPLUS:
                   7054:   min = 1;
                   7055:   max = 0;
                   7056:   cc += 1 + IMM2_SIZE + 1;
                   7057:   break;
                   7058:   case OP_CRQUERY:
                   7059:   case OP_CRMINQUERY:
                   7060:   min = 0;
                   7061:   max = 1;
                   7062:   cc += 1 + IMM2_SIZE + 1;
                   7063:   break;
                   7064:   case OP_CRRANGE:
                   7065:   case OP_CRMINRANGE:
                   7066:   min = GET2(cc, 1 + IMM2_SIZE + 1);
                   7067:   max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE);
                   7068:   cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;
                   7069:   break;
                   7070:   default:
1.4     ! moko     7071:   SLJIT_UNREACHABLE();
1.1       misha    7072:   break;
                   7073:   }
                   7074: 
                   7075: if (!minimize)
                   7076:   {
                   7077:   if (min == 0)
                   7078:     {
                   7079:     allocate_stack(common, 2);
1.3       moko     7080:     if (ref)
                   7081:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
1.1       misha    7082:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   7083:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
                   7084:     /* Temporary release of STR_PTR. */
1.4     ! moko     7085:     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
1.3       moko     7086:     /* Handles both invalid and empty cases. Since the minimum repeat,
                   7087:     is zero the invalid case is basically the same as an empty case. */
                   7088:     if (ref)
                   7089:       zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
                   7090:     else
                   7091:       {
                   7092:       compile_dnref_search(common, ccbegin, NULL);
                   7093:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
                   7094:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0);
                   7095:       zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
                   7096:       }
1.1       misha    7097:     /* Restore if not zero length. */
1.4     ! moko     7098:     OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
1.1       misha    7099:     }
                   7100:   else
                   7101:     {
                   7102:     allocate_stack(common, 1);
1.3       moko     7103:     if (ref)
                   7104:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
1.1       misha    7105:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.3       moko     7106:     if (ref)
                   7107:       {
                   7108:       add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));
                   7109:       zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
                   7110:       }
                   7111:     else
                   7112:       {
                   7113:       compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);
                   7114:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
                   7115:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0);
                   7116:       zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
                   7117:       }
1.1       misha    7118:     }
                   7119: 
                   7120:   if (min > 1 || max > 1)
1.3       moko     7121:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, 0);
1.1       misha    7122: 
                   7123:   label = LABEL();
1.3       moko     7124:   if (!ref)
                   7125:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);
1.2       misha    7126:   compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);
1.1       misha    7127: 
                   7128:   if (min > 1 || max > 1)
                   7129:     {
1.3       moko     7130:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0);
1.1       misha    7131:     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1.3       moko     7132:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0);
1.1       misha    7133:     if (min > 1)
1.3       moko     7134:       CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, label);
1.1       misha    7135:     if (max > 1)
                   7136:       {
1.3       moko     7137:       jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
1.1       misha    7138:       allocate_stack(common, 1);
                   7139:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   7140:       JUMPTO(SLJIT_JUMP, label);
                   7141:       JUMPHERE(jump);
                   7142:       }
                   7143:     }
                   7144: 
                   7145:   if (max == 0)
                   7146:     {
                   7147:     /* Includes min > 1 case as well. */
                   7148:     allocate_stack(common, 1);
                   7149:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   7150:     JUMPTO(SLJIT_JUMP, label);
                   7151:     }
                   7152: 
                   7153:   JUMPHERE(zerolength);
1.4     ! moko     7154:   BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();
1.1       misha    7155: 
1.2       misha    7156:   count_match(common);
1.1       misha    7157:   return cc;
                   7158:   }
                   7159: 
1.3       moko     7160: allocate_stack(common, ref ? 2 : 3);
                   7161: if (ref)
                   7162:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
1.1       misha    7163: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
                   7164: if (type != OP_CRMINSTAR)
                   7165:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
                   7166: 
                   7167: if (min == 0)
                   7168:   {
1.3       moko     7169:   /* Handles both invalid and empty cases. Since the minimum repeat,
                   7170:   is zero the invalid case is basically the same as an empty case. */
                   7171:   if (ref)
                   7172:     zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
                   7173:   else
                   7174:     {
                   7175:     compile_dnref_search(common, ccbegin, NULL);
                   7176:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
                   7177:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);
                   7178:     zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
                   7179:     }
                   7180:   /* Length is non-zero, we can match real repeats. */
1.1       misha    7181:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   7182:   jump = JUMP(SLJIT_JUMP);
                   7183:   }
                   7184: else
1.3       moko     7185:   {
                   7186:   if (ref)
                   7187:     {
                   7188:     add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));
                   7189:     zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
                   7190:     }
                   7191:   else
                   7192:     {
                   7193:     compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);
                   7194:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
                   7195:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);
                   7196:     zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
                   7197:     }
                   7198:   }
1.1       misha    7199: 
1.4     ! moko     7200: BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();
1.1       misha    7201: if (max > 0)
1.3       moko     7202:   add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
1.1       misha    7203: 
1.3       moko     7204: if (!ref)
                   7205:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
1.2       misha    7206: compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);
1.1       misha    7207: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   7208: 
                   7209: if (min > 1)
                   7210:   {
                   7211:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
                   7212:   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
                   7213:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
1.4     ! moko     7214:   CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(ref_iterator_backtrack)->matchingpath);
1.1       misha    7215:   }
                   7216: else if (max > 0)
                   7217:   OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
                   7218: 
                   7219: if (jump != NULL)
                   7220:   JUMPHERE(jump);
                   7221: JUMPHERE(zerolength);
                   7222: 
1.2       misha    7223: count_match(common);
1.1       misha    7224: return cc;
                   7225: }
                   7226: 
1.2       misha    7227: static SLJIT_INLINE pcre_uchar *compile_recurse_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1       misha    7228: {
                   7229: DEFINE_COMPILER;
1.2       misha    7230: backtrack_common *backtrack;
1.1       misha    7231: recurse_entry *entry = common->entries;
                   7232: recurse_entry *prev = NULL;
1.2       misha    7233: sljit_sw start = GET(cc, 1);
                   7234: pcre_uchar *start_cc;
                   7235: BOOL needs_control_head;
                   7236: 
                   7237: PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);
                   7238: 
                   7239: /* Inlining simple patterns. */
                   7240: if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack)
                   7241:   {
                   7242:   start_cc = common->start + start;
                   7243:   compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack);
                   7244:   BACKTRACK_AS(recurse_backtrack)->inlined_pattern = TRUE;
                   7245:   return cc + 1 + LINK_SIZE;
                   7246:   }
1.1       misha    7247: 
                   7248: while (entry != NULL)
                   7249:   {
                   7250:   if (entry->start == start)
                   7251:     break;
                   7252:   prev = entry;
                   7253:   entry = entry->next;
                   7254:   }
                   7255: 
                   7256: if (entry == NULL)
                   7257:   {
                   7258:   entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
                   7259:   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   7260:     return NULL;
                   7261:   entry->next = NULL;
                   7262:   entry->entry = NULL;
                   7263:   entry->calls = NULL;
                   7264:   entry->start = start;
                   7265: 
                   7266:   if (prev != NULL)
                   7267:     prev->next = entry;
                   7268:   else
                   7269:     common->entries = entry;
                   7270:   }
                   7271: 
1.2       misha    7272: if (common->has_set_som && common->mark_ptr != 0)
                   7273:   {
1.3       moko     7274:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
1.2       misha    7275:   allocate_stack(common, 2);
1.3       moko     7276:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
1.2       misha    7277:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
                   7278:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
                   7279:   }
                   7280: else if (common->has_set_som || common->mark_ptr != 0)
                   7281:   {
1.3       moko     7282:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr);
1.2       misha    7283:   allocate_stack(common, 1);
                   7284:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
                   7285:   }
1.1       misha    7286: 
                   7287: if (entry->entry == NULL)
                   7288:   add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
                   7289: else
                   7290:   JUMPTO(SLJIT_FAST_CALL, entry->entry);
                   7291: /* Leave if the match is failed. */
1.3       moko     7292: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));
1.1       misha    7293: return cc + 1 + LINK_SIZE;
                   7294: }
                   7295: 
1.4     ! moko     7296: static sljit_s32 SLJIT_FUNC do_callout(struct jit_arguments *arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector)
1.2       misha    7297: {
                   7298: const pcre_uchar *begin = arguments->begin;
                   7299: int *offset_vector = arguments->offsets;
                   7300: int offset_count = arguments->offset_count;
                   7301: int i;
                   7302: 
                   7303: if (PUBL(callout) == NULL)
                   7304:   return 0;
                   7305: 
                   7306: callout_block->version = 2;
                   7307: callout_block->callout_data = arguments->callout_data;
                   7308: 
                   7309: /* Offsets in subject. */
                   7310: callout_block->subject_length = arguments->end - arguments->begin;
                   7311: callout_block->start_match = (pcre_uchar*)callout_block->subject - arguments->begin;
                   7312: callout_block->current_position = (pcre_uchar*)callout_block->offset_vector - arguments->begin;
                   7313: #if defined COMPILE_PCRE8
                   7314: callout_block->subject = (PCRE_SPTR)begin;
                   7315: #elif defined COMPILE_PCRE16
                   7316: callout_block->subject = (PCRE_SPTR16)begin;
                   7317: #elif defined COMPILE_PCRE32
                   7318: callout_block->subject = (PCRE_SPTR32)begin;
                   7319: #endif
                   7320: 
                   7321: /* Convert and copy the JIT offset vector to the offset_vector array. */
                   7322: callout_block->capture_top = 0;
                   7323: callout_block->offset_vector = offset_vector;
                   7324: for (i = 2; i < offset_count; i += 2)
                   7325:   {
                   7326:   offset_vector[i] = jit_ovector[i] - begin;
                   7327:   offset_vector[i + 1] = jit_ovector[i + 1] - begin;
                   7328:   if (jit_ovector[i] >= begin)
                   7329:     callout_block->capture_top = i;
                   7330:   }
                   7331: 
                   7332: callout_block->capture_top = (callout_block->capture_top >> 1) + 1;
                   7333: if (offset_count > 0)
                   7334:   offset_vector[0] = -1;
                   7335: if (offset_count > 1)
                   7336:   offset_vector[1] = -1;
                   7337: return (*PUBL(callout))(callout_block);
                   7338: }
                   7339: 
                   7340: /* Aligning to 8 byte. */
                   7341: #define CALLOUT_ARG_SIZE \
                   7342:     (((int)sizeof(PUBL(callout_block)) + 7) & ~7)
                   7343: 
                   7344: #define CALLOUT_ARG_OFFSET(arg) \
1.4     ! moko     7345:     SLJIT_OFFSETOF(PUBL(callout_block), arg)
1.2       misha    7346: 
                   7347: static SLJIT_INLINE pcre_uchar *compile_callout_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
                   7348: {
                   7349: DEFINE_COMPILER;
                   7350: backtrack_common *backtrack;
                   7351: 
                   7352: PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
                   7353: 
                   7354: allocate_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
                   7355: 
1.3       moko     7356: SLJIT_ASSERT(common->capture_last_ptr != 0);
                   7357: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
1.2       misha    7358: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1.4     ! moko     7359: OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]);
        !          7360: OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);
1.2       misha    7361: 
                   7362: /* These pointer sized fields temporarly stores internal variables. */
1.3       moko     7363: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
1.2       misha    7364: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0);
                   7365: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(subject), TMP2, 0);
                   7366: 
                   7367: if (common->mark_ptr != 0)
                   7368:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr));
1.4     ! moko     7369: OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2));
        !          7370: OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE));
1.2       misha    7371: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0);
                   7372: 
                   7373: /* Needed to save important temporary registers. */
1.3       moko     7374: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
1.4     ! moko     7375: /* SLJIT_R0 = arguments */
        !          7376: OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);
1.3       moko     7377: GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);
1.4     ! moko     7378: sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(S32) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));
1.3       moko     7379: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
1.2       misha    7380: free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
                   7381: 
                   7382: /* Check return value. */
1.4     ! moko     7383: OP2(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
        !          7384: add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER32));
1.2       misha    7385: if (common->forced_quit_label == NULL)
1.4     ! moko     7386:   add_jump(compiler, &common->forced_quit, JUMP(SLJIT_NOT_EQUAL32) /* SIG_LESS */);
1.2       misha    7387: else
1.4     ! moko     7388:   JUMPTO(SLJIT_NOT_EQUAL32 /* SIG_LESS */, common->forced_quit_label);
1.2       misha    7389: return cc + 2 + 2 * LINK_SIZE;
                   7390: }
                   7391: 
                   7392: #undef CALLOUT_ARG_SIZE
                   7393: #undef CALLOUT_ARG_OFFSET
                   7394: 
1.4     ! moko     7395: static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(pcre_uchar *cc)
        !          7396: {
        !          7397: while (TRUE)
        !          7398:   {
        !          7399:   switch (*cc)
        !          7400:     {
        !          7401:     case OP_NOT_WORD_BOUNDARY:
        !          7402:     case OP_WORD_BOUNDARY:
        !          7403:     case OP_CIRC:
        !          7404:     case OP_CIRCM:
        !          7405:     case OP_DOLL:
        !          7406:     case OP_DOLLM:
        !          7407:     case OP_CALLOUT:
        !          7408:     case OP_ALT:
        !          7409:     cc += PRIV(OP_lengths)[*cc];
        !          7410:     break;
        !          7411: 
        !          7412:     case OP_KET:
        !          7413:     return FALSE;
        !          7414: 
        !          7415:     default:
        !          7416:     return TRUE;
        !          7417:     }
        !          7418:   }
        !          7419: }
        !          7420: 
1.2       misha    7421: static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional)
1.1       misha    7422: {
                   7423: DEFINE_COMPILER;
                   7424: int framesize;
1.2       misha    7425: int extrasize;
                   7426: BOOL needs_control_head;
                   7427: int private_data_ptr;
                   7428: backtrack_common altbacktrack;
1.1       misha    7429: pcre_uchar *ccbegin;
                   7430: pcre_uchar opcode;
                   7431: pcre_uchar bra = OP_BRA;
                   7432: jump_list *tmp = NULL;
1.2       misha    7433: jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;
1.1       misha    7434: jump_list **found;
                   7435: /* Saving previous accept variables. */
1.2       misha    7436: BOOL save_local_exit = common->local_exit;
                   7437: BOOL save_positive_assert = common->positive_assert;
                   7438: then_trap_backtrack *save_then_trap = common->then_trap;
                   7439: struct sljit_label *save_quit_label = common->quit_label;
                   7440: struct sljit_label *save_accept_label = common->accept_label;
                   7441: jump_list *save_quit = common->quit;
                   7442: jump_list *save_positive_assert_quit = common->positive_assert_quit;
                   7443: jump_list *save_accept = common->accept;
1.1       misha    7444: struct sljit_jump *jump;
                   7445: struct sljit_jump *brajump = NULL;
1.2       misha    7446: 
                   7447: /* Assert captures then. */
                   7448: common->then_trap = NULL;
1.1       misha    7449: 
                   7450: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
                   7451:   {
                   7452:   SLJIT_ASSERT(!conditional);
                   7453:   bra = *cc;
                   7454:   cc++;
                   7455:   }
1.2       misha    7456: private_data_ptr = PRIVATE_DATA(cc);
                   7457: SLJIT_ASSERT(private_data_ptr != 0);
                   7458: framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);
                   7459: backtrack->framesize = framesize;
                   7460: backtrack->private_data_ptr = private_data_ptr;
1.1       misha    7461: opcode = *cc;
                   7462: SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
                   7463: found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
                   7464: ccbegin = cc;
                   7465: cc += GET(cc, 1);
                   7466: 
                   7467: if (bra == OP_BRAMINZERO)
                   7468:   {
1.2       misha    7469:   /* This is a braminzero backtrack path. */
1.1       misha    7470:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   7471:   free_stack(common, 1);
1.3       moko     7472:   brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
1.1       misha    7473:   }
                   7474: 
                   7475: if (framesize < 0)
                   7476:   {
1.4     ! moko     7477:   extrasize = 1;
        !          7478:   if (bra == OP_BRA && !assert_needs_str_ptr_saving(ccbegin + 1 + LINK_SIZE))
        !          7479:     extrasize = 0;
        !          7480: 
        !          7481:   if (needs_control_head)
        !          7482:     extrasize++;
        !          7483: 
1.2       misha    7484:   if (framesize == no_frame)
1.3       moko     7485:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);
1.4     ! moko     7486: 
        !          7487:   if (extrasize > 0)
        !          7488:     allocate_stack(common, extrasize);
        !          7489: 
1.2       misha    7490:   if (needs_control_head)
1.3       moko     7491:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
1.4     ! moko     7492: 
        !          7493:   if (extrasize > 0)
        !          7494:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
        !          7495: 
1.2       misha    7496:   if (needs_control_head)
                   7497:     {
1.4     ! moko     7498:     SLJIT_ASSERT(extrasize == 2);
1.3       moko     7499:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
1.2       misha    7500:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
                   7501:     }
1.1       misha    7502:   }
                   7503: else
                   7504:   {
1.2       misha    7505:   extrasize = needs_control_head ? 3 : 2;
                   7506:   allocate_stack(common, framesize + extrasize);
1.4     ! moko     7507: 
1.3       moko     7508:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.4     ! moko     7509:   OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
1.3       moko     7510:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);
1.2       misha    7511:   if (needs_control_head)
1.3       moko     7512:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
1.1       misha    7513:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
1.4     ! moko     7514: 
1.2       misha    7515:   if (needs_control_head)
                   7516:     {
                   7517:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
                   7518:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
1.3       moko     7519:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
1.2       misha    7520:     }
                   7521:   else
                   7522:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
1.4     ! moko     7523: 
1.2       misha    7524:   init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE);
                   7525:   }
                   7526: 
                   7527: memset(&altbacktrack, 0, sizeof(backtrack_common));
                   7528: if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
                   7529:   {
                   7530:   /* Negative assert is stronger than positive assert. */
                   7531:   common->local_exit = TRUE;
                   7532:   common->quit_label = NULL;
                   7533:   common->quit = NULL;
                   7534:   common->positive_assert = FALSE;
1.1       misha    7535:   }
1.2       misha    7536: else
                   7537:   common->positive_assert = TRUE;
                   7538: common->positive_assert_quit = NULL;
1.1       misha    7539: 
                   7540: while (1)
                   7541:   {
1.2       misha    7542:   common->accept_label = NULL;
1.1       misha    7543:   common->accept = NULL;
1.2       misha    7544:   altbacktrack.top = NULL;
                   7545:   altbacktrack.topbacktracks = NULL;
1.1       misha    7546: 
1.4     ! moko     7547:   if (*ccbegin == OP_ALT && extrasize > 0)
1.1       misha    7548:     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   7549: 
1.2       misha    7550:   altbacktrack.cc = ccbegin;
                   7551:   compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);
1.1       misha    7552:   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   7553:     {
1.2       misha    7554:     if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
                   7555:       {
                   7556:       common->local_exit = save_local_exit;
                   7557:       common->quit_label = save_quit_label;
                   7558:       common->quit = save_quit;
                   7559:       }
                   7560:     common->positive_assert = save_positive_assert;
                   7561:     common->then_trap = save_then_trap;
                   7562:     common->accept_label = save_accept_label;
                   7563:     common->positive_assert_quit = save_positive_assert_quit;
1.1       misha    7564:     common->accept = save_accept;
                   7565:     return NULL;
                   7566:     }
1.2       misha    7567:   common->accept_label = LABEL();
1.1       misha    7568:   if (common->accept != NULL)
1.2       misha    7569:     set_jumps(common->accept, common->accept_label);
1.1       misha    7570: 
                   7571:   /* Reset stack. */
                   7572:   if (framesize < 0)
1.2       misha    7573:     {
                   7574:     if (framesize == no_frame)
1.3       moko     7575:       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.4     ! moko     7576:     else if (extrasize > 0)
1.2       misha    7577:       free_stack(common, extrasize);
1.4     ! moko     7578: 
1.2       misha    7579:     if (needs_control_head)
1.4     ! moko     7580:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
1.2       misha    7581:     }
                   7582:   else
                   7583:     {
1.1       misha    7584:     if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)
                   7585:       {
1.2       misha    7586:       /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
1.4     ! moko     7587:       OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
1.2       misha    7588:       if (needs_control_head)
1.4     ! moko     7589:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
1.1       misha    7590:       }
                   7591:     else
                   7592:       {
1.3       moko     7593:       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    7594:       if (needs_control_head)
1.4     ! moko     7595:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 2));
1.1       misha    7596:       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
                   7597:       }
1.2       misha    7598:     }
1.1       misha    7599: 
                   7600:   if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
                   7601:     {
                   7602:     /* We know that STR_PTR was stored on the top of the stack. */
                   7603:     if (conditional)
1.4     ! moko     7604:       {
        !          7605:       if (extrasize > 0)
        !          7606:         OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? STACK(-2) : STACK(-1));
        !          7607:       }
1.1       misha    7608:     else if (bra == OP_BRAZERO)
                   7609:       {
                   7610:       if (framesize < 0)
1.4     ! moko     7611:         OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));
1.1       misha    7612:       else
                   7613:         {
1.4     ! moko     7614:         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
        !          7615:         OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - extrasize));
1.3       moko     7616:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);
1.1       misha    7617:         }
1.4     ! moko     7618:       OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
1.1       misha    7619:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
                   7620:       }
                   7621:     else if (framesize >= 0)
                   7622:       {
                   7623:       /* For OP_BRA and OP_BRAMINZERO. */
1.4     ! moko     7624:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
1.1       misha    7625:       }
                   7626:     }
                   7627:   add_jump(compiler, found, JUMP(SLJIT_JUMP));
                   7628: 
1.2       misha    7629:   compile_backtrackingpath(common, altbacktrack.top);
1.1       misha    7630:   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   7631:     {
1.2       misha    7632:     if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
                   7633:       {
                   7634:       common->local_exit = save_local_exit;
                   7635:       common->quit_label = save_quit_label;
                   7636:       common->quit = save_quit;
                   7637:       }
                   7638:     common->positive_assert = save_positive_assert;
                   7639:     common->then_trap = save_then_trap;
                   7640:     common->accept_label = save_accept_label;
                   7641:     common->positive_assert_quit = save_positive_assert_quit;
1.1       misha    7642:     common->accept = save_accept;
                   7643:     return NULL;
                   7644:     }
1.2       misha    7645:   set_jumps(altbacktrack.topbacktracks, LABEL());
1.1       misha    7646: 
                   7647:   if (*cc != OP_ALT)
                   7648:     break;
                   7649: 
                   7650:   ccbegin = cc;
                   7651:   cc += GET(cc, 1);
                   7652:   }
1.2       misha    7653: 
                   7654: if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
                   7655:   {
                   7656:   SLJIT_ASSERT(common->positive_assert_quit == NULL);
                   7657:   /* Makes the check less complicated below. */
                   7658:   common->positive_assert_quit = common->quit;
                   7659:   }
                   7660: 
1.1       misha    7661: /* None of them matched. */
1.2       misha    7662: if (common->positive_assert_quit != NULL)
                   7663:   {
                   7664:   jump = JUMP(SLJIT_JUMP);
                   7665:   set_jumps(common->positive_assert_quit, LABEL());
                   7666:   SLJIT_ASSERT(framesize != no_stack);
                   7667:   if (framesize < 0)
1.4     ! moko     7668:     OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
1.2       misha    7669:   else
                   7670:     {
1.3       moko     7671:     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    7672:     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
1.4     ! moko     7673:     OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
1.2       misha    7674:     }
                   7675:   JUMPHERE(jump);
                   7676:   }
                   7677: 
                   7678: if (needs_control_head)
1.3       moko     7679:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1));
1.1       misha    7680: 
                   7681: if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
                   7682:   {
                   7683:   /* Assert is failed. */
1.4     ! moko     7684:   if ((conditional && extrasize > 0) || bra == OP_BRAZERO)
1.1       misha    7685:     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   7686: 
                   7687:   if (framesize < 0)
                   7688:     {
                   7689:     /* The topmost item should be 0. */
                   7690:     if (bra == OP_BRAZERO)
1.2       misha    7691:       {
                   7692:       if (extrasize == 2)
                   7693:         free_stack(common, 1);
1.1       misha    7694:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.2       misha    7695:       }
1.4     ! moko     7696:     else if (extrasize > 0)
1.2       misha    7697:       free_stack(common, extrasize);
1.1       misha    7698:     }
                   7699:   else
                   7700:     {
1.2       misha    7701:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));
1.1       misha    7702:     /* The topmost item should be 0. */
                   7703:     if (bra == OP_BRAZERO)
                   7704:       {
1.2       misha    7705:       free_stack(common, framesize + extrasize - 1);
1.1       misha    7706:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
                   7707:       }
                   7708:     else
1.2       misha    7709:       free_stack(common, framesize + extrasize);
1.3       moko     7710:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);
1.1       misha    7711:     }
                   7712:   jump = JUMP(SLJIT_JUMP);
                   7713:   if (bra != OP_BRAZERO)
                   7714:     add_jump(compiler, target, jump);
                   7715: 
                   7716:   /* Assert is successful. */
                   7717:   set_jumps(tmp, LABEL());
                   7718:   if (framesize < 0)
                   7719:     {
                   7720:     /* We know that STR_PTR was stored on the top of the stack. */
1.4     ! moko     7721:     if (extrasize > 0)
        !          7722:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));
        !          7723: 
1.1       misha    7724:     /* Keep the STR_PTR on the top of the stack. */
                   7725:     if (bra == OP_BRAZERO)
1.2       misha    7726:       {
1.4     ! moko     7727:       OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
1.2       misha    7728:       if (extrasize == 2)
                   7729:         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   7730:       }
1.1       misha    7731:     else if (bra == OP_BRAMINZERO)
                   7732:       {
1.4     ! moko     7733:       OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
1.1       misha    7734:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
                   7735:       }
                   7736:     }
                   7737:   else
                   7738:     {
                   7739:     if (bra == OP_BRA)
                   7740:       {
1.2       misha    7741:       /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
1.4     ! moko     7742:       OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
        !          7743:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize + 1));
1.1       misha    7744:       }
                   7745:     else
                   7746:       {
1.2       misha    7747:       /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
1.4     ! moko     7748:       OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw));
1.2       misha    7749:       if (extrasize == 2)
                   7750:         {
                   7751:         OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   7752:         if (bra == OP_BRAMINZERO)
                   7753:           OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
                   7754:         }
                   7755:       else
                   7756:         {
                   7757:         OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
                   7758:         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);
                   7759:         }
1.1       misha    7760:       }
                   7761:     }
                   7762: 
                   7763:   if (bra == OP_BRAZERO)
                   7764:     {
1.2       misha    7765:     backtrack->matchingpath = LABEL();
                   7766:     SET_LABEL(jump, backtrack->matchingpath);
1.1       misha    7767:     }
                   7768:   else if (bra == OP_BRAMINZERO)
                   7769:     {
1.2       misha    7770:     JUMPTO(SLJIT_JUMP, backtrack->matchingpath);
1.1       misha    7771:     JUMPHERE(brajump);
                   7772:     if (framesize >= 0)
                   7773:       {
1.3       moko     7774:       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.1       misha    7775:       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
1.4     ! moko     7776:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
1.1       misha    7777:       }
1.2       misha    7778:     set_jumps(backtrack->common.topbacktracks, LABEL());
1.1       misha    7779:     }
                   7780:   }
                   7781: else
                   7782:   {
                   7783:   /* AssertNot is successful. */
                   7784:   if (framesize < 0)
                   7785:     {
1.4     ! moko     7786:     if (extrasize > 0)
        !          7787:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
        !          7788: 
1.1       misha    7789:     if (bra != OP_BRA)
1.2       misha    7790:       {
                   7791:       if (extrasize == 2)
                   7792:         free_stack(common, 1);
1.1       misha    7793:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.2       misha    7794:       }
1.4     ! moko     7795:     else if (extrasize > 0)
1.2       misha    7796:       free_stack(common, extrasize);
1.1       misha    7797:     }
                   7798:   else
                   7799:     {
                   7800:     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.2       misha    7801:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));
1.1       misha    7802:     /* The topmost item should be 0. */
                   7803:     if (bra != OP_BRA)
                   7804:       {
1.2       misha    7805:       free_stack(common, framesize + extrasize - 1);
1.1       misha    7806:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
                   7807:       }
                   7808:     else
1.2       misha    7809:       free_stack(common, framesize + extrasize);
1.3       moko     7810:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);
1.1       misha    7811:     }
                   7812: 
                   7813:   if (bra == OP_BRAZERO)
1.2       misha    7814:     backtrack->matchingpath = LABEL();
1.1       misha    7815:   else if (bra == OP_BRAMINZERO)
                   7816:     {
1.2       misha    7817:     JUMPTO(SLJIT_JUMP, backtrack->matchingpath);
1.1       misha    7818:     JUMPHERE(brajump);
                   7819:     }
                   7820: 
                   7821:   if (bra != OP_BRA)
                   7822:     {
1.2       misha    7823:     SLJIT_ASSERT(found == &backtrack->common.topbacktracks);
                   7824:     set_jumps(backtrack->common.topbacktracks, LABEL());
                   7825:     backtrack->common.topbacktracks = NULL;
1.1       misha    7826:     }
                   7827:   }
                   7828: 
1.2       misha    7829: if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
                   7830:   {
                   7831:   common->local_exit = save_local_exit;
                   7832:   common->quit_label = save_quit_label;
                   7833:   common->quit = save_quit;
                   7834:   }
                   7835: common->positive_assert = save_positive_assert;
                   7836: common->then_trap = save_then_trap;
                   7837: common->accept_label = save_accept_label;
                   7838: common->positive_assert_quit = save_positive_assert_quit;
1.1       misha    7839: common->accept = save_accept;
                   7840: return cc + 1 + LINK_SIZE;
                   7841: }
                   7842: 
1.2       misha    7843: static SLJIT_INLINE void match_once_common(compiler_common *common, pcre_uchar ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)
                   7844: {
                   7845: DEFINE_COMPILER;
                   7846: int stacksize;
                   7847: 
                   7848: if (framesize < 0)
                   7849:   {
                   7850:   if (framesize == no_frame)
1.3       moko     7851:     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    7852:   else
                   7853:     {
                   7854:     stacksize = needs_control_head ? 1 : 0;
                   7855:     if (ket != OP_KET || has_alternatives)
                   7856:       stacksize++;
1.4     ! moko     7857: 
        !          7858:     if (stacksize > 0)
        !          7859:       free_stack(common, stacksize);
1.2       misha    7860:     }
                   7861: 
                   7862:   if (needs_control_head)
1.4     ! moko     7863:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? STACK(-2) : STACK(-1));
1.2       misha    7864: 
                   7865:   /* TMP2 which is set here used by OP_KETRMAX below. */
                   7866:   if (ket == OP_KETRMAX)
1.4     ! moko     7867:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));
1.2       misha    7868:   else if (ket == OP_KETRMIN)
                   7869:     {
                   7870:     /* Move the STR_PTR to the private_data_ptr. */
1.4     ! moko     7871:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
1.2       misha    7872:     }
                   7873:   }
                   7874: else
                   7875:   {
                   7876:   stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1;
1.4     ! moko     7877:   OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw));
1.2       misha    7878:   if (needs_control_head)
1.4     ! moko     7879:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));
1.2       misha    7880: 
                   7881:   if (ket == OP_KETRMAX)
                   7882:     {
                   7883:     /* TMP2 which is set here used by OP_KETRMAX below. */
                   7884:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   7885:     }
                   7886:   }
                   7887: if (needs_control_head)
1.3       moko     7888:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0);
1.2       misha    7889: }
                   7890: 
                   7891: static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr)
                   7892: {
                   7893: DEFINE_COMPILER;
                   7894: 
                   7895: if (common->capture_last_ptr != 0)
                   7896:   {
1.3       moko     7897:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
                   7898:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);
1.2       misha    7899:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
                   7900:   stacksize++;
                   7901:   }
                   7902: if (common->optimized_cbracket[offset >> 1] == 0)
                   7903:   {
1.3       moko     7904:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
                   7905:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
1.2       misha    7906:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
1.3       moko     7907:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    7908:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);
1.3       moko     7909:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
                   7910:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);
1.2       misha    7911:   stacksize += 2;
                   7912:   }
                   7913: return stacksize;
                   7914: }
                   7915: 
1.1       misha    7916: /*
                   7917:   Handling bracketed expressions is probably the most complex part.
                   7918: 
                   7919:   Stack layout naming characters:
                   7920:     S - Push the current STR_PTR
                   7921:     0 - Push a 0 (NULL)
                   7922:     A - Push the current STR_PTR. Needed for restoring the STR_PTR
                   7923:         before the next alternative. Not pushed if there are no alternatives.
                   7924:     M - Any values pushed by the current alternative. Can be empty, or anything.
                   7925:     C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
                   7926:     L - Push the previous local (pointed by localptr) to the stack
                   7927:    () - opional values stored on the stack
                   7928:   ()* - optonal, can be stored multiple times
                   7929: 
                   7930:   The following list shows the regular expression templates, their PCRE byte codes
                   7931:   and stack layout supported by pcre-sljit.
                   7932: 
                   7933:   (?:)                     OP_BRA     | OP_KET                A M
                   7934:   ()                       OP_CBRA    | OP_KET                C M
                   7935:   (?:)+                    OP_BRA     | OP_KETRMAX        0   A M S   ( A M S )*
                   7936:                            OP_SBRA    | OP_KETRMAX        0   L M S   ( L M S )*
                   7937:   (?:)+?                   OP_BRA     | OP_KETRMIN        0   A M S   ( A M S )*
                   7938:                            OP_SBRA    | OP_KETRMIN        0   L M S   ( L M S )*
                   7939:   ()+                      OP_CBRA    | OP_KETRMAX        0   C M S   ( C M S )*
                   7940:                            OP_SCBRA   | OP_KETRMAX        0   C M S   ( C M S )*
                   7941:   ()+?                     OP_CBRA    | OP_KETRMIN        0   C M S   ( C M S )*
                   7942:                            OP_SCBRA   | OP_KETRMIN        0   C M S   ( C M S )*
                   7943:   (?:)?    OP_BRAZERO    | OP_BRA     | OP_KET            S ( A M 0 )
                   7944:   (?:)??   OP_BRAMINZERO | OP_BRA     | OP_KET            S ( A M 0 )
                   7945:   ()?      OP_BRAZERO    | OP_CBRA    | OP_KET            S ( C M 0 )
                   7946:   ()??     OP_BRAMINZERO | OP_CBRA    | OP_KET            S ( C M 0 )
                   7947:   (?:)*    OP_BRAZERO    | OP_BRA     | OP_KETRMAX      S 0 ( A M S )*
                   7948:            OP_BRAZERO    | OP_SBRA    | OP_KETRMAX      S 0 ( L M S )*
                   7949:   (?:)*?   OP_BRAMINZERO | OP_BRA     | OP_KETRMIN      S 0 ( A M S )*
                   7950:            OP_BRAMINZERO | OP_SBRA    | OP_KETRMIN      S 0 ( L M S )*
                   7951:   ()*      OP_BRAZERO    | OP_CBRA    | OP_KETRMAX      S 0 ( C M S )*
                   7952:            OP_BRAZERO    | OP_SCBRA   | OP_KETRMAX      S 0 ( C M S )*
                   7953:   ()*?     OP_BRAMINZERO | OP_CBRA    | OP_KETRMIN      S 0 ( C M S )*
                   7954:            OP_BRAMINZERO | OP_SCBRA   | OP_KETRMIN      S 0 ( C M S )*
                   7955: 
                   7956: 
                   7957:   Stack layout naming characters:
                   7958:     A - Push the alternative index (starting from 0) on the stack.
                   7959:         Not pushed if there is no alternatives.
                   7960:     M - Any values pushed by the current alternative. Can be empty, or anything.
                   7961: 
                   7962:   The next list shows the possible content of a bracket:
                   7963:   (|)     OP_*BRA    | OP_ALT ...         M A
                   7964:   (?()|)  OP_*COND   | OP_ALT             M A
                   7965:   (?>|)   OP_ONCE    | OP_ALT ...         [stack trace] M A
                   7966:   (?>|)   OP_ONCE_NC | OP_ALT ...         [stack trace] M A
                   7967:                                           Or nothing, if trace is unnecessary
                   7968: */
                   7969: 
1.2       misha    7970: static pcre_uchar *compile_bracket_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1       misha    7971: {
                   7972: DEFINE_COMPILER;
1.2       misha    7973: backtrack_common *backtrack;
1.1       misha    7974: pcre_uchar opcode;
1.2       misha    7975: int private_data_ptr = 0;
1.1       misha    7976: int offset = 0;
1.3       moko     7977: int i, stacksize;
1.2       misha    7978: int repeat_ptr = 0, repeat_length = 0;
                   7979: int repeat_type = 0, repeat_count = 0;
1.1       misha    7980: pcre_uchar *ccbegin;
1.2       misha    7981: pcre_uchar *matchingpath;
1.3       moko     7982: pcre_uchar *slot;
1.1       misha    7983: pcre_uchar bra = OP_BRA;
                   7984: pcre_uchar ket;
1.2       misha    7985: assert_backtrack *assert;
1.1       misha    7986: BOOL has_alternatives;
1.2       misha    7987: BOOL needs_control_head = FALSE;
1.1       misha    7988: struct sljit_jump *jump;
                   7989: struct sljit_jump *skip;
1.2       misha    7990: struct sljit_label *rmax_label = NULL;
                   7991: struct sljit_jump *braminzero = NULL;
1.1       misha    7992: 
1.2       misha    7993: PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);
1.1       misha    7994: 
                   7995: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
                   7996:   {
                   7997:   bra = *cc;
                   7998:   cc++;
                   7999:   opcode = *cc;
                   8000:   }
                   8001: 
                   8002: opcode = *cc;
                   8003: ccbegin = cc;
1.2       misha    8004: matchingpath = bracketend(cc) - 1 - LINK_SIZE;
                   8005: ket = *matchingpath;
                   8006: if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)
                   8007:   {
                   8008:   repeat_ptr = PRIVATE_DATA(matchingpath);
                   8009:   repeat_length = PRIVATE_DATA(matchingpath + 1);
                   8010:   repeat_type = PRIVATE_DATA(matchingpath + 2);
                   8011:   repeat_count = PRIVATE_DATA(matchingpath + 3);
                   8012:   SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0);
                   8013:   if (repeat_type == OP_UPTO)
                   8014:     ket = OP_KETRMAX;
                   8015:   if (repeat_type == OP_MINUPTO)
                   8016:     ket = OP_KETRMIN;
                   8017:   }
1.1       misha    8018: 
                   8019: if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
                   8020:   {
1.2       misha    8021:   /* Drop this bracket_backtrack. */
                   8022:   parent->top = backtrack->prev;
                   8023:   return matchingpath + 1 + LINK_SIZE + repeat_length;
1.1       misha    8024:   }
                   8025: 
1.2       misha    8026: matchingpath = ccbegin + 1 + LINK_SIZE;
1.1       misha    8027: SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
                   8028: SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
                   8029: cc += GET(cc, 1);
                   8030: 
                   8031: has_alternatives = *cc == OP_ALT;
1.3       moko     8032: if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND))
                   8033:   has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL) ? FALSE : TRUE;
1.1       misha    8034: 
                   8035: if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
                   8036:   opcode = OP_SCOND;
                   8037: if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
                   8038:   opcode = OP_ONCE;
                   8039: 
                   8040: if (opcode == OP_CBRA || opcode == OP_SCBRA)
                   8041:   {
                   8042:   /* Capturing brackets has a pre-allocated space. */
                   8043:   offset = GET2(ccbegin, 1 + LINK_SIZE);
1.2       misha    8044:   if (common->optimized_cbracket[offset] == 0)
                   8045:     {
                   8046:     private_data_ptr = OVECTOR_PRIV(offset);
                   8047:     offset <<= 1;
                   8048:     }
                   8049:   else
                   8050:     {
                   8051:     offset <<= 1;
                   8052:     private_data_ptr = OVECTOR(offset);
                   8053:     }
                   8054:   BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;
                   8055:   matchingpath += IMM2_SIZE;
1.1       misha    8056:   }
                   8057: else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
                   8058:   {
                   8059:   /* Other brackets simply allocate the next entry. */
1.2       misha    8060:   private_data_ptr = PRIVATE_DATA(ccbegin);
                   8061:   SLJIT_ASSERT(private_data_ptr != 0);
                   8062:   BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;
1.1       misha    8063:   if (opcode == OP_ONCE)
1.2       misha    8064:     BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, NULL, FALSE, &needs_control_head);
1.1       misha    8065:   }
                   8066: 
                   8067: /* Instructions before the first alternative. */
                   8068: stacksize = 0;
1.2       misha    8069: if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
1.1       misha    8070:   stacksize++;
                   8071: if (bra == OP_BRAZERO)
                   8072:   stacksize++;
                   8073: 
                   8074: if (stacksize > 0)
                   8075:   allocate_stack(common, stacksize);
                   8076: 
                   8077: stacksize = 0;
1.2       misha    8078: if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
1.1       misha    8079:   {
                   8080:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
                   8081:   stacksize++;
                   8082:   }
                   8083: 
                   8084: if (bra == OP_BRAZERO)
                   8085:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
                   8086: 
                   8087: if (bra == OP_BRAMINZERO)
                   8088:   {
1.2       misha    8089:   /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */
1.1       misha    8090:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   8091:   if (ket != OP_KETRMIN)
                   8092:     {
                   8093:     free_stack(common, 1);
1.3       moko     8094:     braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
1.1       misha    8095:     }
                   8096:   else
                   8097:     {
                   8098:     if (opcode == OP_ONCE || opcode >= OP_SBRA)
                   8099:       {
1.3       moko     8100:       jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
1.1       misha    8101:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
                   8102:       /* Nothing stored during the first run. */
                   8103:       skip = JUMP(SLJIT_JUMP);
                   8104:       JUMPHERE(jump);
                   8105:       /* Checking zero-length iteration. */
1.2       misha    8106:       if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
1.1       misha    8107:         {
1.2       misha    8108:         /* When we come from outside, private_data_ptr contains the previous STR_PTR. */
1.3       moko     8109:         braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.1       misha    8110:         }
                   8111:       else
                   8112:         {
                   8113:         /* Except when the whole stack frame must be saved. */
1.3       moko     8114:         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.4     ! moko     8115:         braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2));
1.1       misha    8116:         }
                   8117:       JUMPHERE(skip);
                   8118:       }
                   8119:     else
                   8120:       {
1.3       moko     8121:       jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
1.1       misha    8122:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
                   8123:       JUMPHERE(jump);
                   8124:       }
                   8125:     }
                   8126:   }
                   8127: 
1.2       misha    8128: if (repeat_type != 0)
                   8129:   {
1.3       moko     8130:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, repeat_count);
1.2       misha    8131:   if (repeat_type == OP_EXACT)
                   8132:     rmax_label = LABEL();
                   8133:   }
                   8134: 
1.1       misha    8135: if (ket == OP_KETRMIN)
1.2       misha    8136:   BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
1.1       misha    8137: 
                   8138: if (ket == OP_KETRMAX)
                   8139:   {
1.2       misha    8140:   rmax_label = LABEL();
                   8141:   if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0)
                   8142:     BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label;
1.1       misha    8143:   }
                   8144: 
                   8145: /* Handling capturing brackets and alternatives. */
                   8146: if (opcode == OP_ONCE)
                   8147:   {
1.2       misha    8148:   stacksize = 0;
                   8149:   if (needs_control_head)
                   8150:     {
1.3       moko     8151:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
1.2       misha    8152:     stacksize++;
                   8153:     }
                   8154: 
                   8155:   if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
1.1       misha    8156:     {
1.2       misha    8157:     /* Neither capturing brackets nor recursions are found in the block. */
1.1       misha    8158:     if (ket == OP_KETRMIN)
                   8159:       {
1.2       misha    8160:       stacksize += 2;
                   8161:       if (!needs_control_head)
1.3       moko     8162:         OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    8163:       }
                   8164:     else
                   8165:       {
                   8166:       if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)
1.3       moko     8167:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);
1.2       misha    8168:       if (ket == OP_KETRMAX || has_alternatives)
                   8169:         stacksize++;
                   8170:       }
                   8171: 
                   8172:     if (stacksize > 0)
                   8173:       allocate_stack(common, stacksize);
                   8174: 
                   8175:     stacksize = 0;
                   8176:     if (needs_control_head)
                   8177:       {
                   8178:       stacksize++;
                   8179:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
1.1       misha    8180:       }
1.2       misha    8181: 
                   8182:     if (ket == OP_KETRMIN)
1.1       misha    8183:       {
1.2       misha    8184:       if (needs_control_head)
1.3       moko     8185:         OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    8186:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
                   8187:       if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)
1.4     ! moko     8188:         OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw));
1.2       misha    8189:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);
1.1       misha    8190:       }
1.2       misha    8191:     else if (ket == OP_KETRMAX || has_alternatives)
                   8192:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
1.1       misha    8193:     }
                   8194:   else
                   8195:     {
1.2       misha    8196:     if (ket != OP_KET || has_alternatives)
                   8197:       stacksize++;
                   8198: 
                   8199:     stacksize += BACKTRACK_AS(bracket_backtrack)->u.framesize + 1;
                   8200:     allocate_stack(common, stacksize);
                   8201: 
                   8202:     if (needs_control_head)
                   8203:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
                   8204: 
1.3       moko     8205:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.4     ! moko     8206:     OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
1.2       misha    8207: 
                   8208:     stacksize = needs_control_head ? 1 : 0;
                   8209:     if (ket != OP_KET || has_alternatives)
1.1       misha    8210:       {
1.2       misha    8211:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
1.3       moko     8212:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);
1.2       misha    8213:       stacksize++;
                   8214:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
1.1       misha    8215:       }
                   8216:     else
                   8217:       {
1.3       moko     8218:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);
1.2       misha    8219:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
1.1       misha    8220:       }
1.2       misha    8221:     init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1, FALSE);
1.1       misha    8222:     }
                   8223:   }
                   8224: else if (opcode == OP_CBRA || opcode == OP_SCBRA)
                   8225:   {
                   8226:   /* Saving the previous values. */
1.2       misha    8227:   if (common->optimized_cbracket[offset >> 1] != 0)
                   8228:     {
                   8229:     SLJIT_ASSERT(private_data_ptr == OVECTOR(offset));
                   8230:     allocate_stack(common, 2);
1.3       moko     8231:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
                   8232:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));
                   8233:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);
1.2       misha    8234:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
                   8235:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
                   8236:     }
                   8237:   else
                   8238:     {
1.3       moko     8239:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    8240:     allocate_stack(common, 1);
1.3       moko     8241:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);
1.2       misha    8242:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
                   8243:     }
1.1       misha    8244:   }
                   8245: else if (opcode == OP_SBRA || opcode == OP_SCOND)
                   8246:   {
                   8247:   /* Saving the previous value. */
1.3       moko     8248:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.1       misha    8249:   allocate_stack(common, 1);
1.3       moko     8250:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);
1.1       misha    8251:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
                   8252:   }
                   8253: else if (has_alternatives)
                   8254:   {
                   8255:   /* Pushing the starting string pointer. */
                   8256:   allocate_stack(common, 1);
                   8257:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   8258:   }
                   8259: 
                   8260: /* Generating code for the first alternative. */
                   8261: if (opcode == OP_COND || opcode == OP_SCOND)
                   8262:   {
1.2       misha    8263:   if (*matchingpath == OP_CREF)
1.1       misha    8264:     {
                   8265:     SLJIT_ASSERT(has_alternatives);
1.2       misha    8266:     add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed),
1.3       moko     8267:       CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));
1.2       misha    8268:     matchingpath += 1 + IMM2_SIZE;
1.1       misha    8269:     }
1.3       moko     8270:   else if (*matchingpath == OP_DNCREF)
1.1       misha    8271:     {
                   8272:     SLJIT_ASSERT(has_alternatives);
                   8273: 
1.3       moko     8274:     i = GET2(matchingpath, 1 + IMM2_SIZE);
                   8275:     slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;
                   8276:     OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
                   8277:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
1.4     ! moko     8278:     OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
1.3       moko     8279:     slot += common->name_entry_size;
                   8280:     i--;
                   8281:     while (i-- > 0)
                   8282:       {
                   8283:       OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
1.4     ! moko     8284:       OP2(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, STR_PTR, 0);
1.3       moko     8285:       slot += common->name_entry_size;
                   8286:       }
                   8287:     OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
                   8288:     add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO));
                   8289:     matchingpath += 1 + 2 * IMM2_SIZE;
1.1       misha    8290:     }
1.3       moko     8291:   else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL)
1.1       misha    8292:     {
                   8293:     /* Never has other case. */
1.2       misha    8294:     BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;
1.3       moko     8295:     SLJIT_ASSERT(!has_alternatives);
1.1       misha    8296: 
1.3       moko     8297:     if (*matchingpath == OP_FAIL)
1.1       misha    8298:       stacksize = 0;
1.4     ! moko     8299:     else if (*matchingpath == OP_RREF)
1.3       moko     8300:       {
                   8301:       stacksize = GET2(matchingpath, 1);
                   8302:       if (common->currententry == NULL)
                   8303:         stacksize = 0;
                   8304:       else if (stacksize == RREF_ANY)
                   8305:         stacksize = 1;
                   8306:       else if (common->currententry->start == 0)
                   8307:         stacksize = stacksize == 0;
                   8308:       else
                   8309:         stacksize = stacksize == (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
1.1       misha    8310: 
                   8311:       if (stacksize != 0)
1.2       misha    8312:         matchingpath += 1 + IMM2_SIZE;
1.3       moko     8313:       }
                   8314:     else
                   8315:       {
                   8316:       if (common->currententry == NULL || common->currententry->start == 0)
                   8317:         stacksize = 0;
1.1       misha    8318:       else
                   8319:         {
1.3       moko     8320:         stacksize = GET2(matchingpath, 1 + IMM2_SIZE);
                   8321:         slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;
                   8322:         i = (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
                   8323:         while (stacksize > 0)
                   8324:           {
                   8325:           if ((int)GET2(slot, 0) == i)
                   8326:             break;
                   8327:           slot += common->name_entry_size;
                   8328:           stacksize--;
                   8329:           }
                   8330:         }
                   8331: 
                   8332:       if (stacksize != 0)
                   8333:         matchingpath += 1 + 2 * IMM2_SIZE;
                   8334:       }
                   8335: 
                   8336:       /* The stacksize == 0 is a common "else" case. */
                   8337:       if (stacksize == 0)
                   8338:         {
1.1       misha    8339:         if (*cc == OP_ALT)
                   8340:           {
1.2       misha    8341:           matchingpath = cc + 1 + LINK_SIZE;
1.1       misha    8342:           cc += GET(cc, 1);
                   8343:           }
                   8344:         else
1.2       misha    8345:           matchingpath = cc;
1.1       misha    8346:         }
                   8347:     }
                   8348:   else
                   8349:     {
1.2       misha    8350:     SLJIT_ASSERT(has_alternatives && *matchingpath >= OP_ASSERT && *matchingpath <= OP_ASSERTBACK_NOT);
                   8351:     /* Similar code as PUSH_BACKTRACK macro. */
                   8352:     assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack));
1.1       misha    8353:     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   8354:       return NULL;
1.2       misha    8355:     memset(assert, 0, sizeof(assert_backtrack));
                   8356:     assert->common.cc = matchingpath;
                   8357:     BACKTRACK_AS(bracket_backtrack)->u.assert = assert;
                   8358:     matchingpath = compile_assert_matchingpath(common, matchingpath, assert, TRUE);
1.1       misha    8359:     }
                   8360:   }
                   8361: 
1.2       misha    8362: compile_matchingpath(common, matchingpath, cc, backtrack);
1.1       misha    8363: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   8364:   return NULL;
                   8365: 
                   8366: if (opcode == OP_ONCE)
1.2       misha    8367:   match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
                   8368: 
                   8369: stacksize = 0;
                   8370: if (repeat_type == OP_MINUPTO)
1.1       misha    8371:   {
1.2       misha    8372:   /* We need to preserve the counter. TMP2 will be used below. */
1.3       moko     8373:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);
1.2       misha    8374:   stacksize++;
1.1       misha    8375:   }
                   8376: if (ket != OP_KET || bra != OP_BRA)
                   8377:   stacksize++;
1.2       misha    8378: if (offset != 0)
                   8379:   {
                   8380:   if (common->capture_last_ptr != 0)
                   8381:     stacksize++;
                   8382:   if (common->optimized_cbracket[offset >> 1] == 0)
                   8383:     stacksize += 2;
                   8384:   }
1.1       misha    8385: if (has_alternatives && opcode != OP_ONCE)
                   8386:   stacksize++;
                   8387: 
                   8388: if (stacksize > 0)
                   8389:   allocate_stack(common, stacksize);
                   8390: 
                   8391: stacksize = 0;
1.2       misha    8392: if (repeat_type == OP_MINUPTO)
1.1       misha    8393:   {
1.2       misha    8394:   /* TMP2 was set above. */
                   8395:   OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
1.1       misha    8396:   stacksize++;
                   8397:   }
1.2       misha    8398: 
                   8399: if (ket != OP_KET || bra != OP_BRA)
1.1       misha    8400:   {
1.2       misha    8401:   if (ket != OP_KET)
                   8402:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
                   8403:   else
                   8404:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
1.1       misha    8405:   stacksize++;
                   8406:   }
                   8407: 
1.2       misha    8408: if (offset != 0)
                   8409:   stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);
                   8410: 
1.1       misha    8411: if (has_alternatives)
                   8412:   {
                   8413:   if (opcode != OP_ONCE)
                   8414:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
                   8415:   if (ket != OP_KETRMAX)
1.2       misha    8416:     BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
1.1       misha    8417:   }
                   8418: 
1.2       misha    8419: /* Must be after the matchingpath label. */
                   8420: if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0)
1.1       misha    8421:   {
1.2       misha    8422:   SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));
1.3       moko     8423:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
1.1       misha    8424:   }
                   8425: 
                   8426: if (ket == OP_KETRMAX)
                   8427:   {
1.2       misha    8428:   if (repeat_type != 0)
                   8429:     {
                   8430:     if (has_alternatives)
                   8431:       BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
1.4     ! moko     8432:     OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
1.3       moko     8433:     JUMPTO(SLJIT_NOT_ZERO, rmax_label);
1.2       misha    8434:     /* Drop STR_PTR for greedy plus quantifier. */
                   8435:     if (opcode != OP_ONCE)
                   8436:       free_stack(common, 1);
                   8437:     }
                   8438:   else if (opcode == OP_ONCE || opcode >= OP_SBRA)
1.1       misha    8439:     {
                   8440:     if (has_alternatives)
1.2       misha    8441:       BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
1.1       misha    8442:     /* Checking zero-length iteration. */
                   8443:     if (opcode != OP_ONCE)
1.2       misha    8444:       {
1.3       moko     8445:       CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0, rmax_label);
1.2       misha    8446:       /* Drop STR_PTR for greedy plus quantifier. */
                   8447:       if (bra != OP_BRAZERO)
                   8448:         free_stack(common, 1);
                   8449:       }
1.1       misha    8450:     else
                   8451:       /* TMP2 must contain the starting STR_PTR. */
1.3       moko     8452:       CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label);
1.1       misha    8453:     }
                   8454:   else
1.2       misha    8455:     JUMPTO(SLJIT_JUMP, rmax_label);
                   8456:   BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
                   8457:   }
                   8458: 
                   8459: if (repeat_type == OP_EXACT)
                   8460:   {
1.3       moko     8461:   count_match(common);
1.4     ! moko     8462:   OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
1.3       moko     8463:   JUMPTO(SLJIT_NOT_ZERO, rmax_label);
1.2       misha    8464:   }
                   8465: else if (repeat_type == OP_UPTO)
                   8466:   {
                   8467:   /* We need to preserve the counter. */
1.3       moko     8468:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);
1.2       misha    8469:   allocate_stack(common, 1);
                   8470:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
1.1       misha    8471:   }
                   8472: 
                   8473: if (bra == OP_BRAZERO)
1.2       misha    8474:   BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();
1.1       misha    8475: 
                   8476: if (bra == OP_BRAMINZERO)
                   8477:   {
1.2       misha    8478:   /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
                   8479:   JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);
                   8480:   if (braminzero != NULL)
1.1       misha    8481:     {
1.2       misha    8482:     JUMPHERE(braminzero);
1.1       misha    8483:     /* We need to release the end pointer to perform the
1.2       misha    8484:     backtrack for the zero-length iteration. When
1.1       misha    8485:     framesize is < 0, OP_ONCE will do the release itself. */
1.2       misha    8486:     if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0)
1.1       misha    8487:       {
1.3       moko     8488:       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.1       misha    8489:       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
                   8490:       }
                   8491:     else if (ket == OP_KETRMIN && opcode != OP_ONCE)
                   8492:       free_stack(common, 1);
                   8493:     }
1.2       misha    8494:   /* Continue to the normal backtrack. */
1.1       misha    8495:   }
                   8496: 
                   8497: if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
1.2       misha    8498:   count_match(common);
1.1       misha    8499: 
                   8500: /* Skip the other alternatives. */
                   8501: while (*cc == OP_ALT)
                   8502:   cc += GET(cc, 1);
                   8503: cc += 1 + LINK_SIZE;
1.2       misha    8504: 
                   8505: if (opcode == OP_ONCE)
1.4     ! moko     8506:   {
        !          8507:   /* We temporarily encode the needs_control_head in the lowest bit.
        !          8508:      Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns
        !          8509:      the same value for small signed numbers (including negative numbers). */
1.2       misha    8510:   BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
1.4     ! moko     8511:   }
1.2       misha    8512: return cc + repeat_length;
1.1       misha    8513: }
                   8514: 
1.2       misha    8515: static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1       misha    8516: {
                   8517: DEFINE_COMPILER;
1.2       misha    8518: backtrack_common *backtrack;
1.1       misha    8519: pcre_uchar opcode;
1.2       misha    8520: int private_data_ptr;
1.1       misha    8521: int cbraprivptr = 0;
1.2       misha    8522: BOOL needs_control_head;
1.1       misha    8523: int framesize;
                   8524: int stacksize;
                   8525: int offset = 0;
                   8526: BOOL zero = FALSE;
                   8527: pcre_uchar *ccbegin = NULL;
1.2       misha    8528: int stack; /* Also contains the offset of control head. */
1.1       misha    8529: struct sljit_label *loop = NULL;
                   8530: struct jump_list *emptymatch = NULL;
                   8531: 
1.2       misha    8532: PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL);
1.1       misha    8533: if (*cc == OP_BRAPOSZERO)
                   8534:   {
                   8535:   zero = TRUE;
                   8536:   cc++;
                   8537:   }
                   8538: 
                   8539: opcode = *cc;
1.2       misha    8540: private_data_ptr = PRIVATE_DATA(cc);
                   8541: SLJIT_ASSERT(private_data_ptr != 0);
                   8542: BACKTRACK_AS(bracketpos_backtrack)->private_data_ptr = private_data_ptr;
1.1       misha    8543: switch(opcode)
                   8544:   {
                   8545:   case OP_BRAPOS:
                   8546:   case OP_SBRAPOS:
                   8547:   ccbegin = cc + 1 + LINK_SIZE;
                   8548:   break;
                   8549: 
                   8550:   case OP_CBRAPOS:
                   8551:   case OP_SCBRAPOS:
                   8552:   offset = GET2(cc, 1 + LINK_SIZE);
1.2       misha    8553:   /* This case cannot be optimized in the same was as
                   8554:   normal capturing brackets. */
                   8555:   SLJIT_ASSERT(common->optimized_cbracket[offset] == 0);
1.1       misha    8556:   cbraprivptr = OVECTOR_PRIV(offset);
                   8557:   offset <<= 1;
                   8558:   ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;
                   8559:   break;
                   8560: 
                   8561:   default:
1.4     ! moko     8562:   SLJIT_UNREACHABLE();
1.1       misha    8563:   break;
                   8564:   }
                   8565: 
1.2       misha    8566: framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);
                   8567: BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize;
1.1       misha    8568: if (framesize < 0)
                   8569:   {
1.2       misha    8570:   if (offset != 0)
                   8571:     {
                   8572:     stacksize = 2;
                   8573:     if (common->capture_last_ptr != 0)
                   8574:       stacksize++;
                   8575:     }
                   8576:   else
                   8577:     stacksize = 1;
                   8578: 
                   8579:   if (needs_control_head)
                   8580:     stacksize++;
1.1       misha    8581:   if (!zero)
                   8582:     stacksize++;
1.2       misha    8583: 
                   8584:   BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
1.1       misha    8585:   allocate_stack(common, stacksize);
1.2       misha    8586:   if (framesize == no_frame)
1.3       moko     8587:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);
1.1       misha    8588: 
1.2       misha    8589:   stack = 0;
                   8590:   if (offset != 0)
1.1       misha    8591:     {
1.2       misha    8592:     stack = 2;
1.3       moko     8593:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
                   8594:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
1.1       misha    8595:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
1.2       misha    8596:     if (common->capture_last_ptr != 0)
1.3       moko     8597:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
1.1       misha    8598:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
1.2       misha    8599:     if (needs_control_head)
1.3       moko     8600:       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
1.2       misha    8601:     if (common->capture_last_ptr != 0)
                   8602:       {
                   8603:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
                   8604:       stack = 3;
                   8605:       }
1.1       misha    8606:     }
                   8607:   else
1.2       misha    8608:     {
                   8609:     if (needs_control_head)
1.3       moko     8610:       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
1.1       misha    8611:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
1.2       misha    8612:     stack = 1;
                   8613:     }
1.1       misha    8614: 
1.2       misha    8615:   if (needs_control_head)
                   8616:     stack++;
1.1       misha    8617:   if (!zero)
1.2       misha    8618:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), SLJIT_IMM, 1);
                   8619:   if (needs_control_head)
                   8620:     {
                   8621:     stack--;
                   8622:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);
                   8623:     }
1.1       misha    8624:   }
                   8625: else
                   8626:   {
                   8627:   stacksize = framesize + 1;
                   8628:   if (!zero)
                   8629:     stacksize++;
1.2       misha    8630:   if (needs_control_head)
1.1       misha    8631:     stacksize++;
1.2       misha    8632:   if (offset == 0)
                   8633:     stacksize++;
                   8634:   BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
                   8635: 
1.1       misha    8636:   allocate_stack(common, stacksize);
1.3       moko     8637:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    8638:   if (needs_control_head)
1.3       moko     8639:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
1.4     ! moko     8640:   OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
1.1       misha    8641: 
                   8642:   stack = 0;
                   8643:   if (!zero)
                   8644:     {
                   8645:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);
1.2       misha    8646:     stack = 1;
                   8647:     }
                   8648:   if (needs_control_head)
                   8649:     {
                   8650:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);
1.1       misha    8651:     stack++;
                   8652:     }
1.2       misha    8653:   if (offset == 0)
1.1       misha    8654:     {
                   8655:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);
                   8656:     stack++;
                   8657:     }
                   8658:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);
1.2       misha    8659:   init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize, FALSE);
                   8660:   stack -= 1 + (offset == 0);
1.1       misha    8661:   }
                   8662: 
1.2       misha    8663: if (offset != 0)
1.3       moko     8664:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);
1.1       misha    8665: 
                   8666: loop = LABEL();
                   8667: while (*cc != OP_KETRPOS)
                   8668:   {
1.2       misha    8669:   backtrack->top = NULL;
                   8670:   backtrack->topbacktracks = NULL;
1.1       misha    8671:   cc += GET(cc, 1);
                   8672: 
1.2       misha    8673:   compile_matchingpath(common, ccbegin, cc, backtrack);
1.1       misha    8674:   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   8675:     return NULL;
                   8676: 
                   8677:   if (framesize < 0)
                   8678:     {
1.2       misha    8679:     if (framesize == no_frame)
1.3       moko     8680:       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.1       misha    8681: 
1.2       misha    8682:     if (offset != 0)
1.1       misha    8683:       {
1.3       moko     8684:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);
                   8685:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
                   8686:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);
1.2       misha    8687:       if (common->capture_last_ptr != 0)
1.3       moko     8688:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);
                   8689:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);
1.1       misha    8690:       }
                   8691:     else
                   8692:       {
                   8693:       if (opcode == OP_SBRAPOS)
                   8694:         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   8695:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   8696:       }
                   8697: 
1.4     ! moko     8698:     /* Even if the match is empty, we need to reset the control head. */
        !          8699:     if (needs_control_head)
        !          8700:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
        !          8701: 
1.1       misha    8702:     if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
1.3       moko     8703:       add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));
1.1       misha    8704: 
                   8705:     if (!zero)
                   8706:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
                   8707:     }
                   8708:   else
                   8709:     {
1.2       misha    8710:     if (offset != 0)
1.1       misha    8711:       {
1.4     ! moko     8712:       OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw));
1.3       moko     8713:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);
                   8714:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
                   8715:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);
1.2       misha    8716:       if (common->capture_last_ptr != 0)
1.3       moko     8717:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);
                   8718:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);
1.1       misha    8719:       }
                   8720:     else
                   8721:       {
1.3       moko     8722:       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.4     ! moko     8723:       OP2(SLJIT_SUB, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
1.1       misha    8724:       if (opcode == OP_SBRAPOS)
1.4     ! moko     8725:         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));
        !          8726:       OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(-framesize - 2), STR_PTR, 0);
1.1       misha    8727:       }
                   8728: 
1.4     ! moko     8729:     /* Even if the match is empty, we need to reset the control head. */
        !          8730:     if (needs_control_head)
        !          8731:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
        !          8732: 
1.1       misha    8733:     if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
1.3       moko     8734:       add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));
1.1       misha    8735: 
                   8736:     if (!zero)
                   8737:       {
                   8738:       if (framesize < 0)
                   8739:         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
                   8740:       else
                   8741:         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
                   8742:       }
                   8743:     }
1.2       misha    8744: 
1.1       misha    8745:   JUMPTO(SLJIT_JUMP, loop);
                   8746:   flush_stubs(common);
                   8747: 
1.2       misha    8748:   compile_backtrackingpath(common, backtrack->top);
1.1       misha    8749:   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   8750:     return NULL;
1.2       misha    8751:   set_jumps(backtrack->topbacktracks, LABEL());
1.1       misha    8752: 
                   8753:   if (framesize < 0)
                   8754:     {
1.2       misha    8755:     if (offset != 0)
1.3       moko     8756:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);
1.1       misha    8757:     else
                   8758:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   8759:     }
                   8760:   else
                   8761:     {
1.2       misha    8762:     if (offset != 0)
1.1       misha    8763:       {
                   8764:       /* Last alternative. */
                   8765:       if (*cc == OP_KETRPOS)
1.3       moko     8766:         OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
                   8767:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);
1.1       misha    8768:       }
                   8769:     else
                   8770:       {
1.3       moko     8771:       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.4     ! moko     8772:       OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));
1.1       misha    8773:       }
                   8774:     }
                   8775: 
                   8776:   if (*cc == OP_KETRPOS)
                   8777:     break;
                   8778:   ccbegin = cc + 1 + LINK_SIZE;
                   8779:   }
                   8780: 
1.2       misha    8781: /* We don't have to restore the control head in case of a failed match. */
                   8782: 
                   8783: backtrack->topbacktracks = NULL;
1.1       misha    8784: if (!zero)
                   8785:   {
                   8786:   if (framesize < 0)
1.3       moko     8787:     add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
1.2       misha    8788:   else /* TMP2 is set to [private_data_ptr] above. */
1.4     ! moko     8789:     add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), STACK(-stacksize), SLJIT_IMM, 0));
1.1       misha    8790:   }
                   8791: 
                   8792: /* None of them matched. */
                   8793: set_jumps(emptymatch, LABEL());
1.2       misha    8794: count_match(common);
1.1       misha    8795: return cc + 1 + LINK_SIZE;
                   8796: }
                   8797: 
1.4     ! moko     8798: static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, sljit_u32 *max, sljit_u32 *exact, pcre_uchar **end)
1.1       misha    8799: {
                   8800: int class_len;
                   8801: 
                   8802: *opcode = *cc;
1.4     ! moko     8803: *exact = 0;
        !          8804: 
1.1       misha    8805: if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)
                   8806:   {
                   8807:   cc++;
                   8808:   *type = OP_CHAR;
                   8809:   }
                   8810: else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)
                   8811:   {
                   8812:   cc++;
                   8813:   *type = OP_CHARI;
                   8814:   *opcode -= OP_STARI - OP_STAR;
                   8815:   }
                   8816: else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)
                   8817:   {
                   8818:   cc++;
                   8819:   *type = OP_NOT;
                   8820:   *opcode -= OP_NOTSTAR - OP_STAR;
                   8821:   }
                   8822: else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)
                   8823:   {
                   8824:   cc++;
                   8825:   *type = OP_NOTI;
                   8826:   *opcode -= OP_NOTSTARI - OP_STAR;
                   8827:   }
                   8828: else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)
                   8829:   {
                   8830:   cc++;
                   8831:   *opcode -= OP_TYPESTAR - OP_STAR;
1.4     ! moko     8832:   *type = OP_END;
1.1       misha    8833:   }
                   8834: else
                   8835:   {
1.3       moko     8836:   SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS);
1.1       misha    8837:   *type = *opcode;
                   8838:   cc++;
                   8839:   class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0);
                   8840:   *opcode = cc[class_len - 1];
1.4     ! moko     8841: 
1.1       misha    8842:   if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)
                   8843:     {
                   8844:     *opcode -= OP_CRSTAR - OP_STAR;
1.4     ! moko     8845:     *end = cc + class_len;
        !          8846: 
        !          8847:     if (*opcode == OP_PLUS || *opcode == OP_MINPLUS)
        !          8848:       {
        !          8849:       *exact = 1;
        !          8850:       *opcode -= OP_PLUS - OP_STAR;
        !          8851:       }
1.1       misha    8852:     }
1.3       moko     8853:   else if (*opcode >= OP_CRPOSSTAR && *opcode <= OP_CRPOSQUERY)
                   8854:     {
                   8855:     *opcode -= OP_CRPOSSTAR - OP_POSSTAR;
1.4     ! moko     8856:     *end = cc + class_len;
        !          8857: 
        !          8858:     if (*opcode == OP_POSPLUS)
        !          8859:       {
        !          8860:       *exact = 1;
        !          8861:       *opcode = OP_POSSTAR;
        !          8862:       }
1.3       moko     8863:     }
1.1       misha    8864:   else
                   8865:     {
1.3       moko     8866:     SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE);
                   8867:     *max = GET2(cc, (class_len + IMM2_SIZE));
1.4     ! moko     8868:     *exact = GET2(cc, class_len);
1.1       misha    8869: 
1.4     ! moko     8870:     if (*max == 0)
        !          8871:       {
        !          8872:       if (*opcode == OP_CRPOSRANGE)
        !          8873:         *opcode = OP_POSSTAR;
        !          8874:       else
        !          8875:         *opcode -= OP_CRRANGE - OP_STAR;
        !          8876:       }
        !          8877:     else
1.1       misha    8878:       {
1.4     ! moko     8879:       *max -= *exact;
        !          8880:       if (*max == 0)
        !          8881:         *opcode = OP_EXACT;
        !          8882:       else if (*max == 1)
        !          8883:         {
        !          8884:         if (*opcode == OP_CRPOSRANGE)
        !          8885:           *opcode = OP_POSQUERY;
        !          8886:         else
        !          8887:           *opcode -= OP_CRRANGE - OP_QUERY;
        !          8888:         }
        !          8889:       else
        !          8890:         {
        !          8891:         if (*opcode == OP_CRPOSRANGE)
        !          8892:           *opcode = OP_POSUPTO;
        !          8893:         else
        !          8894:           *opcode -= OP_CRRANGE - OP_UPTO;
        !          8895:         }
1.1       misha    8896:       }
1.4     ! moko     8897:     *end = cc + class_len + 2 * IMM2_SIZE;
1.1       misha    8898:     }
                   8899:   return cc;
                   8900:   }
                   8901: 
1.4     ! moko     8902: switch(*opcode)
1.1       misha    8903:   {
1.4     ! moko     8904:   case OP_EXACT:
        !          8905:   *exact = GET2(cc, 0);
        !          8906:   cc += IMM2_SIZE;
        !          8907:   break;
        !          8908: 
        !          8909:   case OP_PLUS:
        !          8910:   case OP_MINPLUS:
        !          8911:   *exact = 1;
        !          8912:   *opcode -= OP_PLUS - OP_STAR;
        !          8913:   break;
        !          8914: 
        !          8915:   case OP_POSPLUS:
        !          8916:   *exact = 1;
        !          8917:   *opcode = OP_POSSTAR;
        !          8918:   break;
        !          8919: 
        !          8920:   case OP_UPTO:
        !          8921:   case OP_MINUPTO:
        !          8922:   case OP_POSUPTO:
1.3       moko     8923:   *max = GET2(cc, 0);
1.1       misha    8924:   cc += IMM2_SIZE;
1.4     ! moko     8925:   break;
1.1       misha    8926:   }
                   8927: 
1.4     ! moko     8928: if (*type == OP_END)
1.1       misha    8929:   {
                   8930:   *type = *cc;
1.4     ! moko     8931:   *end = next_opcode(common, cc);
1.1       misha    8932:   cc++;
                   8933:   return cc;
                   8934:   }
                   8935: 
1.4     ! moko     8936: *end = cc + 1;
1.1       misha    8937: #ifdef SUPPORT_UTF
1.4     ! moko     8938: if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);
1.1       misha    8939: #endif
                   8940: return cc;
                   8941: }
                   8942: 
1.2       misha    8943: static pcre_uchar *compile_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1       misha    8944: {
                   8945: DEFINE_COMPILER;
1.2       misha    8946: backtrack_common *backtrack;
1.1       misha    8947: pcre_uchar opcode;
                   8948: pcre_uchar type;
1.4     ! moko     8949: sljit_u32 max = 0, exact;
        !          8950: BOOL fast_fail;
        !          8951: sljit_s32 fast_str_ptr;
        !          8952: BOOL charpos_enabled;
        !          8953: pcre_uchar charpos_char;
        !          8954: unsigned int charpos_othercasebit;
1.3       moko     8955: pcre_uchar *end;
1.4     ! moko     8956: jump_list *no_match = NULL;
        !          8957: jump_list *no_char1_match = NULL;
1.1       misha    8958: struct sljit_jump *jump = NULL;
                   8959: struct sljit_label *label;
1.2       misha    8960: int private_data_ptr = PRIVATE_DATA(cc);
1.3       moko     8961: int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP);
1.2       misha    8962: int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;
                   8963: int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);
                   8964: int tmp_base, tmp_offset;
1.1       misha    8965: 
1.4     ! moko     8966: PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL);
        !          8967: 
        !          8968: fast_str_ptr = PRIVATE_DATA(cc + 1);
        !          8969: fast_fail = TRUE;
        !          8970: 
        !          8971: SLJIT_ASSERT(common->fast_forward_bc_ptr == NULL || fast_str_ptr == 0 || cc == common->fast_forward_bc_ptr);
        !          8972: 
        !          8973: if (cc == common->fast_forward_bc_ptr)
        !          8974:   fast_fail = FALSE;
        !          8975: else if (common->fast_fail_start_ptr == 0)
        !          8976:   fast_str_ptr = 0;
        !          8977: 
        !          8978: SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || fast_str_ptr == 0
        !          8979:   || (fast_str_ptr >= common->fast_fail_start_ptr && fast_str_ptr <= common->fast_fail_end_ptr));
1.1       misha    8980: 
1.4     ! moko     8981: cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end);
1.1       misha    8982: 
1.4     ! moko     8983: if (type != OP_EXTUNI)
1.2       misha    8984:   {
                   8985:   tmp_base = TMP3;
                   8986:   tmp_offset = 0;
1.4     ! moko     8987:   }
        !          8988: else
        !          8989:   {
        !          8990:   tmp_base = SLJIT_MEM1(SLJIT_SP);
        !          8991:   tmp_offset = POSSESSIVE0;
        !          8992:   }
1.2       misha    8993: 
1.4     ! moko     8994: if (fast_fail && fast_str_ptr != 0)
        !          8995:   add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), fast_str_ptr));
1.2       misha    8996: 
1.4     ! moko     8997: /* Handle fixed part first. */
        !          8998: if (exact > 1)
        !          8999:   {
        !          9000:   SLJIT_ASSERT(fast_str_ptr == 0);
        !          9001:   if (common->mode == JIT_COMPILE
        !          9002: #ifdef SUPPORT_UTF
        !          9003:       && !common->utf
        !          9004: #endif
        !          9005:       && type != OP_ANYNL && type != OP_EXTUNI)
        !          9006:     {
        !          9007:     OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));
        !          9008:     add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0));
        !          9009:     OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);
        !          9010:     label = LABEL();
        !          9011:     compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
        !          9012:     OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
        !          9013:     JUMPTO(SLJIT_NOT_ZERO, label);
        !          9014:     }
        !          9015:   else
        !          9016:     {
        !          9017:     OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);
        !          9018:     label = LABEL();
        !          9019:     compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);
        !          9020:     OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
        !          9021:     JUMPTO(SLJIT_NOT_ZERO, label);
        !          9022:     }
1.2       misha    9023:   }
1.4     ! moko     9024: else if (exact == 1)
        !          9025:   compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);
1.2       misha    9026: 
1.1       misha    9027: switch(opcode)
                   9028:   {
                   9029:   case OP_STAR:
                   9030:   case OP_UPTO:
1.4     ! moko     9031:   SLJIT_ASSERT(fast_str_ptr == 0 || opcode == OP_STAR);
        !          9032: 
1.1       misha    9033:   if (type == OP_ANYNL || type == OP_EXTUNI)
                   9034:     {
1.2       misha    9035:     SLJIT_ASSERT(private_data_ptr == 0);
1.4     ! moko     9036:     SLJIT_ASSERT(fast_str_ptr == 0);
        !          9037: 
        !          9038:     allocate_stack(common, 2);
        !          9039:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
        !          9040:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
1.2       misha    9041: 
1.4     ! moko     9042:     if (opcode == OP_UPTO)
        !          9043:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, max);
1.1       misha    9044: 
                   9045:     label = LABEL();
1.4     ! moko     9046:     compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE);
        !          9047:     if (opcode == OP_UPTO)
1.1       misha    9048:       {
1.3       moko     9049:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0);
1.4     ! moko     9050:       OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
        !          9051:       jump = JUMP(SLJIT_ZERO);
1.3       moko     9052:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0);
1.1       misha    9053:       }
                   9054: 
1.2       misha    9055:     /* We cannot use TMP3 because of this allocate_stack. */
1.1       misha    9056:     allocate_stack(common, 1);
                   9057:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   9058:     JUMPTO(SLJIT_JUMP, label);
                   9059:     if (jump != NULL)
                   9060:       JUMPHERE(jump);
                   9061:     }
                   9062:   else
                   9063:     {
1.4     ! moko     9064:     charpos_enabled = FALSE;
        !          9065:     charpos_char = 0;
        !          9066:     charpos_othercasebit = 0;
        !          9067: 
        !          9068:     if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))
        !          9069:       {
        !          9070:       charpos_enabled = TRUE;
        !          9071: #ifdef SUPPORT_UTF
        !          9072:       charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);
        !          9073: #endif
        !          9074:       if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1))
        !          9075:         {
        !          9076:         charpos_othercasebit = char_get_othercase_bit(common, end + 1);
        !          9077:         if (charpos_othercasebit == 0)
        !          9078:           charpos_enabled = FALSE;
        !          9079:         }
        !          9080: 
        !          9081:       if (charpos_enabled)
        !          9082:         {
        !          9083:         charpos_char = end[1];
        !          9084:         /* Consumpe the OP_CHAR opcode. */
        !          9085:         end += 2;
        !          9086: #if defined COMPILE_PCRE8
        !          9087:         SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);
        !          9088: #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
        !          9089:         SLJIT_ASSERT((charpos_othercasebit >> 9) == 0);
        !          9090:         if ((charpos_othercasebit & 0x100) != 0)
        !          9091:           charpos_othercasebit = (charpos_othercasebit & 0xff) << 8;
        !          9092: #endif
        !          9093:         if (charpos_othercasebit != 0)
        !          9094:           charpos_char |= charpos_othercasebit;
        !          9095: 
        !          9096:         BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE;
        !          9097:         BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char;
        !          9098:         BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit;
        !          9099:         }
        !          9100:       }
        !          9101: 
        !          9102:     if (charpos_enabled)
        !          9103:       {
        !          9104:       if (opcode == OP_UPTO)
        !          9105:         OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1);
        !          9106: 
        !          9107:       /* Search the first instance of charpos_char. */
        !          9108:       jump = JUMP(SLJIT_JUMP);
        !          9109:       label = LABEL();
        !          9110:       if (opcode == OP_UPTO)
        !          9111:         {
        !          9112:         OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
        !          9113:         add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO));
        !          9114:         }
        !          9115:       compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
        !          9116:       if (fast_str_ptr != 0)
        !          9117:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
        !          9118:       JUMPHERE(jump);
        !          9119: 
        !          9120:       detect_partial_match(common, &backtrack->topbacktracks);
        !          9121:       OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
        !          9122:       if (charpos_othercasebit != 0)
        !          9123:         OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
        !          9124:       CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
        !          9125: 
        !          9126:       if (private_data_ptr == 0)
        !          9127:         allocate_stack(common, 2);
        !          9128:       OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
1.2       misha    9129:       OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
1.4     ! moko     9130:       if (opcode == OP_UPTO)
        !          9131:         {
        !          9132:         OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
        !          9133:         add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
        !          9134:         }
        !          9135: 
        !          9136:       /* Search the last instance of charpos_char. */
        !          9137:       label = LABEL();
        !          9138:       compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
        !          9139:       if (fast_str_ptr != 0)
        !          9140:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
        !          9141:       detect_partial_match(common, &no_match);
        !          9142:       OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
        !          9143:       if (charpos_othercasebit != 0)
        !          9144:         OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
        !          9145:       if (opcode == OP_STAR)
        !          9146:         {
        !          9147:         CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
        !          9148:         OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
        !          9149:         }
        !          9150:       else
        !          9151:         {
        !          9152:         jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);
        !          9153:         OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
        !          9154:         JUMPHERE(jump);
        !          9155:         }
        !          9156: 
        !          9157:       if (opcode == OP_UPTO)
        !          9158:         {
        !          9159:         OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
        !          9160:         JUMPTO(SLJIT_NOT_ZERO, label);
        !          9161:         }
        !          9162:       else
        !          9163:         JUMPTO(SLJIT_JUMP, label);
        !          9164: 
        !          9165:       set_jumps(no_match, LABEL());
        !          9166:       OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
        !          9167:       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          9168:       OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
        !          9169:       }
        !          9170: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          9171:     else if (common->utf)
1.1       misha    9172:       {
1.4     ! moko     9173:       if (private_data_ptr == 0)
        !          9174:         allocate_stack(common, 2);
        !          9175: 
        !          9176:       OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
        !          9177:       OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
        !          9178: 
        !          9179:       if (opcode == OP_UPTO)
        !          9180:         OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
        !          9181: 
        !          9182:       label = LABEL();
        !          9183:       compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
        !          9184:       OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
        !          9185: 
        !          9186:       if (opcode == OP_UPTO)
        !          9187:         {
        !          9188:         OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
        !          9189:         JUMPTO(SLJIT_NOT_ZERO, label);
        !          9190:         }
        !          9191:       else
        !          9192:         JUMPTO(SLJIT_JUMP, label);
        !          9193: 
        !          9194:       set_jumps(no_match, LABEL());
        !          9195:       OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
        !          9196:       if (fast_str_ptr != 0)
        !          9197:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
1.1       misha    9198:       }
1.4     ! moko     9199: #endif
1.1       misha    9200:     else
                   9201:       {
1.4     ! moko     9202:       if (private_data_ptr == 0)
        !          9203:         allocate_stack(common, 2);
        !          9204: 
        !          9205:       OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
        !          9206:       if (opcode == OP_UPTO)
        !          9207:         OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
        !          9208: 
        !          9209:       label = LABEL();
        !          9210:       detect_partial_match(common, &no_match);
        !          9211:       compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
        !          9212:       if (opcode == OP_UPTO)
        !          9213:         {
        !          9214:         OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
        !          9215:         JUMPTO(SLJIT_NOT_ZERO, label);
        !          9216:         OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          9217:         }
        !          9218:       else
        !          9219:         JUMPTO(SLJIT_JUMP, label);
        !          9220: 
        !          9221:       set_jumps(no_char1_match, LABEL());
        !          9222:       OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          9223:       set_jumps(no_match, LABEL());
        !          9224:       OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
        !          9225:       if (fast_str_ptr != 0)
        !          9226:         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
        !          9227:       }
1.1       misha    9228:     }
1.4     ! moko     9229:   BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
1.1       misha    9230:   break;
                   9231: 
                   9232:   case OP_MINSTAR:
1.2       misha    9233:   if (private_data_ptr == 0)
                   9234:     allocate_stack(common, 1);
                   9235:   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
1.4     ! moko     9236:   BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
        !          9237:   if (fast_str_ptr != 0)
        !          9238:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
1.1       misha    9239:   break;
                   9240: 
                   9241:   case OP_MINUPTO:
1.4     ! moko     9242:   SLJIT_ASSERT(fast_str_ptr == 0);
1.2       misha    9243:   if (private_data_ptr == 0)
                   9244:     allocate_stack(common, 2);
                   9245:   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
1.4     ! moko     9246:   OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, max + 1);
        !          9247:   BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
1.1       misha    9248:   break;
                   9249: 
                   9250:   case OP_QUERY:
                   9251:   case OP_MINQUERY:
1.4     ! moko     9252:   SLJIT_ASSERT(fast_str_ptr == 0);
1.2       misha    9253:   if (private_data_ptr == 0)
                   9254:     allocate_stack(common, 1);
                   9255:   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
1.1       misha    9256:   if (opcode == OP_QUERY)
1.4     ! moko     9257:     compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE);
        !          9258:   BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
1.1       misha    9259:   break;
                   9260: 
                   9261:   case OP_EXACT:
1.4     ! moko     9262:   break;
        !          9263: 
        !          9264:   case OP_POSSTAR:
        !          9265: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          9266:   if (common->utf)
        !          9267:     {
        !          9268:     OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
        !          9269:     label = LABEL();
        !          9270:     compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
        !          9271:     OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
        !          9272:     JUMPTO(SLJIT_JUMP, label);
        !          9273:     set_jumps(no_match, LABEL());
        !          9274:     OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
        !          9275:     if (fast_str_ptr != 0)
        !          9276:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
        !          9277:     break;
        !          9278:     }
        !          9279: #endif
1.1       misha    9280:   label = LABEL();
1.4     ! moko     9281:   detect_partial_match(common, &no_match);
        !          9282:   compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
        !          9283:   JUMPTO(SLJIT_JUMP, label);
        !          9284:   set_jumps(no_char1_match, LABEL());
        !          9285:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          9286:   set_jumps(no_match, LABEL());
        !          9287:   if (fast_str_ptr != 0)
        !          9288:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
1.1       misha    9289:   break;
                   9290: 
                   9291:   case OP_POSUPTO:
1.4     ! moko     9292:   SLJIT_ASSERT(fast_str_ptr == 0);
        !          9293: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
        !          9294:   if (common->utf)
1.1       misha    9295:     {
1.4     ! moko     9296:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
        !          9297:     OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
        !          9298:     label = LABEL();
        !          9299:     compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
        !          9300:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
        !          9301:     OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
1.3       moko     9302:     JUMPTO(SLJIT_NOT_ZERO, label);
1.4     ! moko     9303:     set_jumps(no_match, LABEL());
        !          9304:     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);
        !          9305:     break;
1.1       misha    9306:     }
1.4     ! moko     9307: #endif
        !          9308:   OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
        !          9309:   label = LABEL();
        !          9310:   detect_partial_match(common, &no_match);
        !          9311:   compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
        !          9312:   OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
        !          9313:   JUMPTO(SLJIT_NOT_ZERO, label);
        !          9314:   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          9315:   set_jumps(no_char1_match, LABEL());
        !          9316:   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          9317:   set_jumps(no_match, LABEL());
1.1       misha    9318:   break;
                   9319: 
                   9320:   case OP_POSQUERY:
1.4     ! moko     9321:   SLJIT_ASSERT(fast_str_ptr == 0);
1.2       misha    9322:   OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
1.4     ! moko     9323:   compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
1.3       moko     9324:   OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
1.4     ! moko     9325:   set_jumps(no_match, LABEL());
1.3       moko     9326:   OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
                   9327:   break;
                   9328: 
1.1       misha    9329:   default:
1.4     ! moko     9330:   SLJIT_UNREACHABLE();
1.1       misha    9331:   break;
                   9332:   }
                   9333: 
1.2       misha    9334: count_match(common);
1.1       misha    9335: return end;
                   9336: }
                   9337: 
1.2       misha    9338: static SLJIT_INLINE pcre_uchar *compile_fail_accept_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1       misha    9339: {
                   9340: DEFINE_COMPILER;
1.2       misha    9341: backtrack_common *backtrack;
1.1       misha    9342: 
1.2       misha    9343: PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
1.1       misha    9344: 
                   9345: if (*cc == OP_FAIL)
                   9346:   {
1.2       misha    9347:   add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
1.1       misha    9348:   return cc + 1;
                   9349:   }
                   9350: 
1.3       moko     9351: if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be_empty)
1.1       misha    9352:   {
                   9353:   /* No need to check notempty conditions. */
1.2       misha    9354:   if (common->accept_label == NULL)
1.1       misha    9355:     add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
                   9356:   else
1.2       misha    9357:     JUMPTO(SLJIT_JUMP, common->accept_label);
1.1       misha    9358:   return cc + 1;
                   9359:   }
                   9360: 
1.2       misha    9361: if (common->accept_label == NULL)
1.3       moko     9362:   add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)));
1.1       misha    9363: else
1.3       moko     9364:   CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label);
1.1       misha    9365: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1.4     ! moko     9366: OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
1.3       moko     9367: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.4     ! moko     9368: OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
1.2       misha    9369: if (common->accept_label == NULL)
1.3       moko     9370:   add_jump(compiler, &common->accept, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.1       misha    9371: else
1.3       moko     9372:   CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->accept_label);
1.1       misha    9373: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1.2       misha    9374: if (common->accept_label == NULL)
1.3       moko     9375:   add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
1.1       misha    9376: else
1.3       moko     9377:   CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label);
1.2       misha    9378: add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
1.1       misha    9379: return cc + 1;
                   9380: }
                   9381: 
1.2       misha    9382: static SLJIT_INLINE pcre_uchar *compile_close_matchingpath(compiler_common *common, pcre_uchar *cc)
1.1       misha    9383: {
                   9384: DEFINE_COMPILER;
                   9385: int offset = GET2(cc, 1);
1.2       misha    9386: BOOL optimized_cbracket = common->optimized_cbracket[offset] != 0;
1.1       misha    9387: 
                   9388: /* Data will be discarded anyway... */
                   9389: if (common->currententry != NULL)
                   9390:   return cc + 1 + IMM2_SIZE;
                   9391: 
1.2       misha    9392: if (!optimized_cbracket)
1.3       moko     9393:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR_PRIV(offset));
1.1       misha    9394: offset <<= 1;
1.3       moko     9395: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
1.2       misha    9396: if (!optimized_cbracket)
1.3       moko     9397:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);
1.1       misha    9398: return cc + 1 + IMM2_SIZE;
                   9399: }
                   9400: 
1.2       misha    9401: static SLJIT_INLINE pcre_uchar *compile_control_verb_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
                   9402: {
                   9403: DEFINE_COMPILER;
                   9404: backtrack_common *backtrack;
                   9405: pcre_uchar opcode = *cc;
                   9406: pcre_uchar *ccend = cc + 1;
                   9407: 
                   9408: if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)
                   9409:   ccend += 2 + cc[1];
                   9410: 
                   9411: PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
                   9412: 
                   9413: if (opcode == OP_SKIP)
                   9414:   {
                   9415:   allocate_stack(common, 1);
                   9416:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   9417:   return ccend;
                   9418:   }
                   9419: 
                   9420: if (opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)
                   9421:   {
                   9422:   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
                   9423:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
1.3       moko     9424:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);
1.2       misha    9425:   OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
                   9426:   }
                   9427: 
                   9428: return ccend;
                   9429: }
                   9430: 
                   9431: static pcre_uchar then_trap_opcode[1] = { OP_THEN_TRAP };
                   9432: 
                   9433: static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
                   9434: {
                   9435: DEFINE_COMPILER;
                   9436: backtrack_common *backtrack;
                   9437: BOOL needs_control_head;
                   9438: int size;
                   9439: 
                   9440: PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);
                   9441: common->then_trap = BACKTRACK_AS(then_trap_backtrack);
                   9442: BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;
                   9443: BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start);
                   9444: BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head);
                   9445: 
                   9446: size = BACKTRACK_AS(then_trap_backtrack)->framesize;
                   9447: size = 3 + (size < 0 ? 0 : size);
                   9448: 
1.3       moko     9449: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
1.2       misha    9450: allocate_stack(common, size);
                   9451: if (size > 3)
1.4     ! moko     9452:   OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw));
1.2       misha    9453: else
1.3       moko     9454:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0);
1.2       misha    9455: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start);
                   9456: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap);
                   9457: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0);
                   9458: 
                   9459: size = BACKTRACK_AS(then_trap_backtrack)->framesize;
                   9460: if (size >= 0)
                   9461:   init_frame(common, cc, ccend, size - 1, 0, FALSE);
                   9462: }
                   9463: 
                   9464: static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
1.1       misha    9465: {
                   9466: DEFINE_COMPILER;
1.2       misha    9467: backtrack_common *backtrack;
                   9468: BOOL has_then_trap = FALSE;
                   9469: then_trap_backtrack *save_then_trap = NULL;
                   9470: 
                   9471: SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS));
                   9472: 
                   9473: if (common->has_then && common->then_offsets[cc - common->start] != 0)
                   9474:   {
                   9475:   SLJIT_ASSERT(*ccend != OP_END && common->control_head_ptr != 0);
                   9476:   has_then_trap = TRUE;
                   9477:   save_then_trap = common->then_trap;
                   9478:   /* Tail item on backtrack. */
                   9479:   compile_then_trap_matchingpath(common, cc, ccend, parent);
                   9480:   }
1.1       misha    9481: 
                   9482: while (cc < ccend)
                   9483:   {
                   9484:   switch(*cc)
                   9485:     {
                   9486:     case OP_SOD:
                   9487:     case OP_SOM:
                   9488:     case OP_NOT_WORD_BOUNDARY:
                   9489:     case OP_WORD_BOUNDARY:
1.4     ! moko     9490:     case OP_EODN:
        !          9491:     case OP_EOD:
        !          9492:     case OP_DOLL:
        !          9493:     case OP_DOLLM:
        !          9494:     case OP_CIRC:
        !          9495:     case OP_CIRCM:
        !          9496:     case OP_REVERSE:
        !          9497:     cc = compile_simple_assertion_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
        !          9498:     break;
        !          9499: 
1.1       misha    9500:     case OP_NOT_DIGIT:
                   9501:     case OP_DIGIT:
                   9502:     case OP_NOT_WHITESPACE:
                   9503:     case OP_WHITESPACE:
                   9504:     case OP_NOT_WORDCHAR:
                   9505:     case OP_WORDCHAR:
                   9506:     case OP_ANY:
                   9507:     case OP_ALLANY:
                   9508:     case OP_ANYBYTE:
                   9509:     case OP_NOTPROP:
                   9510:     case OP_PROP:
                   9511:     case OP_ANYNL:
                   9512:     case OP_NOT_HSPACE:
                   9513:     case OP_HSPACE:
                   9514:     case OP_NOT_VSPACE:
                   9515:     case OP_VSPACE:
                   9516:     case OP_EXTUNI:
                   9517:     case OP_NOT:
                   9518:     case OP_NOTI:
1.4     ! moko     9519:     cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
1.1       misha    9520:     break;
                   9521: 
                   9522:     case OP_SET_SOM:
1.2       misha    9523:     PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
1.3       moko     9524:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
1.1       misha    9525:     allocate_stack(common, 1);
1.3       moko     9526:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);
1.2       misha    9527:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
1.1       misha    9528:     cc++;
                   9529:     break;
                   9530: 
                   9531:     case OP_CHAR:
                   9532:     case OP_CHARI:
1.2       misha    9533:     if (common->mode == JIT_COMPILE)
                   9534:       cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
                   9535:     else
1.4     ! moko     9536:       cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
1.1       misha    9537:     break;
                   9538: 
                   9539:     case OP_STAR:
                   9540:     case OP_MINSTAR:
                   9541:     case OP_PLUS:
                   9542:     case OP_MINPLUS:
                   9543:     case OP_QUERY:
                   9544:     case OP_MINQUERY:
                   9545:     case OP_UPTO:
                   9546:     case OP_MINUPTO:
                   9547:     case OP_EXACT:
                   9548:     case OP_POSSTAR:
                   9549:     case OP_POSPLUS:
                   9550:     case OP_POSQUERY:
                   9551:     case OP_POSUPTO:
                   9552:     case OP_STARI:
                   9553:     case OP_MINSTARI:
                   9554:     case OP_PLUSI:
                   9555:     case OP_MINPLUSI:
                   9556:     case OP_QUERYI:
                   9557:     case OP_MINQUERYI:
                   9558:     case OP_UPTOI:
                   9559:     case OP_MINUPTOI:
                   9560:     case OP_EXACTI:
                   9561:     case OP_POSSTARI:
                   9562:     case OP_POSPLUSI:
                   9563:     case OP_POSQUERYI:
                   9564:     case OP_POSUPTOI:
                   9565:     case OP_NOTSTAR:
                   9566:     case OP_NOTMINSTAR:
                   9567:     case OP_NOTPLUS:
                   9568:     case OP_NOTMINPLUS:
                   9569:     case OP_NOTQUERY:
                   9570:     case OP_NOTMINQUERY:
                   9571:     case OP_NOTUPTO:
                   9572:     case OP_NOTMINUPTO:
                   9573:     case OP_NOTEXACT:
                   9574:     case OP_NOTPOSSTAR:
                   9575:     case OP_NOTPOSPLUS:
                   9576:     case OP_NOTPOSQUERY:
                   9577:     case OP_NOTPOSUPTO:
                   9578:     case OP_NOTSTARI:
                   9579:     case OP_NOTMINSTARI:
                   9580:     case OP_NOTPLUSI:
                   9581:     case OP_NOTMINPLUSI:
                   9582:     case OP_NOTQUERYI:
                   9583:     case OP_NOTMINQUERYI:
                   9584:     case OP_NOTUPTOI:
                   9585:     case OP_NOTMINUPTOI:
                   9586:     case OP_NOTEXACTI:
                   9587:     case OP_NOTPOSSTARI:
                   9588:     case OP_NOTPOSPLUSI:
                   9589:     case OP_NOTPOSQUERYI:
                   9590:     case OP_NOTPOSUPTOI:
                   9591:     case OP_TYPESTAR:
                   9592:     case OP_TYPEMINSTAR:
                   9593:     case OP_TYPEPLUS:
                   9594:     case OP_TYPEMINPLUS:
                   9595:     case OP_TYPEQUERY:
                   9596:     case OP_TYPEMINQUERY:
                   9597:     case OP_TYPEUPTO:
                   9598:     case OP_TYPEMINUPTO:
                   9599:     case OP_TYPEEXACT:
                   9600:     case OP_TYPEPOSSTAR:
                   9601:     case OP_TYPEPOSPLUS:
                   9602:     case OP_TYPEPOSQUERY:
                   9603:     case OP_TYPEPOSUPTO:
1.2       misha    9604:     cc = compile_iterator_matchingpath(common, cc, parent);
1.1       misha    9605:     break;
                   9606: 
                   9607:     case OP_CLASS:
                   9608:     case OP_NCLASS:
1.3       moko     9609:     if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRPOSRANGE)
1.2       misha    9610:       cc = compile_iterator_matchingpath(common, cc, parent);
1.1       misha    9611:     else
1.4     ! moko     9612:       cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
1.1       misha    9613:     break;
                   9614: 
1.2       misha    9615: #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1.1       misha    9616:     case OP_XCLASS:
1.3       moko     9617:     if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRPOSRANGE)
1.2       misha    9618:       cc = compile_iterator_matchingpath(common, cc, parent);
1.1       misha    9619:     else
1.4     ! moko     9620:       cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
1.1       misha    9621:     break;
                   9622: #endif
                   9623: 
                   9624:     case OP_REF:
                   9625:     case OP_REFI:
1.3       moko     9626:     if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRPOSRANGE)
                   9627:       cc = compile_ref_iterator_matchingpath(common, cc, parent);
                   9628:     else
                   9629:       {
                   9630:       compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
                   9631:       cc += 1 + IMM2_SIZE;
                   9632:       }
                   9633:     break;
                   9634: 
                   9635:     case OP_DNREF:
                   9636:     case OP_DNREFI:
                   9637:     if (cc[1 + 2 * IMM2_SIZE] >= OP_CRSTAR && cc[1 + 2 * IMM2_SIZE] <= OP_CRPOSRANGE)
1.2       misha    9638:       cc = compile_ref_iterator_matchingpath(common, cc, parent);
1.1       misha    9639:     else
1.3       moko     9640:       {
                   9641:       compile_dnref_search(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
                   9642:       compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
                   9643:       cc += 1 + 2 * IMM2_SIZE;
                   9644:       }
1.1       misha    9645:     break;
                   9646: 
                   9647:     case OP_RECURSE:
1.2       misha    9648:     cc = compile_recurse_matchingpath(common, cc, parent);
                   9649:     break;
                   9650: 
                   9651:     case OP_CALLOUT:
                   9652:     cc = compile_callout_matchingpath(common, cc, parent);
1.1       misha    9653:     break;
                   9654: 
                   9655:     case OP_ASSERT:
                   9656:     case OP_ASSERT_NOT:
                   9657:     case OP_ASSERTBACK:
                   9658:     case OP_ASSERTBACK_NOT:
1.2       misha    9659:     PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
                   9660:     cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
1.1       misha    9661:     break;
                   9662: 
                   9663:     case OP_BRAMINZERO:
1.2       misha    9664:     PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc);
1.1       misha    9665:     cc = bracketend(cc + 1);
                   9666:     if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)
                   9667:       {
                   9668:       allocate_stack(common, 1);
                   9669:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   9670:       }
                   9671:     else
                   9672:       {
                   9673:       allocate_stack(common, 2);
                   9674:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
                   9675:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
                   9676:       }
1.2       misha    9677:     BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL();
1.4     ! moko     9678:     count_match(common);
1.1       misha    9679:     break;
                   9680: 
                   9681:     case OP_ONCE:
                   9682:     case OP_ONCE_NC:
                   9683:     case OP_BRA:
                   9684:     case OP_CBRA:
                   9685:     case OP_COND:
                   9686:     case OP_SBRA:
                   9687:     case OP_SCBRA:
                   9688:     case OP_SCOND:
1.2       misha    9689:     cc = compile_bracket_matchingpath(common, cc, parent);
1.1       misha    9690:     break;
                   9691: 
                   9692:     case OP_BRAZERO:
                   9693:     if (cc[1] > OP_ASSERTBACK_NOT)
1.2       misha    9694:       cc = compile_bracket_matchingpath(common, cc, parent);
1.1       misha    9695:     else
                   9696:       {
1.2       misha    9697:       PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
                   9698:       cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
1.1       misha    9699:       }
                   9700:     break;
                   9701: 
                   9702:     case OP_BRAPOS:
                   9703:     case OP_CBRAPOS:
                   9704:     case OP_SBRAPOS:
                   9705:     case OP_SCBRAPOS:
                   9706:     case OP_BRAPOSZERO:
1.2       misha    9707:     cc = compile_bracketpos_matchingpath(common, cc, parent);
                   9708:     break;
                   9709: 
                   9710:     case OP_MARK:
                   9711:     PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
                   9712:     SLJIT_ASSERT(common->mark_ptr != 0);
1.3       moko     9713:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
1.2       misha    9714:     allocate_stack(common, common->has_skip_arg ? 5 : 1);
                   9715:     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
                   9716:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0);
                   9717:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
1.3       moko     9718:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);
1.2       misha    9719:     OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
                   9720:     if (common->has_skip_arg)
                   9721:       {
1.3       moko     9722:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
                   9723:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0);
1.2       misha    9724:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark);
                   9725:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2));
                   9726:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0);
                   9727:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
                   9728:       }
                   9729:     cc += 1 + 2 + cc[1];
                   9730:     break;
                   9731: 
                   9732:     case OP_PRUNE:
                   9733:     case OP_PRUNE_ARG:
                   9734:     case OP_SKIP:
                   9735:     case OP_SKIP_ARG:
                   9736:     case OP_THEN:
                   9737:     case OP_THEN_ARG:
                   9738:     case OP_COMMIT:
                   9739:     cc = compile_control_verb_matchingpath(common, cc, parent);
1.1       misha    9740:     break;
                   9741: 
                   9742:     case OP_FAIL:
                   9743:     case OP_ACCEPT:
                   9744:     case OP_ASSERT_ACCEPT:
1.2       misha    9745:     cc = compile_fail_accept_matchingpath(common, cc, parent);
1.1       misha    9746:     break;
                   9747: 
                   9748:     case OP_CLOSE:
1.2       misha    9749:     cc = compile_close_matchingpath(common, cc);
1.1       misha    9750:     break;
                   9751: 
                   9752:     case OP_SKIPZERO:
                   9753:     cc = bracketend(cc + 1);
                   9754:     break;
                   9755: 
                   9756:     default:
1.4     ! moko     9757:     SLJIT_UNREACHABLE();
1.1       misha    9758:     return;
                   9759:     }
                   9760:   if (cc == NULL)
                   9761:     return;
                   9762:   }
1.2       misha    9763: 
                   9764: if (has_then_trap)
                   9765:   {
                   9766:   /* Head item on backtrack. */
                   9767:   PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);
                   9768:   BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;
                   9769:   BACKTRACK_AS(then_trap_backtrack)->then_trap = common->then_trap;
                   9770:   common->then_trap = save_then_trap;
                   9771:   }
1.1       misha    9772: SLJIT_ASSERT(cc == ccend);
                   9773: }
                   9774: 
1.2       misha    9775: #undef PUSH_BACKTRACK
                   9776: #undef PUSH_BACKTRACK_NOVALUE
                   9777: #undef BACKTRACK_AS
1.1       misha    9778: 
1.2       misha    9779: #define COMPILE_BACKTRACKINGPATH(current) \
1.1       misha    9780:   do \
                   9781:     { \
1.2       misha    9782:     compile_backtrackingpath(common, (current)); \
1.1       misha    9783:     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
                   9784:       return; \
                   9785:     } \
                   9786:   while (0)
                   9787: 
1.2       misha    9788: #define CURRENT_AS(type) ((type *)current)
1.1       misha    9789: 
1.2       misha    9790: static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)
1.1       misha    9791: {
                   9792: DEFINE_COMPILER;
                   9793: pcre_uchar *cc = current->cc;
                   9794: pcre_uchar opcode;
                   9795: pcre_uchar type;
1.4     ! moko     9796: sljit_u32 max = 0, exact;
1.1       misha    9797: struct sljit_label *label = NULL;
                   9798: struct sljit_jump *jump = NULL;
1.2       misha    9799: jump_list *jumplist = NULL;
1.4     ! moko     9800: pcre_uchar *end;
1.2       misha    9801: int private_data_ptr = PRIVATE_DATA(cc);
1.3       moko     9802: int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP);
1.2       misha    9803: int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;
                   9804: int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);
1.1       misha    9805: 
1.4     ! moko     9806: cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end);
1.1       misha    9807: 
                   9808: switch(opcode)
                   9809:   {
                   9810:   case OP_STAR:
                   9811:   case OP_UPTO:
                   9812:   if (type == OP_ANYNL || type == OP_EXTUNI)
                   9813:     {
1.2       misha    9814:     SLJIT_ASSERT(private_data_ptr == 0);
1.4     ! moko     9815:     set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL());
1.1       misha    9816:     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   9817:     free_stack(common, 1);
1.4     ! moko     9818:     CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);
1.1       misha    9819:     }
                   9820:   else
                   9821:     {
1.4     ! moko     9822:     if (CURRENT_AS(char_iterator_backtrack)->u.charpos.enabled)
1.2       misha    9823:       {
                   9824:       OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
1.4     ! moko     9825:       OP1(SLJIT_MOV, TMP2, 0, base, offset1);
        !          9826:       OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
        !          9827: 
        !          9828:       jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
        !          9829:       label = LABEL();
        !          9830:       OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
        !          9831:       OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
        !          9832:       if (CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit != 0)
        !          9833:         OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit);
        !          9834:       CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath);
        !          9835:       skip_char_back(common);
        !          9836:       CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label);
1.2       misha    9837:       }
                   9838:     else
                   9839:       {
                   9840:       OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
1.4     ! moko     9841:       jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1);
        !          9842:       skip_char_back(common);
        !          9843:       OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
        !          9844:       JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
1.2       misha    9845:       }
1.1       misha    9846:     JUMPHERE(jump);
1.2       misha    9847:     if (private_data_ptr == 0)
                   9848:       free_stack(common, 2);
1.1       misha    9849:     }
                   9850:   break;
                   9851: 
                   9852:   case OP_MINSTAR:
1.2       misha    9853:   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
1.4     ! moko     9854:   compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);
1.2       misha    9855:   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
1.4     ! moko     9856:   JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
1.2       misha    9857:   set_jumps(jumplist, LABEL());
                   9858:   if (private_data_ptr == 0)
                   9859:     free_stack(common, 1);
1.1       misha    9860:   break;
                   9861: 
                   9862:   case OP_MINUPTO:
1.4     ! moko     9863:   OP1(SLJIT_MOV, TMP1, 0, base, offset1);
1.2       misha    9864:   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
1.4     ! moko     9865:   OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
        !          9866:   add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO));
1.1       misha    9867: 
1.4     ! moko     9868:   OP1(SLJIT_MOV, base, offset1, TMP1, 0);
        !          9869:   compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);
1.2       misha    9870:   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
1.4     ! moko     9871:   JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
1.1       misha    9872: 
1.2       misha    9873:   set_jumps(jumplist, LABEL());
                   9874:   if (private_data_ptr == 0)
                   9875:     free_stack(common, 2);
1.1       misha    9876:   break;
                   9877: 
                   9878:   case OP_QUERY:
1.2       misha    9879:   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
                   9880:   OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
1.4     ! moko     9881:   CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);
1.1       misha    9882:   jump = JUMP(SLJIT_JUMP);
1.4     ! moko     9883:   set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL());
1.2       misha    9884:   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
                   9885:   OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
1.4     ! moko     9886:   JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
1.1       misha    9887:   JUMPHERE(jump);
1.2       misha    9888:   if (private_data_ptr == 0)
                   9889:     free_stack(common, 1);
1.1       misha    9890:   break;
                   9891: 
                   9892:   case OP_MINQUERY:
1.2       misha    9893:   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
                   9894:   OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
1.3       moko     9895:   jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
1.4     ! moko     9896:   compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);
        !          9897:   JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
1.2       misha    9898:   set_jumps(jumplist, LABEL());
1.1       misha    9899:   JUMPHERE(jump);
1.2       misha    9900:   if (private_data_ptr == 0)
                   9901:     free_stack(common, 1);
1.1       misha    9902:   break;
                   9903: 
                   9904:   case OP_EXACT:
                   9905:   case OP_POSSTAR:
                   9906:   case OP_POSQUERY:
                   9907:   case OP_POSUPTO:
                   9908:   break;
                   9909: 
                   9910:   default:
1.4     ! moko     9911:   SLJIT_UNREACHABLE();
1.1       misha    9912:   break;
                   9913:   }
1.4     ! moko     9914: 
        !          9915: set_jumps(current->topbacktracks, LABEL());
1.1       misha    9916: }
                   9917: 
1.2       misha    9918: static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)
1.1       misha    9919: {
                   9920: DEFINE_COMPILER;
                   9921: pcre_uchar *cc = current->cc;
1.3       moko     9922: BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
1.1       misha    9923: pcre_uchar type;
                   9924: 
1.3       moko     9925: type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE];
                   9926: 
1.1       misha    9927: if ((type & 0x1) == 0)
                   9928:   {
1.3       moko     9929:   /* Maximize case. */
1.2       misha    9930:   set_jumps(current->topbacktracks, LABEL());
1.1       misha    9931:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   9932:   free_stack(common, 1);
1.4     ! moko     9933:   CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath);
1.1       misha    9934:   return;
                   9935:   }
                   9936: 
                   9937: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.4     ! moko     9938: CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath);
1.2       misha    9939: set_jumps(current->topbacktracks, LABEL());
1.3       moko     9940: free_stack(common, ref ? 2 : 3);
1.1       misha    9941: }
                   9942: 
1.2       misha    9943: static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current)
1.1       misha    9944: {
                   9945: DEFINE_COMPILER;
                   9946: 
1.2       misha    9947: if (CURRENT_AS(recurse_backtrack)->inlined_pattern)
                   9948:   compile_backtrackingpath(common, current->top);
                   9949: set_jumps(current->topbacktracks, LABEL());
                   9950: if (CURRENT_AS(recurse_backtrack)->inlined_pattern)
                   9951:   return;
                   9952: 
                   9953: if (common->has_set_som && common->mark_ptr != 0)
                   9954:   {
                   9955:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   9956:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
                   9957:   free_stack(common, 2);
1.3       moko     9958:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP2, 0);
                   9959:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0);
1.2       misha    9960:   }
                   9961: else if (common->has_set_som || common->mark_ptr != 0)
                   9962:   {
                   9963:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   9964:   free_stack(common, 1);
1.3       moko     9965:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0);
1.2       misha    9966:   }
1.1       misha    9967: }
                   9968: 
1.2       misha    9969: static void compile_assert_backtrackingpath(compiler_common *common, struct backtrack_common *current)
1.1       misha    9970: {
                   9971: DEFINE_COMPILER;
                   9972: pcre_uchar *cc = current->cc;
                   9973: pcre_uchar bra = OP_BRA;
                   9974: struct sljit_jump *brajump = NULL;
                   9975: 
                   9976: SLJIT_ASSERT(*cc != OP_BRAMINZERO);
                   9977: if (*cc == OP_BRAZERO)
                   9978:   {
                   9979:   bra = *cc;
                   9980:   cc++;
                   9981:   }
                   9982: 
                   9983: if (bra == OP_BRAZERO)
                   9984:   {
1.2       misha    9985:   SLJIT_ASSERT(current->topbacktracks == NULL);
1.1       misha    9986:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   9987:   }
                   9988: 
1.2       misha    9989: if (CURRENT_AS(assert_backtrack)->framesize < 0)
1.1       misha    9990:   {
1.2       misha    9991:   set_jumps(current->topbacktracks, LABEL());
1.1       misha    9992: 
                   9993:   if (bra == OP_BRAZERO)
                   9994:     {
                   9995:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.3       moko     9996:     CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);
1.1       misha    9997:     free_stack(common, 1);
                   9998:     }
                   9999:   return;
                   10000:   }
                   10001: 
                   10002: if (bra == OP_BRAZERO)
                   10003:   {
                   10004:   if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)
                   10005:     {
                   10006:     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.3       moko     10007:     CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);
1.1       misha    10008:     free_stack(common, 1);
                   10009:     return;
                   10010:     }
                   10011:   free_stack(common, 1);
1.3       moko     10012:   brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
1.1       misha    10013:   }
                   10014: 
                   10015: if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
                   10016:   {
1.3       moko     10017:   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr);
1.1       misha    10018:   add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
1.4     ! moko     10019:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(assert_backtrack)->framesize - 1));
1.1       misha    10020: 
1.2       misha    10021:   set_jumps(current->topbacktracks, LABEL());
1.1       misha    10022:   }
                   10023: else
1.2       misha    10024:   set_jumps(current->topbacktracks, LABEL());
1.1       misha    10025: 
                   10026: if (bra == OP_BRAZERO)
                   10027:   {
                   10028:   /* We know there is enough place on the stack. */
1.4     ! moko     10029:   OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
1.1       misha    10030:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.2       misha    10031:   JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->matchingpath);
1.1       misha    10032:   JUMPHERE(brajump);
                   10033:   }
                   10034: }
                   10035: 
1.2       misha    10036: static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)
1.1       misha    10037: {
                   10038: DEFINE_COMPILER;
1.3       moko     10039: int opcode, stacksize, alt_count, alt_max;
1.1       misha    10040: int offset = 0;
1.2       misha    10041: int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;
                   10042: int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;
1.1       misha    10043: pcre_uchar *cc = current->cc;
                   10044: pcre_uchar *ccbegin;
                   10045: pcre_uchar *ccprev;
                   10046: pcre_uchar bra = OP_BRA;
                   10047: pcre_uchar ket;
1.2       misha    10048: assert_backtrack *assert;
1.3       moko     10049: sljit_uw *next_update_addr = NULL;
1.1       misha    10050: BOOL has_alternatives;
1.2       misha    10051: BOOL needs_control_head = FALSE;
1.1       misha    10052: struct sljit_jump *brazero = NULL;
1.3       moko     10053: struct sljit_jump *alt1 = NULL;
                   10054: struct sljit_jump *alt2 = NULL;
1.1       misha    10055: struct sljit_jump *once = NULL;
                   10056: struct sljit_jump *cond = NULL;
1.2       misha    10057: struct sljit_label *rmin_label = NULL;
                   10058: struct sljit_label *exact_label = NULL;
1.1       misha    10059: 
                   10060: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
                   10061:   {
                   10062:   bra = *cc;
                   10063:   cc++;
                   10064:   }
                   10065: 
                   10066: opcode = *cc;
1.2       misha    10067: ccbegin = bracketend(cc) - 1 - LINK_SIZE;
                   10068: ket = *ccbegin;
                   10069: if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0)
                   10070:   {
                   10071:   repeat_ptr = PRIVATE_DATA(ccbegin);
                   10072:   repeat_type = PRIVATE_DATA(ccbegin + 2);
                   10073:   repeat_count = PRIVATE_DATA(ccbegin + 3);
                   10074:   SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0);
                   10075:   if (repeat_type == OP_UPTO)
                   10076:     ket = OP_KETRMAX;
                   10077:   if (repeat_type == OP_MINUPTO)
                   10078:     ket = OP_KETRMIN;
                   10079:   }
1.1       misha    10080: ccbegin = cc;
                   10081: cc += GET(cc, 1);
                   10082: has_alternatives = *cc == OP_ALT;
                   10083: if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
1.2       misha    10084:   has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL;
1.1       misha    10085: if (opcode == OP_CBRA || opcode == OP_SCBRA)
                   10086:   offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;
                   10087: if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
                   10088:   opcode = OP_SCOND;
                   10089: if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
                   10090:   opcode = OP_ONCE;
                   10091: 
1.3       moko     10092: alt_max = has_alternatives ? no_alternatives(ccbegin) : 0;
                   10093: 
1.2       misha    10094: /* Decoding the needs_control_head in framesize. */
                   10095: if (opcode == OP_ONCE)
                   10096:   {
                   10097:   needs_control_head = (CURRENT_AS(bracket_backtrack)->u.framesize & 0x1) != 0;
                   10098:   CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;
                   10099:   }
                   10100: 
                   10101: if (ket != OP_KET && repeat_type != 0)
                   10102:   {
                   10103:   /* TMP1 is used in OP_KETRMIN below. */
                   10104:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10105:   free_stack(common, 1);
                   10106:   if (repeat_type == OP_UPTO)
1.3       moko     10107:     OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0, SLJIT_IMM, 1);
1.2       misha    10108:   else
1.3       moko     10109:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0);
1.2       misha    10110:   }
                   10111: 
1.1       misha    10112: if (ket == OP_KETRMAX)
                   10113:   {
1.2       misha    10114:   if (bra == OP_BRAZERO)
1.1       misha    10115:     {
                   10116:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10117:     free_stack(common, 1);
1.3       moko     10118:     brazero = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
1.1       misha    10119:     }
                   10120:   }
                   10121: else if (ket == OP_KETRMIN)
                   10122:   {
                   10123:   if (bra != OP_BRAMINZERO)
                   10124:     {
                   10125:     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.2       misha    10126:     if (repeat_type != 0)
                   10127:       {
                   10128:       /* TMP1 was set a few lines above. */
1.3       moko     10129:       CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
1.2       misha    10130:       /* Drop STR_PTR for non-greedy plus quantifier. */
                   10131:       if (opcode != OP_ONCE)
                   10132:         free_stack(common, 1);
                   10133:       }
                   10134:     else if (opcode >= OP_SBRA || opcode == OP_ONCE)
1.1       misha    10135:       {
                   10136:       /* Checking zero-length iteration. */
1.2       misha    10137:       if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)
1.3       moko     10138:         CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
1.1       misha    10139:       else
                   10140:         {
1.3       moko     10141:         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.4     ! moko     10142:         CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 2), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
1.1       misha    10143:         }
1.2       misha    10144:       /* Drop STR_PTR for non-greedy plus quantifier. */
1.1       misha    10145:       if (opcode != OP_ONCE)
                   10146:         free_stack(common, 1);
                   10147:       }
                   10148:     else
1.2       misha    10149:       JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
1.1       misha    10150:     }
1.2       misha    10151:   rmin_label = LABEL();
                   10152:   if (repeat_type != 0)
1.3       moko     10153:     OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
1.1       misha    10154:   }
                   10155: else if (bra == OP_BRAZERO)
                   10156:   {
                   10157:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10158:   free_stack(common, 1);
1.3       moko     10159:   brazero = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
1.1       misha    10160:   }
1.2       misha    10161: else if (repeat_type == OP_EXACT)
                   10162:   {
1.3       moko     10163:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
1.2       misha    10164:   exact_label = LABEL();
                   10165:   }
                   10166: 
                   10167: if (offset != 0)
                   10168:   {
                   10169:   if (common->capture_last_ptr != 0)
                   10170:     {
                   10171:     SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0);
                   10172:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10173:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
1.3       moko     10174:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);
1.2       misha    10175:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
                   10176:     free_stack(common, 3);
1.3       moko     10177:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP2, 0);
                   10178:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);
1.2       misha    10179:     }
                   10180:   else if (common->optimized_cbracket[offset >> 1] == 0)
                   10181:     {
                   10182:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10183:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
                   10184:     free_stack(common, 2);
1.3       moko     10185:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);
                   10186:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);
1.2       misha    10187:     }
                   10188:   }
1.1       misha    10189: 
                   10190: if (SLJIT_UNLIKELY(opcode == OP_ONCE))
                   10191:   {
1.2       misha    10192:   if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
1.1       misha    10193:     {
1.3       moko     10194:     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.1       misha    10195:     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
                   10196:     }
                   10197:   once = JUMP(SLJIT_JUMP);
                   10198:   }
                   10199: else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
                   10200:   {
                   10201:   if (has_alternatives)
                   10202:     {
                   10203:     /* Always exactly one alternative. */
                   10204:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10205:     free_stack(common, 1);
                   10206: 
1.3       moko     10207:     alt_max = 2;
                   10208:     alt1 = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
1.1       misha    10209:     }
                   10210:   }
1.3       moko     10211: else if (has_alternatives)
1.1       misha    10212:   {
                   10213:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10214:   free_stack(common, 1);
1.3       moko     10215: 
                   10216:   if (alt_max > 4)
1.1       misha    10217:     {
1.3       moko     10218:     /* Table jump if alt_max is greater than 4. */
                   10219:     next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw));
                   10220:     if (SLJIT_UNLIKELY(next_update_addr == NULL))
1.1       misha    10221:       return;
1.3       moko     10222:     sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr);
                   10223:     add_label_addr(common, next_update_addr++);
                   10224:     }
                   10225:   else
                   10226:     {
                   10227:     if (alt_max == 4)
                   10228:       alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
                   10229:     alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
1.1       misha    10230:     }
                   10231:   }
                   10232: 
1.2       misha    10233: COMPILE_BACKTRACKINGPATH(current->top);
                   10234: if (current->topbacktracks)
                   10235:   set_jumps(current->topbacktracks, LABEL());
1.1       misha    10236: 
                   10237: if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
                   10238:   {
                   10239:   /* Conditional block always has at most one alternative. */
                   10240:   if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)
                   10241:     {
                   10242:     SLJIT_ASSERT(has_alternatives);
1.2       misha    10243:     assert = CURRENT_AS(bracket_backtrack)->u.assert;
1.1       misha    10244:     if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))
                   10245:       {
1.3       moko     10246:       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr);
1.1       misha    10247:       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
1.4     ! moko     10248:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-assert->framesize - 1));
1.1       misha    10249:       }
                   10250:     cond = JUMP(SLJIT_JUMP);
1.2       misha    10251:     set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());
1.1       misha    10252:     }
1.2       misha    10253:   else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL)
1.1       misha    10254:     {
                   10255:     SLJIT_ASSERT(has_alternatives);
                   10256:     cond = JUMP(SLJIT_JUMP);
1.2       misha    10257:     set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL());
1.1       misha    10258:     }
                   10259:   else
                   10260:     SLJIT_ASSERT(!has_alternatives);
                   10261:   }
                   10262: 
                   10263: if (has_alternatives)
                   10264:   {
1.3       moko     10265:   alt_count = sizeof(sljit_uw);
1.1       misha    10266:   do
                   10267:     {
                   10268:     current->top = NULL;
1.2       misha    10269:     current->topbacktracks = NULL;
                   10270:     current->nextbacktracks = NULL;
                   10271:     /* Conditional blocks always have an additional alternative, even if it is empty. */
1.1       misha    10272:     if (*cc == OP_ALT)
                   10273:       {
                   10274:       ccprev = cc + 1 + LINK_SIZE;
                   10275:       cc += GET(cc, 1);
                   10276:       if (opcode != OP_COND && opcode != OP_SCOND)
                   10277:         {
1.2       misha    10278:         if (opcode != OP_ONCE)
                   10279:           {
                   10280:           if (private_data_ptr != 0)
1.3       moko     10281:             OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
1.2       misha    10282:           else
                   10283:             OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10284:           }
1.1       misha    10285:         else
1.2       misha    10286:           OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0));
1.1       misha    10287:         }
1.2       misha    10288:       compile_matchingpath(common, ccprev, cc, current);
1.1       misha    10289:       if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   10290:         return;
                   10291:       }
                   10292: 
1.2       misha    10293:     /* Instructions after the current alternative is successfully matched. */
                   10294:     /* There is a similar code in compile_bracket_matchingpath. */
1.1       misha    10295:     if (opcode == OP_ONCE)
1.2       misha    10296:       match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
1.1       misha    10297: 
                   10298:     stacksize = 0;
1.2       misha    10299:     if (repeat_type == OP_MINUPTO)
                   10300:       {
                   10301:       /* We need to preserve the counter. TMP2 will be used below. */
1.3       moko     10302:       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);
1.1       misha    10303:       stacksize++;
1.2       misha    10304:       }
1.1       misha    10305:     if (ket != OP_KET || bra != OP_BRA)
                   10306:       stacksize++;
1.2       misha    10307:     if (offset != 0)
                   10308:       {
                   10309:       if (common->capture_last_ptr != 0)
                   10310:         stacksize++;
                   10311:       if (common->optimized_cbracket[offset >> 1] == 0)
                   10312:         stacksize += 2;
                   10313:       }
                   10314:     if (opcode != OP_ONCE)
                   10315:       stacksize++;
1.1       misha    10316: 
1.2       misha    10317:     if (stacksize > 0)
                   10318:       allocate_stack(common, stacksize);
1.1       misha    10319: 
                   10320:     stacksize = 0;
1.2       misha    10321:     if (repeat_type == OP_MINUPTO)
                   10322:       {
                   10323:       /* TMP2 was set above. */
                   10324:       OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
                   10325:       stacksize++;
                   10326:       }
                   10327: 
1.1       misha    10328:     if (ket != OP_KET || bra != OP_BRA)
                   10329:       {
                   10330:       if (ket != OP_KET)
                   10331:         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
                   10332:       else
                   10333:         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
                   10334:       stacksize++;
                   10335:       }
                   10336: 
1.2       misha    10337:     if (offset != 0)
                   10338:       stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);
                   10339: 
1.1       misha    10340:     if (opcode != OP_ONCE)
1.3       moko     10341:       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);
1.1       misha    10342: 
1.2       misha    10343:     if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)
1.1       misha    10344:       {
1.2       misha    10345:       /* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */
                   10346:       SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));
1.3       moko     10347:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
1.1       misha    10348:       }
                   10349: 
1.2       misha    10350:     JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath);
1.1       misha    10351: 
                   10352:     if (opcode != OP_ONCE)
                   10353:       {
1.3       moko     10354:       if (alt_max > 4)
                   10355:         add_label_addr(common, next_update_addr++);
                   10356:       else
                   10357:         {
                   10358:         if (alt_count != 2 * sizeof(sljit_uw))
                   10359:           {
                   10360:           JUMPHERE(alt1);
                   10361:           if (alt_max == 3 && alt_count == sizeof(sljit_uw))
                   10362:             alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
                   10363:           }
                   10364:         else
                   10365:           {
                   10366:           JUMPHERE(alt2);
                   10367:           if (alt_max == 4)
                   10368:             alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw));
                   10369:           }
                   10370:         }
                   10371:       alt_count += sizeof(sljit_uw);
1.1       misha    10372:       }
                   10373: 
1.2       misha    10374:     COMPILE_BACKTRACKINGPATH(current->top);
                   10375:     if (current->topbacktracks)
                   10376:       set_jumps(current->topbacktracks, LABEL());
                   10377:     SLJIT_ASSERT(!current->nextbacktracks);
1.1       misha    10378:     }
                   10379:   while (*cc == OP_ALT);
                   10380: 
                   10381:   if (cond != NULL)
                   10382:     {
                   10383:     SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);
1.2       misha    10384:     assert = CURRENT_AS(bracket_backtrack)->u.assert;
1.1       misha    10385:     if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)
                   10386:       {
1.3       moko     10387:       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr);
1.1       misha    10388:       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
1.4     ! moko     10389:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-assert->framesize - 1));
1.1       misha    10390:       }
                   10391:     JUMPHERE(cond);
                   10392:     }
                   10393: 
                   10394:   /* Free the STR_PTR. */
1.2       misha    10395:   if (private_data_ptr == 0)
1.1       misha    10396:     free_stack(common, 1);
                   10397:   }
                   10398: 
                   10399: if (offset != 0)
                   10400:   {
                   10401:   /* Using both tmp register is better for instruction scheduling. */
1.2       misha    10402:   if (common->optimized_cbracket[offset >> 1] != 0)
                   10403:     {
                   10404:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10405:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
                   10406:     free_stack(common, 2);
1.3       moko     10407:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);
                   10408:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);
1.2       misha    10409:     }
                   10410:   else
                   10411:     {
                   10412:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10413:     free_stack(common, 1);
1.3       moko     10414:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);
1.2       misha    10415:     }
1.1       misha    10416:   }
                   10417: else if (opcode == OP_SBRA || opcode == OP_SCOND)
                   10418:   {
1.3       moko     10419:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0));
1.1       misha    10420:   free_stack(common, 1);
                   10421:   }
                   10422: else if (opcode == OP_ONCE)
                   10423:   {
                   10424:   cc = ccbegin + GET(ccbegin, 1);
1.2       misha    10425:   stacksize = needs_control_head ? 1 : 0;
                   10426: 
                   10427:   if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
1.1       misha    10428:     {
                   10429:     /* Reset head and drop saved frame. */
1.2       misha    10430:     stacksize += CURRENT_AS(bracket_backtrack)->u.framesize + ((ket != OP_KET || *cc == OP_ALT) ? 2 : 1);
1.1       misha    10431:     }
                   10432:   else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))
                   10433:     {
                   10434:     /* The STR_PTR must be released. */
1.2       misha    10435:     stacksize++;
1.1       misha    10436:     }
1.4     ! moko     10437: 
        !          10438:   if (stacksize > 0)
        !          10439:     free_stack(common, stacksize);
1.1       misha    10440: 
                   10441:   JUMPHERE(once);
1.2       misha    10442:   /* Restore previous private_data_ptr */
                   10443:   if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
1.4     ! moko     10444:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 1));
1.1       misha    10445:   else if (ket == OP_KETRMIN)
                   10446:     {
                   10447:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
                   10448:     /* See the comment below. */
                   10449:     free_stack(common, 2);
1.3       moko     10450:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);
1.1       misha    10451:     }
                   10452:   }
                   10453: 
1.2       misha    10454: if (repeat_type == OP_EXACT)
                   10455:   {
1.3       moko     10456:   OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
                   10457:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0);
                   10458:   CMPTO(SLJIT_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label);
1.2       misha    10459:   }
                   10460: else if (ket == OP_KETRMAX)
1.1       misha    10461:   {
                   10462:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.2       misha    10463:   if (bra != OP_BRAZERO)
                   10464:     free_stack(common, 1);
                   10465: 
1.3       moko     10466:   CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
1.1       misha    10467:   if (bra == OP_BRAZERO)
                   10468:     {
                   10469:     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
1.2       misha    10470:     JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);
1.1       misha    10471:     JUMPHERE(brazero);
1.2       misha    10472:     free_stack(common, 1);
1.1       misha    10473:     }
                   10474:   }
                   10475: else if (ket == OP_KETRMIN)
                   10476:   {
                   10477:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10478: 
1.2       misha    10479:   /* OP_ONCE removes everything in case of a backtrack, so we don't
1.1       misha    10480:   need to explicitly release the STR_PTR. The extra release would
                   10481:   affect badly the free_stack(2) above. */
                   10482:   if (opcode != OP_ONCE)
                   10483:     free_stack(common, 1);
1.3       moko     10484:   CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label);
1.1       misha    10485:   if (opcode == OP_ONCE)
                   10486:     free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);
                   10487:   else if (bra == OP_BRAMINZERO)
                   10488:     free_stack(common, 1);
                   10489:   }
                   10490: else if (bra == OP_BRAZERO)
                   10491:   {
                   10492:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.2       misha    10493:   JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);
1.1       misha    10494:   JUMPHERE(brazero);
                   10495:   }
                   10496: }
                   10497: 
1.2       misha    10498: static SLJIT_INLINE void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current)
1.1       misha    10499: {
                   10500: DEFINE_COMPILER;
                   10501: int offset;
                   10502: struct sljit_jump *jump;
                   10503: 
1.2       misha    10504: if (CURRENT_AS(bracketpos_backtrack)->framesize < 0)
1.1       misha    10505:   {
                   10506:   if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)
                   10507:     {
                   10508:     offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1;
                   10509:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10510:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
1.3       moko     10511:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);
1.2       misha    10512:     if (common->capture_last_ptr != 0)
                   10513:       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
1.3       moko     10514:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);
1.2       misha    10515:     if (common->capture_last_ptr != 0)
1.3       moko     10516:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);
1.1       misha    10517:     }
1.2       misha    10518:   set_jumps(current->topbacktracks, LABEL());
                   10519:   free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
1.1       misha    10520:   return;
                   10521:   }
                   10522: 
1.3       moko     10523: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr);
1.1       misha    10524: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
                   10525: 
1.2       misha    10526: if (current->topbacktracks)
1.1       misha    10527:   {
                   10528:   jump = JUMP(SLJIT_JUMP);
1.2       misha    10529:   set_jumps(current->topbacktracks, LABEL());
1.1       misha    10530:   /* Drop the stack frame. */
1.2       misha    10531:   free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
1.1       misha    10532:   JUMPHERE(jump);
                   10533:   }
1.4     ! moko     10534: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracketpos_backtrack)->framesize - 1));
1.1       misha    10535: }
                   10536: 
1.2       misha    10537: static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current)
1.1       misha    10538: {
1.2       misha    10539: assert_backtrack backtrack;
1.1       misha    10540: 
                   10541: current->top = NULL;
1.2       misha    10542: current->topbacktracks = NULL;
                   10543: current->nextbacktracks = NULL;
1.1       misha    10544: if (current->cc[1] > OP_ASSERTBACK_NOT)
                   10545:   {
1.2       misha    10546:   /* Manual call of compile_bracket_matchingpath and compile_bracket_backtrackingpath. */
                   10547:   compile_bracket_matchingpath(common, current->cc, current);
                   10548:   compile_bracket_backtrackingpath(common, current->top);
                   10549:   }
                   10550: else
                   10551:   {
                   10552:   memset(&backtrack, 0, sizeof(backtrack));
                   10553:   backtrack.common.cc = current->cc;
                   10554:   backtrack.matchingpath = CURRENT_AS(braminzero_backtrack)->matchingpath;
                   10555:   /* Manual call of compile_assert_matchingpath. */
                   10556:   compile_assert_matchingpath(common, current->cc, &backtrack, FALSE);
                   10557:   }
                   10558: SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks);
                   10559: }
                   10560: 
                   10561: static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current)
                   10562: {
                   10563: DEFINE_COMPILER;
                   10564: pcre_uchar opcode = *current->cc;
                   10565: struct sljit_label *loop;
                   10566: struct sljit_jump *jump;
                   10567: 
                   10568: if (opcode == OP_THEN || opcode == OP_THEN_ARG)
                   10569:   {
                   10570:   if (common->then_trap != NULL)
                   10571:     {
                   10572:     SLJIT_ASSERT(common->control_head_ptr != 0);
                   10573: 
1.3       moko     10574:     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
1.2       misha    10575:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap);
                   10576:     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start);
                   10577:     jump = JUMP(SLJIT_JUMP);
                   10578: 
                   10579:     loop = LABEL();
1.4     ! moko     10580:     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.2       misha    10581:     JUMPHERE(jump);
1.4     ! moko     10582:     CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, loop);
        !          10583:     CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0, loop);
1.2       misha    10584:     add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));
                   10585:     return;
                   10586:     }
                   10587:   else if (common->positive_assert)
                   10588:     {
                   10589:     add_jump(compiler, &common->positive_assert_quit, JUMP(SLJIT_JUMP));
                   10590:     return;
                   10591:     }
                   10592:   }
                   10593: 
                   10594: if (common->local_exit)
                   10595:   {
                   10596:   if (common->quit_label == NULL)
                   10597:     add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
                   10598:   else
                   10599:     JUMPTO(SLJIT_JUMP, common->quit_label);
                   10600:   return;
                   10601:   }
                   10602: 
                   10603: if (opcode == OP_SKIP_ARG)
                   10604:   {
                   10605:   SLJIT_ASSERT(common->control_head_ptr != 0);
1.3       moko     10606:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
                   10607:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
1.2       misha    10608:   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));
1.4     ! moko     10609:   sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark));
1.3       moko     10610:   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
1.2       misha    10611: 
                   10612:   OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
1.4     ! moko     10613:   add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0));
1.2       misha    10614:   return;
1.1       misha    10615:   }
1.2       misha    10616: 
                   10617: if (opcode == OP_SKIP)
                   10618:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.1       misha    10619: else
1.2       misha    10620:   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0);
                   10621: add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP));
                   10622: }
                   10623: 
                   10624: static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current)
                   10625: {
                   10626: DEFINE_COMPILER;
                   10627: struct sljit_jump *jump;
                   10628: int size;
                   10629: 
                   10630: if (CURRENT_AS(then_trap_backtrack)->then_trap)
1.1       misha    10631:   {
1.2       misha    10632:   common->then_trap = CURRENT_AS(then_trap_backtrack)->then_trap;
                   10633:   return;
1.1       misha    10634:   }
1.2       misha    10635: 
                   10636: size = CURRENT_AS(then_trap_backtrack)->framesize;
                   10637: size = 3 + (size < 0 ? 0 : size);
                   10638: 
                   10639: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 3));
                   10640: free_stack(common, size);
                   10641: jump = JUMP(SLJIT_JUMP);
                   10642: 
                   10643: set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL());
                   10644: /* STACK_TOP is set by THEN. */
                   10645: if (CURRENT_AS(then_trap_backtrack)->framesize >= 0)
                   10646:   add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
                   10647: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10648: free_stack(common, 3);
                   10649: 
                   10650: JUMPHERE(jump);
1.3       moko     10651: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0);
1.1       misha    10652: }
                   10653: 
1.2       misha    10654: static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current)
1.1       misha    10655: {
                   10656: DEFINE_COMPILER;
1.2       misha    10657: then_trap_backtrack *save_then_trap = common->then_trap;
1.1       misha    10658: 
                   10659: while (current)
                   10660:   {
1.2       misha    10661:   if (current->nextbacktracks != NULL)
                   10662:     set_jumps(current->nextbacktracks, LABEL());
1.1       misha    10663:   switch(*current->cc)
                   10664:     {
                   10665:     case OP_SET_SOM:
                   10666:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10667:     free_stack(common, 1);
1.3       moko     10668:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP1, 0);
1.1       misha    10669:     break;
                   10670: 
                   10671:     case OP_STAR:
                   10672:     case OP_MINSTAR:
                   10673:     case OP_PLUS:
                   10674:     case OP_MINPLUS:
                   10675:     case OP_QUERY:
                   10676:     case OP_MINQUERY:
                   10677:     case OP_UPTO:
                   10678:     case OP_MINUPTO:
                   10679:     case OP_EXACT:
                   10680:     case OP_POSSTAR:
                   10681:     case OP_POSPLUS:
                   10682:     case OP_POSQUERY:
                   10683:     case OP_POSUPTO:
                   10684:     case OP_STARI:
                   10685:     case OP_MINSTARI:
                   10686:     case OP_PLUSI:
                   10687:     case OP_MINPLUSI:
                   10688:     case OP_QUERYI:
                   10689:     case OP_MINQUERYI:
                   10690:     case OP_UPTOI:
                   10691:     case OP_MINUPTOI:
                   10692:     case OP_EXACTI:
                   10693:     case OP_POSSTARI:
                   10694:     case OP_POSPLUSI:
                   10695:     case OP_POSQUERYI:
                   10696:     case OP_POSUPTOI:
                   10697:     case OP_NOTSTAR:
                   10698:     case OP_NOTMINSTAR:
                   10699:     case OP_NOTPLUS:
                   10700:     case OP_NOTMINPLUS:
                   10701:     case OP_NOTQUERY:
                   10702:     case OP_NOTMINQUERY:
                   10703:     case OP_NOTUPTO:
                   10704:     case OP_NOTMINUPTO:
                   10705:     case OP_NOTEXACT:
                   10706:     case OP_NOTPOSSTAR:
                   10707:     case OP_NOTPOSPLUS:
                   10708:     case OP_NOTPOSQUERY:
                   10709:     case OP_NOTPOSUPTO:
                   10710:     case OP_NOTSTARI:
                   10711:     case OP_NOTMINSTARI:
                   10712:     case OP_NOTPLUSI:
                   10713:     case OP_NOTMINPLUSI:
                   10714:     case OP_NOTQUERYI:
                   10715:     case OP_NOTMINQUERYI:
                   10716:     case OP_NOTUPTOI:
                   10717:     case OP_NOTMINUPTOI:
                   10718:     case OP_NOTEXACTI:
                   10719:     case OP_NOTPOSSTARI:
                   10720:     case OP_NOTPOSPLUSI:
                   10721:     case OP_NOTPOSQUERYI:
                   10722:     case OP_NOTPOSUPTOI:
                   10723:     case OP_TYPESTAR:
                   10724:     case OP_TYPEMINSTAR:
                   10725:     case OP_TYPEPLUS:
                   10726:     case OP_TYPEMINPLUS:
                   10727:     case OP_TYPEQUERY:
                   10728:     case OP_TYPEMINQUERY:
                   10729:     case OP_TYPEUPTO:
                   10730:     case OP_TYPEMINUPTO:
                   10731:     case OP_TYPEEXACT:
                   10732:     case OP_TYPEPOSSTAR:
                   10733:     case OP_TYPEPOSPLUS:
                   10734:     case OP_TYPEPOSQUERY:
                   10735:     case OP_TYPEPOSUPTO:
                   10736:     case OP_CLASS:
                   10737:     case OP_NCLASS:
                   10738: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
                   10739:     case OP_XCLASS:
                   10740: #endif
1.2       misha    10741:     compile_iterator_backtrackingpath(common, current);
1.1       misha    10742:     break;
                   10743: 
                   10744:     case OP_REF:
                   10745:     case OP_REFI:
1.3       moko     10746:     case OP_DNREF:
                   10747:     case OP_DNREFI:
1.2       misha    10748:     compile_ref_iterator_backtrackingpath(common, current);
1.1       misha    10749:     break;
                   10750: 
                   10751:     case OP_RECURSE:
1.2       misha    10752:     compile_recurse_backtrackingpath(common, current);
1.1       misha    10753:     break;
                   10754: 
                   10755:     case OP_ASSERT:
                   10756:     case OP_ASSERT_NOT:
                   10757:     case OP_ASSERTBACK:
                   10758:     case OP_ASSERTBACK_NOT:
1.2       misha    10759:     compile_assert_backtrackingpath(common, current);
1.1       misha    10760:     break;
                   10761: 
                   10762:     case OP_ONCE:
                   10763:     case OP_ONCE_NC:
                   10764:     case OP_BRA:
                   10765:     case OP_CBRA:
                   10766:     case OP_COND:
                   10767:     case OP_SBRA:
                   10768:     case OP_SCBRA:
                   10769:     case OP_SCOND:
1.2       misha    10770:     compile_bracket_backtrackingpath(common, current);
1.1       misha    10771:     break;
                   10772: 
                   10773:     case OP_BRAZERO:
                   10774:     if (current->cc[1] > OP_ASSERTBACK_NOT)
1.2       misha    10775:       compile_bracket_backtrackingpath(common, current);
1.1       misha    10776:     else
1.2       misha    10777:       compile_assert_backtrackingpath(common, current);
1.1       misha    10778:     break;
                   10779: 
                   10780:     case OP_BRAPOS:
                   10781:     case OP_CBRAPOS:
                   10782:     case OP_SBRAPOS:
                   10783:     case OP_SCBRAPOS:
                   10784:     case OP_BRAPOSZERO:
1.2       misha    10785:     compile_bracketpos_backtrackingpath(common, current);
1.1       misha    10786:     break;
                   10787: 
                   10788:     case OP_BRAMINZERO:
1.2       misha    10789:     compile_braminzero_backtrackingpath(common, current);
                   10790:     break;
                   10791: 
                   10792:     case OP_MARK:
                   10793:     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0));
                   10794:     if (common->has_skip_arg)
                   10795:       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10796:     free_stack(common, common->has_skip_arg ? 5 : 1);
1.3       moko     10797:     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0);
1.2       misha    10798:     if (common->has_skip_arg)
1.3       moko     10799:       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0);
1.2       misha    10800:     break;
                   10801: 
                   10802:     case OP_THEN:
                   10803:     case OP_THEN_ARG:
                   10804:     case OP_PRUNE:
                   10805:     case OP_PRUNE_ARG:
                   10806:     case OP_SKIP:
                   10807:     case OP_SKIP_ARG:
                   10808:     compile_control_verb_backtrackingpath(common, current);
                   10809:     break;
                   10810: 
                   10811:     case OP_COMMIT:
                   10812:     if (!common->local_exit)
                   10813:       OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
                   10814:     if (common->quit_label == NULL)
                   10815:       add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
                   10816:     else
                   10817:       JUMPTO(SLJIT_JUMP, common->quit_label);
1.1       misha    10818:     break;
                   10819: 
1.2       misha    10820:     case OP_CALLOUT:
1.1       misha    10821:     case OP_FAIL:
                   10822:     case OP_ACCEPT:
                   10823:     case OP_ASSERT_ACCEPT:
1.2       misha    10824:     set_jumps(current->topbacktracks, LABEL());
                   10825:     break;
                   10826: 
                   10827:     case OP_THEN_TRAP:
                   10828:     /* A virtual opcode for then traps. */
                   10829:     compile_then_trap_backtrackingpath(common, current);
1.1       misha    10830:     break;
                   10831: 
                   10832:     default:
1.4     ! moko     10833:     SLJIT_UNREACHABLE();
1.1       misha    10834:     break;
                   10835:     }
                   10836:   current = current->prev;
                   10837:   }
1.2       misha    10838: common->then_trap = save_then_trap;
1.1       misha    10839: }
                   10840: 
                   10841: static SLJIT_INLINE void compile_recurse(compiler_common *common)
                   10842: {
                   10843: DEFINE_COMPILER;
                   10844: pcre_uchar *cc = common->start + common->currententry->start;
                   10845: pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);
1.4     ! moko     10846: pcre_uchar *ccend = bracketend(cc) - (1 + LINK_SIZE);
1.2       misha    10847: BOOL needs_control_head;
                   10848: int framesize = get_framesize(common, cc, NULL, TRUE, &needs_control_head);
                   10849: int private_data_size = get_private_data_copy_length(common, ccbegin, ccend, needs_control_head);
1.1       misha    10850: int alternativesize;
1.2       misha    10851: BOOL needs_frame;
                   10852: backtrack_common altbacktrack;
1.1       misha    10853: struct sljit_jump *jump;
                   10854: 
1.2       misha    10855: /* Recurse captures then. */
                   10856: common->then_trap = NULL;
                   10857: 
1.1       misha    10858: SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);
1.2       misha    10859: needs_frame = framesize >= 0;
                   10860: if (!needs_frame)
1.1       misha    10861:   framesize = 0;
                   10862: alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;
                   10863: 
1.2       misha    10864: SLJIT_ASSERT(common->currententry->entry == NULL && common->recursive_head_ptr != 0);
1.1       misha    10865: common->currententry->entry = LABEL();
                   10866: set_jumps(common->currententry->calls, common->currententry->entry);
                   10867: 
1.2       misha    10868: sljit_emit_fast_enter(compiler, TMP2, 0);
1.4     ! moko     10869: count_match(common);
1.2       misha    10870: allocate_stack(common, private_data_size + framesize + alternativesize);
                   10871: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0);
1.4     ! moko     10872: copy_private_data(common, ccbegin, ccend, TRUE, framesize + alternativesize, private_data_size + framesize + alternativesize, needs_control_head);
1.2       misha    10873: if (needs_control_head)
1.3       moko     10874:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
                   10875: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0);
1.2       misha    10876: if (needs_frame)
                   10877:   init_frame(common, cc, NULL, framesize + alternativesize - 1, alternativesize, TRUE);
1.1       misha    10878: 
                   10879: if (alternativesize > 0)
                   10880:   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
                   10881: 
1.2       misha    10882: memset(&altbacktrack, 0, sizeof(backtrack_common));
                   10883: common->quit_label = NULL;
                   10884: common->accept_label = NULL;
                   10885: common->quit = NULL;
1.1       misha    10886: common->accept = NULL;
1.2       misha    10887: altbacktrack.cc = ccbegin;
1.1       misha    10888: cc += GET(cc, 1);
                   10889: while (1)
                   10890:   {
1.2       misha    10891:   altbacktrack.top = NULL;
                   10892:   altbacktrack.topbacktracks = NULL;
1.1       misha    10893: 
1.2       misha    10894:   if (altbacktrack.cc != ccbegin)
1.1       misha    10895:     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
                   10896: 
1.2       misha    10897:   compile_matchingpath(common, altbacktrack.cc, cc, &altbacktrack);
1.1       misha    10898:   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   10899:     return;
                   10900: 
                   10901:   add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
                   10902: 
1.2       misha    10903:   compile_backtrackingpath(common, altbacktrack.top);
1.1       misha    10904:   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   10905:     return;
1.2       misha    10906:   set_jumps(altbacktrack.topbacktracks, LABEL());
1.1       misha    10907: 
                   10908:   if (*cc != OP_ALT)
                   10909:     break;
                   10910: 
1.2       misha    10911:   altbacktrack.cc = cc + 1 + LINK_SIZE;
1.1       misha    10912:   cc += GET(cc, 1);
                   10913:   }
1.2       misha    10914: 
1.1       misha    10915: /* None of them matched. */
                   10916: OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
                   10917: jump = JUMP(SLJIT_JUMP);
                   10918: 
1.2       misha    10919: if (common->quit != NULL)
                   10920:   {
                   10921:   set_jumps(common->quit, LABEL());
1.3       moko     10922:   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
1.2       misha    10923:   if (needs_frame)
                   10924:     {
1.4     ! moko     10925:     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
        !          10926:     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
1.2       misha    10927:     OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
                   10928:     }
                   10929:   OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
                   10930:   common->quit = NULL;
                   10931:   add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
                   10932:   }
                   10933: 
1.1       misha    10934: set_jumps(common->accept, LABEL());
1.3       moko     10935: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
1.2       misha    10936: if (needs_frame)
1.1       misha    10937:   {
1.4     ! moko     10938:   OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
        !          10939:   add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
1.2       misha    10940:   OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
1.1       misha    10941:   }
                   10942: OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
                   10943: 
                   10944: JUMPHERE(jump);
1.2       misha    10945: if (common->quit != NULL)
                   10946:   set_jumps(common->quit, LABEL());
1.4     ! moko     10947: copy_private_data(common, ccbegin, ccend, FALSE, framesize + alternativesize, private_data_size + framesize + alternativesize, needs_control_head);
1.2       misha    10948: free_stack(common, private_data_size + framesize + alternativesize);
                   10949: if (needs_control_head)
                   10950:   {
1.4     ! moko     10951:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-3));
        !          10952:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));
1.3       moko     10953:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP1, 0);
1.2       misha    10954:   OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
1.3       moko     10955:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0);
1.2       misha    10956:   }
                   10957: else
                   10958:   {
1.4     ! moko     10959:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));
1.2       misha    10960:   OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
1.3       moko     10961:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP2, 0);
1.2       misha    10962:   }
1.4     ! moko     10963: sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), STACK(-1));
1.1       misha    10964: }
                   10965: 
1.2       misha    10966: #undef COMPILE_BACKTRACKINGPATH
1.1       misha    10967: #undef CURRENT_AS
                   10968: 
                   10969: void
1.2       misha    10970: PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode)
1.1       misha    10971: {
                   10972: struct sljit_compiler *compiler;
1.2       misha    10973: backtrack_common rootbacktrack;
1.1       misha    10974: compiler_common common_data;
                   10975: compiler_common *common = &common_data;
1.4     ! moko     10976: const sljit_u8 *tables = re->tables;
1.1       misha    10977: pcre_study_data *study;
1.2       misha    10978: int private_data_size;
1.1       misha    10979: pcre_uchar *ccend;
1.2       misha    10980: executable_functions *functions;
1.1       misha    10981: void *executable_func;
                   10982: sljit_uw executable_size;
1.3       moko     10983: sljit_uw total_length;
                   10984: label_addr_list *label_addr;
1.2       misha    10985: struct sljit_label *mainloop_label = NULL;
                   10986: struct sljit_label *continue_match_label;
1.3       moko     10987: struct sljit_label *empty_match_found_label = NULL;
                   10988: struct sljit_label *empty_match_backtrack_label = NULL;
1.2       misha    10989: struct sljit_label *reset_match_label;
1.3       moko     10990: struct sljit_label *quit_label;
1.2       misha    10991: struct sljit_jump *jump;
                   10992: struct sljit_jump *minlength_check_failed = NULL;
1.1       misha    10993: struct sljit_jump *reqbyte_notfound = NULL;
1.3       moko     10994: struct sljit_jump *empty_match = NULL;
1.1       misha    10995: 
                   10996: SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
                   10997: study = extra->study_data;
                   10998: 
                   10999: if (!tables)
                   11000:   tables = PRIV(default_tables);
                   11001: 
1.2       misha    11002: memset(&rootbacktrack, 0, sizeof(backtrack_common));
                   11003: memset(common, 0, sizeof(compiler_common));
                   11004: rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
1.1       misha    11005: 
1.2       misha    11006: common->start = rootbacktrack.cc;
1.3       moko     11007: common->read_only_data_head = NULL;
1.1       misha    11008: common->fcc = tables + fcc_offset;
1.2       misha    11009: common->lcc = (sljit_sw)(tables + lcc_offset);
                   11010: common->mode = mode;
1.3       moko     11011: common->might_be_empty = study->minlength == 0;
1.1       misha    11012: common->nltype = NLTYPE_FIXED;
                   11013: switch(re->options & PCRE_NEWLINE_BITS)
                   11014:   {
                   11015:   case 0:
                   11016:   /* Compile-time default */
1.2       misha    11017:   switch(NEWLINE)
1.1       misha    11018:     {
                   11019:     case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
                   11020:     case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
                   11021:     default: common->newline = NEWLINE; break;
                   11022:     }
                   11023:   break;
                   11024:   case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break;
                   11025:   case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break;
                   11026:   case PCRE_NEWLINE_CR+
                   11027:        PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;
                   11028:   case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
                   11029:   case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
                   11030:   default: return;
                   11031:   }
1.3       moko     11032: common->nlmax = READ_CHAR_MAX;
                   11033: common->nlmin = 0;
1.1       misha    11034: if ((re->options & PCRE_BSR_ANYCRLF) != 0)
                   11035:   common->bsr_nltype = NLTYPE_ANYCRLF;
                   11036: else if ((re->options & PCRE_BSR_UNICODE) != 0)
                   11037:   common->bsr_nltype = NLTYPE_ANY;
                   11038: else
                   11039:   {
                   11040: #ifdef BSR_ANYCRLF
                   11041:   common->bsr_nltype = NLTYPE_ANYCRLF;
                   11042: #else
                   11043:   common->bsr_nltype = NLTYPE_ANY;
                   11044: #endif
                   11045:   }
1.3       moko     11046: common->bsr_nlmax = READ_CHAR_MAX;
                   11047: common->bsr_nlmin = 0;
1.1       misha    11048: common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
1.2       misha    11049: common->ctypes = (sljit_sw)(tables + ctypes_offset);
1.3       moko     11050: common->name_table = ((pcre_uchar *)re) + re->name_table_offset;
1.1       misha    11051: common->name_count = re->name_count;
                   11052: common->name_entry_size = re->name_entry_size;
                   11053: common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
                   11054: #ifdef SUPPORT_UTF
1.2       misha    11055: /* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */
1.1       misha    11056: common->utf = (re->options & PCRE_UTF8) != 0;
                   11057: #ifdef SUPPORT_UCP
                   11058: common->use_ucp = (re->options & PCRE_UCP) != 0;
                   11059: #endif
1.3       moko     11060: if (common->utf)
                   11061:   {
                   11062:   if (common->nltype == NLTYPE_ANY)
                   11063:     common->nlmax = 0x2029;
                   11064:   else if (common->nltype == NLTYPE_ANYCRLF)
                   11065:     common->nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;
                   11066:   else
                   11067:     {
                   11068:     /* We only care about the first newline character. */
                   11069:     common->nlmax = common->newline & 0xff;
                   11070:     }
                   11071: 
                   11072:   if (common->nltype == NLTYPE_FIXED)
                   11073:     common->nlmin = common->newline & 0xff;
                   11074:   else
                   11075:     common->nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;
                   11076: 
                   11077:   if (common->bsr_nltype == NLTYPE_ANY)
                   11078:     common->bsr_nlmax = 0x2029;
                   11079:   else
                   11080:     common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;
                   11081:   common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;
                   11082:   }
1.2       misha    11083: #endif /* SUPPORT_UTF */
1.3       moko     11084: ccend = bracketend(common->start);
1.2       misha    11085: 
                   11086: /* Calculate the local space size on the stack. */
                   11087: common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);
1.4     ! moko     11088: common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, compiler->allocator_data);
1.2       misha    11089: if (!common->optimized_cbracket)
                   11090:   return;
                   11091: #if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1
                   11092: memset(common->optimized_cbracket, 0, re->top_bracket + 1);
                   11093: #else
                   11094: memset(common->optimized_cbracket, 1, re->top_bracket + 1);
1.1       misha    11095: #endif
1.2       misha    11096: 
1.3       moko     11097: SLJIT_ASSERT(*common->start == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
1.2       misha    11098: #if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 2
                   11099: common->capture_last_ptr = common->ovector_start;
                   11100: common->ovector_start += sizeof(sljit_sw);
1.1       misha    11101: #endif
1.3       moko     11102: if (!check_opcode_types(common, common->start, ccend))
1.2       misha    11103:   {
1.3       moko     11104:   SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
1.1       misha    11105:   return;
1.2       misha    11106:   }
                   11107: 
                   11108: /* Checking flags and updating ovector_start. */
                   11109: if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
                   11110:   {
                   11111:   common->req_char_ptr = common->ovector_start;
                   11112:   common->ovector_start += sizeof(sljit_sw);
                   11113:   }
                   11114: if (mode != JIT_COMPILE)
                   11115:   {
                   11116:   common->start_used_ptr = common->ovector_start;
                   11117:   common->ovector_start += sizeof(sljit_sw);
                   11118:   if (mode == JIT_PARTIAL_SOFT_COMPILE)
                   11119:     {
                   11120:     common->hit_start = common->ovector_start;
                   11121:     common->ovector_start += 2 * sizeof(sljit_sw);
                   11122:     }
                   11123:   }
                   11124: if ((re->options & PCRE_FIRSTLINE) != 0)
                   11125:   {
1.4     ! moko     11126:   common->match_end_ptr = common->ovector_start;
1.2       misha    11127:   common->ovector_start += sizeof(sljit_sw);
                   11128:   }
                   11129: #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
                   11130: common->control_head_ptr = 1;
                   11131: #endif
                   11132: if (common->control_head_ptr != 0)
                   11133:   {
                   11134:   common->control_head_ptr = common->ovector_start;
                   11135:   common->ovector_start += sizeof(sljit_sw);
                   11136:   }
1.4     ! moko     11137: if (common->has_set_som)
1.2       misha    11138:   {
                   11139:   /* Saving the real start pointer is necessary. */
                   11140:   common->start_ptr = common->ovector_start;
                   11141:   common->ovector_start += sizeof(sljit_sw);
                   11142:   }
                   11143: 
                   11144: /* Aligning ovector to even number of sljit words. */
                   11145: if ((common->ovector_start & sizeof(sljit_sw)) != 0)
                   11146:   common->ovector_start += sizeof(sljit_sw);
                   11147: 
                   11148: if (common->start_ptr == 0)
                   11149:   common->start_ptr = OVECTOR(0);
                   11150: 
                   11151: /* Capturing brackets cannot be optimized if callouts are allowed. */
                   11152: if (common->capture_last_ptr != 0)
                   11153:   memset(common->optimized_cbracket, 0, re->top_bracket + 1);
                   11154: 
                   11155: SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
                   11156: common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
                   11157: 
1.3       moko     11158: total_length = ccend - common->start;
1.4     ! moko     11159: common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), compiler->allocator_data);
1.2       misha    11160: if (!common->private_data_ptrs)
                   11161:   {
1.3       moko     11162:   SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
1.1       misha    11163:   return;
1.2       misha    11164:   }
1.4     ! moko     11165: memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32));
1.2       misha    11166: 
                   11167: private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);
                   11168: set_private_data_ptrs(common, &private_data_size, ccend);
1.4     ! moko     11169: if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
        !          11170:   {
        !          11171:   if (!detect_fast_forward_skip(common, &private_data_size) && !common->has_skip_in_assert_back)
        !          11172:     detect_fast_fail(common, common->start, &private_data_size, 4);
        !          11173:   }
        !          11174: 
        !          11175: SLJIT_ASSERT(common->fast_fail_start_ptr <= common->fast_fail_end_ptr);
        !          11176: 
1.2       misha    11177: if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
                   11178:   {
1.3       moko     11179:   SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
                   11180:   SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
1.1       misha    11181:   return;
1.2       misha    11182:   }
                   11183: 
                   11184: if (common->has_then)
                   11185:   {
1.4     ! moko     11186:   common->then_offsets = (sljit_u8 *)(common->private_data_ptrs + total_length);
1.3       moko     11187:   memset(common->then_offsets, 0, total_length);
                   11188:   set_then_offsets(common, common->start, NULL);
1.2       misha    11189:   }
1.1       misha    11190: 
1.3       moko     11191: compiler = sljit_create_compiler(NULL);
1.1       misha    11192: if (!compiler)
                   11193:   {
1.3       moko     11194:   SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
                   11195:   SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
1.1       misha    11196:   return;
                   11197:   }
                   11198: common->compiler = compiler;
                   11199: 
                   11200: /* Main pcre_jit_exec entry. */
1.4     ! moko     11201: sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size);
1.1       misha    11202: 
                   11203: /* Register init. */
                   11204: reset_ovector(common, (re->top_bracket + 1) * 2);
1.2       misha    11205: if (common->req_char_ptr != 0)
1.3       moko     11206:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, SLJIT_R0, 0);
1.1       misha    11207: 
1.3       moko     11208: OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_S0, 0);
                   11209: OP1(SLJIT_MOV, TMP1, 0, SLJIT_S0, 0);
1.1       misha    11210: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
                   11211: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
                   11212: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
1.4     ! moko     11213: OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
        !          11214: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, end));
        !          11215: OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, start));
        !          11216: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1.3       moko     11217: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);
1.2       misha    11218: 
1.4     ! moko     11219: if (common->fast_fail_start_ptr < common->fast_fail_end_ptr)
        !          11220:   reset_fast_fail(common);
        !          11221: 
1.2       misha    11222: if (mode == JIT_PARTIAL_SOFT_COMPILE)
1.3       moko     11223:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);
1.2       misha    11224: if (common->mark_ptr != 0)
1.3       moko     11225:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);
1.2       misha    11226: if (common->control_head_ptr != 0)
1.3       moko     11227:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
1.1       misha    11228: 
                   11229: /* Main part of the matching */
                   11230: if ((re->options & PCRE_ANCHORED) == 0)
                   11231:   {
1.4     ! moko     11232:   mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0);
1.2       misha    11233:   continue_match_label = LABEL();
1.1       misha    11234:   /* Forward search if possible. */
1.2       misha    11235:   if ((re->options & PCRE_NO_START_OPTIMIZE) == 0)
                   11236:     {
1.4     ! moko     11237:     if (mode == JIT_COMPILE && fast_forward_first_n_chars(common))
1.3       moko     11238:       ;
1.2       misha    11239:     else if ((re->flags & PCRE_FIRSTSET) != 0)
1.4     ! moko     11240:       fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0);
1.2       misha    11241:     else if ((re->flags & PCRE_STARTLINE) != 0)
1.4     ! moko     11242:       fast_forward_newline(common);
1.3       moko     11243:     else if (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
1.4     ! moko     11244:       fast_forward_start_bits(common, study->start_bits);
1.2       misha    11245:     }
                   11246:   }
                   11247: else
                   11248:   continue_match_label = LABEL();
                   11249: 
                   11250: if (mode == JIT_COMPILE && study->minlength > 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
                   11251:   {
                   11252:   OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
                   11253:   OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));
1.3       moko     11254:   minlength_check_failed = CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0);
1.1       misha    11255:   }
1.2       misha    11256: if (common->req_char_ptr != 0)
                   11257:   reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0);
1.1       misha    11258: 
                   11259: /* Store the current STR_PTR in OVECTOR(0). */
1.3       moko     11260: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);
1.1       misha    11261: /* Copy the limit of allowed recursions. */
1.3       moko     11262: OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH);
1.2       misha    11263: if (common->capture_last_ptr != 0)
1.3       moko     11264:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, -1);
1.4     ! moko     11265: if (common->fast_forward_bc_ptr != NULL)
        !          11266:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1), STR_PTR, 0);
1.2       misha    11267: 
1.4     ! moko     11268: if (common->start_ptr != OVECTOR(0))
1.3       moko     11269:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0);
1.2       misha    11270: 
                   11271: /* Copy the beginning of the string. */
                   11272: if (mode == JIT_PARTIAL_SOFT_COMPILE)
                   11273:   {
1.3       moko     11274:   jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);
                   11275:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
                   11276:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start + sizeof(sljit_sw), STR_PTR, 0);
1.2       misha    11277:   JUMPHERE(jump);
                   11278:   }
                   11279: else if (mode == JIT_PARTIAL_HARD_COMPILE)
1.3       moko     11280:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
1.1       misha    11281: 
1.3       moko     11282: compile_matchingpath(common, common->start, ccend, &rootbacktrack);
1.1       misha    11283: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   11284:   {
                   11285:   sljit_free_compiler(compiler);
1.3       moko     11286:   SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
                   11287:   SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
                   11288:   free_read_only_data(common->read_only_data_head, compiler->allocator_data);
1.1       misha    11289:   return;
                   11290:   }
                   11291: 
1.3       moko     11292: if (common->might_be_empty)
                   11293:   {
                   11294:   empty_match = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
                   11295:   empty_match_found_label = LABEL();
                   11296:   }
1.1       misha    11297: 
1.2       misha    11298: common->accept_label = LABEL();
1.1       misha    11299: if (common->accept != NULL)
1.2       misha    11300:   set_jumps(common->accept, common->accept_label);
1.1       misha    11301: 
                   11302: /* This means we have a match. Update the ovector. */
                   11303: copy_ovector(common, re->top_bracket + 1);
1.2       misha    11304: common->quit_label = common->forced_quit_label = LABEL();
                   11305: if (common->quit != NULL)
                   11306:   set_jumps(common->quit, common->quit_label);
                   11307: if (common->forced_quit != NULL)
                   11308:   set_jumps(common->forced_quit, common->forced_quit_label);
                   11309: if (minlength_check_failed != NULL)
                   11310:   SET_LABEL(minlength_check_failed, common->forced_quit_label);
1.1       misha    11311: sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);
                   11312: 
1.2       misha    11313: if (mode != JIT_COMPILE)
                   11314:   {
                   11315:   common->partialmatchlabel = LABEL();
                   11316:   set_jumps(common->partialmatch, common->partialmatchlabel);
                   11317:   return_with_partial_match(common, common->quit_label);
                   11318:   }
                   11319: 
1.3       moko     11320: if (common->might_be_empty)
                   11321:   empty_match_backtrack_label = LABEL();
1.2       misha    11322: compile_backtrackingpath(common, rootbacktrack.top);
1.1       misha    11323: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   11324:   {
                   11325:   sljit_free_compiler(compiler);
1.3       moko     11326:   SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
                   11327:   SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
                   11328:   free_read_only_data(common->read_only_data_head, compiler->allocator_data);
1.1       misha    11329:   return;
                   11330:   }
                   11331: 
1.2       misha    11332: SLJIT_ASSERT(rootbacktrack.prev == NULL);
                   11333: reset_match_label = LABEL();
                   11334: 
                   11335: if (mode == JIT_PARTIAL_SOFT_COMPILE)
                   11336:   {
                   11337:   /* Update hit_start only in the first time. */
1.3       moko     11338:   jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
                   11339:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr);
                   11340:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);
                   11341:   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, TMP1, 0);
1.2       misha    11342:   JUMPHERE(jump);
                   11343:   }
1.1       misha    11344: 
                   11345: /* Check we have remaining characters. */
1.2       misha    11346: if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_FIRSTLINE) != 0)
                   11347:   {
1.4     ! moko     11348:   SLJIT_ASSERT(common->match_end_ptr != 0);
        !          11349:   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
1.2       misha    11350:   }
                   11351: 
1.4     ! moko     11352: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP),
        !          11353:     (common->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1)) : common->start_ptr);
1.1       misha    11354: 
                   11355: if ((re->options & PCRE_ANCHORED) == 0)
                   11356:   {
1.3       moko     11357:   if (common->ff_newline_shortcut != NULL)
                   11358:     {
                   11359:     if ((re->options & PCRE_FIRSTLINE) == 0)
                   11360:       CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut);
                   11361:     /* There cannot be more newlines here. */
                   11362:     }
1.1       misha    11363:   else
1.4     ! moko     11364:     CMPTO(SLJIT_LESS, STR_PTR, 0, ((re->options & PCRE_FIRSTLINE) == 0) ? STR_END : TMP1, 0, mainloop_label);
1.1       misha    11365:   }
                   11366: 
1.2       misha    11367: /* No more remaining characters. */
1.1       misha    11368: if (reqbyte_notfound != NULL)
                   11369:   JUMPHERE(reqbyte_notfound);
1.2       misha    11370: 
                   11371: if (mode == JIT_PARTIAL_SOFT_COMPILE)
1.3       moko     11372:   CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel);
1.2       misha    11373: 
1.1       misha    11374: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
1.2       misha    11375: JUMPTO(SLJIT_JUMP, common->quit_label);
1.1       misha    11376: 
                   11377: flush_stubs(common);
                   11378: 
1.3       moko     11379: if (common->might_be_empty)
                   11380:   {
                   11381:   JUMPHERE(empty_match);
                   11382:   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1.4     ! moko     11383:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
1.3       moko     11384:   CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label);
1.4     ! moko     11385:   OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
1.3       moko     11386:   CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label);
                   11387:   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
                   11388:   CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label);
                   11389:   JUMPTO(SLJIT_JUMP, empty_match_backtrack_label);
                   11390:   }
1.1       misha    11391: 
1.4     ! moko     11392: common->fast_forward_bc_ptr = NULL;
        !          11393: common->fast_fail_start_ptr = 0;
        !          11394: common->fast_fail_end_ptr = 0;
1.1       misha    11395: common->currententry = common->entries;
1.2       misha    11396: common->local_exit = TRUE;
                   11397: quit_label = common->quit_label;
1.1       misha    11398: while (common->currententry != NULL)
                   11399:   {
                   11400:   /* Might add new entries. */
                   11401:   compile_recurse(common);
                   11402:   if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
                   11403:     {
                   11404:     sljit_free_compiler(compiler);
1.3       moko     11405:     SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
                   11406:     SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
                   11407:     free_read_only_data(common->read_only_data_head, compiler->allocator_data);
1.1       misha    11408:     return;
                   11409:     }
                   11410:   flush_stubs(common);
                   11411:   common->currententry = common->currententry->next;
                   11412:   }
1.2       misha    11413: common->local_exit = FALSE;
                   11414: common->quit_label = quit_label;
1.1       misha    11415: 
                   11416: /* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */
                   11417: /* This is a (really) rare case. */
                   11418: set_jumps(common->stackalloc, LABEL());
                   11419: /* RETURN_ADDR is not a saved register. */
1.3       moko     11420: sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
1.1       misha    11421: 
1.4     ! moko     11422: SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1);
        !          11423: 
        !          11424: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STACK_TOP, 0);
        !          11425: OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
        !          11426: OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE);
        !          11427: OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack));
        !          11428: OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0);
        !          11429: 
        !          11430: sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
        !          11431: jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
        !          11432: OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0);
        !          11433: OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0);
        !          11434: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
        !          11435: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
        !          11436: sljit_emit_fast_return(compiler, TMP1, 0);
1.1       misha    11437: 
                   11438: /* Allocation failed. */
1.2       misha    11439: JUMPHERE(jump);
1.1       misha    11440: /* We break the return address cache here, but this is a really rare case. */
                   11441: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
1.2       misha    11442: JUMPTO(SLJIT_JUMP, common->quit_label);
1.1       misha    11443: 
                   11444: /* Call limit reached. */
                   11445: set_jumps(common->calllimit, LABEL());
                   11446: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
1.2       misha    11447: JUMPTO(SLJIT_JUMP, common->quit_label);
1.1       misha    11448: 
                   11449: if (common->revertframes != NULL)
                   11450:   {
                   11451:   set_jumps(common->revertframes, LABEL());
                   11452:   do_revertframes(common);
                   11453:   }
                   11454: if (common->wordboundary != NULL)
                   11455:   {
                   11456:   set_jumps(common->wordboundary, LABEL());
                   11457:   check_wordboundary(common);
                   11458:   }
                   11459: if (common->anynewline != NULL)
                   11460:   {
                   11461:   set_jumps(common->anynewline, LABEL());
                   11462:   check_anynewline(common);
                   11463:   }
                   11464: if (common->hspace != NULL)
                   11465:   {
                   11466:   set_jumps(common->hspace, LABEL());
                   11467:   check_hspace(common);
                   11468:   }
                   11469: if (common->vspace != NULL)
                   11470:   {
                   11471:   set_jumps(common->vspace, LABEL());
                   11472:   check_vspace(common);
                   11473:   }
                   11474: if (common->casefulcmp != NULL)
                   11475:   {
                   11476:   set_jumps(common->casefulcmp, LABEL());
                   11477:   do_casefulcmp(common);
                   11478:   }
                   11479: if (common->caselesscmp != NULL)
                   11480:   {
                   11481:   set_jumps(common->caselesscmp, LABEL());
                   11482:   do_caselesscmp(common);
                   11483:   }
1.2       misha    11484: if (common->reset_match != NULL)
                   11485:   {
                   11486:   set_jumps(common->reset_match, LABEL());
                   11487:   do_reset_match(common, (re->top_bracket + 1) * 2);
1.3       moko     11488:   CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label);
1.2       misha    11489:   OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
                   11490:   JUMPTO(SLJIT_JUMP, reset_match_label);
                   11491:   }
1.1       misha    11492: #ifdef SUPPORT_UTF
1.3       moko     11493: #ifdef COMPILE_PCRE8
1.1       misha    11494: if (common->utfreadchar != NULL)
                   11495:   {
                   11496:   set_jumps(common->utfreadchar, LABEL());
                   11497:   do_utfreadchar(common);
                   11498:   }
1.3       moko     11499: if (common->utfreadchar16 != NULL)
                   11500:   {
                   11501:   set_jumps(common->utfreadchar16, LABEL());
                   11502:   do_utfreadchar16(common);
                   11503:   }
1.1       misha    11504: if (common->utfreadtype8 != NULL)
                   11505:   {
                   11506:   set_jumps(common->utfreadtype8, LABEL());
                   11507:   do_utfreadtype8(common);
                   11508:   }
                   11509: #endif /* COMPILE_PCRE8 */
1.2       misha    11510: #endif /* SUPPORT_UTF */
1.1       misha    11511: #ifdef SUPPORT_UCP
                   11512: if (common->getucd != NULL)
                   11513:   {
                   11514:   set_jumps(common->getucd, LABEL());
                   11515:   do_getucd(common);
                   11516:   }
                   11517: #endif
                   11518: 
1.3       moko     11519: SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
                   11520: SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
1.2       misha    11521: 
1.1       misha    11522: executable_func = sljit_generate_code(compiler);
                   11523: executable_size = sljit_get_generated_code_size(compiler);
1.3       moko     11524: label_addr = common->label_addrs;
                   11525: while (label_addr != NULL)
                   11526:   {
                   11527:   *label_addr->update_addr = sljit_get_label_addr(label_addr->label);
                   11528:   label_addr = label_addr->next;
                   11529:   }
1.1       misha    11530: sljit_free_compiler(compiler);
                   11531: if (executable_func == NULL)
1.3       moko     11532:   {
                   11533:   free_read_only_data(common->read_only_data_head, compiler->allocator_data);
1.1       misha    11534:   return;
1.3       moko     11535:   }
1.1       misha    11536: 
1.2       misha    11537: /* Reuse the function descriptor if possible. */
                   11538: if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)
                   11539:   functions = (executable_functions *)extra->executable_jit;
                   11540: else
1.1       misha    11541:   {
1.2       misha    11542:   /* Note: If your memory-checker has flagged the allocation below as a
                   11543:    * memory leak, it is probably because you either forgot to call
                   11544:    * pcre_free_study() (or pcre16_free_study()) on the pcre_extra (or
                   11545:    * pcre16_extra) object, or you called said function after having
                   11546:    * cleared the PCRE_EXTRA_EXECUTABLE_JIT bit from the "flags" field
                   11547:    * of the object. (The function will only free the JIT data if the
                   11548:    * bit remains set, as the bit indicates that the pointer to the data
                   11549:    * is valid.)
                   11550:    */
1.3       moko     11551:   functions = SLJIT_MALLOC(sizeof(executable_functions), compiler->allocator_data);
1.2       misha    11552:   if (functions == NULL)
                   11553:     {
                   11554:     /* This case is highly unlikely since we just recently
1.3       moko     11555:     freed a lot of memory. Not impossible though. */
1.2       misha    11556:     sljit_free_code(executable_func);
1.3       moko     11557:     free_read_only_data(common->read_only_data_head, compiler->allocator_data);
1.2       misha    11558:     return;
                   11559:     }
                   11560:   memset(functions, 0, sizeof(executable_functions));
                   11561:   functions->top_bracket = (re->top_bracket + 1) * 2;
                   11562:   functions->limit_match = (re->flags & PCRE_MLSET) != 0 ? re->limit_match : 0;
                   11563:   extra->executable_jit = functions;
                   11564:   extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
1.1       misha    11565:   }
                   11566: 
1.2       misha    11567: functions->executable_funcs[mode] = executable_func;
1.3       moko     11568: functions->read_only_data_heads[mode] = common->read_only_data_head;
1.2       misha    11569: functions->executable_sizes[mode] = executable_size;
1.1       misha    11570: }
                   11571: 
1.3       moko     11572: static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, void *executable_func)
1.1       misha    11573: {
                   11574: union {
1.3       moko     11575:    void *executable_func;
1.1       misha    11576:    jit_function call_executable_func;
                   11577: } convert_executable_func;
1.4     ! moko     11578: sljit_u8 local_space[MACHINE_STACK_SIZE];
1.1       misha    11579: struct sljit_stack local_stack;
                   11580: 
1.4     ! moko     11581: local_stack.min_start = local_space;
        !          11582: local_stack.start = local_space;
        !          11583: local_stack.end = local_space + MACHINE_STACK_SIZE;
        !          11584: local_stack.top = local_space + MACHINE_STACK_SIZE;
1.1       misha    11585: arguments->stack = &local_stack;
1.2       misha    11586: convert_executable_func.executable_func = executable_func;
1.1       misha    11587: return convert_executable_func.call_executable_func(arguments);
                   11588: }
                   11589: 
                   11590: int
1.2       misha    11591: PRIV(jit_exec)(const PUBL(extra) *extra_data, const pcre_uchar *subject,
                   11592:   int length, int start_offset, int options, int *offsets, int offset_count)
1.1       misha    11593: {
1.2       misha    11594: executable_functions *functions = (executable_functions *)extra_data->executable_jit;
1.1       misha    11595: union {
1.3       moko     11596:    void *executable_func;
1.1       misha    11597:    jit_function call_executable_func;
                   11598: } convert_executable_func;
                   11599: jit_arguments arguments;
1.2       misha    11600: int max_offset_count;
1.1       misha    11601: int retval;
1.2       misha    11602: int mode = JIT_COMPILE;
                   11603: 
                   11604: if ((options & PCRE_PARTIAL_HARD) != 0)
                   11605:   mode = JIT_PARTIAL_HARD_COMPILE;
                   11606: else if ((options & PCRE_PARTIAL_SOFT) != 0)
                   11607:   mode = JIT_PARTIAL_SOFT_COMPILE;
                   11608: 
                   11609: if (functions->executable_funcs[mode] == NULL)
                   11610:   return PCRE_ERROR_JIT_BADOPTION;
1.1       misha    11611: 
                   11612: /* Sanity checks should be handled by pcre_exec. */
                   11613: arguments.str = subject + start_offset;
                   11614: arguments.begin = subject;
                   11615: arguments.end = subject + length;
1.2       misha    11616: arguments.mark_ptr = NULL;
                   11617: /* JIT decreases this value less frequently than the interpreter. */
1.4     ! moko     11618: arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit);
1.2       misha    11619: if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
                   11620:   arguments.limit_match = functions->limit_match;
1.1       misha    11621: arguments.notbol = (options & PCRE_NOTBOL) != 0;
                   11622: arguments.noteol = (options & PCRE_NOTEOL) != 0;
                   11623: arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
                   11624: arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
                   11625: arguments.offsets = offsets;
1.2       misha    11626: arguments.callout_data = (extra_data->flags & PCRE_EXTRA_CALLOUT_DATA) != 0 ? extra_data->callout_data : NULL;
                   11627: arguments.real_offset_count = offset_count;
1.1       misha    11628: 
1.2       misha    11629: /* pcre_exec() rounds offset_count to a multiple of 3, and then uses only 2/3 of
1.1       misha    11630: the output vector for storing captured strings, with the remainder used as
                   11631: workspace. We don't need the workspace here. For compatibility, we limit the
                   11632: number of captured strings in the same way as pcre_exec(), so that the user
                   11633: gets the same result with and without JIT. */
                   11634: 
1.2       misha    11635: if (offset_count != 2)
                   11636:   offset_count = ((offset_count - (offset_count % 3)) * 2) / 3;
                   11637: max_offset_count = functions->top_bracket;
                   11638: if (offset_count > max_offset_count)
                   11639:   offset_count = max_offset_count;
                   11640: arguments.offset_count = offset_count;
1.1       misha    11641: 
1.2       misha    11642: if (functions->callback)
                   11643:   arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata);
1.1       misha    11644: else
1.2       misha    11645:   arguments.stack = (struct sljit_stack *)functions->userdata;
1.1       misha    11646: 
                   11647: if (arguments.stack == NULL)
1.2       misha    11648:   retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]);
1.1       misha    11649: else
                   11650:   {
1.2       misha    11651:   convert_executable_func.executable_func = functions->executable_funcs[mode];
1.1       misha    11652:   retval = convert_executable_func.call_executable_func(&arguments);
                   11653:   }
                   11654: 
1.2       misha    11655: if (retval * 2 > offset_count)
                   11656:   retval = 0;
                   11657: if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
                   11658:   *(extra_data->mark) = arguments.mark_ptr;
                   11659: 
                   11660: return retval;
                   11661: }
                   11662: 
                   11663: #if defined COMPILE_PCRE8
                   11664: PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
                   11665: pcre_jit_exec(const pcre *argument_re, const pcre_extra *extra_data,
                   11666:   PCRE_SPTR subject, int length, int start_offset, int options,
                   11667:   int *offsets, int offset_count, pcre_jit_stack *stack)
                   11668: #elif defined COMPILE_PCRE16
                   11669: PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
                   11670: pcre16_jit_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
                   11671:   PCRE_SPTR16 subject, int length, int start_offset, int options,
                   11672:   int *offsets, int offset_count, pcre16_jit_stack *stack)
                   11673: #elif defined COMPILE_PCRE32
                   11674: PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
                   11675: pcre32_jit_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
                   11676:   PCRE_SPTR32 subject, int length, int start_offset, int options,
                   11677:   int *offsets, int offset_count, pcre32_jit_stack *stack)
                   11678: #endif
                   11679: {
                   11680: pcre_uchar *subject_ptr = (pcre_uchar *)subject;
                   11681: executable_functions *functions = (executable_functions *)extra_data->executable_jit;
                   11682: union {
1.3       moko     11683:    void *executable_func;
1.2       misha    11684:    jit_function call_executable_func;
                   11685: } convert_executable_func;
                   11686: jit_arguments arguments;
                   11687: int max_offset_count;
                   11688: int retval;
                   11689: int mode = JIT_COMPILE;
                   11690: 
                   11691: SLJIT_UNUSED_ARG(argument_re);
                   11692: 
                   11693: /* Plausibility checks */
                   11694: if ((options & ~PUBLIC_JIT_EXEC_OPTIONS) != 0) return PCRE_ERROR_JIT_BADOPTION;
                   11695: 
                   11696: if ((options & PCRE_PARTIAL_HARD) != 0)
                   11697:   mode = JIT_PARTIAL_HARD_COMPILE;
                   11698: else if ((options & PCRE_PARTIAL_SOFT) != 0)
                   11699:   mode = JIT_PARTIAL_SOFT_COMPILE;
                   11700: 
1.4     ! moko     11701: if (functions == NULL || functions->executable_funcs[mode] == NULL)
1.2       misha    11702:   return PCRE_ERROR_JIT_BADOPTION;
                   11703: 
                   11704: /* Sanity checks should be handled by pcre_exec. */
                   11705: arguments.stack = (struct sljit_stack *)stack;
                   11706: arguments.str = subject_ptr + start_offset;
                   11707: arguments.begin = subject_ptr;
                   11708: arguments.end = subject_ptr + length;
                   11709: arguments.mark_ptr = NULL;
                   11710: /* JIT decreases this value less frequently than the interpreter. */
1.4     ! moko     11711: arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit);
1.2       misha    11712: if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
                   11713:   arguments.limit_match = functions->limit_match;
                   11714: arguments.notbol = (options & PCRE_NOTBOL) != 0;
                   11715: arguments.noteol = (options & PCRE_NOTEOL) != 0;
                   11716: arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
                   11717: arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
                   11718: arguments.offsets = offsets;
                   11719: arguments.callout_data = (extra_data->flags & PCRE_EXTRA_CALLOUT_DATA) != 0 ? extra_data->callout_data : NULL;
                   11720: arguments.real_offset_count = offset_count;
                   11721: 
                   11722: /* pcre_exec() rounds offset_count to a multiple of 3, and then uses only 2/3 of
                   11723: the output vector for storing captured strings, with the remainder used as
                   11724: workspace. We don't need the workspace here. For compatibility, we limit the
                   11725: number of captured strings in the same way as pcre_exec(), so that the user
                   11726: gets the same result with and without JIT. */
                   11727: 
                   11728: if (offset_count != 2)
                   11729:   offset_count = ((offset_count - (offset_count % 3)) * 2) / 3;
                   11730: max_offset_count = functions->top_bracket;
                   11731: if (offset_count > max_offset_count)
                   11732:   offset_count = max_offset_count;
                   11733: arguments.offset_count = offset_count;
                   11734: 
                   11735: convert_executable_func.executable_func = functions->executable_funcs[mode];
                   11736: retval = convert_executable_func.call_executable_func(&arguments);
                   11737: 
                   11738: if (retval * 2 > offset_count)
1.1       misha    11739:   retval = 0;
1.2       misha    11740: if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
                   11741:   *(extra_data->mark) = arguments.mark_ptr;
                   11742: 
1.1       misha    11743: return retval;
                   11744: }
                   11745: 
                   11746: void
1.2       misha    11747: PRIV(jit_free)(void *executable_funcs)
1.1       misha    11748: {
1.2       misha    11749: int i;
                   11750: executable_functions *functions = (executable_functions *)executable_funcs;
                   11751: for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
                   11752:   {
                   11753:   if (functions->executable_funcs[i] != NULL)
                   11754:     sljit_free_code(functions->executable_funcs[i]);
1.3       moko     11755:   free_read_only_data(functions->read_only_data_heads[i], NULL);
1.2       misha    11756:   }
1.3       moko     11757: SLJIT_FREE(functions, compiler->allocator_data);
1.1       misha    11758: }
                   11759: 
                   11760: int
1.2       misha    11761: PRIV(jit_get_size)(void *executable_funcs)
1.1       misha    11762: {
1.2       misha    11763: int i;
                   11764: sljit_uw size = 0;
                   11765: sljit_uw *executable_sizes = ((executable_functions *)executable_funcs)->executable_sizes;
                   11766: for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
                   11767:   size += executable_sizes[i];
                   11768: return (int)size;
1.1       misha    11769: }
                   11770: 
                   11771: const char*
                   11772: PRIV(jit_get_target)(void)
                   11773: {
                   11774: return sljit_get_platform_name();
                   11775: }
                   11776: 
1.2       misha    11777: #if defined COMPILE_PCRE8
1.1       misha    11778: PCRE_EXP_DECL pcre_jit_stack *
                   11779: pcre_jit_stack_alloc(int startsize, int maxsize)
1.2       misha    11780: #elif defined COMPILE_PCRE16
1.1       misha    11781: PCRE_EXP_DECL pcre16_jit_stack *
                   11782: pcre16_jit_stack_alloc(int startsize, int maxsize)
1.2       misha    11783: #elif defined COMPILE_PCRE32
                   11784: PCRE_EXP_DECL pcre32_jit_stack *
                   11785: pcre32_jit_stack_alloc(int startsize, int maxsize)
1.1       misha    11786: #endif
                   11787: {
                   11788: if (startsize < 1 || maxsize < 1)
                   11789:   return NULL;
                   11790: if (startsize > maxsize)
                   11791:   startsize = maxsize;
                   11792: startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
                   11793: maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
1.3       moko     11794: return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize, NULL);
1.1       misha    11795: }
                   11796: 
1.2       misha    11797: #if defined COMPILE_PCRE8
1.1       misha    11798: PCRE_EXP_DECL void
                   11799: pcre_jit_stack_free(pcre_jit_stack *stack)
1.2       misha    11800: #elif defined COMPILE_PCRE16
1.1       misha    11801: PCRE_EXP_DECL void
                   11802: pcre16_jit_stack_free(pcre16_jit_stack *stack)
1.2       misha    11803: #elif defined COMPILE_PCRE32
                   11804: PCRE_EXP_DECL void
                   11805: pcre32_jit_stack_free(pcre32_jit_stack *stack)
1.1       misha    11806: #endif
                   11807: {
1.3       moko     11808: sljit_free_stack((struct sljit_stack *)stack, NULL);
1.1       misha    11809: }
                   11810: 
1.2       misha    11811: #if defined COMPILE_PCRE8
1.1       misha    11812: PCRE_EXP_DECL void
                   11813: pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
1.2       misha    11814: #elif defined COMPILE_PCRE16
1.1       misha    11815: PCRE_EXP_DECL void
                   11816: pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
1.2       misha    11817: #elif defined COMPILE_PCRE32
                   11818: PCRE_EXP_DECL void
                   11819: pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *userdata)
1.1       misha    11820: #endif
                   11821: {
1.2       misha    11822: executable_functions *functions;
1.1       misha    11823: if (extra != NULL &&
                   11824:     (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
                   11825:     extra->executable_jit != NULL)
                   11826:   {
1.2       misha    11827:   functions = (executable_functions *)extra->executable_jit;
                   11828:   functions->callback = callback;
                   11829:   functions->userdata = userdata;
1.1       misha    11830:   }
                   11831: }
                   11832: 
1.3       moko     11833: #if defined COMPILE_PCRE8
                   11834: PCRE_EXP_DECL void
                   11835: pcre_jit_free_unused_memory(void)
                   11836: #elif defined COMPILE_PCRE16
                   11837: PCRE_EXP_DECL void
                   11838: pcre16_jit_free_unused_memory(void)
                   11839: #elif defined COMPILE_PCRE32
                   11840: PCRE_EXP_DECL void
                   11841: pcre32_jit_free_unused_memory(void)
                   11842: #endif
                   11843: {
                   11844: sljit_free_unused_memory_exec();
                   11845: }
                   11846: 
1.1       misha    11847: #else  /* SUPPORT_JIT */
                   11848: 
                   11849: /* These are dummy functions to avoid linking errors when JIT support is not
                   11850: being compiled. */
                   11851: 
1.2       misha    11852: #if defined COMPILE_PCRE8
1.1       misha    11853: PCRE_EXP_DECL pcre_jit_stack *
                   11854: pcre_jit_stack_alloc(int startsize, int maxsize)
1.2       misha    11855: #elif defined COMPILE_PCRE16
1.1       misha    11856: PCRE_EXP_DECL pcre16_jit_stack *
                   11857: pcre16_jit_stack_alloc(int startsize, int maxsize)
1.2       misha    11858: #elif defined COMPILE_PCRE32
                   11859: PCRE_EXP_DECL pcre32_jit_stack *
                   11860: pcre32_jit_stack_alloc(int startsize, int maxsize)
1.1       misha    11861: #endif
                   11862: {
                   11863: (void)startsize;
                   11864: (void)maxsize;
                   11865: return NULL;
                   11866: }
                   11867: 
1.2       misha    11868: #if defined COMPILE_PCRE8
1.1       misha    11869: PCRE_EXP_DECL void
                   11870: pcre_jit_stack_free(pcre_jit_stack *stack)
1.2       misha    11871: #elif defined COMPILE_PCRE16
1.1       misha    11872: PCRE_EXP_DECL void
                   11873: pcre16_jit_stack_free(pcre16_jit_stack *stack)
1.2       misha    11874: #elif defined COMPILE_PCRE32
                   11875: PCRE_EXP_DECL void
                   11876: pcre32_jit_stack_free(pcre32_jit_stack *stack)
1.1       misha    11877: #endif
                   11878: {
                   11879: (void)stack;
                   11880: }
                   11881: 
1.2       misha    11882: #if defined COMPILE_PCRE8
1.1       misha    11883: PCRE_EXP_DECL void
                   11884: pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
1.2       misha    11885: #elif defined COMPILE_PCRE16
1.1       misha    11886: PCRE_EXP_DECL void
                   11887: pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
1.2       misha    11888: #elif defined COMPILE_PCRE32
                   11889: PCRE_EXP_DECL void
                   11890: pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *userdata)
1.1       misha    11891: #endif
                   11892: {
                   11893: (void)extra;
                   11894: (void)callback;
                   11895: (void)userdata;
                   11896: }
                   11897: 
1.3       moko     11898: #if defined COMPILE_PCRE8
                   11899: PCRE_EXP_DECL void
                   11900: pcre_jit_free_unused_memory(void)
                   11901: #elif defined COMPILE_PCRE16
                   11902: PCRE_EXP_DECL void
                   11903: pcre16_jit_free_unused_memory(void)
                   11904: #elif defined COMPILE_PCRE32
                   11905: PCRE_EXP_DECL void
                   11906: pcre32_jit_free_unused_memory(void)
                   11907: #endif
                   11908: {
                   11909: }
                   11910: 
1.1       misha    11911: #endif
                   11912: 
                   11913: /* End of pcre_jit_compile.c */

E-mail: