Annotation of embedaddon/pcre/pcre_jit_compile.c, revision 1.1.1.3
1.1 misho 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.1.1.2 misho 9: Copyright (c) 1997-2012 University of Cambridge
1.1 misho 10:
11: The machine code generator part (this module) was written by Zoltan Herczeg
1.1.1.2 misho 12: Copyright (c) 2010-2012
1.1 misho 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:
49: #ifdef SUPPORT_JIT
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.1.1.2 misho 55: #define SLJIT_MALLOC(size) (PUBL(malloc))(size)
56: #define SLJIT_FREE(ptr) (PUBL(free))(ptr)
1.1 misho 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
1.1.1.2 misho 65: #error Unsupported architecture
1.1 misho 66: #endif
67:
68: /* Allocate memory on the stack. Fast, but limited size. */
69: #define LOCAL_SPACE_SIZE 32768
70:
71: #define STACK_GROWTH_RATE 8192
72:
73: /* Enable to check that the allocation could destroy temporaries. */
74: #if defined SLJIT_DEBUG && SLJIT_DEBUG
75: #define DESTROY_REGISTERS 1
76: #endif
77:
78: /*
79: Short summary about the backtracking mechanism empolyed by the jit code generator:
80:
81: The code generator follows the recursive nature of the PERL compatible regular
82: expressions. The basic blocks of regular expressions are condition checkers
83: whose execute different commands depending on the result of the condition check.
84: The relationship between the operators can be horizontal (concatenation) and
1.1.1.3 ! misho 85: vertical (sub-expression) (See struct backtrack_common for more details).
1.1 misho 86:
87: 'ab' - 'a' and 'b' regexps are concatenated
88: 'a+' - 'a' is the sub-expression of the '+' operator
89:
90: The condition checkers are boolean (true/false) checkers. Machine code is generated
91: for the checker itself and for the actions depending on the result of the checker.
1.1.1.3 ! misho 92: The 'true' case is called as the try path (expected path), and the other is called as
! 93: the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken
! 94: branches on the try path.
1.1 misho 95:
96: Greedy star operator (*) :
1.1.1.3 ! misho 97: Try path: match happens.
! 98: Backtrack path: match failed.
1.1 misho 99: Non-greedy star operator (*?) :
1.1.1.3 ! misho 100: Try path: no need to perform a match.
! 101: Backtrack path: match is required.
1.1 misho 102:
103: The following example shows how the code generated for a capturing bracket
104: with two alternatives. Let A, B, C, D are arbirary regular expressions, and
105: we have the following regular expression:
106:
107: A(B|C)D
108:
109: The generated code will be the following:
110:
1.1.1.3 ! misho 111: A try path
! 112: '(' try path (pushing arguments to the stack)
! 113: B try path
! 114: ')' try path (pushing arguments to the stack)
! 115: D try path
1.1 misho 116: return with successful match
117:
1.1.1.3 ! misho 118: D backtrack path
! 119: ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")
! 120: B backtrack path
1.1 misho 121: C expected path
1.1.1.3 ! misho 122: jump to D try path
! 123: C backtrack path
! 124: A backtrack path
1.1 misho 125:
1.1.1.3 ! misho 126: Notice, that the order of backtrack code paths are the opposite of the fast
1.1 misho 127: code paths. In this way the topmost value on the stack is always belong
1.1.1.3 ! misho 128: to the current backtrack code path. The backtrack path must check
1.1 misho 129: whether there is a next alternative. If so, it needs to jump back to
1.1.1.3 ! misho 130: the try path eventually. Otherwise it needs to clear out its own stack
! 131: frame and continue the execution on the backtrack code paths.
1.1 misho 132: */
133:
134: /*
135: Saved stack frames:
136:
137: Atomic blocks and asserts require reloading the values of local variables
1.1.1.3 ! misho 138: when the backtrack mechanism performed. Because of OP_RECURSE, the locals
1.1 misho 139: are not necessarly known in compile time, thus we need a dynamic restore
140: mechanism.
141:
142: The stack frames are stored in a chain list, and have the following format:
143: ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
144:
145: Thus we can restore the locals to a particular point in the stack.
146: */
147:
148: typedef struct jit_arguments {
149: /* Pointers first. */
150: struct sljit_stack *stack;
1.1.1.2 misho 151: const pcre_uchar *str;
152: const pcre_uchar *begin;
153: const pcre_uchar *end;
1.1 misho 154: int *offsets;
1.1.1.3 ! misho 155: pcre_uchar *uchar_ptr;
! 156: pcre_uchar *mark_ptr;
1.1 misho 157: /* Everything else after. */
158: int offsetcount;
159: int calllimit;
1.1.1.2 misho 160: pcre_uint8 notbol;
161: pcre_uint8 noteol;
162: pcre_uint8 notempty;
163: pcre_uint8 notempty_atstart;
1.1 misho 164: } jit_arguments;
165:
1.1.1.3 ! misho 166: typedef struct executable_functions {
! 167: void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];
1.1.1.2 misho 168: PUBL(jit_callback) callback;
1.1 misho 169: void *userdata;
1.1.1.3 ! misho 170: sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
! 171: } executable_functions;
1.1 misho 172:
173: typedef struct jump_list {
174: struct sljit_jump *jump;
175: struct jump_list *next;
176: } jump_list;
177:
178: enum stub_types { stack_alloc };
179:
180: typedef struct stub_list {
181: enum stub_types type;
182: int data;
183: struct sljit_jump *start;
184: struct sljit_label *leave;
185: struct stub_list *next;
186: } stub_list;
187:
188: typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
189:
190: /* The following structure is the key data type for the recursive
1.1.1.3 ! misho 191: code generator. It is allocated by compile_trypath, and contains
! 192: the aguments for compile_backtrackpath. Must be the first member
1.1 misho 193: of its descendants. */
1.1.1.3 ! misho 194: typedef struct backtrack_common {
1.1 misho 195: /* Concatenation stack. */
1.1.1.3 ! misho 196: struct backtrack_common *prev;
! 197: jump_list *nextbacktracks;
1.1 misho 198: /* Internal stack (for component operators). */
1.1.1.3 ! misho 199: struct backtrack_common *top;
! 200: jump_list *topbacktracks;
1.1 misho 201: /* Opcode pointer. */
1.1.1.2 misho 202: pcre_uchar *cc;
1.1.1.3 ! misho 203: } backtrack_common;
1.1 misho 204:
1.1.1.3 ! misho 205: typedef struct assert_backtrack {
! 206: backtrack_common common;
1.1 misho 207: jump_list *condfailed;
208: /* Less than 0 (-1) if a frame is not needed. */
209: int framesize;
210: /* Points to our private memory word on the stack. */
211: int localptr;
212: /* For iterators. */
1.1.1.3 ! misho 213: struct sljit_label *trypath;
! 214: } assert_backtrack;
1.1 misho 215:
1.1.1.3 ! misho 216: typedef struct bracket_backtrack {
! 217: backtrack_common common;
1.1 misho 218: /* Where to coninue if an alternative is successfully matched. */
1.1.1.3 ! misho 219: struct sljit_label *alttrypath;
1.1 misho 220: /* For rmin and rmax iterators. */
1.1.1.3 ! misho 221: struct sljit_label *recursivetrypath;
1.1 misho 222: /* For greedy ? operator. */
1.1.1.3 ! misho 223: struct sljit_label *zerotrypath;
1.1 misho 224: /* Contains the branches of a failed condition. */
225: union {
226: /* Both for OP_COND, OP_SCOND. */
227: jump_list *condfailed;
1.1.1.3 ! misho 228: assert_backtrack *assert;
1.1 misho 229: /* For OP_ONCE. -1 if not needed. */
230: int framesize;
231: } u;
232: /* Points to our private memory word on the stack. */
233: int localptr;
1.1.1.3 ! misho 234: } bracket_backtrack;
1.1 misho 235:
1.1.1.3 ! misho 236: typedef struct bracketpos_backtrack {
! 237: backtrack_common common;
1.1 misho 238: /* Points to our private memory word on the stack. */
239: int localptr;
240: /* Reverting stack is needed. */
241: int framesize;
242: /* Allocated stack size. */
243: int stacksize;
1.1.1.3 ! misho 244: } bracketpos_backtrack;
1.1 misho 245:
1.1.1.3 ! misho 246: typedef struct braminzero_backtrack {
! 247: backtrack_common common;
! 248: struct sljit_label *trypath;
! 249: } braminzero_backtrack;
1.1 misho 250:
1.1.1.3 ! misho 251: typedef struct iterator_backtrack {
! 252: backtrack_common common;
1.1 misho 253: /* Next iteration. */
1.1.1.3 ! misho 254: struct sljit_label *trypath;
! 255: } iterator_backtrack;
1.1 misho 256:
257: typedef struct recurse_entry {
258: struct recurse_entry *next;
259: /* Contains the function entry. */
260: struct sljit_label *entry;
261: /* Collects the calls until the function is not created. */
262: jump_list *calls;
263: /* Points to the starting opcode. */
264: int start;
265: } recurse_entry;
266:
1.1.1.3 ! misho 267: typedef struct recurse_backtrack {
! 268: backtrack_common common;
! 269: } recurse_backtrack;
1.1 misho 270:
271: typedef struct compiler_common {
272: struct sljit_compiler *compiler;
1.1.1.2 misho 273: pcre_uchar *start;
1.1.1.3 ! misho 274:
! 275: /* Opcode local area direct map. */
1.1 misho 276: int *localptrs;
1.1.1.3 ! misho 277: int cbraptr;
! 278: /* OVector starting point. Must be divisible by 2. */
! 279: int ovector_start;
! 280: /* Last known position of the requested byte. */
! 281: int req_char_ptr;
! 282: /* Head of the last recursion. */
! 283: int recursive_head;
! 284: /* First inspected character for partial matching. */
! 285: int start_used_ptr;
! 286: /* Starting pointer for partial soft matches. */
! 287: int hit_start;
! 288: /* End pointer of the first line. */
! 289: int first_line_end;
! 290: /* Points to the marked string. */
! 291: int mark_ptr;
! 292:
! 293: /* Other */
1.1.1.2 misho 294: const pcre_uint8 *fcc;
1.1 misho 295: sljit_w lcc;
1.1.1.3 ! misho 296: int mode;
1.1 misho 297: int nltype;
298: int newline;
299: int bsr_nltype;
300: int endonly;
1.1.1.3 ! misho 301: BOOL has_set_som;
1.1 misho 302: sljit_w ctypes;
303: sljit_uw name_table;
304: sljit_w name_count;
305: sljit_w name_entry_size;
1.1.1.3 ! misho 306:
! 307: /* Labels and jump lists. */
! 308: struct sljit_label *partialmatchlabel;
! 309: struct sljit_label *leavelabel;
1.1 misho 310: struct sljit_label *acceptlabel;
311: stub_list *stubs;
312: recurse_entry *entries;
313: recurse_entry *currententry;
1.1.1.3 ! misho 314: jump_list *partialmatch;
! 315: jump_list *leave;
1.1 misho 316: jump_list *accept;
317: jump_list *calllimit;
318: jump_list *stackalloc;
319: jump_list *revertframes;
320: jump_list *wordboundary;
321: jump_list *anynewline;
322: jump_list *hspace;
323: jump_list *vspace;
324: jump_list *casefulcmp;
325: jump_list *caselesscmp;
326: BOOL jscript_compat;
1.1.1.2 misho 327: #ifdef SUPPORT_UTF
328: BOOL utf;
1.1 misho 329: #ifdef SUPPORT_UCP
1.1.1.2 misho 330: BOOL use_ucp;
1.1 misho 331: #endif
1.1.1.2 misho 332: jump_list *utfreadchar;
333: #ifdef COMPILE_PCRE8
334: jump_list *utfreadtype8;
1.1 misho 335: #endif
1.1.1.2 misho 336: #endif /* SUPPORT_UTF */
1.1 misho 337: #ifdef SUPPORT_UCP
338: jump_list *getucd;
339: #endif
340: } compiler_common;
341:
342: /* For byte_sequence_compare. */
343:
344: typedef struct compare_context {
345: int length;
346: int sourcereg;
347: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
1.1.1.2 misho 348: int ucharptr;
1.1 misho 349: union {
1.1.1.2 misho 350: sljit_i asint;
351: sljit_uh asushort;
352: #ifdef COMPILE_PCRE8
1.1 misho 353: sljit_ub asbyte;
1.1.1.2 misho 354: sljit_ub asuchars[4];
355: #else
356: #ifdef COMPILE_PCRE16
357: sljit_uh asuchars[2];
358: #endif
359: #endif
1.1 misho 360: } c;
361: union {
1.1.1.2 misho 362: sljit_i asint;
363: sljit_uh asushort;
364: #ifdef COMPILE_PCRE8
1.1 misho 365: sljit_ub asbyte;
1.1.1.2 misho 366: sljit_ub asuchars[4];
367: #else
368: #ifdef COMPILE_PCRE16
369: sljit_uh asuchars[2];
370: #endif
371: #endif
1.1 misho 372: } oc;
373: #endif
374: } compare_context;
375:
376: enum {
377: frame_end = 0,
1.1.1.3 ! misho 378: frame_setstrbegin = -1,
! 379: frame_setmark = -2
1.1 misho 380: };
381:
1.1.1.2 misho 382: /* Undefine sljit macros. */
383: #undef CMP
384:
1.1 misho 385: /* Used for accessing the elements of the stack. */
386: #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w))
387:
388: #define TMP1 SLJIT_TEMPORARY_REG1
389: #define TMP2 SLJIT_TEMPORARY_REG3
390: #define TMP3 SLJIT_TEMPORARY_EREG2
1.1.1.2 misho 391: #define STR_PTR SLJIT_SAVED_REG1
392: #define STR_END SLJIT_SAVED_REG2
1.1 misho 393: #define STACK_TOP SLJIT_TEMPORARY_REG2
1.1.1.2 misho 394: #define STACK_LIMIT SLJIT_SAVED_REG3
395: #define ARGUMENTS SLJIT_SAVED_EREG1
396: #define CALL_COUNT SLJIT_SAVED_EREG2
1.1 misho 397: #define RETURN_ADDR SLJIT_TEMPORARY_EREG1
398:
399: /* Locals layout. */
400: /* These two locals can be used by the current opcode. */
401: #define LOCALS0 (0 * sizeof(sljit_w))
402: #define LOCALS1 (1 * sizeof(sljit_w))
403: /* Two local variables for possessive quantifiers (char1 cannot use them). */
404: #define POSSESSIVE0 (2 * sizeof(sljit_w))
405: #define POSSESSIVE1 (3 * sizeof(sljit_w))
406: /* Max limit of recursions. */
1.1.1.3 ! misho 407: #define CALL_LIMIT (4 * sizeof(sljit_w))
1.1 misho 408: /* The output vector is stored on the stack, and contains pointers
409: to characters. The vector data is divided into two groups: the first
410: group contains the start / end character pointers, and the second is
411: the start pointers when the end of the capturing group has not yet reached. */
1.1.1.3 ! misho 412: #define OVECTOR_START (common->ovector_start)
1.1 misho 413: #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w))
414: #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w))
1.1.1.2 misho 415: #define PRIV_DATA(cc) (common->localptrs[(cc) - common->start])
416:
417: #ifdef COMPILE_PCRE8
418: #define MOV_UCHAR SLJIT_MOV_UB
419: #define MOVU_UCHAR SLJIT_MOVU_UB
420: #else
421: #ifdef COMPILE_PCRE16
422: #define MOV_UCHAR SLJIT_MOV_UH
423: #define MOVU_UCHAR SLJIT_MOVU_UH
424: #else
425: #error Unsupported compiling mode
426: #endif
427: #endif
1.1 misho 428:
429: /* Shortcuts. */
430: #define DEFINE_COMPILER \
431: struct sljit_compiler *compiler = common->compiler
432: #define OP1(op, dst, dstw, src, srcw) \
433: sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
434: #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
435: sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
436: #define LABEL() \
437: sljit_emit_label(compiler)
438: #define JUMP(type) \
439: sljit_emit_jump(compiler, (type))
440: #define JUMPTO(type, label) \
441: sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
442: #define JUMPHERE(jump) \
443: sljit_set_label((jump), sljit_emit_label(compiler))
444: #define CMP(type, src1, src1w, src2, src2w) \
445: sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
446: #define CMPTO(type, src1, src1w, src2, src2w, label) \
447: sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
448: #define COND_VALUE(op, dst, dstw, type) \
449: sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
1.1.1.3 ! misho 450: #define GET_LOCAL_BASE(dst, dstw, offset) \
! 451: sljit_get_local_base(compiler, (dst), (dstw), (offset))
1.1 misho 452:
1.1.1.2 misho 453: static pcre_uchar* bracketend(pcre_uchar* cc)
1.1 misho 454: {
455: SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
456: do cc += GET(cc, 1); while (*cc == OP_ALT);
457: SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
458: cc += 1 + LINK_SIZE;
459: return cc;
460: }
461:
462: /* Functions whose might need modification for all new supported opcodes:
463: next_opcode
464: get_localspace
465: set_localptrs
466: get_framesize
467: init_frame
468: get_localsize
469: copy_locals
1.1.1.3 ! misho 470: compile_trypath
! 471: compile_backtrackpath
1.1 misho 472: */
473:
1.1.1.2 misho 474: static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc)
1.1 misho 475: {
476: SLJIT_UNUSED_ARG(common);
477: switch(*cc)
478: {
479: case OP_SOD:
480: case OP_SOM:
481: case OP_SET_SOM:
482: case OP_NOT_WORD_BOUNDARY:
483: case OP_WORD_BOUNDARY:
484: case OP_NOT_DIGIT:
485: case OP_DIGIT:
486: case OP_NOT_WHITESPACE:
487: case OP_WHITESPACE:
488: case OP_NOT_WORDCHAR:
489: case OP_WORDCHAR:
490: case OP_ANY:
491: case OP_ALLANY:
492: case OP_ANYNL:
493: case OP_NOT_HSPACE:
494: case OP_HSPACE:
495: case OP_NOT_VSPACE:
496: case OP_VSPACE:
497: case OP_EXTUNI:
498: case OP_EODN:
499: case OP_EOD:
500: case OP_CIRC:
501: case OP_CIRCM:
502: case OP_DOLL:
503: case OP_DOLLM:
504: case OP_TYPESTAR:
505: case OP_TYPEMINSTAR:
506: case OP_TYPEPLUS:
507: case OP_TYPEMINPLUS:
508: case OP_TYPEQUERY:
509: case OP_TYPEMINQUERY:
510: case OP_TYPEPOSSTAR:
511: case OP_TYPEPOSPLUS:
512: case OP_TYPEPOSQUERY:
513: case OP_CRSTAR:
514: case OP_CRMINSTAR:
515: case OP_CRPLUS:
516: case OP_CRMINPLUS:
517: case OP_CRQUERY:
518: case OP_CRMINQUERY:
519: case OP_DEF:
520: case OP_BRAZERO:
521: case OP_BRAMINZERO:
522: case OP_BRAPOSZERO:
1.1.1.3 ! misho 523: case OP_COMMIT:
1.1 misho 524: case OP_FAIL:
525: case OP_ACCEPT:
526: case OP_ASSERT_ACCEPT:
527: case OP_SKIPZERO:
528: return cc + 1;
529:
530: case OP_ANYBYTE:
1.1.1.2 misho 531: #ifdef SUPPORT_UTF
532: if (common->utf) return NULL;
1.1 misho 533: #endif
534: return cc + 1;
535:
536: case OP_CHAR:
537: case OP_CHARI:
538: case OP_NOT:
539: case OP_NOTI:
540: case OP_STAR:
541: case OP_MINSTAR:
542: case OP_PLUS:
543: case OP_MINPLUS:
544: case OP_QUERY:
545: case OP_MINQUERY:
546: case OP_POSSTAR:
547: case OP_POSPLUS:
548: case OP_POSQUERY:
549: case OP_STARI:
550: case OP_MINSTARI:
551: case OP_PLUSI:
552: case OP_MINPLUSI:
553: case OP_QUERYI:
554: case OP_MINQUERYI:
555: case OP_POSSTARI:
556: case OP_POSPLUSI:
557: case OP_POSQUERYI:
558: case OP_NOTSTAR:
559: case OP_NOTMINSTAR:
560: case OP_NOTPLUS:
561: case OP_NOTMINPLUS:
562: case OP_NOTQUERY:
563: case OP_NOTMINQUERY:
564: case OP_NOTPOSSTAR:
565: case OP_NOTPOSPLUS:
566: case OP_NOTPOSQUERY:
567: case OP_NOTSTARI:
568: case OP_NOTMINSTARI:
569: case OP_NOTPLUSI:
570: case OP_NOTMINPLUSI:
571: case OP_NOTQUERYI:
572: case OP_NOTMINQUERYI:
573: case OP_NOTPOSSTARI:
574: case OP_NOTPOSPLUSI:
575: case OP_NOTPOSQUERYI:
576: cc += 2;
1.1.1.2 misho 577: #ifdef SUPPORT_UTF
578: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 579: #endif
580: return cc;
581:
582: case OP_UPTO:
583: case OP_MINUPTO:
584: case OP_EXACT:
585: case OP_POSUPTO:
586: case OP_UPTOI:
587: case OP_MINUPTOI:
588: case OP_EXACTI:
589: case OP_POSUPTOI:
590: case OP_NOTUPTO:
591: case OP_NOTMINUPTO:
592: case OP_NOTEXACT:
593: case OP_NOTPOSUPTO:
594: case OP_NOTUPTOI:
595: case OP_NOTMINUPTOI:
596: case OP_NOTEXACTI:
597: case OP_NOTPOSUPTOI:
1.1.1.2 misho 598: cc += 2 + IMM2_SIZE;
599: #ifdef SUPPORT_UTF
600: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 601: #endif
602: return cc;
603:
604: case OP_NOTPROP:
605: case OP_PROP:
1.1.1.2 misho 606: return cc + 1 + 2;
607:
1.1 misho 608: case OP_TYPEUPTO:
609: case OP_TYPEMINUPTO:
610: case OP_TYPEEXACT:
611: case OP_TYPEPOSUPTO:
612: case OP_REF:
613: case OP_REFI:
614: case OP_CREF:
615: case OP_NCREF:
616: case OP_RREF:
617: case OP_NRREF:
618: case OP_CLOSE:
1.1.1.2 misho 619: cc += 1 + IMM2_SIZE;
1.1 misho 620: return cc;
621:
622: case OP_CRRANGE:
623: case OP_CRMINRANGE:
1.1.1.2 misho 624: return cc + 1 + 2 * IMM2_SIZE;
1.1 misho 625:
626: case OP_CLASS:
627: case OP_NCLASS:
1.1.1.2 misho 628: return cc + 1 + 32 / sizeof(pcre_uchar);
1.1 misho 629:
1.1.1.2 misho 630: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 631: case OP_XCLASS:
632: return cc + GET(cc, 1);
633: #endif
634:
635: case OP_RECURSE:
636: case OP_ASSERT:
637: case OP_ASSERT_NOT:
638: case OP_ASSERTBACK:
639: case OP_ASSERTBACK_NOT:
640: case OP_REVERSE:
641: case OP_ONCE:
642: case OP_ONCE_NC:
643: case OP_BRA:
644: case OP_BRAPOS:
645: case OP_COND:
646: case OP_SBRA:
647: case OP_SBRAPOS:
648: case OP_SCOND:
649: case OP_ALT:
650: case OP_KET:
651: case OP_KETRMAX:
652: case OP_KETRMIN:
653: case OP_KETRPOS:
654: return cc + 1 + LINK_SIZE;
655:
656: case OP_CBRA:
657: case OP_CBRAPOS:
658: case OP_SCBRA:
659: case OP_SCBRAPOS:
1.1.1.2 misho 660: return cc + 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 661:
1.1.1.3 ! misho 662: case OP_MARK:
! 663: return cc + 1 + 2 + cc[1];
! 664:
1.1 misho 665: default:
666: return NULL;
667: }
668: }
669:
1.1.1.2 misho 670: static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
1.1 misho 671: {
672: int localspace = 0;
1.1.1.2 misho 673: pcre_uchar *alternative;
1.1 misho 674: /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
675: while (cc < ccend)
676: {
677: switch(*cc)
678: {
1.1.1.3 ! misho 679: case OP_SET_SOM:
! 680: common->has_set_som = TRUE;
! 681: cc += 1;
! 682: break;
! 683:
1.1 misho 684: case OP_ASSERT:
685: case OP_ASSERT_NOT:
686: case OP_ASSERTBACK:
687: case OP_ASSERTBACK_NOT:
688: case OP_ONCE:
689: case OP_ONCE_NC:
690: case OP_BRAPOS:
691: case OP_SBRA:
692: case OP_SBRAPOS:
693: case OP_SCOND:
694: localspace += sizeof(sljit_w);
695: cc += 1 + LINK_SIZE;
696: break;
697:
698: case OP_CBRAPOS:
699: case OP_SCBRAPOS:
700: localspace += sizeof(sljit_w);
1.1.1.2 misho 701: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 702: break;
703:
704: case OP_COND:
705: /* Might be a hidden SCOND. */
706: alternative = cc + GET(cc, 1);
707: if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
708: localspace += sizeof(sljit_w);
709: cc += 1 + LINK_SIZE;
710: break;
711:
1.1.1.3 ! misho 712: case OP_RECURSE:
! 713: /* Set its value only once. */
! 714: if (common->recursive_head == 0)
! 715: {
! 716: common->recursive_head = common->ovector_start;
! 717: common->ovector_start += sizeof(sljit_w);
! 718: }
! 719: cc += 1 + LINK_SIZE;
! 720: break;
! 721:
! 722: case OP_MARK:
! 723: if (common->mark_ptr == 0)
! 724: {
! 725: common->mark_ptr = common->ovector_start;
! 726: common->ovector_start += sizeof(sljit_w);
! 727: }
! 728: cc += 1 + 2 + cc[1];
! 729: break;
! 730:
1.1 misho 731: default:
732: cc = next_opcode(common, cc);
733: if (cc == NULL)
734: return -1;
735: break;
736: }
737: }
738: return localspace;
739: }
740:
1.1.1.2 misho 741: static void set_localptrs(compiler_common *common, int localptr, pcre_uchar *ccend)
1.1 misho 742: {
1.1.1.2 misho 743: pcre_uchar *cc = common->start;
744: pcre_uchar *alternative;
1.1 misho 745: while (cc < ccend)
746: {
747: switch(*cc)
748: {
749: case OP_ASSERT:
750: case OP_ASSERT_NOT:
751: case OP_ASSERTBACK:
752: case OP_ASSERTBACK_NOT:
753: case OP_ONCE:
754: case OP_ONCE_NC:
755: case OP_BRAPOS:
756: case OP_SBRA:
757: case OP_SBRAPOS:
758: case OP_SCOND:
759: common->localptrs[cc - common->start] = localptr;
760: localptr += sizeof(sljit_w);
761: cc += 1 + LINK_SIZE;
762: break;
763:
764: case OP_CBRAPOS:
765: case OP_SCBRAPOS:
766: common->localptrs[cc - common->start] = localptr;
767: localptr += sizeof(sljit_w);
1.1.1.2 misho 768: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 769: break;
770:
771: case OP_COND:
772: /* Might be a hidden SCOND. */
773: alternative = cc + GET(cc, 1);
774: if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
775: {
776: common->localptrs[cc - common->start] = localptr;
777: localptr += sizeof(sljit_w);
778: }
779: cc += 1 + LINK_SIZE;
780: break;
781:
782: default:
783: cc = next_opcode(common, cc);
784: SLJIT_ASSERT(cc != NULL);
785: break;
786: }
787: }
788: }
789:
790: /* Returns with -1 if no need for frame. */
1.1.1.2 misho 791: static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive)
1.1 misho 792: {
1.1.1.2 misho 793: pcre_uchar *ccend = bracketend(cc);
1.1 misho 794: int length = 0;
795: BOOL possessive = FALSE;
1.1.1.3 ! misho 796: BOOL setsom_found = recursive;
! 797: BOOL setmark_found = recursive;
1.1 misho 798:
799: if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
800: {
801: length = 3;
802: possessive = TRUE;
803: }
804:
805: cc = next_opcode(common, cc);
806: SLJIT_ASSERT(cc != NULL);
807: while (cc < ccend)
808: switch(*cc)
809: {
810: case OP_SET_SOM:
1.1.1.3 ! misho 811: SLJIT_ASSERT(common->has_set_som);
1.1 misho 812: if (!setsom_found)
813: {
814: length += 2;
815: setsom_found = TRUE;
816: }
1.1.1.3 ! misho 817: cc += 1;
! 818: break;
! 819:
! 820: case OP_MARK:
! 821: SLJIT_ASSERT(common->mark_ptr != 0);
! 822: if (!setmark_found)
! 823: {
! 824: length += 2;
! 825: setmark_found = TRUE;
! 826: }
! 827: cc += 1 + 2 + cc[1];
! 828: break;
! 829:
! 830: case OP_RECURSE:
! 831: if (common->has_set_som && !setsom_found)
! 832: {
! 833: length += 2;
! 834: setsom_found = TRUE;
! 835: }
! 836: if (common->mark_ptr != 0 && !setmark_found)
! 837: {
! 838: length += 2;
! 839: setmark_found = TRUE;
! 840: }
! 841: cc += 1 + LINK_SIZE;
1.1 misho 842: break;
843:
844: case OP_CBRA:
845: case OP_CBRAPOS:
846: case OP_SCBRA:
847: case OP_SCBRAPOS:
848: length += 3;
1.1.1.2 misho 849: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 850: break;
851:
852: default:
853: cc = next_opcode(common, cc);
854: SLJIT_ASSERT(cc != NULL);
855: break;
856: }
857:
858: /* Possessive quantifiers can use a special case. */
859: if (SLJIT_UNLIKELY(possessive) && length == 3)
860: return -1;
861:
862: if (length > 0)
863: return length + 1;
864: return -1;
865: }
866:
1.1.1.2 misho 867: static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive)
1.1 misho 868: {
869: DEFINE_COMPILER;
1.1.1.2 misho 870: pcre_uchar *ccend = bracketend(cc);
1.1.1.3 ! misho 871: BOOL setsom_found = recursive;
! 872: BOOL setmark_found = recursive;
1.1 misho 873: int offset;
874:
875: /* >= 1 + shortest item size (2) */
1.1.1.2 misho 876: SLJIT_UNUSED_ARG(stacktop);
1.1 misho 877: SLJIT_ASSERT(stackpos >= stacktop + 2);
878:
879: stackpos = STACK(stackpos);
880: if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS))
881: cc = next_opcode(common, cc);
882: SLJIT_ASSERT(cc != NULL);
883: while (cc < ccend)
884: switch(*cc)
885: {
886: case OP_SET_SOM:
1.1.1.3 ! misho 887: SLJIT_ASSERT(common->has_set_som);
1.1 misho 888: if (!setsom_found)
889: {
890: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
891: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
892: stackpos += (int)sizeof(sljit_w);
893: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
894: stackpos += (int)sizeof(sljit_w);
895: setsom_found = TRUE;
896: }
1.1.1.3 ! misho 897: cc += 1;
! 898: break;
! 899:
! 900: case OP_MARK:
! 901: SLJIT_ASSERT(common->mark_ptr != 0);
! 902: if (!setmark_found)
! 903: {
! 904: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
! 905: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark);
! 906: stackpos += (int)sizeof(sljit_w);
! 907: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
! 908: stackpos += (int)sizeof(sljit_w);
! 909: setmark_found = TRUE;
! 910: }
! 911: cc += 1 + 2 + cc[1];
! 912: break;
! 913:
! 914: case OP_RECURSE:
! 915: if (common->has_set_som && !setsom_found)
! 916: {
! 917: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
! 918: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
! 919: stackpos += (int)sizeof(sljit_w);
! 920: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
! 921: stackpos += (int)sizeof(sljit_w);
! 922: setsom_found = TRUE;
! 923: }
! 924: if (common->mark_ptr != 0 && !setmark_found)
! 925: {
! 926: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
! 927: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark);
! 928: stackpos += (int)sizeof(sljit_w);
! 929: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
! 930: stackpos += (int)sizeof(sljit_w);
! 931: setmark_found = TRUE;
! 932: }
! 933: cc += 1 + LINK_SIZE;
1.1 misho 934: break;
935:
936: case OP_CBRA:
937: case OP_CBRAPOS:
938: case OP_SCBRA:
939: case OP_SCBRAPOS:
940: offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
941: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
942: stackpos += (int)sizeof(sljit_w);
943: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
944: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
945: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
946: stackpos += (int)sizeof(sljit_w);
947: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
948: stackpos += (int)sizeof(sljit_w);
949:
1.1.1.2 misho 950: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 951: break;
952:
953: default:
954: cc = next_opcode(common, cc);
955: SLJIT_ASSERT(cc != NULL);
956: break;
957: }
958:
959: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end);
960: SLJIT_ASSERT(stackpos == STACK(stacktop));
961: }
962:
1.1.1.2 misho 963: static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
1.1 misho 964: {
965: int localsize = 2;
1.1.1.2 misho 966: pcre_uchar *alternative;
1.1 misho 967: /* Calculate the sum of the local variables. */
968: while (cc < ccend)
969: {
970: switch(*cc)
971: {
972: case OP_ASSERT:
973: case OP_ASSERT_NOT:
974: case OP_ASSERTBACK:
975: case OP_ASSERTBACK_NOT:
976: case OP_ONCE:
977: case OP_ONCE_NC:
978: case OP_BRAPOS:
979: case OP_SBRA:
980: case OP_SBRAPOS:
981: case OP_SCOND:
982: localsize++;
983: cc += 1 + LINK_SIZE;
984: break;
985:
986: case OP_CBRA:
987: case OP_SCBRA:
988: localsize++;
1.1.1.2 misho 989: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 990: break;
991:
992: case OP_CBRAPOS:
993: case OP_SCBRAPOS:
994: localsize += 2;
1.1.1.2 misho 995: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 996: break;
997:
998: case OP_COND:
999: /* Might be a hidden SCOND. */
1000: alternative = cc + GET(cc, 1);
1001: if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
1002: localsize++;
1003: cc += 1 + LINK_SIZE;
1004: break;
1005:
1006: default:
1007: cc = next_opcode(common, cc);
1008: SLJIT_ASSERT(cc != NULL);
1009: break;
1010: }
1011: }
1012: SLJIT_ASSERT(cc == ccend);
1013: return localsize;
1014: }
1015:
1.1.1.2 misho 1016: static void copy_locals(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend,
1.1 misho 1017: BOOL save, int stackptr, int stacktop)
1018: {
1019: DEFINE_COMPILER;
1020: int srcw[2];
1021: int count;
1022: BOOL tmp1next = TRUE;
1023: BOOL tmp1empty = TRUE;
1024: BOOL tmp2empty = TRUE;
1.1.1.2 misho 1025: pcre_uchar *alternative;
1.1 misho 1026: enum {
1027: start,
1028: loop,
1029: end
1030: } status;
1031:
1032: status = save ? start : loop;
1033: stackptr = STACK(stackptr - 2);
1034: stacktop = STACK(stacktop - 1);
1035:
1036: if (!save)
1037: {
1038: stackptr += sizeof(sljit_w);
1039: if (stackptr < stacktop)
1040: {
1041: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1042: stackptr += sizeof(sljit_w);
1043: tmp1empty = FALSE;
1044: }
1045: if (stackptr < stacktop)
1046: {
1047: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1048: stackptr += sizeof(sljit_w);
1049: tmp2empty = FALSE;
1050: }
1051: /* The tmp1next must be TRUE in either way. */
1052: }
1053:
1054: while (status != end)
1055: {
1056: count = 0;
1057: switch(status)
1058: {
1059: case start:
1.1.1.3 ! misho 1060: SLJIT_ASSERT(save && common->recursive_head != 0);
1.1 misho 1061: count = 1;
1.1.1.3 ! misho 1062: srcw[0] = common->recursive_head;
1.1 misho 1063: status = loop;
1064: break;
1065:
1066: case loop:
1067: if (cc >= ccend)
1068: {
1069: status = end;
1070: break;
1071: }
1072:
1073: switch(*cc)
1074: {
1075: case OP_ASSERT:
1076: case OP_ASSERT_NOT:
1077: case OP_ASSERTBACK:
1078: case OP_ASSERTBACK_NOT:
1079: case OP_ONCE:
1080: case OP_ONCE_NC:
1081: case OP_BRAPOS:
1082: case OP_SBRA:
1083: case OP_SBRAPOS:
1084: case OP_SCOND:
1085: count = 1;
1.1.1.2 misho 1086: srcw[0] = PRIV_DATA(cc);
1.1 misho 1087: SLJIT_ASSERT(srcw[0] != 0);
1088: cc += 1 + LINK_SIZE;
1089: break;
1090:
1091: case OP_CBRA:
1092: case OP_SCBRA:
1093: count = 1;
1094: srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
1.1.1.2 misho 1095: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 1096: break;
1097:
1098: case OP_CBRAPOS:
1099: case OP_SCBRAPOS:
1100: count = 2;
1101: srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
1.1.1.2 misho 1102: srcw[0] = PRIV_DATA(cc);
1.1 misho 1103: SLJIT_ASSERT(srcw[0] != 0);
1.1.1.2 misho 1104: cc += 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 1105: break;
1106:
1107: case OP_COND:
1108: /* Might be a hidden SCOND. */
1109: alternative = cc + GET(cc, 1);
1110: if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
1111: {
1112: count = 1;
1.1.1.2 misho 1113: srcw[0] = PRIV_DATA(cc);
1.1 misho 1114: SLJIT_ASSERT(srcw[0] != 0);
1115: }
1116: cc += 1 + LINK_SIZE;
1117: break;
1118:
1119: default:
1120: cc = next_opcode(common, cc);
1121: SLJIT_ASSERT(cc != NULL);
1122: break;
1123: }
1124: break;
1125:
1126: case end:
1127: SLJIT_ASSERT_STOP();
1128: break;
1129: }
1130:
1131: while (count > 0)
1132: {
1133: count--;
1134: if (save)
1135: {
1136: if (tmp1next)
1137: {
1138: if (!tmp1empty)
1139: {
1140: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1141: stackptr += sizeof(sljit_w);
1142: }
1143: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1144: tmp1empty = FALSE;
1145: tmp1next = FALSE;
1146: }
1147: else
1148: {
1149: if (!tmp2empty)
1150: {
1151: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1152: stackptr += sizeof(sljit_w);
1153: }
1154: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1155: tmp2empty = FALSE;
1156: tmp1next = TRUE;
1157: }
1158: }
1159: else
1160: {
1161: if (tmp1next)
1162: {
1163: SLJIT_ASSERT(!tmp1empty);
1164: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0);
1165: tmp1empty = stackptr >= stacktop;
1166: if (!tmp1empty)
1167: {
1168: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1169: stackptr += sizeof(sljit_w);
1170: }
1171: tmp1next = FALSE;
1172: }
1173: else
1174: {
1175: SLJIT_ASSERT(!tmp2empty);
1176: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0);
1177: tmp2empty = stackptr >= stacktop;
1178: if (!tmp2empty)
1179: {
1180: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1181: stackptr += sizeof(sljit_w);
1182: }
1183: tmp1next = TRUE;
1184: }
1185: }
1186: }
1187: }
1188:
1189: if (save)
1190: {
1191: if (tmp1next)
1192: {
1193: if (!tmp1empty)
1194: {
1195: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1196: stackptr += sizeof(sljit_w);
1197: }
1198: if (!tmp2empty)
1199: {
1200: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1201: stackptr += sizeof(sljit_w);
1202: }
1203: }
1204: else
1205: {
1206: if (!tmp2empty)
1207: {
1208: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1209: stackptr += sizeof(sljit_w);
1210: }
1211: if (!tmp1empty)
1212: {
1213: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1214: stackptr += sizeof(sljit_w);
1215: }
1216: }
1217: }
1218: SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
1219: }
1220:
1221: static SLJIT_INLINE BOOL ispowerof2(unsigned int value)
1222: {
1223: return (value & (value - 1)) == 0;
1224: }
1225:
1226: static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)
1227: {
1228: while (list)
1229: {
1230: /* sljit_set_label is clever enough to do nothing
1231: if either the jump or the label is NULL */
1232: sljit_set_label(list->jump, label);
1233: list = list->next;
1234: }
1235: }
1236:
1237: static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump)
1238: {
1239: jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));
1240: if (list_item)
1241: {
1242: list_item->next = *list;
1243: list_item->jump = jump;
1244: *list = list_item;
1245: }
1246: }
1247:
1248: static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start)
1249: {
1250: DEFINE_COMPILER;
1251: stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list));
1252:
1253: if (list_item)
1254: {
1255: list_item->type = type;
1256: list_item->data = data;
1257: list_item->start = start;
1258: list_item->leave = LABEL();
1259: list_item->next = common->stubs;
1260: common->stubs = list_item;
1261: }
1262: }
1263:
1264: static void flush_stubs(compiler_common *common)
1265: {
1266: DEFINE_COMPILER;
1267: stub_list* list_item = common->stubs;
1268:
1269: while (list_item)
1270: {
1271: JUMPHERE(list_item->start);
1272: switch(list_item->type)
1273: {
1274: case stack_alloc:
1275: add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
1276: break;
1277: }
1278: JUMPTO(SLJIT_JUMP, list_item->leave);
1279: list_item = list_item->next;
1280: }
1281: common->stubs = NULL;
1282: }
1283:
1284: static SLJIT_INLINE void decrease_call_count(compiler_common *common)
1285: {
1286: DEFINE_COMPILER;
1287:
1288: OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1);
1289: add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
1290: }
1291:
1292: static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
1293: {
1294: /* May destroy all locals and registers except TMP2. */
1295: DEFINE_COMPILER;
1296:
1297: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1298: #ifdef DESTROY_REGISTERS
1299: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
1300: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
1301: OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
1302: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0);
1303: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
1304: #endif
1305: add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
1306: }
1307:
1308: static SLJIT_INLINE void free_stack(compiler_common *common, int size)
1309: {
1310: DEFINE_COMPILER;
1311: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1312: }
1313:
1314: static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
1315: {
1316: DEFINE_COMPILER;
1317: struct sljit_label *loop;
1318: int i;
1319: /* At this point we can freely use all temporary registers. */
1320: /* TMP1 returns with begin - 1. */
1.1.1.2 misho 1321: OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1322: if (length < 8)
1323: {
1324: for (i = 0; i < length; i++)
1325: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0);
1326: }
1327: else
1328: {
1.1.1.3 ! misho 1329: GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, OVECTOR_START - sizeof(sljit_w));
1.1 misho 1330: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);
1331: loop = LABEL();
1332: OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);
1333: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
1334: JUMPTO(SLJIT_C_NOT_ZERO, loop);
1335: }
1336: }
1337:
1338: static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
1339: {
1340: DEFINE_COMPILER;
1341: struct sljit_label *loop;
1342: struct sljit_jump *earlyexit;
1343:
1344: /* At this point we can freely use all registers. */
1.1.1.2 misho 1345: OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
1.1 misho 1346: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);
1347:
1348: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);
1.1.1.3 ! misho 1349: if (common->mark_ptr != 0)
! 1350: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
1.1 misho 1351: OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
1.1.1.3 ! misho 1352: if (common->mark_ptr != 0)
! 1353: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_TEMPORARY_REG3, 0);
1.1 misho 1354: OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
1355: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
1.1.1.3 ! misho 1356: GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START);
1.1 misho 1357: /* Unlikely, but possible */
1358: earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);
1359: loop = LABEL();
1.1.1.2 misho 1360: OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0);
1361: OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w));
1.1 misho 1362: /* Copy the integer value to the output buffer */
1.1.1.2 misho 1363: #ifdef COMPILE_PCRE16
1364: OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1);
1365: #endif
1366: OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0);
1.1 misho 1367: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1368: JUMPTO(SLJIT_C_NOT_ZERO, loop);
1369: JUMPHERE(earlyexit);
1370:
1371: /* Calculate the return value, which is the maximum ovector value. */
1372: if (topbracket > 1)
1373: {
1.1.1.3 ! misho 1374: GET_LOCAL_BASE(SLJIT_TEMPORARY_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_w));
1.1 misho 1375: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1);
1376:
1.1.1.2 misho 1377: /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
1.1 misho 1378: loop = LABEL();
1379: OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w)));
1380: OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1.1.1.2 misho 1381: CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop);
1.1 misho 1382: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0);
1383: }
1384: else
1385: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
1386: }
1387:
1.1.1.3 ! misho 1388: static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *leave)
! 1389: {
! 1390: DEFINE_COMPILER;
! 1391:
! 1392: SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2);
! 1393: SLJIT_ASSERT(common->start_used_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0));
! 1394:
! 1395: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
! 1396: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL);
! 1397: OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount));
! 1398: CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, leave);
! 1399:
! 1400: /* Store match begin and end. */
! 1401: OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin));
! 1402: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsets));
! 1403: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start);
! 1404: OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0);
! 1405: #ifdef COMPILE_PCRE16
! 1406: OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1);
! 1407: #endif
! 1408: OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(int), SLJIT_SAVED_REG2, 0);
! 1409:
! 1410: OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG1, 0);
! 1411: #ifdef COMPILE_PCRE16
! 1412: OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
! 1413: #endif
! 1414: OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0);
! 1415:
! 1416: JUMPTO(SLJIT_JUMP, leave);
! 1417: }
! 1418:
! 1419: static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)
! 1420: {
! 1421: /* May destroy TMP1. */
! 1422: DEFINE_COMPILER;
! 1423: struct sljit_jump *jump;
! 1424:
! 1425: if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
! 1426: {
! 1427: /* The value of -1 must be kept for start_used_ptr! */
! 1428: OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, 1);
! 1429: /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting
! 1430: is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */
! 1431: jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0);
! 1432: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
! 1433: JUMPHERE(jump);
! 1434: }
! 1435: else if (common->mode == JIT_PARTIAL_HARD_COMPILE)
! 1436: {
! 1437: jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
! 1438: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
! 1439: JUMPHERE(jump);
! 1440: }
! 1441: }
! 1442:
1.1.1.2 misho 1443: static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc)
1.1 misho 1444: {
1445: /* Detects if the character has an othercase. */
1446: unsigned int c;
1447:
1.1.1.2 misho 1448: #ifdef SUPPORT_UTF
1449: if (common->utf)
1.1 misho 1450: {
1451: GETCHAR(c, cc);
1452: if (c > 127)
1453: {
1454: #ifdef SUPPORT_UCP
1455: return c != UCD_OTHERCASE(c);
1456: #else
1457: return FALSE;
1458: #endif
1459: }
1.1.1.2 misho 1460: #ifndef COMPILE_PCRE8
1461: return common->fcc[c] != c;
1462: #endif
1.1 misho 1463: }
1464: else
1465: #endif
1466: c = *cc;
1.1.1.2 misho 1467: return MAX_255(c) ? common->fcc[c] != c : FALSE;
1.1 misho 1468: }
1469:
1470: static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)
1471: {
1472: /* Returns with the othercase. */
1.1.1.2 misho 1473: #ifdef SUPPORT_UTF
1474: if (common->utf && c > 127)
1.1 misho 1475: {
1476: #ifdef SUPPORT_UCP
1477: return UCD_OTHERCASE(c);
1478: #else
1479: return c;
1480: #endif
1481: }
1482: #endif
1.1.1.2 misho 1483: return TABLE_GET(c, common->fcc, c);
1.1 misho 1484: }
1485:
1.1.1.2 misho 1486: static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc)
1.1 misho 1487: {
1488: /* Detects if the character and its othercase has only 1 bit difference. */
1489: unsigned int c, oc, bit;
1.1.1.2 misho 1490: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.1 misho 1491: int n;
1492: #endif
1493:
1.1.1.2 misho 1494: #ifdef SUPPORT_UTF
1495: if (common->utf)
1.1 misho 1496: {
1497: GETCHAR(c, cc);
1498: if (c <= 127)
1499: oc = common->fcc[c];
1500: else
1501: {
1502: #ifdef SUPPORT_UCP
1503: oc = UCD_OTHERCASE(c);
1504: #else
1505: oc = c;
1506: #endif
1507: }
1508: }
1509: else
1510: {
1511: c = *cc;
1.1.1.2 misho 1512: oc = TABLE_GET(c, common->fcc, c);
1.1 misho 1513: }
1514: #else
1515: c = *cc;
1.1.1.2 misho 1516: oc = TABLE_GET(c, common->fcc, c);
1.1 misho 1517: #endif
1518:
1519: SLJIT_ASSERT(c != oc);
1520:
1521: bit = c ^ oc;
1522: /* Optimized for English alphabet. */
1523: if (c <= 127 && bit == 0x20)
1524: return (0 << 8) | 0x20;
1525:
1526: /* Since c != oc, they must have at least 1 bit difference. */
1527: if (!ispowerof2(bit))
1528: return 0;
1529:
1.1.1.2 misho 1530: #ifdef COMPILE_PCRE8
1531:
1532: #ifdef SUPPORT_UTF
1533: if (common->utf && c > 127)
1.1 misho 1534: {
1.1.1.2 misho 1535: n = GET_EXTRALEN(*cc);
1.1 misho 1536: while ((bit & 0x3f) == 0)
1537: {
1538: n--;
1539: bit >>= 6;
1540: }
1541: return (n << 8) | bit;
1542: }
1.1.1.2 misho 1543: #endif /* SUPPORT_UTF */
1.1 misho 1544: return (0 << 8) | bit;
1.1.1.2 misho 1545:
1546: #else /* COMPILE_PCRE8 */
1547:
1548: #ifdef COMPILE_PCRE16
1549: #ifdef SUPPORT_UTF
1550: if (common->utf && c > 65535)
1551: {
1552: if (bit >= (1 << 10))
1553: bit >>= 10;
1554: else
1555: return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));
1556: }
1557: #endif /* SUPPORT_UTF */
1558: return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8));
1559: #endif /* COMPILE_PCRE16 */
1560:
1561: #endif /* COMPILE_PCRE8 */
1.1 misho 1562: }
1563:
1.1.1.3 ! misho 1564: static void check_partial(compiler_common *common, BOOL force)
! 1565: {
! 1566: /* Checks whether a partial matching is occured. Does not modify registers. */
! 1567: DEFINE_COMPILER;
! 1568: struct sljit_jump *jump = NULL;
! 1569:
! 1570: SLJIT_ASSERT(!force || common->mode != JIT_COMPILE);
! 1571:
! 1572: if (common->mode == JIT_COMPILE)
! 1573: return;
! 1574:
! 1575: if (!force)
! 1576: jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
! 1577: else if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
! 1578: jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1);
! 1579:
! 1580: if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
! 1581: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
! 1582: else
! 1583: {
! 1584: if (common->partialmatchlabel != NULL)
! 1585: JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
! 1586: else
! 1587: add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
! 1588: }
! 1589:
! 1590: if (jump != NULL)
! 1591: JUMPHERE(jump);
! 1592: }
! 1593:
! 1594: static struct sljit_jump *check_str_end(compiler_common *common)
! 1595: {
! 1596: /* Does not affect registers. Usually used in a tight spot. */
! 1597: DEFINE_COMPILER;
! 1598: struct sljit_jump *jump;
! 1599: struct sljit_jump *nohit;
! 1600: struct sljit_jump *return_value;
! 1601:
! 1602: if (common->mode == JIT_COMPILE)
! 1603: return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
! 1604:
! 1605: jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
! 1606: if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
! 1607: {
! 1608: nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
! 1609: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
! 1610: JUMPHERE(nohit);
! 1611: return_value = JUMP(SLJIT_JUMP);
! 1612: }
! 1613: else
! 1614: {
! 1615: return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
! 1616: if (common->partialmatchlabel != NULL)
! 1617: JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
! 1618: else
! 1619: add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
! 1620: }
! 1621: JUMPHERE(jump);
! 1622: return return_value;
! 1623: }
! 1624:
! 1625: static void detect_partial_match(compiler_common *common, jump_list **backtracks)
1.1 misho 1626: {
1627: DEFINE_COMPILER;
1.1.1.3 ! misho 1628: struct sljit_jump *jump;
! 1629:
! 1630: if (common->mode == JIT_COMPILE)
! 1631: {
! 1632: add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
! 1633: return;
! 1634: }
! 1635:
! 1636: /* Partial matching mode. */
! 1637: jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
! 1638: add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0));
! 1639: if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
! 1640: {
! 1641: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
! 1642: add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
! 1643: }
! 1644: else
! 1645: {
! 1646: if (common->partialmatchlabel != NULL)
! 1647: JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
! 1648: else
! 1649: add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
! 1650: }
! 1651: JUMPHERE(jump);
1.1 misho 1652: }
1653:
1654: static void read_char(compiler_common *common)
1655: {
1656: /* Reads the character into TMP1, updates STR_PTR.
1657: Does not check STR_END. TMP2 Destroyed. */
1658: DEFINE_COMPILER;
1.1.1.2 misho 1659: #ifdef SUPPORT_UTF
1.1 misho 1660: struct sljit_jump *jump;
1661: #endif
1662:
1.1.1.2 misho 1663: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1664: #ifdef SUPPORT_UTF
1665: if (common->utf)
1.1 misho 1666: {
1.1.1.2 misho 1667: #ifdef COMPILE_PCRE8
1.1 misho 1668: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.1.1.2 misho 1669: #else
1670: #ifdef COMPILE_PCRE16
1671: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
1672: #endif
1673: #endif /* COMPILE_PCRE8 */
1674: add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
1.1 misho 1675: JUMPHERE(jump);
1676: }
1677: #endif
1.1.1.2 misho 1678: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1679: }
1680:
1681: static void peek_char(compiler_common *common)
1682: {
1683: /* Reads the character into TMP1, keeps STR_PTR.
1684: Does not check STR_END. TMP2 Destroyed. */
1685: DEFINE_COMPILER;
1.1.1.2 misho 1686: #ifdef SUPPORT_UTF
1.1 misho 1687: struct sljit_jump *jump;
1688: #endif
1689:
1.1.1.2 misho 1690: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1691: #ifdef SUPPORT_UTF
1692: if (common->utf)
1.1 misho 1693: {
1.1.1.2 misho 1694: #ifdef COMPILE_PCRE8
1.1 misho 1695: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.1.1.2 misho 1696: #else
1697: #ifdef COMPILE_PCRE16
1698: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
1699: #endif
1700: #endif /* COMPILE_PCRE8 */
1701: add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
1.1 misho 1702: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1703: JUMPHERE(jump);
1704: }
1705: #endif
1706: }
1707:
1708: static void read_char8_type(compiler_common *common)
1709: {
1710: /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
1711: DEFINE_COMPILER;
1.1.1.2 misho 1712: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
1.1 misho 1713: struct sljit_jump *jump;
1714: #endif
1715:
1.1.1.2 misho 1716: #ifdef SUPPORT_UTF
1717: if (common->utf)
1.1 misho 1718: {
1.1.1.2 misho 1719: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1720: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1721: #ifdef COMPILE_PCRE8
1.1 misho 1722: /* This can be an extra read in some situations, but hopefully
1.1.1.2 misho 1723: it is needed in most cases. */
1.1 misho 1724: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1725: jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
1.1.1.2 misho 1726: add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
1727: JUMPHERE(jump);
1728: #else
1729: #ifdef COMPILE_PCRE16
1730: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1731: jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
1732: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1.1 misho 1733: JUMPHERE(jump);
1.1.1.2 misho 1734: /* Skip low surrogate if necessary. */
1735: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00);
1736: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800);
1737: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1738: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
1739: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1740: #endif
1741: #endif /* COMPILE_PCRE8 */
1.1 misho 1742: return;
1743: }
1744: #endif
1.1.1.2 misho 1745: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1746: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1747: #ifdef COMPILE_PCRE16
1748: /* The ctypes array contains only 256 values. */
1749: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1750: jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
1751: #endif
1752: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1753: #ifdef COMPILE_PCRE16
1754: JUMPHERE(jump);
1755: #endif
1.1 misho 1756: }
1757:
1758: static void skip_char_back(compiler_common *common)
1759: {
1.1.1.2 misho 1760: /* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
1.1 misho 1761: DEFINE_COMPILER;
1.1.1.2 misho 1762: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1.1 misho 1763: struct sljit_label *label;
1764:
1.1.1.2 misho 1765: if (common->utf)
1.1 misho 1766: {
1767: label = LABEL();
1.1.1.2 misho 1768: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
1769: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1770: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
1771: CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
1772: return;
1773: }
1774: #endif
1.1.1.2 misho 1775: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
1776: if (common->utf)
1777: {
1778: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
1779: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1780: /* Skip low surrogate if necessary. */
1781: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
1782: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
1783: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1784: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1785: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1786: return;
1787: }
1788: #endif
1789: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1790: }
1791:
1.1.1.3 ! misho 1792: static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpiftrue)
1.1 misho 1793: {
1794: /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
1795: DEFINE_COMPILER;
1796:
1797: if (nltype == NLTYPE_ANY)
1798: {
1799: add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
1.1.1.3 ! misho 1800: add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1.1 misho 1801: }
1802: else if (nltype == NLTYPE_ANYCRLF)
1803: {
1804: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR);
1805: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1806: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1807: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1.1.1.3 ! misho 1808: add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1.1 misho 1809: }
1810: else
1811: {
1.1.1.2 misho 1812: SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);
1.1.1.3 ! misho 1813: add_jump(compiler, backtracks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
1.1 misho 1814: }
1815: }
1816:
1.1.1.2 misho 1817: #ifdef SUPPORT_UTF
1818:
1819: #ifdef COMPILE_PCRE8
1820: static void do_utfreadchar(compiler_common *common)
1.1 misho 1821: {
1.1.1.2 misho 1822: /* Fast decoding a UTF-8 character. TMP1 contains the first byte
1.1 misho 1823: of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */
1824: DEFINE_COMPILER;
1825: struct sljit_jump *jump;
1826:
1.1.1.3 ! misho 1827: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 1828: /* Searching for the first zero. */
1829: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
1830: jump = JUMP(SLJIT_C_NOT_ZERO);
1.1.1.2 misho 1831: /* Two byte sequence. */
1832: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1833: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1834: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f);
1835: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
1836: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1837: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 misho 1838: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1839: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1840: JUMPHERE(jump);
1841:
1842: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10);
1843: jump = JUMP(SLJIT_C_NOT_ZERO);
1.1.1.2 misho 1844: /* Three byte sequence. */
1845: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 1846: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f);
1847: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12);
1848: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1849: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1850: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 misho 1851: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
1852: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 1853: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1854: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 misho 1855: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 1856: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1857: JUMPHERE(jump);
1858:
1.1.1.2 misho 1859: /* Four byte sequence. */
1860: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 1861: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07);
1862: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18);
1863: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1864: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
1865: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 misho 1866: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
1.1 misho 1867: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1868: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1869: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 misho 1870: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3));
1871: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
1.1 misho 1872: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1873: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 misho 1874: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));
1.1 misho 1875: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1876: }
1877:
1.1.1.2 misho 1878: static void do_utfreadtype8(compiler_common *common)
1.1 misho 1879: {
1.1.1.2 misho 1880: /* Fast decoding a UTF-8 character type. TMP2 contains the first byte
1881: of the character (>= 0xc0). Return value in TMP1. */
1.1 misho 1882: DEFINE_COMPILER;
1883: struct sljit_jump *jump;
1884: struct sljit_jump *compare;
1885:
1.1.1.3 ! misho 1886: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 1887:
1888: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
1889: jump = JUMP(SLJIT_C_NOT_ZERO);
1.1.1.2 misho 1890: /* Two byte sequence. */
1891: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1892: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 1893: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);
1894: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1895: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
1896: OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
1897: compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
1898: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1899: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1900:
1901: JUMPHERE(compare);
1902: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1903: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1904: JUMPHERE(jump);
1905:
1906: /* We only have types for characters less than 256. */
1.1.1.2 misho 1907: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(utf8_table4) - 0xc0);
1.1 misho 1908: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1909: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1910: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1911: }
1912:
1.1.1.2 misho 1913: #else /* COMPILE_PCRE8 */
1914:
1915: #ifdef COMPILE_PCRE16
1916: static void do_utfreadchar(compiler_common *common)
1917: {
1918: /* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char
1919: of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */
1920: DEFINE_COMPILER;
1921: struct sljit_jump *jump;
1922:
1.1.1.3 ! misho 1923: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1.1.2 misho 1924: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);
1925: /* Do nothing, only return. */
1926: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1927:
1928: JUMPHERE(jump);
1929: /* Combine two 16 bit characters. */
1930: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1931: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1932: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
1933: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);
1934: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff);
1935: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1936: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
1937: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
1938: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1939: }
1940: #endif /* COMPILE_PCRE16 */
1941:
1942: #endif /* COMPILE_PCRE8 */
1943:
1944: #endif /* SUPPORT_UTF */
1.1 misho 1945:
1946: #ifdef SUPPORT_UCP
1947:
1948: /* UCD_BLOCK_SIZE must be 128 (see the assert below). */
1949: #define UCD_BLOCK_MASK 127
1950: #define UCD_BLOCK_SHIFT 7
1951:
1952: static void do_getucd(compiler_common *common)
1953: {
1954: /* Search the UCD record for the character comes in TMP1.
1955: Returns chartype in TMP1 and UCD offset in TMP2. */
1956: DEFINE_COMPILER;
1957:
1958: SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
1959:
1.1.1.3 ! misho 1960: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 1961: OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1.1.1.2 misho 1962: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1));
1.1 misho 1963: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
1964: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1965: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
1.1.1.2 misho 1966: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_stage2));
1.1 misho 1967: OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
1.1.1.2 misho 1968: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
1.1 misho 1969: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1970: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1971: }
1972: #endif
1973:
1974: static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline)
1975: {
1976: DEFINE_COMPILER;
1977: struct sljit_label *mainloop;
1978: struct sljit_label *newlinelabel = NULL;
1979: struct sljit_jump *start;
1980: struct sljit_jump *end = NULL;
1981: struct sljit_jump *nl = NULL;
1.1.1.2 misho 1982: #ifdef SUPPORT_UTF
1983: struct sljit_jump *singlechar;
1.1 misho 1984: #endif
1985: jump_list *newline = NULL;
1986: BOOL newlinecheck = FALSE;
1.1.1.2 misho 1987: BOOL readuchar = FALSE;
1.1 misho 1988:
1989: if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY ||
1990: common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
1991: newlinecheck = TRUE;
1992:
1993: if (firstline)
1994: {
1995: /* Search for the end of the first line. */
1.1.1.3 ! misho 1996: SLJIT_ASSERT(common->first_line_end != 0);
1.1 misho 1997: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);
1.1.1.3 ! misho 1998: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_END, 0);
1.1 misho 1999:
2000: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2001: {
2002: mainloop = LABEL();
1.1.1.2 misho 2003: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2004: end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 misho 2005: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
2006: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1 misho 2007: CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
2008: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
1.1.1.3 ! misho 2009: OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2010: }
2011: else
2012: {
2013: end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2014: mainloop = LABEL();
2015: /* Continual stores does not cause data dependency. */
1.1.1.3 ! misho 2016: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
1.1 misho 2017: read_char(common);
2018: check_newlinechar(common, common->nltype, &newline, TRUE);
2019: CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
1.1.1.3 ! misho 2020: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
1.1 misho 2021: set_jumps(newline, LABEL());
2022: }
2023:
2024: JUMPHERE(end);
2025: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2026: }
2027:
2028: start = JUMP(SLJIT_JUMP);
2029:
2030: if (newlinecheck)
2031: {
2032: newlinelabel = LABEL();
1.1.1.2 misho 2033: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2034: end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 misho 2035: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 2036: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
2037: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1.1.1.2 misho 2038: #ifdef COMPILE_PCRE16
2039: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2040: #endif
1.1 misho 2041: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2042: nl = JUMP(SLJIT_JUMP);
2043: }
2044:
2045: mainloop = LABEL();
2046:
2047: /* Increasing the STR_PTR here requires one less jump in the most common case. */
1.1.1.2 misho 2048: #ifdef SUPPORT_UTF
2049: if (common->utf) readuchar = TRUE;
1.1 misho 2050: #endif
1.1.1.2 misho 2051: if (newlinecheck) readuchar = TRUE;
1.1 misho 2052:
1.1.1.2 misho 2053: if (readuchar)
2054: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 2055:
2056: if (newlinecheck)
2057: CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);
2058:
1.1.1.2 misho 2059: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
2060: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2061: if (common->utf)
1.1 misho 2062: {
1.1.1.2 misho 2063: singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
2064: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
1.1 misho 2065: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1.1.1.2 misho 2066: JUMPHERE(singlechar);
2067: }
2068: #endif
2069: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2070: if (common->utf)
2071: {
2072: singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
2073: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
2074: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
2075: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
2076: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2077: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2078: JUMPHERE(singlechar);
1.1 misho 2079: }
2080: #endif
2081: JUMPHERE(start);
2082:
2083: if (newlinecheck)
2084: {
2085: JUMPHERE(end);
2086: JUMPHERE(nl);
2087: }
2088:
2089: return mainloop;
2090: }
2091:
1.1.1.2 misho 2092: static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline)
1.1 misho 2093: {
2094: DEFINE_COMPILER;
2095: struct sljit_label *start;
2096: struct sljit_jump *leave;
2097: struct sljit_jump *found;
1.1.1.2 misho 2098: pcre_uchar oc, bit;
1.1 misho 2099:
2100: if (firstline)
2101: {
2102: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1.1.1.3 ! misho 2103: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
1.1 misho 2104: }
2105:
2106: start = LABEL();
2107: leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 misho 2108: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 2109:
1.1.1.2 misho 2110: oc = first_char;
2111: if (caseless)
2112: {
2113: oc = TABLE_GET(first_char, common->fcc, first_char);
2114: #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
2115: if (first_char > 127 && common->utf)
2116: oc = UCD_OTHERCASE(first_char);
2117: #endif
2118: }
2119: if (first_char == oc)
2120: found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char);
1.1 misho 2121: else
2122: {
1.1.1.2 misho 2123: bit = first_char ^ oc;
1.1 misho 2124: if (ispowerof2(bit))
2125: {
2126: OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);
1.1.1.2 misho 2127: found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit);
1.1 misho 2128: }
2129: else
2130: {
1.1.1.2 misho 2131: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char);
1.1 misho 2132: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2133: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
2134: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2135: found = JUMP(SLJIT_C_NOT_ZERO);
2136: }
2137: }
2138:
1.1.1.2 misho 2139: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
2140: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2141: if (common->utf)
1.1 misho 2142: {
2143: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
1.1.1.2 misho 2144: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
2145: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2146: }
2147: #endif
2148: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2149: if (common->utf)
2150: {
2151: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
2152: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
2153: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
2154: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
2155: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1.1 misho 2156: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2157: }
2158: #endif
2159: JUMPTO(SLJIT_JUMP, start);
2160: JUMPHERE(found);
2161: JUMPHERE(leave);
2162:
2163: if (firstline)
2164: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
2165: }
2166:
2167: static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)
2168: {
2169: DEFINE_COMPILER;
2170: struct sljit_label *loop;
2171: struct sljit_jump *lastchar;
2172: struct sljit_jump *firstchar;
2173: struct sljit_jump *leave;
2174: struct sljit_jump *foundcr = NULL;
2175: struct sljit_jump *notfoundnl;
2176: jump_list *newline = NULL;
2177:
2178: if (firstline)
2179: {
2180: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1.1.1.3 ! misho 2181: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
1.1 misho 2182: }
2183:
2184: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2185: {
2186: lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2187: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2188: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
2189: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2190: firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
2191:
1.1.1.2 misho 2192: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 2193: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
2194: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL);
1.1.1.2 misho 2195: #ifdef COMPILE_PCRE16
2196: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2197: #endif
1.1 misho 2198: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2199:
2200: loop = LABEL();
1.1.1.2 misho 2201: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2202: leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 misho 2203: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
2204: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
1.1 misho 2205: CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);
2206: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);
2207:
2208: JUMPHERE(leave);
2209: JUMPHERE(firstchar);
2210: JUMPHERE(lastchar);
2211:
2212: if (firstline)
2213: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
2214: return;
2215: }
2216:
2217: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2218: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
2219: firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
2220: skip_char_back(common);
2221:
2222: loop = LABEL();
2223: read_char(common);
2224: lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2225: if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
2226: foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
2227: check_newlinechar(common, common->nltype, &newline, FALSE);
2228: set_jumps(newline, loop);
2229:
2230: if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
2231: {
2232: leave = JUMP(SLJIT_JUMP);
2233: JUMPHERE(foundcr);
2234: notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 misho 2235: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 2236: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
2237: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1.1.1.2 misho 2238: #ifdef COMPILE_PCRE16
2239: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2240: #endif
1.1 misho 2241: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2242: JUMPHERE(notfoundnl);
2243: JUMPHERE(leave);
2244: }
2245: JUMPHERE(lastchar);
2246: JUMPHERE(firstchar);
2247:
2248: if (firstline)
2249: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
2250: }
2251:
2252: static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline)
2253: {
2254: DEFINE_COMPILER;
2255: struct sljit_label *start;
2256: struct sljit_jump *leave;
2257: struct sljit_jump *found;
1.1.1.2 misho 2258: #ifndef COMPILE_PCRE8
2259: struct sljit_jump *jump;
2260: #endif
1.1 misho 2261:
2262: if (firstline)
2263: {
2264: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1.1.1.3 ! misho 2265: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
1.1 misho 2266: }
2267:
2268: start = LABEL();
2269: leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1.1.1.2 misho 2270: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2271: #ifdef SUPPORT_UTF
2272: if (common->utf)
1.1 misho 2273: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2274: #endif
1.1.1.2 misho 2275: #ifndef COMPILE_PCRE8
2276: jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255);
2277: OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255);
2278: JUMPHERE(jump);
2279: #endif
1.1 misho 2280: OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
2281: OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
2282: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits);
2283: OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
2284: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
2285: found = JUMP(SLJIT_C_NOT_ZERO);
2286:
1.1.1.2 misho 2287: #ifdef SUPPORT_UTF
2288: if (common->utf)
1.1 misho 2289: OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2290: #endif
1.1.1.2 misho 2291: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
2292: #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2293: if (common->utf)
1.1 misho 2294: {
2295: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
1.1.1.2 misho 2296: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
2297: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2298: }
2299: #endif
2300: #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2301: if (common->utf)
2302: {
2303: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
2304: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
2305: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
2306: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
2307: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1.1 misho 2308: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2309: }
2310: #endif
2311: JUMPTO(SLJIT_JUMP, start);
2312: JUMPHERE(found);
2313: JUMPHERE(leave);
2314:
2315: if (firstline)
2316: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
2317: }
2318:
1.1.1.2 misho 2319: static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar)
1.1 misho 2320: {
2321: DEFINE_COMPILER;
2322: struct sljit_label *loop;
2323: struct sljit_jump *toolong;
2324: struct sljit_jump *alreadyfound;
2325: struct sljit_jump *found;
2326: struct sljit_jump *foundoc = NULL;
2327: struct sljit_jump *notfound;
1.1.1.2 misho 2328: pcre_uchar oc, bit;
1.1 misho 2329:
1.1.1.3 ! misho 2330: SLJIT_ASSERT(common->req_char_ptr != 0);
! 2331: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr);
1.1 misho 2332: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
2333: toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);
2334: alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);
2335:
1.1.1.2 misho 2336: if (has_firstchar)
2337: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2338: else
2339: OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);
2340:
2341: loop = LABEL();
2342: notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0);
2343:
1.1.1.2 misho 2344: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0);
2345: oc = req_char;
2346: if (caseless)
2347: {
2348: oc = TABLE_GET(req_char, common->fcc, req_char);
2349: #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
2350: if (req_char > 127 && common->utf)
2351: oc = UCD_OTHERCASE(req_char);
2352: #endif
2353: }
2354: if (req_char == oc)
2355: found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
1.1 misho 2356: else
2357: {
1.1.1.2 misho 2358: bit = req_char ^ oc;
1.1 misho 2359: if (ispowerof2(bit))
2360: {
2361: OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);
1.1.1.2 misho 2362: found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit);
1.1 misho 2363: }
2364: else
2365: {
1.1.1.2 misho 2366: found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
1.1 misho 2367: foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc);
2368: }
2369: }
1.1.1.2 misho 2370: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2371: JUMPTO(SLJIT_JUMP, loop);
2372:
2373: JUMPHERE(found);
2374: if (foundoc)
2375: JUMPHERE(foundoc);
1.1.1.3 ! misho 2376: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, TMP1, 0);
1.1 misho 2377: JUMPHERE(alreadyfound);
2378: JUMPHERE(toolong);
2379: return notfound;
2380: }
2381:
2382: static void do_revertframes(compiler_common *common)
2383: {
2384: DEFINE_COMPILER;
2385: struct sljit_jump *jump;
2386: struct sljit_label *mainloop;
2387:
1.1.1.3 ! misho 2388: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 2389: OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);
1.1.1.3 ! misho 2390: GET_LOCAL_BASE(TMP3, 0, 0);
1.1 misho 2391:
2392: /* Drop frames until we reach STACK_TOP. */
2393: mainloop = LABEL();
2394: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
2395: jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
1.1.1.3 ! misho 2396: OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
1.1 misho 2397: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
2398: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));
2399: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));
2400: JUMPTO(SLJIT_JUMP, mainloop);
2401:
2402: JUMPHERE(jump);
2403: jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
2404: /* End of dropping frames. */
2405: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2406:
2407: JUMPHERE(jump);
2408: jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);
2409: /* Set string begin. */
2410: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
2411: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2412: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
2413: JUMPTO(SLJIT_JUMP, mainloop);
2414:
2415: JUMPHERE(jump);
1.1.1.3 ! misho 2416: if (common->mark_ptr != 0)
! 2417: {
! 2418: jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmark);
! 2419: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
! 2420: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
! 2421: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0);
! 2422: JUMPTO(SLJIT_JUMP, mainloop);
! 2423:
! 2424: JUMPHERE(jump);
! 2425: }
! 2426:
1.1 misho 2427: /* Unknown command. */
2428: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2429: JUMPTO(SLJIT_JUMP, mainloop);
2430: }
2431:
2432: static void check_wordboundary(compiler_common *common)
2433: {
2434: DEFINE_COMPILER;
1.1.1.3 ! misho 2435: struct sljit_jump *skipread;
1.1.1.2 misho 2436: #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
1.1 misho 2437: struct sljit_jump *jump;
2438: #endif
2439:
2440: SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);
2441:
1.1.1.3 ! misho 2442: sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
1.1 misho 2443: /* Get type of the previous char, and put it to LOCALS1. */
2444: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2445: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2446: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);
1.1.1.3 ! misho 2447: skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
1.1 misho 2448: skip_char_back(common);
1.1.1.3 ! misho 2449: check_start_used_ptr(common);
1.1 misho 2450: read_char(common);
2451:
2452: /* Testing char type. */
2453: #ifdef SUPPORT_UCP
1.1.1.2 misho 2454: if (common->use_ucp)
1.1 misho 2455: {
2456: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2457: jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2458: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2459: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2460: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2461: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2462: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2463: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2464: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2465: JUMPHERE(jump);
2466: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
2467: }
2468: else
2469: #endif
2470: {
1.1.1.2 misho 2471: #ifndef COMPILE_PCRE8
2472: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2473: #elif defined SUPPORT_UTF
1.1 misho 2474: /* Here LOCALS1 has already been zeroed. */
2475: jump = NULL;
1.1.1.2 misho 2476: if (common->utf)
1.1 misho 2477: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.1.1.2 misho 2478: #endif /* COMPILE_PCRE8 */
1.1 misho 2479: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
2480: OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
2481: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2482: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
1.1.1.2 misho 2483: #ifndef COMPILE_PCRE8
2484: JUMPHERE(jump);
2485: #elif defined SUPPORT_UTF
1.1 misho 2486: if (jump != NULL)
2487: JUMPHERE(jump);
1.1.1.2 misho 2488: #endif /* COMPILE_PCRE8 */
1.1 misho 2489: }
1.1.1.3 ! misho 2490: JUMPHERE(skipread);
1.1 misho 2491:
2492: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
1.1.1.3 ! misho 2493: skipread = check_str_end(common);
1.1 misho 2494: peek_char(common);
2495:
2496: /* Testing char type. This is a code duplication. */
2497: #ifdef SUPPORT_UCP
1.1.1.2 misho 2498: if (common->use_ucp)
1.1 misho 2499: {
2500: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2501: jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2502: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2503: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2504: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2505: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2506: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2507: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2508: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2509: JUMPHERE(jump);
2510: }
2511: else
2512: #endif
2513: {
1.1.1.2 misho 2514: #ifndef COMPILE_PCRE8
2515: /* TMP2 may be destroyed by peek_char. */
2516: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2517: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2518: #elif defined SUPPORT_UTF
1.1 misho 2519: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2520: jump = NULL;
1.1.1.2 misho 2521: if (common->utf)
1.1 misho 2522: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2523: #endif
2524: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
2525: OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
2526: OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
1.1.1.2 misho 2527: #ifndef COMPILE_PCRE8
2528: JUMPHERE(jump);
2529: #elif defined SUPPORT_UTF
1.1 misho 2530: if (jump != NULL)
2531: JUMPHERE(jump);
1.1.1.2 misho 2532: #endif /* COMPILE_PCRE8 */
1.1 misho 2533: }
1.1.1.3 ! misho 2534: JUMPHERE(skipread);
1.1 misho 2535:
2536: OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2537: sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2538: }
2539:
2540: static void check_anynewline(compiler_common *common)
2541: {
2542: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2543: DEFINE_COMPILER;
2544:
1.1.1.3 ! misho 2545: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 2546:
2547: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2548: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2549: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2550: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
1.1.1.2 misho 2551: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2552: #ifdef COMPILE_PCRE8
2553: if (common->utf)
1.1 misho 2554: {
1.1.1.2 misho 2555: #endif
1.1 misho 2556: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2557: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2558: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
1.1.1.2 misho 2559: #ifdef COMPILE_PCRE8
1.1 misho 2560: }
2561: #endif
1.1.1.2 misho 2562: #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
1.1 misho 2563: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2564: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2565: }
2566:
2567: static void check_hspace(compiler_common *common)
2568: {
2569: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2570: DEFINE_COMPILER;
2571:
1.1.1.3 ! misho 2572: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 2573:
2574: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
2575: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2576: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
2577: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2578: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
1.1.1.2 misho 2579: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2580: #ifdef COMPILE_PCRE8
2581: if (common->utf)
1.1 misho 2582: {
1.1.1.2 misho 2583: #endif
1.1 misho 2584: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2585: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
2586: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2587: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
2588: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2589: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
2590: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
2591: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2592: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
2593: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2594: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
2595: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2596: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
1.1.1.2 misho 2597: #ifdef COMPILE_PCRE8
1.1 misho 2598: }
2599: #endif
1.1.1.2 misho 2600: #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
1.1 misho 2601: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2602:
2603: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2604: }
2605:
2606: static void check_vspace(compiler_common *common)
2607: {
2608: /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2609: DEFINE_COMPILER;
2610:
1.1.1.3 ! misho 2611: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 2612:
2613: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2614: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2615: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2616: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
1.1.1.2 misho 2617: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2618: #ifdef COMPILE_PCRE8
2619: if (common->utf)
1.1 misho 2620: {
1.1.1.2 misho 2621: #endif
1.1 misho 2622: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2623: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2624: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
1.1.1.2 misho 2625: #ifdef COMPILE_PCRE8
1.1 misho 2626: }
2627: #endif
1.1.1.2 misho 2628: #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
1.1 misho 2629: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2630:
2631: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2632: }
2633:
2634: #define CHAR1 STR_END
2635: #define CHAR2 STACK_TOP
2636:
2637: static void do_casefulcmp(compiler_common *common)
2638: {
2639: DEFINE_COMPILER;
2640: struct sljit_jump *jump;
2641: struct sljit_label *label;
2642:
1.1.1.3 ! misho 2643: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 2644: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2645: OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
2646: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);
1.1.1.2 misho 2647: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
2648: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2649:
2650: label = LABEL();
1.1.1.2 misho 2651: OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
2652: OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 2653: jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
1.1.1.2 misho 2654: OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2655: JUMPTO(SLJIT_C_NOT_ZERO, label);
2656:
2657: JUMPHERE(jump);
1.1.1.2 misho 2658: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2659: OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
2660: OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2661: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2662: }
2663:
2664: #define LCC_TABLE STACK_LIMIT
2665:
2666: static void do_caselesscmp(compiler_common *common)
2667: {
2668: DEFINE_COMPILER;
2669: struct sljit_jump *jump;
2670: struct sljit_label *label;
2671:
1.1.1.3 ! misho 2672: sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
1.1 misho 2673: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2674:
2675: OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
2676: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0);
2677: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0);
2678: OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
1.1.1.2 misho 2679: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
2680: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2681:
2682: label = LABEL();
1.1.1.2 misho 2683: OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
2684: OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
2685: #ifndef COMPILE_PCRE8
2686: jump = CMP(SLJIT_C_GREATER, CHAR1, 0, SLJIT_IMM, 255);
2687: #endif
1.1 misho 2688: OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
1.1.1.2 misho 2689: #ifndef COMPILE_PCRE8
2690: JUMPHERE(jump);
2691: jump = CMP(SLJIT_C_GREATER, CHAR2, 0, SLJIT_IMM, 255);
2692: #endif
1.1 misho 2693: OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
1.1.1.2 misho 2694: #ifndef COMPILE_PCRE8
2695: JUMPHERE(jump);
2696: #endif
1.1 misho 2697: jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
1.1.1.2 misho 2698: OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2699: JUMPTO(SLJIT_C_NOT_ZERO, label);
2700:
2701: JUMPHERE(jump);
1.1.1.2 misho 2702: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 2703: OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
2704: OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2705: OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2706: sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2707: }
2708:
2709: #undef LCC_TABLE
2710: #undef CHAR1
2711: #undef CHAR2
2712:
1.1.1.2 misho 2713: #if defined SUPPORT_UTF && defined SUPPORT_UCP
1.1 misho 2714:
1.1.1.2 misho 2715: static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1)
1.1 misho 2716: {
2717: /* This function would be ineffective to do in JIT level. */
2718: int c1, c2;
1.1.1.3 ! misho 2719: const pcre_uchar *src2 = args->uchar_ptr;
1.1.1.2 misho 2720: const pcre_uchar *end2 = args->end;
1.1 misho 2721:
2722: while (src1 < end1)
2723: {
2724: if (src2 >= end2)
1.1.1.3 ! misho 2725: return (pcre_uchar*)1;
1.1 misho 2726: GETCHARINC(c1, src1);
2727: GETCHARINC(c2, src2);
1.1.1.3 ! misho 2728: if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return NULL;
1.1 misho 2729: }
2730: return src2;
2731: }
2732:
1.1.1.2 misho 2733: #endif /* SUPPORT_UTF && SUPPORT_UCP */
1.1 misho 2734:
1.1.1.2 misho 2735: static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc,
1.1.1.3 ! misho 2736: compare_context* context, jump_list **backtracks)
1.1 misho 2737: {
2738: DEFINE_COMPILER;
2739: unsigned int othercasebit = 0;
1.1.1.2 misho 2740: pcre_uchar *othercasechar = NULL;
2741: #ifdef SUPPORT_UTF
2742: int utflength;
1.1 misho 2743: #endif
2744:
2745: if (caseless && char_has_othercase(common, cc))
2746: {
2747: othercasebit = char_get_othercase_bit(common, cc);
2748: SLJIT_ASSERT(othercasebit);
2749: /* Extracting bit difference info. */
1.1.1.2 misho 2750: #ifdef COMPILE_PCRE8
2751: othercasechar = cc + (othercasebit >> 8);
1.1 misho 2752: othercasebit &= 0xff;
1.1.1.2 misho 2753: #else
2754: #ifdef COMPILE_PCRE16
2755: othercasechar = cc + (othercasebit >> 9);
2756: if ((othercasebit & 0x100) != 0)
2757: othercasebit = (othercasebit & 0xff) << 8;
2758: else
2759: othercasebit &= 0xff;
2760: #endif
2761: #endif
1.1 misho 2762: }
2763:
2764: if (context->sourcereg == -1)
2765: {
1.1.1.2 misho 2766: #ifdef COMPILE_PCRE8
1.1 misho 2767: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2768: if (context->length >= 4)
2769: OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2770: else if (context->length >= 2)
1.1.1.2 misho 2771: OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1 misho 2772: else
2773: #endif
2774: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1.1.2 misho 2775: #else
2776: #ifdef COMPILE_PCRE16
2777: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2778: if (context->length >= 4)
2779: OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2780: else
2781: #endif
2782: OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2783: #endif
2784: #endif /* COMPILE_PCRE8 */
1.1 misho 2785: context->sourcereg = TMP2;
2786: }
2787:
1.1.1.2 misho 2788: #ifdef SUPPORT_UTF
2789: utflength = 1;
2790: if (common->utf && HAS_EXTRALEN(*cc))
2791: utflength += GET_EXTRALEN(*cc);
1.1 misho 2792:
2793: do
2794: {
2795: #endif
2796:
1.1.1.2 misho 2797: context->length -= IN_UCHARS(1);
1.1 misho 2798: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2799:
2800: /* Unaligned read is supported. */
1.1.1.2 misho 2801: if (othercasebit != 0 && othercasechar == cc)
1.1 misho 2802: {
1.1.1.2 misho 2803: context->c.asuchars[context->ucharptr] = *cc | othercasebit;
2804: context->oc.asuchars[context->ucharptr] = othercasebit;
1.1 misho 2805: }
2806: else
2807: {
1.1.1.2 misho 2808: context->c.asuchars[context->ucharptr] = *cc;
2809: context->oc.asuchars[context->ucharptr] = 0;
1.1 misho 2810: }
1.1.1.2 misho 2811: context->ucharptr++;
1.1 misho 2812:
1.1.1.2 misho 2813: #ifdef COMPILE_PCRE8
2814: if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))
2815: #else
2816: if (context->ucharptr >= 2 || context->length == 0)
2817: #endif
1.1 misho 2818: {
2819: if (context->length >= 4)
2820: OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1.1.2 misho 2821: #ifdef COMPILE_PCRE8
1.1 misho 2822: else if (context->length >= 2)
1.1.1.2 misho 2823: OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1 misho 2824: else if (context->length >= 1)
2825: OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1.1.2 misho 2826: #else
2827: else if (context->length >= 2)
2828: OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2829: #endif
1.1 misho 2830: context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2831:
1.1.1.2 misho 2832: switch(context->ucharptr)
1.1 misho 2833: {
1.1.1.2 misho 2834: case 4 / sizeof(pcre_uchar):
1.1 misho 2835: if (context->oc.asint != 0)
2836: OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
1.1.1.3 ! misho 2837: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
1.1 misho 2838: break;
2839:
1.1.1.2 misho 2840: case 2 / sizeof(pcre_uchar):
2841: if (context->oc.asushort != 0)
2842: OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);
1.1.1.3 ! misho 2843: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));
1.1 misho 2844: break;
2845:
1.1.1.2 misho 2846: #ifdef COMPILE_PCRE8
1.1 misho 2847: case 1:
2848: if (context->oc.asbyte != 0)
2849: OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
1.1.1.3 ! misho 2850: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
1.1 misho 2851: break;
1.1.1.2 misho 2852: #endif
1.1 misho 2853:
2854: default:
2855: SLJIT_ASSERT_STOP();
2856: break;
2857: }
1.1.1.2 misho 2858: context->ucharptr = 0;
1.1 misho 2859: }
2860:
2861: #else
2862:
2863: /* Unaligned read is unsupported. */
1.1.1.2 misho 2864: #ifdef COMPILE_PCRE8
1.1 misho 2865: if (context->length > 0)
2866: OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
1.1.1.2 misho 2867: #else
2868: if (context->length > 0)
2869: OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2870: #endif
1.1 misho 2871: context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2872:
1.1.1.2 misho 2873: if (othercasebit != 0 && othercasechar == cc)
1.1 misho 2874: {
2875: OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
1.1.1.3 ! misho 2876: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
1.1 misho 2877: }
2878: else
1.1.1.3 ! misho 2879: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));
1.1 misho 2880:
2881: #endif
2882:
2883: cc++;
1.1.1.2 misho 2884: #ifdef SUPPORT_UTF
2885: utflength--;
1.1 misho 2886: }
1.1.1.2 misho 2887: while (utflength > 0);
1.1 misho 2888: #endif
2889:
2890: return cc;
2891: }
2892:
1.1.1.2 misho 2893: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 2894:
2895: #define SET_TYPE_OFFSET(value) \
2896: if ((value) != typeoffset) \
2897: { \
2898: if ((value) > typeoffset) \
2899: OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
2900: else \
2901: OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
2902: } \
2903: typeoffset = (value);
2904:
2905: #define SET_CHAR_OFFSET(value) \
2906: if ((value) != charoffset) \
2907: { \
2908: if ((value) > charoffset) \
2909: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
2910: else \
2911: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
2912: } \
2913: charoffset = (value);
2914:
1.1.1.3 ! misho 2915: static void compile_xclass_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
1.1 misho 2916: {
2917: DEFINE_COMPILER;
2918: jump_list *found = NULL;
1.1.1.3 ! misho 2919: jump_list **list = (*cc & XCL_NOT) == 0 ? &found : backtracks;
1.1 misho 2920: unsigned int c;
2921: int compares;
2922: struct sljit_jump *jump = NULL;
1.1.1.2 misho 2923: pcre_uchar *ccbegin;
1.1 misho 2924: #ifdef SUPPORT_UCP
2925: BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
2926: BOOL charsaved = FALSE;
2927: int typereg = TMP1, scriptreg = TMP1;
2928: unsigned int typeoffset;
2929: #endif
2930: int invertcmp, numberofcmps;
2931: unsigned int charoffset;
2932:
1.1.1.2 misho 2933: /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */
1.1.1.3 ! misho 2934: detect_partial_match(common, backtracks);
1.1 misho 2935: read_char(common);
2936:
2937: if ((*cc++ & XCL_MAP) != 0)
2938: {
2939: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
1.1.1.2 misho 2940: #ifndef COMPILE_PCRE8
2941: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2942: #elif defined SUPPORT_UTF
2943: if (common->utf)
1.1 misho 2944: jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
1.1.1.2 misho 2945: #endif
1.1 misho 2946:
2947: OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
2948: OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
2949: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
2950: OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
2951: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
2952: add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));
2953:
1.1.1.2 misho 2954: #ifndef COMPILE_PCRE8
2955: JUMPHERE(jump);
2956: #elif defined SUPPORT_UTF
2957: if (common->utf)
1.1 misho 2958: JUMPHERE(jump);
1.1.1.2 misho 2959: #endif
1.1 misho 2960: OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2961: #ifdef SUPPORT_UCP
2962: charsaved = TRUE;
2963: #endif
1.1.1.2 misho 2964: cc += 32 / sizeof(pcre_uchar);
1.1 misho 2965: }
2966:
2967: /* Scanning the necessary info. */
2968: ccbegin = cc;
2969: compares = 0;
2970: while (*cc != XCL_END)
2971: {
2972: compares++;
2973: if (*cc == XCL_SINGLE)
2974: {
2975: cc += 2;
1.1.1.2 misho 2976: #ifdef SUPPORT_UTF
2977: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 2978: #endif
2979: #ifdef SUPPORT_UCP
2980: needschar = TRUE;
2981: #endif
2982: }
2983: else if (*cc == XCL_RANGE)
2984: {
2985: cc += 2;
1.1.1.2 misho 2986: #ifdef SUPPORT_UTF
2987: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 2988: #endif
2989: cc++;
1.1.1.2 misho 2990: #ifdef SUPPORT_UTF
2991: if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
1.1 misho 2992: #endif
2993: #ifdef SUPPORT_UCP
2994: needschar = TRUE;
2995: #endif
2996: }
2997: #ifdef SUPPORT_UCP
2998: else
2999: {
3000: SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
3001: cc++;
3002: switch(*cc)
3003: {
3004: case PT_ANY:
3005: break;
3006:
3007: case PT_LAMP:
3008: case PT_GC:
3009: case PT_PC:
3010: case PT_ALNUM:
3011: needstype = TRUE;
3012: break;
3013:
3014: case PT_SC:
3015: needsscript = TRUE;
3016: break;
3017:
3018: case PT_SPACE:
3019: case PT_PXSPACE:
3020: case PT_WORD:
3021: needstype = TRUE;
3022: needschar = TRUE;
3023: break;
3024:
3025: default:
3026: SLJIT_ASSERT_STOP();
3027: break;
3028: }
3029: cc += 2;
3030: }
3031: #endif
3032: }
3033:
3034: #ifdef SUPPORT_UCP
3035: /* Simple register allocation. TMP1 is preferred if possible. */
3036: if (needstype || needsscript)
3037: {
3038: if (needschar && !charsaved)
3039: OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
3040: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
3041: if (needschar)
3042: {
3043: if (needstype)
3044: {
3045: OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
3046: typereg = RETURN_ADDR;
3047: }
3048:
3049: if (needsscript)
3050: scriptreg = TMP3;
3051: OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
3052: }
3053: else if (needstype && needsscript)
3054: scriptreg = TMP3;
3055: /* In all other cases only one of them was specified, and that can goes to TMP1. */
3056:
3057: if (needsscript)
3058: {
3059: if (scriptreg == TMP1)
3060: {
1.1.1.2 misho 3061: OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
1.1 misho 3062: OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);
3063: }
3064: else
3065: {
3066: OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
1.1.1.2 misho 3067: OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
1.1 misho 3068: OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
3069: }
3070: }
3071: }
3072: #endif
3073:
3074: /* Generating code. */
3075: cc = ccbegin;
3076: charoffset = 0;
3077: numberofcmps = 0;
3078: #ifdef SUPPORT_UCP
3079: typeoffset = 0;
3080: #endif
3081:
3082: while (*cc != XCL_END)
3083: {
3084: compares--;
1.1.1.3 ! misho 3085: invertcmp = (compares == 0 && list != backtracks);
1.1 misho 3086: jump = NULL;
3087:
3088: if (*cc == XCL_SINGLE)
3089: {
3090: cc ++;
1.1.1.2 misho 3091: #ifdef SUPPORT_UTF
3092: if (common->utf)
1.1 misho 3093: {
3094: GETCHARINC(c, cc);
3095: }
3096: else
3097: #endif
3098: c = *cc++;
3099:
3100: if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
3101: {
3102: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
3103: COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
3104: numberofcmps++;
3105: }
3106: else if (numberofcmps > 0)
3107: {
3108: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
3109: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3110: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
3111: numberofcmps = 0;
3112: }
3113: else
3114: {
3115: jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
3116: numberofcmps = 0;
3117: }
3118: }
3119: else if (*cc == XCL_RANGE)
3120: {
3121: cc ++;
1.1.1.2 misho 3122: #ifdef SUPPORT_UTF
3123: if (common->utf)
1.1 misho 3124: {
3125: GETCHARINC(c, cc);
3126: }
3127: else
3128: #endif
3129: c = *cc++;
3130: SET_CHAR_OFFSET(c);
1.1.1.2 misho 3131: #ifdef SUPPORT_UTF
3132: if (common->utf)
1.1 misho 3133: {
3134: GETCHARINC(c, cc);
3135: }
3136: else
3137: #endif
3138: c = *cc++;
3139: if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
3140: {
3141: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
3142: COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
3143: numberofcmps++;
3144: }
3145: else if (numberofcmps > 0)
3146: {
3147: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
3148: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
3149: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
3150: numberofcmps = 0;
3151: }
3152: else
3153: {
3154: jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
3155: numberofcmps = 0;
3156: }
3157: }
3158: #ifdef SUPPORT_UCP
3159: else
3160: {
3161: if (*cc == XCL_NOTPROP)
3162: invertcmp ^= 0x1;
3163: cc++;
3164: switch(*cc)
3165: {
3166: case PT_ANY:
1.1.1.3 ! misho 3167: if (list != backtracks)
1.1 misho 3168: {
3169: if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
3170: continue;
3171: }
3172: else if (cc[-1] == XCL_NOTPROP)
3173: continue;
3174: jump = JUMP(SLJIT_JUMP);
3175: break;
3176:
3177: case PT_LAMP:
3178: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
3179: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3180: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
3181: COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
3182: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
3183: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3184: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
3185: break;
3186:
3187: case PT_GC:
1.1.1.2 misho 3188: c = PRIV(ucp_typerange)[(int)cc[1] * 2];
1.1 misho 3189: SET_TYPE_OFFSET(c);
1.1.1.2 misho 3190: jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c);
1.1 misho 3191: break;
3192:
3193: case PT_PC:
3194: jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);
3195: break;
3196:
3197: case PT_SC:
3198: jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);
3199: break;
3200:
3201: case PT_SPACE:
3202: case PT_PXSPACE:
3203: if (*cc == PT_SPACE)
3204: {
3205: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
3206: jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset);
3207: }
3208: SET_CHAR_OFFSET(9);
3209: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9);
3210: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
3211: if (*cc == PT_SPACE)
3212: JUMPHERE(jump);
3213:
3214: SET_TYPE_OFFSET(ucp_Zl);
3215: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
3216: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
3217: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
3218: break;
3219:
3220: case PT_WORD:
3221: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset);
3222: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3223: /* ... fall through */
3224:
3225: case PT_ALNUM:
3226: SET_TYPE_OFFSET(ucp_Ll);
3227: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
3228: COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
3229: SET_TYPE_OFFSET(ucp_Nd);
3230: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
3231: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
3232: jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
3233: break;
3234: }
3235: cc += 2;
3236: }
3237: #endif
3238:
3239: if (jump != NULL)
1.1.1.3 ! misho 3240: add_jump(compiler, compares > 0 ? list : backtracks, jump);
1.1 misho 3241: }
3242:
3243: if (found != NULL)
3244: set_jumps(found, LABEL());
3245: }
3246:
3247: #undef SET_TYPE_OFFSET
3248: #undef SET_CHAR_OFFSET
3249:
3250: #endif
3251:
1.1.1.3 ! misho 3252: static pcre_uchar *compile_char1_trypath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks)
1.1 misho 3253: {
3254: DEFINE_COMPILER;
3255: int length;
3256: unsigned int c, oc, bit;
3257: compare_context context;
3258: struct sljit_jump *jump[4];
1.1.1.2 misho 3259: #ifdef SUPPORT_UTF
1.1 misho 3260: struct sljit_label *label;
3261: #ifdef SUPPORT_UCP
1.1.1.2 misho 3262: pcre_uchar propdata[5];
1.1 misho 3263: #endif
3264: #endif
3265:
3266: switch(type)
3267: {
3268: case OP_SOD:
3269: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
3270: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1.1.1.3 ! misho 3271: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
1.1 misho 3272: return cc;
3273:
3274: case OP_SOM:
3275: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
3276: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1.1.1.3 ! misho 3277: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
1.1 misho 3278: return cc;
3279:
3280: case OP_NOT_WORD_BOUNDARY:
3281: case OP_WORD_BOUNDARY:
3282: add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
1.1.1.3 ! misho 3283: add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1.1 misho 3284: return cc;
3285:
3286: case OP_NOT_DIGIT:
3287: case OP_DIGIT:
1.1.1.3 ! misho 3288: detect_partial_match(common, backtracks);
1.1 misho 3289: read_char8_type(common);
3290: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
1.1.1.3 ! misho 3291: add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
1.1 misho 3292: return cc;
3293:
3294: case OP_NOT_WHITESPACE:
3295: case OP_WHITESPACE:
1.1.1.3 ! misho 3296: detect_partial_match(common, backtracks);
1.1 misho 3297: read_char8_type(common);
3298: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
1.1.1.3 ! misho 3299: add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
1.1 misho 3300: return cc;
3301:
3302: case OP_NOT_WORDCHAR:
3303: case OP_WORDCHAR:
1.1.1.3 ! misho 3304: detect_partial_match(common, backtracks);
1.1 misho 3305: read_char8_type(common);
3306: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
1.1.1.3 ! misho 3307: add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
1.1 misho 3308: return cc;
3309:
3310: case OP_ANY:
1.1.1.3 ! misho 3311: detect_partial_match(common, backtracks);
1.1 misho 3312: read_char(common);
3313: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3314: {
3315: jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
1.1.1.3 ! misho 3316: if (common->mode != JIT_PARTIAL_HARD_COMPILE)
! 3317: jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
! 3318: else
! 3319: jump[1] = check_str_end(common);
! 3320:
1.1.1.2 misho 3321: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1.1.3 ! misho 3322: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
! 3323: if (jump[1] != NULL)
! 3324: JUMPHERE(jump[1]);
1.1 misho 3325: JUMPHERE(jump[0]);
3326: }
3327: else
1.1.1.3 ! misho 3328: check_newlinechar(common, common->nltype, backtracks, TRUE);
1.1 misho 3329: return cc;
3330:
3331: case OP_ALLANY:
1.1.1.3 ! misho 3332: detect_partial_match(common, backtracks);
1.1.1.2 misho 3333: #ifdef SUPPORT_UTF
3334: if (common->utf)
1.1 misho 3335: {
1.1.1.2 misho 3336: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3337: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
3338: #ifdef COMPILE_PCRE8
1.1 misho 3339: jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.1.1.2 misho 3340: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
1.1 misho 3341: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1.1.1.2 misho 3342: #else /* COMPILE_PCRE8 */
3343: #ifdef COMPILE_PCRE16
3344: jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
3345: OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
3346: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
3347: COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
3348: OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3349: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
3350: #endif /* COMPILE_PCRE16 */
3351: #endif /* COMPILE_PCRE8 */
1.1 misho 3352: JUMPHERE(jump[0]);
3353: return cc;
3354: }
3355: #endif
1.1.1.2 misho 3356: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3357: return cc;
3358:
3359: case OP_ANYBYTE:
1.1.1.3 ! misho 3360: detect_partial_match(common, backtracks);
1.1.1.2 misho 3361: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3362: return cc;
3363:
1.1.1.2 misho 3364: #ifdef SUPPORT_UTF
1.1 misho 3365: #ifdef SUPPORT_UCP
3366: case OP_NOTPROP:
3367: case OP_PROP:
3368: propdata[0] = 0;
3369: propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
3370: propdata[2] = cc[0];
3371: propdata[3] = cc[1];
3372: propdata[4] = XCL_END;
1.1.1.3 ! misho 3373: compile_xclass_trypath(common, propdata, backtracks);
1.1 misho 3374: return cc + 2;
3375: #endif
3376: #endif
3377:
3378: case OP_ANYNL:
1.1.1.3 ! misho 3379: detect_partial_match(common, backtracks);
1.1 misho 3380: read_char(common);
3381: jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1.1.1.3 ! misho 3382: /* We don't need to handle soft partial matching case. */
! 3383: if (common->mode != JIT_PARTIAL_HARD_COMPILE)
! 3384: jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
! 3385: else
! 3386: jump[1] = check_str_end(common);
1.1.1.2 misho 3387: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1.1 misho 3388: jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
1.1.1.2 misho 3389: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3390: jump[3] = JUMP(SLJIT_JUMP);
3391: JUMPHERE(jump[0]);
1.1.1.3 ! misho 3392: check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);
1.1 misho 3393: JUMPHERE(jump[1]);
3394: JUMPHERE(jump[2]);
3395: JUMPHERE(jump[3]);
3396: return cc;
3397:
3398: case OP_NOT_HSPACE:
3399: case OP_HSPACE:
1.1.1.3 ! misho 3400: detect_partial_match(common, backtracks);
1.1 misho 3401: read_char(common);
3402: add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
1.1.1.3 ! misho 3403: add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1.1 misho 3404: return cc;
3405:
3406: case OP_NOT_VSPACE:
3407: case OP_VSPACE:
1.1.1.3 ! misho 3408: detect_partial_match(common, backtracks);
1.1 misho 3409: read_char(common);
3410: add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
1.1.1.3 ! misho 3411: add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1.1 misho 3412: return cc;
3413:
3414: #ifdef SUPPORT_UCP
3415: case OP_EXTUNI:
1.1.1.3 ! misho 3416: detect_partial_match(common, backtracks);
1.1 misho 3417: read_char(common);
3418: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
3419: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
1.1.1.3 ! misho 3420: add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));
1.1 misho 3421:
3422: label = LABEL();
3423: jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
3424: OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
3425: read_char(common);
3426: add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
3427: OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
3428: CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label);
3429:
3430: OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
3431: JUMPHERE(jump[0]);
1.1.1.3 ! misho 3432: if (common->mode == JIT_PARTIAL_HARD_COMPILE)
! 3433: {
! 3434: jump[0] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
! 3435: /* Since we successfully read a char above, partial matching must occure. */
! 3436: check_partial(common, TRUE);
! 3437: JUMPHERE(jump[0]);
! 3438: }
1.1 misho 3439: return cc;
3440: #endif
3441:
3442: case OP_EODN:
1.1.1.3 ! misho 3443: /* Requires rather complex checks. */
1.1 misho 3444: jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
3445: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3446: {
1.1.1.2 misho 3447: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
3448: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1.1.3 ! misho 3449: if (common->mode == JIT_COMPILE)
! 3450: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
! 3451: else
! 3452: {
! 3453: jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0);
! 3454: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
! 3455: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS);
! 3456: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
! 3457: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_NOT_EQUAL);
! 3458: add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL));
! 3459: check_partial(common, TRUE);
! 3460: add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
! 3461: JUMPHERE(jump[1]);
! 3462: }
1.1.1.2 misho 3463: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1.1.3 ! misho 3464: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
! 3465: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
1.1 misho 3466: }
3467: else if (common->nltype == NLTYPE_FIXED)
3468: {
1.1.1.2 misho 3469: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
3470: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1.1.3 ! misho 3471: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
! 3472: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
1.1 misho 3473: }
3474: else
3475: {
1.1.1.2 misho 3476: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1 misho 3477: jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1.1.1.2 misho 3478: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.1 misho 3479: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
3480: jump[2] = JUMP(SLJIT_C_GREATER);
1.1.1.3 ! misho 3481: add_jump(compiler, backtracks, JUMP(SLJIT_C_LESS));
1.1.1.2 misho 3482: /* Equal. */
3483: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1 misho 3484: jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
1.1.1.3 ! misho 3485: add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
1.1 misho 3486:
3487: JUMPHERE(jump[1]);
3488: if (common->nltype == NLTYPE_ANYCRLF)
3489: {
1.1.1.2 misho 3490: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1.1.3 ! misho 3491: add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
! 3492: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
1.1 misho 3493: }
3494: else
3495: {
3496: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
3497: read_char(common);
1.1.1.3 ! misho 3498: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
1.1 misho 3499: add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
1.1.1.3 ! misho 3500: add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
1.1 misho 3501: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
3502: }
3503: JUMPHERE(jump[2]);
3504: JUMPHERE(jump[3]);
3505: }
3506: JUMPHERE(jump[0]);
1.1.1.3 ! misho 3507: check_partial(common, FALSE);
1.1 misho 3508: return cc;
3509:
3510: case OP_EOD:
1.1.1.3 ! misho 3511: add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
! 3512: check_partial(common, FALSE);
1.1 misho 3513: return cc;
3514:
3515: case OP_CIRC:
3516: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3517: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
1.1.1.3 ! misho 3518: add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0));
1.1 misho 3519: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
1.1.1.3 ! misho 3520: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.1 misho 3521: return cc;
3522:
3523: case OP_CIRCM:
3524: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3525: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
3526: jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0);
3527: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
1.1.1.3 ! misho 3528: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.1 misho 3529: jump[0] = JUMP(SLJIT_JUMP);
3530: JUMPHERE(jump[1]);
3531:
1.1.1.3 ! misho 3532: add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1.1 misho 3533: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3534: {
1.1.1.2 misho 3535: OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
1.1.1.3 ! misho 3536: add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0));
1.1.1.2 misho 3537: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
3538: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
1.1.1.3 ! misho 3539: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
! 3540: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
1.1 misho 3541: }
3542: else
3543: {
3544: skip_char_back(common);
3545: read_char(common);
1.1.1.3 ! misho 3546: check_newlinechar(common, common->nltype, backtracks, FALSE);
1.1 misho 3547: }
3548: JUMPHERE(jump[0]);
3549: return cc;
3550:
3551: case OP_DOLL:
3552: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3553: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
1.1.1.3 ! misho 3554: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.1 misho 3555:
3556: if (!common->endonly)
1.1.1.3 ! misho 3557: compile_char1_trypath(common, OP_EODN, cc, backtracks);
1.1 misho 3558: else
1.1.1.3 ! misho 3559: {
! 3560: add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
! 3561: check_partial(common, FALSE);
! 3562: }
1.1 misho 3563: return cc;
3564:
3565: case OP_DOLLM:
3566: jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
3567: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3568: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
1.1.1.3 ! misho 3569: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
! 3570: check_partial(common, FALSE);
1.1 misho 3571: jump[0] = JUMP(SLJIT_JUMP);
3572: JUMPHERE(jump[1]);
3573:
3574: if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3575: {
1.1.1.2 misho 3576: OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
3577: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
1.1.1.3 ! misho 3578: if (common->mode == JIT_COMPILE)
! 3579: add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
! 3580: else
! 3581: {
! 3582: jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0);
! 3583: /* STR_PTR = STR_END - IN_UCHARS(1) */
! 3584: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
! 3585: check_partial(common, TRUE);
! 3586: add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
! 3587: JUMPHERE(jump[1]);
! 3588: }
! 3589:
1.1.1.2 misho 3590: OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
1.1.1.3 ! misho 3591: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
! 3592: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
1.1 misho 3593: }
3594: else
3595: {
3596: peek_char(common);
1.1.1.3 ! misho 3597: check_newlinechar(common, common->nltype, backtracks, FALSE);
1.1 misho 3598: }
3599: JUMPHERE(jump[0]);
3600: return cc;
3601:
3602: case OP_CHAR:
3603: case OP_CHARI:
3604: length = 1;
1.1.1.2 misho 3605: #ifdef SUPPORT_UTF
3606: if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
1.1 misho 3607: #endif
1.1.1.3 ! misho 3608: if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0))
1.1 misho 3609: {
1.1.1.2 misho 3610: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
1.1.1.3 ! misho 3611: add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
1.1 misho 3612:
1.1.1.2 misho 3613: context.length = IN_UCHARS(length);
1.1 misho 3614: context.sourcereg = -1;
3615: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
1.1.1.2 misho 3616: context.ucharptr = 0;
1.1 misho 3617: #endif
1.1.1.3 ! misho 3618: return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);
1.1 misho 3619: }
1.1.1.3 ! misho 3620: detect_partial_match(common, backtracks);
1.1 misho 3621: read_char(common);
1.1.1.2 misho 3622: #ifdef SUPPORT_UTF
3623: if (common->utf)
1.1 misho 3624: {
3625: GETCHAR(c, cc);
3626: }
3627: else
3628: #endif
3629: c = *cc;
1.1.1.3 ! misho 3630: if (type == OP_CHAR || !char_has_othercase(common, cc))
! 3631: {
! 3632: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));
! 3633: return cc + length;
! 3634: }
! 3635: oc = char_othercase(common, c);
! 3636: bit = c ^ oc;
! 3637: if (ispowerof2(bit))
! 3638: {
! 3639: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
! 3640: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
! 3641: return cc + length;
! 3642: }
1.1 misho 3643: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
3644: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3645: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));
3646: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1.1.1.3 ! misho 3647: add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
1.1 misho 3648: return cc + length;
3649:
3650: case OP_NOT:
3651: case OP_NOTI:
1.1.1.3 ! misho 3652: detect_partial_match(common, backtracks);
1.1 misho 3653: length = 1;
1.1.1.2 misho 3654: #ifdef SUPPORT_UTF
3655: if (common->utf)
1.1 misho 3656: {
1.1.1.2 misho 3657: #ifdef COMPILE_PCRE8
3658: c = *cc;
3659: if (c < 128)
1.1 misho 3660: {
3661: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3662: if (type == OP_NOT || !char_has_othercase(common, cc))
1.1.1.3 ! misho 3663: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
1.1 misho 3664: else
3665: {
3666: /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
3667: OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);
1.1.1.3 ! misho 3668: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));
1.1 misho 3669: }
3670: /* Skip the variable-length character. */
1.1.1.2 misho 3671: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
1.1 misho 3672: jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
1.1.1.2 misho 3673: OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
1.1 misho 3674: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
3675: JUMPHERE(jump[0]);
1.1.1.2 misho 3676: return cc + 1;
1.1 misho 3677: }
3678: else
1.1.1.2 misho 3679: #endif /* COMPILE_PCRE8 */
3680: {
3681: GETCHARLEN(c, cc, length);
1.1 misho 3682: read_char(common);
1.1.1.2 misho 3683: }
1.1 misho 3684: }
3685: else
1.1.1.2 misho 3686: #endif /* SUPPORT_UTF */
1.1 misho 3687: {
1.1.1.2 misho 3688: read_char(common);
1.1 misho 3689: c = *cc;
3690: }
3691:
3692: if (type == OP_NOT || !char_has_othercase(common, cc))
1.1.1.3 ! misho 3693: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
1.1 misho 3694: else
3695: {
3696: oc = char_othercase(common, c);
3697: bit = c ^ oc;
3698: if (ispowerof2(bit))
3699: {
3700: OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
1.1.1.3 ! misho 3701: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
1.1 misho 3702: }
3703: else
3704: {
1.1.1.3 ! misho 3705: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
! 3706: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
1.1 misho 3707: }
3708: }
1.1.1.3 ! misho 3709: return cc + length;
1.1 misho 3710:
3711: case OP_CLASS:
3712: case OP_NCLASS:
1.1.1.3 ! misho 3713: detect_partial_match(common, backtracks);
1.1 misho 3714: read_char(common);
1.1.1.2 misho 3715: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 3716: jump[0] = NULL;
1.1.1.2 misho 3717: #ifdef COMPILE_PCRE8
3718: /* This check only affects 8 bit mode. In other modes, we
3719: always need to compare the value with 255. */
3720: if (common->utf)
3721: #endif /* COMPILE_PCRE8 */
1.1 misho 3722: {
3723: jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
3724: if (type == OP_CLASS)
3725: {
1.1.1.3 ! misho 3726: add_jump(compiler, backtracks, jump[0]);
1.1 misho 3727: jump[0] = NULL;
3728: }
3729: }
1.1.1.2 misho 3730: #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
1.1 misho 3731: OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
3732: OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
3733: OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
3734: OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
3735: OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
1.1.1.3 ! misho 3736: add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
1.1.1.2 misho 3737: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 3738: if (jump[0] != NULL)
3739: JUMPHERE(jump[0]);
1.1.1.2 misho 3740: #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
3741: return cc + 32 / sizeof(pcre_uchar);
1.1 misho 3742:
1.1.1.2 misho 3743: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
1.1 misho 3744: case OP_XCLASS:
1.1.1.3 ! misho 3745: compile_xclass_trypath(common, cc + LINK_SIZE, backtracks);
1.1 misho 3746: return cc + GET(cc, 0) - 1;
3747: #endif
3748:
3749: case OP_REVERSE:
3750: length = GET(cc, 0);
1.1.1.3 ! misho 3751: if (length == 0)
! 3752: return cc + LINK_SIZE;
1.1 misho 3753: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1.1.1.2 misho 3754: #ifdef SUPPORT_UTF
3755: if (common->utf)
1.1 misho 3756: {
1.1.1.2 misho 3757: OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1.1 misho 3758: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
3759: label = LABEL();
1.1.1.3 ! misho 3760: add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
1.1 misho 3761: skip_char_back(common);
3762: OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
3763: JUMPTO(SLJIT_C_NOT_ZERO, label);
3764: }
1.1.1.3 ! misho 3765: else
1.1 misho 3766: #endif
1.1.1.3 ! misho 3767: {
! 3768: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
! 3769: OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
! 3770: add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));
! 3771: }
! 3772: check_start_used_ptr(common);
1.1 misho 3773: return cc + LINK_SIZE;
3774: }
3775: SLJIT_ASSERT_STOP();
3776: return cc;
3777: }
3778:
1.1.1.3 ! misho 3779: static SLJIT_INLINE pcre_uchar *compile_charn_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks)
1.1 misho 3780: {
3781: /* This function consumes at least one input character. */
3782: /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
3783: DEFINE_COMPILER;
1.1.1.2 misho 3784: pcre_uchar *ccbegin = cc;
1.1 misho 3785: compare_context context;
3786: int size;
3787:
3788: context.length = 0;
3789: do
3790: {
3791: if (cc >= ccend)
3792: break;
3793:
3794: if (*cc == OP_CHAR)
3795: {
3796: size = 1;
1.1.1.2 misho 3797: #ifdef SUPPORT_UTF
3798: if (common->utf && HAS_EXTRALEN(cc[1]))
3799: size += GET_EXTRALEN(cc[1]);
1.1 misho 3800: #endif
3801: }
3802: else if (*cc == OP_CHARI)
3803: {
3804: size = 1;
1.1.1.2 misho 3805: #ifdef SUPPORT_UTF
3806: if (common->utf)
1.1 misho 3807: {
3808: if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3809: size = 0;
1.1.1.2 misho 3810: else if (HAS_EXTRALEN(cc[1]))
3811: size += GET_EXTRALEN(cc[1]);
1.1 misho 3812: }
3813: else
3814: #endif
3815: if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3816: size = 0;
3817: }
3818: else
3819: size = 0;
3820:
3821: cc += 1 + size;
1.1.1.2 misho 3822: context.length += IN_UCHARS(size);
1.1 misho 3823: }
3824: while (size > 0 && context.length <= 128);
3825:
3826: cc = ccbegin;
3827: if (context.length > 0)
3828: {
3829: /* We have a fixed-length byte sequence. */
3830: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
1.1.1.3 ! misho 3831: add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
1.1 misho 3832:
3833: context.sourcereg = -1;
3834: #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
1.1.1.2 misho 3835: context.ucharptr = 0;
1.1 misho 3836: #endif
1.1.1.3 ! misho 3837: do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0);
1.1 misho 3838: return cc;
3839: }
3840:
3841: /* A non-fixed length character will be checked if length == 0. */
1.1.1.3 ! misho 3842: return compile_char1_trypath(common, *cc, cc + 1, backtracks);
1.1 misho 3843: }
3844:
1.1.1.3 ! misho 3845: static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
1.1 misho 3846: {
3847: DEFINE_COMPILER;
3848: int offset = GET2(cc, 1) << 1;
3849:
3850: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3851: if (!common->jscript_compat)
3852: {
1.1.1.3 ! misho 3853: if (backtracks == NULL)
1.1 misho 3854: {
1.1.1.3 ! misho 3855: /* OVECTOR(1) contains the "string begin - 1" constant. */
1.1 misho 3856: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
3857: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3858: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3859: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3860: return JUMP(SLJIT_C_NOT_ZERO);
3861: }
1.1.1.3 ! misho 3862: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
1.1 misho 3863: }
3864: return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3865: }
3866:
3867: /* Forward definitions. */
1.1.1.3 ! misho 3868: static void compile_trypath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *);
! 3869: static void compile_backtrackpath(compiler_common *, struct backtrack_common *);
1.1 misho 3870:
1.1.1.3 ! misho 3871: #define PUSH_BACKTRACK(size, ccstart, error) \
1.1 misho 3872: do \
3873: { \
1.1.1.3 ! misho 3874: backtrack = sljit_alloc_memory(compiler, (size)); \
1.1 misho 3875: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3876: return error; \
1.1.1.3 ! misho 3877: memset(backtrack, 0, size); \
! 3878: backtrack->prev = parent->top; \
! 3879: backtrack->cc = (ccstart); \
! 3880: parent->top = backtrack; \
1.1 misho 3881: } \
3882: while (0)
3883:
1.1.1.3 ! misho 3884: #define PUSH_BACKTRACK_NOVALUE(size, ccstart) \
1.1 misho 3885: do \
3886: { \
1.1.1.3 ! misho 3887: backtrack = sljit_alloc_memory(compiler, (size)); \
1.1 misho 3888: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3889: return; \
1.1.1.3 ! misho 3890: memset(backtrack, 0, size); \
! 3891: backtrack->prev = parent->top; \
! 3892: backtrack->cc = (ccstart); \
! 3893: parent->top = backtrack; \
1.1 misho 3894: } \
3895: while (0)
3896:
1.1.1.3 ! misho 3897: #define BACKTRACK_AS(type) ((type *)backtrack)
1.1 misho 3898:
1.1.1.3 ! misho 3899: static pcre_uchar *compile_ref_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)
1.1 misho 3900: {
3901: DEFINE_COMPILER;
3902: int offset = GET2(cc, 1) << 1;
3903: struct sljit_jump *jump = NULL;
1.1.1.3 ! misho 3904: struct sljit_jump *partial;
! 3905: struct sljit_jump *nopartial;
1.1 misho 3906:
3907: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
1.1.1.3 ! misho 3908: /* OVECTOR(1) contains the "string begin - 1" constant. */
1.1 misho 3909: if (withchecks && !common->jscript_compat)
1.1.1.3 ! misho 3910: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
1.1 misho 3911:
1.1.1.2 misho 3912: #if defined SUPPORT_UTF && defined SUPPORT_UCP
3913: if (common->utf && *cc == OP_REFI)
1.1 misho 3914: {
3915: SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3);
3916: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3917: if (withchecks)
3918: jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);
3919:
3920: /* Needed to save important temporary registers. */
3921: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
3922: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
1.1.1.3 ! misho 3923: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0);
1.1.1.2 misho 3924: sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
1.1 misho 3925: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
1.1.1.3 ! misho 3926: if (common->mode == JIT_COMPILE)
! 3927: add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
! 3928: else
! 3929: {
! 3930: add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
! 3931: nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
! 3932: check_partial(common, FALSE);
! 3933: add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
! 3934: JUMPHERE(nopartial);
! 3935: }
1.1 misho 3936: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
3937: }
3938: else
1.1.1.2 misho 3939: #endif /* SUPPORT_UTF && SUPPORT_UCP */
1.1 misho 3940: {
3941: OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
3942: if (withchecks)
3943: jump = JUMP(SLJIT_C_ZERO);
1.1.1.3 ! misho 3944:
1.1 misho 3945: OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1.1.1.3 ! misho 3946: partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0);
! 3947: if (common->mode == JIT_COMPILE)
! 3948: add_jump(compiler, backtracks, partial);
1.1 misho 3949:
3950: add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
1.1.1.3 ! misho 3951: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
! 3952:
! 3953: if (common->mode != JIT_COMPILE)
! 3954: {
! 3955: nopartial = JUMP(SLJIT_JUMP);
! 3956: JUMPHERE(partial);
! 3957: /* TMP2 -= STR_END - STR_PTR */
! 3958: OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0);
! 3959: OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0);
! 3960: partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0);
! 3961: OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
! 3962: add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
! 3963: add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
! 3964: JUMPHERE(partial);
! 3965: check_partial(common, FALSE);
! 3966: add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
! 3967: JUMPHERE(nopartial);
! 3968: }
1.1 misho 3969: }
3970:
3971: if (jump != NULL)
3972: {
3973: if (emptyfail)
1.1.1.3 ! misho 3974: add_jump(compiler, backtracks, jump);
1.1 misho 3975: else
3976: JUMPHERE(jump);
3977: }
1.1.1.2 misho 3978: return cc + 1 + IMM2_SIZE;
1.1 misho 3979: }
3980:
1.1.1.3 ! misho 3981: static SLJIT_INLINE pcre_uchar *compile_ref_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1 misho 3982: {
3983: DEFINE_COMPILER;
1.1.1.3 ! misho 3984: backtrack_common *backtrack;
1.1.1.2 misho 3985: pcre_uchar type;
1.1 misho 3986: struct sljit_label *label;
3987: struct sljit_jump *zerolength;
3988: struct sljit_jump *jump = NULL;
1.1.1.2 misho 3989: pcre_uchar *ccbegin = cc;
1.1 misho 3990: int min = 0, max = 0;
3991: BOOL minimize;
3992:
1.1.1.3 ! misho 3993: PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
1.1 misho 3994:
1.1.1.2 misho 3995: type = cc[1 + IMM2_SIZE];
1.1 misho 3996: minimize = (type & 0x1) != 0;
3997: switch(type)
3998: {
3999: case OP_CRSTAR:
4000: case OP_CRMINSTAR:
4001: min = 0;
4002: max = 0;
1.1.1.2 misho 4003: cc += 1 + IMM2_SIZE + 1;
1.1 misho 4004: break;
4005: case OP_CRPLUS:
4006: case OP_CRMINPLUS:
4007: min = 1;
4008: max = 0;
1.1.1.2 misho 4009: cc += 1 + IMM2_SIZE + 1;
1.1 misho 4010: break;
4011: case OP_CRQUERY:
4012: case OP_CRMINQUERY:
4013: min = 0;
4014: max = 1;
1.1.1.2 misho 4015: cc += 1 + IMM2_SIZE + 1;
1.1 misho 4016: break;
4017: case OP_CRRANGE:
4018: case OP_CRMINRANGE:
1.1.1.2 misho 4019: min = GET2(cc, 1 + IMM2_SIZE + 1);
4020: max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE);
4021: cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;
1.1 misho 4022: break;
4023: default:
4024: SLJIT_ASSERT_STOP();
4025: break;
4026: }
4027:
4028: if (!minimize)
4029: {
4030: if (min == 0)
4031: {
4032: allocate_stack(common, 2);
4033: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4034: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
4035: /* Temporary release of STR_PTR. */
4036: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4037: zerolength = compile_ref_checks(common, ccbegin, NULL);
4038: /* Restore if not zero length. */
4039: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4040: }
4041: else
4042: {
4043: allocate_stack(common, 1);
4044: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.1.1.3 ! misho 4045: zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks);
1.1 misho 4046: }
4047:
4048: if (min > 1 || max > 1)
4049: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
4050:
4051: label = LABEL();
1.1.1.3 ! misho 4052: compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);
1.1 misho 4053:
4054: if (min > 1 || max > 1)
4055: {
4056: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
4057: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
4058: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
4059: if (min > 1)
4060: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label);
4061: if (max > 1)
4062: {
4063: jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
4064: allocate_stack(common, 1);
4065: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4066: JUMPTO(SLJIT_JUMP, label);
4067: JUMPHERE(jump);
4068: }
4069: }
4070:
4071: if (max == 0)
4072: {
4073: /* Includes min > 1 case as well. */
4074: allocate_stack(common, 1);
4075: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4076: JUMPTO(SLJIT_JUMP, label);
4077: }
4078:
4079: JUMPHERE(zerolength);
1.1.1.3 ! misho 4080: BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
1.1 misho 4081:
4082: decrease_call_count(common);
4083: return cc;
4084: }
4085:
4086: allocate_stack(common, 2);
4087: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4088: if (type != OP_CRMINSTAR)
4089: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
4090:
4091: if (min == 0)
4092: {
4093: zerolength = compile_ref_checks(common, ccbegin, NULL);
4094: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4095: jump = JUMP(SLJIT_JUMP);
4096: }
4097: else
1.1.1.3 ! misho 4098: zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks);
1.1 misho 4099:
1.1.1.3 ! misho 4100: BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
1.1 misho 4101: if (max > 0)
1.1.1.3 ! misho 4102: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
1.1 misho 4103:
1.1.1.3 ! misho 4104: compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);
1.1 misho 4105: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4106:
4107: if (min > 1)
4108: {
4109: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4110: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
4111: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
1.1.1.3 ! misho 4112: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->trypath);
1.1 misho 4113: }
4114: else if (max > 0)
4115: OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
4116:
4117: if (jump != NULL)
4118: JUMPHERE(jump);
4119: JUMPHERE(zerolength);
4120:
4121: decrease_call_count(common);
4122: return cc;
4123: }
4124:
1.1.1.3 ! misho 4125: static SLJIT_INLINE pcre_uchar *compile_recurse_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1 misho 4126: {
4127: DEFINE_COMPILER;
1.1.1.3 ! misho 4128: backtrack_common *backtrack;
1.1 misho 4129: recurse_entry *entry = common->entries;
4130: recurse_entry *prev = NULL;
4131: int start = GET(cc, 1);
4132:
1.1.1.3 ! misho 4133: PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);
1.1 misho 4134: while (entry != NULL)
4135: {
4136: if (entry->start == start)
4137: break;
4138: prev = entry;
4139: entry = entry->next;
4140: }
4141:
4142: if (entry == NULL)
4143: {
4144: entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
4145: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4146: return NULL;
4147: entry->next = NULL;
4148: entry->entry = NULL;
4149: entry->calls = NULL;
4150: entry->start = start;
4151:
4152: if (prev != NULL)
4153: prev->next = entry;
4154: else
4155: common->entries = entry;
4156: }
4157:
1.1.1.3 ! misho 4158: if (common->has_set_som && common->mark_ptr != 0)
! 4159: {
! 4160: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
! 4161: allocate_stack(common, 2);
! 4162: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
! 4163: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
! 4164: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
! 4165: }
! 4166: else if (common->has_set_som || common->mark_ptr != 0)
! 4167: {
! 4168: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr);
! 4169: allocate_stack(common, 1);
! 4170: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
! 4171: }
1.1 misho 4172:
4173: if (entry->entry == NULL)
4174: add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
4175: else
4176: JUMPTO(SLJIT_FAST_CALL, entry->entry);
4177: /* Leave if the match is failed. */
1.1.1.3 ! misho 4178: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
1.1 misho 4179: return cc + 1 + LINK_SIZE;
4180: }
4181:
1.1.1.3 ! misho 4182: static pcre_uchar *compile_assert_trypath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional)
1.1 misho 4183: {
4184: DEFINE_COMPILER;
4185: int framesize;
4186: int localptr;
1.1.1.3 ! misho 4187: backtrack_common altbacktrack;
1.1.1.2 misho 4188: pcre_uchar *ccbegin;
4189: pcre_uchar opcode;
4190: pcre_uchar bra = OP_BRA;
1.1 misho 4191: jump_list *tmp = NULL;
1.1.1.3 ! misho 4192: jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;
1.1 misho 4193: jump_list **found;
4194: /* Saving previous accept variables. */
1.1.1.3 ! misho 4195: struct sljit_label *save_leavelabel = common->leavelabel;
1.1 misho 4196: struct sljit_label *save_acceptlabel = common->acceptlabel;
1.1.1.3 ! misho 4197: jump_list *save_leave = common->leave;
! 4198: jump_list *save_accept = common->accept;
1.1 misho 4199: struct sljit_jump *jump;
4200: struct sljit_jump *brajump = NULL;
4201:
4202: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
4203: {
4204: SLJIT_ASSERT(!conditional);
4205: bra = *cc;
4206: cc++;
4207: }
1.1.1.2 misho 4208: localptr = PRIV_DATA(cc);
1.1 misho 4209: SLJIT_ASSERT(localptr != 0);
4210: framesize = get_framesize(common, cc, FALSE);
1.1.1.3 ! misho 4211: backtrack->framesize = framesize;
! 4212: backtrack->localptr = localptr;
1.1 misho 4213: opcode = *cc;
4214: SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
4215: found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
4216: ccbegin = cc;
4217: cc += GET(cc, 1);
4218:
4219: if (bra == OP_BRAMINZERO)
4220: {
1.1.1.3 ! misho 4221: /* This is a braminzero backtrack path. */
1.1 misho 4222: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4223: free_stack(common, 1);
4224: brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
4225: }
4226:
4227: if (framesize < 0)
4228: {
4229: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4230: allocate_stack(common, 1);
4231: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4232: }
4233: else
4234: {
4235: allocate_stack(common, framesize + 2);
4236: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4237: OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1));
4238: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4239: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4240: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
4241: init_frame(common, ccbegin, framesize + 1, 2, FALSE);
4242: }
4243:
1.1.1.3 ! misho 4244: memset(&altbacktrack, 0, sizeof(backtrack_common));
! 4245: common->leavelabel = NULL;
! 4246: common->leave = NULL;
1.1 misho 4247: while (1)
4248: {
4249: common->acceptlabel = NULL;
4250: common->accept = NULL;
1.1.1.3 ! misho 4251: altbacktrack.top = NULL;
! 4252: altbacktrack.topbacktracks = NULL;
1.1 misho 4253:
4254: if (*ccbegin == OP_ALT)
4255: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4256:
1.1.1.3 ! misho 4257: altbacktrack.cc = ccbegin;
! 4258: compile_trypath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);
1.1 misho 4259: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4260: {
1.1.1.3 ! misho 4261: common->leavelabel = save_leavelabel;
1.1 misho 4262: common->acceptlabel = save_acceptlabel;
1.1.1.3 ! misho 4263: common->leave = save_leave;
1.1 misho 4264: common->accept = save_accept;
4265: return NULL;
4266: }
4267: common->acceptlabel = LABEL();
4268: if (common->accept != NULL)
4269: set_jumps(common->accept, common->acceptlabel);
4270:
4271: /* Reset stack. */
4272: if (framesize < 0)
4273: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4274: else {
4275: if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)
4276: {
4277: /* We don't need to keep the STR_PTR, only the previous localptr. */
4278: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w));
4279: }
4280: else
4281: {
4282: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4283: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
4284: }
4285: }
4286:
4287: if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
4288: {
4289: /* We know that STR_PTR was stored on the top of the stack. */
4290: if (conditional)
4291: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
4292: else if (bra == OP_BRAZERO)
4293: {
4294: if (framesize < 0)
4295: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
4296: else
4297: {
4298: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
4299: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w));
4300: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
4301: }
4302: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4303: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4304: }
4305: else if (framesize >= 0)
4306: {
4307: /* For OP_BRA and OP_BRAMINZERO. */
4308: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
4309: }
4310: }
4311: add_jump(compiler, found, JUMP(SLJIT_JUMP));
4312:
1.1.1.3 ! misho 4313: compile_backtrackpath(common, altbacktrack.top);
1.1 misho 4314: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4315: {
1.1.1.3 ! misho 4316: common->leavelabel = save_leavelabel;
1.1 misho 4317: common->acceptlabel = save_acceptlabel;
1.1.1.3 ! misho 4318: common->leave = save_leave;
1.1 misho 4319: common->accept = save_accept;
4320: return NULL;
4321: }
1.1.1.3 ! misho 4322: set_jumps(altbacktrack.topbacktracks, LABEL());
1.1 misho 4323:
4324: if (*cc != OP_ALT)
4325: break;
4326:
4327: ccbegin = cc;
4328: cc += GET(cc, 1);
4329: }
4330: /* None of them matched. */
1.1.1.3 ! misho 4331: if (common->leave != NULL)
! 4332: set_jumps(common->leave, LABEL());
1.1 misho 4333:
4334: if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
4335: {
4336: /* Assert is failed. */
4337: if (conditional || bra == OP_BRAZERO)
4338: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4339:
4340: if (framesize < 0)
4341: {
4342: /* The topmost item should be 0. */
4343: if (bra == OP_BRAZERO)
4344: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4345: else
4346: free_stack(common, 1);
4347: }
4348: else
4349: {
4350: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4351: /* The topmost item should be 0. */
4352: if (bra == OP_BRAZERO)
4353: {
4354: free_stack(common, framesize + 1);
4355: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4356: }
4357: else
4358: free_stack(common, framesize + 2);
4359: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
4360: }
4361: jump = JUMP(SLJIT_JUMP);
4362: if (bra != OP_BRAZERO)
4363: add_jump(compiler, target, jump);
4364:
4365: /* Assert is successful. */
4366: set_jumps(tmp, LABEL());
4367: if (framesize < 0)
4368: {
4369: /* We know that STR_PTR was stored on the top of the stack. */
4370: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
4371: /* Keep the STR_PTR on the top of the stack. */
4372: if (bra == OP_BRAZERO)
4373: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4374: else if (bra == OP_BRAMINZERO)
4375: {
4376: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4377: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4378: }
4379: }
4380: else
4381: {
4382: if (bra == OP_BRA)
4383: {
4384: /* We don't need to keep the STR_PTR, only the previous localptr. */
4385: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w));
4386: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
4387: }
4388: else
4389: {
4390: /* We don't need to keep the STR_PTR, only the previous localptr. */
4391: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_w));
4392: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4393: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);
4394: }
4395: }
4396:
4397: if (bra == OP_BRAZERO)
4398: {
1.1.1.3 ! misho 4399: backtrack->trypath = LABEL();
! 4400: sljit_set_label(jump, backtrack->trypath);
1.1 misho 4401: }
4402: else if (bra == OP_BRAMINZERO)
4403: {
1.1.1.3 ! misho 4404: JUMPTO(SLJIT_JUMP, backtrack->trypath);
1.1 misho 4405: JUMPHERE(brajump);
4406: if (framesize >= 0)
4407: {
4408: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4409: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
4410: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
4411: }
1.1.1.3 ! misho 4412: set_jumps(backtrack->common.topbacktracks, LABEL());
1.1 misho 4413: }
4414: }
4415: else
4416: {
4417: /* AssertNot is successful. */
4418: if (framesize < 0)
4419: {
4420: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4421: if (bra != OP_BRA)
4422: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4423: else
4424: free_stack(common, 1);
4425: }
4426: else
4427: {
4428: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4429: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4430: /* The topmost item should be 0. */
4431: if (bra != OP_BRA)
4432: {
4433: free_stack(common, framesize + 1);
4434: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4435: }
4436: else
4437: free_stack(common, framesize + 2);
4438: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
4439: }
4440:
4441: if (bra == OP_BRAZERO)
1.1.1.3 ! misho 4442: backtrack->trypath = LABEL();
1.1 misho 4443: else if (bra == OP_BRAMINZERO)
4444: {
1.1.1.3 ! misho 4445: JUMPTO(SLJIT_JUMP, backtrack->trypath);
1.1 misho 4446: JUMPHERE(brajump);
4447: }
4448:
4449: if (bra != OP_BRA)
4450: {
1.1.1.3 ! misho 4451: SLJIT_ASSERT(found == &backtrack->common.topbacktracks);
! 4452: set_jumps(backtrack->common.topbacktracks, LABEL());
! 4453: backtrack->common.topbacktracks = NULL;
1.1 misho 4454: }
4455: }
4456:
1.1.1.3 ! misho 4457: common->leavelabel = save_leavelabel;
1.1 misho 4458: common->acceptlabel = save_acceptlabel;
1.1.1.3 ! misho 4459: common->leave = save_leave;
1.1 misho 4460: common->accept = save_accept;
4461: return cc + 1 + LINK_SIZE;
4462: }
4463:
1.1.1.2 misho 4464: static sljit_w SLJIT_CALL do_searchovector(sljit_w refno, sljit_w* locals, pcre_uchar *name_table)
1.1 misho 4465: {
4466: int condition = FALSE;
1.1.1.2 misho 4467: pcre_uchar *slotA = name_table;
4468: pcre_uchar *slotB;
1.1 misho 4469: sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)];
4470: sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)];
4471: sljit_w no_capture;
4472: int i;
4473:
1.1.1.3 ! misho 4474: locals += refno & 0xff;
! 4475: refno >>= 8;
1.1 misho 4476: no_capture = locals[1];
4477:
4478: for (i = 0; i < name_count; i++)
4479: {
4480: if (GET2(slotA, 0) == refno) break;
4481: slotA += name_entry_size;
4482: }
4483:
4484: if (i < name_count)
4485: {
4486: /* Found a name for the number - there can be only one; duplicate names
4487: for different numbers are allowed, but not vice versa. First scan down
4488: for duplicates. */
4489:
4490: slotB = slotA;
4491: while (slotB > name_table)
4492: {
4493: slotB -= name_entry_size;
1.1.1.2 misho 4494: if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
1.1 misho 4495: {
4496: condition = locals[GET2(slotB, 0) << 1] != no_capture;
4497: if (condition) break;
4498: }
4499: else break;
4500: }
4501:
4502: /* Scan up for duplicates */
4503: if (!condition)
4504: {
4505: slotB = slotA;
4506: for (i++; i < name_count; i++)
4507: {
4508: slotB += name_entry_size;
1.1.1.2 misho 4509: if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
1.1 misho 4510: {
4511: condition = locals[GET2(slotB, 0) << 1] != no_capture;
4512: if (condition) break;
4513: }
4514: else break;
4515: }
4516: }
4517: }
4518: return condition;
4519: }
4520:
1.1.1.2 misho 4521: static sljit_w SLJIT_CALL do_searchgroups(sljit_w recno, sljit_w* locals, pcre_uchar *name_table)
1.1 misho 4522: {
4523: int condition = FALSE;
1.1.1.2 misho 4524: pcre_uchar *slotA = name_table;
4525: pcre_uchar *slotB;
1.1 misho 4526: sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)];
4527: sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)];
4528: sljit_w group_num = locals[POSSESSIVE0 / sizeof(sljit_w)];
4529: int i;
4530:
4531: for (i = 0; i < name_count; i++)
4532: {
4533: if (GET2(slotA, 0) == recno) break;
4534: slotA += name_entry_size;
4535: }
4536:
4537: if (i < name_count)
4538: {
4539: /* Found a name for the number - there can be only one; duplicate
4540: names for different numbers are allowed, but not vice versa. First
4541: scan down for duplicates. */
4542:
4543: slotB = slotA;
4544: while (slotB > name_table)
4545: {
4546: slotB -= name_entry_size;
1.1.1.2 misho 4547: if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
1.1 misho 4548: {
4549: condition = GET2(slotB, 0) == group_num;
4550: if (condition) break;
4551: }
4552: else break;
4553: }
4554:
4555: /* Scan up for duplicates */
4556: if (!condition)
4557: {
4558: slotB = slotA;
4559: for (i++; i < name_count; i++)
4560: {
4561: slotB += name_entry_size;
1.1.1.2 misho 4562: if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
1.1 misho 4563: {
4564: condition = GET2(slotB, 0) == group_num;
4565: if (condition) break;
4566: }
4567: else break;
4568: }
4569: }
4570: }
4571: return condition;
4572: }
4573:
4574: /*
4575: Handling bracketed expressions is probably the most complex part.
4576:
4577: Stack layout naming characters:
4578: S - Push the current STR_PTR
4579: 0 - Push a 0 (NULL)
4580: A - Push the current STR_PTR. Needed for restoring the STR_PTR
4581: before the next alternative. Not pushed if there are no alternatives.
4582: M - Any values pushed by the current alternative. Can be empty, or anything.
4583: C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
4584: L - Push the previous local (pointed by localptr) to the stack
4585: () - opional values stored on the stack
4586: ()* - optonal, can be stored multiple times
4587:
4588: The following list shows the regular expression templates, their PCRE byte codes
4589: and stack layout supported by pcre-sljit.
4590:
4591: (?:) OP_BRA | OP_KET A M
4592: () OP_CBRA | OP_KET C M
4593: (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
4594: OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
4595: (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
4596: OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
4597: ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
4598: OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
4599: ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
4600: OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
4601: (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
4602: (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
4603: ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
4604: ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
4605: (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
4606: OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
4607: (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
4608: OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
4609: ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
4610: OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
4611: ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
4612: OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
4613:
4614:
4615: Stack layout naming characters:
4616: A - Push the alternative index (starting from 0) on the stack.
4617: Not pushed if there is no alternatives.
4618: M - Any values pushed by the current alternative. Can be empty, or anything.
4619:
4620: The next list shows the possible content of a bracket:
4621: (|) OP_*BRA | OP_ALT ... M A
4622: (?()|) OP_*COND | OP_ALT M A
4623: (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
4624: (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A
4625: Or nothing, if trace is unnecessary
4626: */
4627:
1.1.1.3 ! misho 4628: static pcre_uchar *compile_bracket_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1 misho 4629: {
4630: DEFINE_COMPILER;
1.1.1.3 ! misho 4631: backtrack_common *backtrack;
1.1.1.2 misho 4632: pcre_uchar opcode;
1.1 misho 4633: int localptr = 0;
4634: int offset = 0;
4635: int stacksize;
1.1.1.2 misho 4636: pcre_uchar *ccbegin;
1.1.1.3 ! misho 4637: pcre_uchar *trypath;
1.1.1.2 misho 4638: pcre_uchar bra = OP_BRA;
4639: pcre_uchar ket;
1.1.1.3 ! misho 4640: assert_backtrack *assert;
1.1 misho 4641: BOOL has_alternatives;
4642: struct sljit_jump *jump;
4643: struct sljit_jump *skip;
4644: struct sljit_label *rmaxlabel = NULL;
4645: struct sljit_jump *braminzerojump = NULL;
4646:
1.1.1.3 ! misho 4647: PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);
1.1 misho 4648:
4649: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
4650: {
4651: bra = *cc;
4652: cc++;
4653: opcode = *cc;
4654: }
4655:
4656: opcode = *cc;
4657: ccbegin = cc;
1.1.1.3 ! misho 4658: trypath = ccbegin + 1 + LINK_SIZE;
1.1 misho 4659:
4660: if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
4661: {
1.1.1.3 ! misho 4662: /* Drop this bracket_backtrack. */
! 4663: parent->top = backtrack->prev;
1.1 misho 4664: return bracketend(cc);
4665: }
4666:
4667: ket = *(bracketend(cc) - 1 - LINK_SIZE);
4668: SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
4669: SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
4670: cc += GET(cc, 1);
4671:
4672: has_alternatives = *cc == OP_ALT;
4673: if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
4674: {
1.1.1.3 ! misho 4675: has_alternatives = (*trypath == OP_RREF) ? FALSE : TRUE;
! 4676: if (*trypath == OP_NRREF)
1.1 misho 4677: {
1.1.1.3 ! misho 4678: stacksize = GET2(trypath, 1);
1.1 misho 4679: if (common->currententry == NULL || stacksize == RREF_ANY)
4680: has_alternatives = FALSE;
4681: else if (common->currententry->start == 0)
4682: has_alternatives = stacksize != 0;
4683: else
4684: has_alternatives = stacksize != GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
4685: }
4686: }
4687:
4688: if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
4689: opcode = OP_SCOND;
4690: if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
4691: opcode = OP_ONCE;
4692:
4693: if (opcode == OP_CBRA || opcode == OP_SCBRA)
4694: {
4695: /* Capturing brackets has a pre-allocated space. */
4696: offset = GET2(ccbegin, 1 + LINK_SIZE);
4697: localptr = OVECTOR_PRIV(offset);
4698: offset <<= 1;
1.1.1.3 ! misho 4699: BACKTRACK_AS(bracket_backtrack)->localptr = localptr;
! 4700: trypath += IMM2_SIZE;
1.1 misho 4701: }
4702: else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
4703: {
4704: /* Other brackets simply allocate the next entry. */
1.1.1.2 misho 4705: localptr = PRIV_DATA(ccbegin);
1.1 misho 4706: SLJIT_ASSERT(localptr != 0);
1.1.1.3 ! misho 4707: BACKTRACK_AS(bracket_backtrack)->localptr = localptr;
1.1 misho 4708: if (opcode == OP_ONCE)
1.1.1.3 ! misho 4709: BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, FALSE);
1.1 misho 4710: }
4711:
4712: /* Instructions before the first alternative. */
4713: stacksize = 0;
4714: if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
4715: stacksize++;
4716: if (bra == OP_BRAZERO)
4717: stacksize++;
4718:
4719: if (stacksize > 0)
4720: allocate_stack(common, stacksize);
4721:
4722: stacksize = 0;
4723: if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
4724: {
4725: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4726: stacksize++;
4727: }
4728:
4729: if (bra == OP_BRAZERO)
4730: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
4731:
4732: if (bra == OP_BRAMINZERO)
4733: {
1.1.1.3 ! misho 4734: /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */
1.1 misho 4735: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4736: if (ket != OP_KETRMIN)
4737: {
4738: free_stack(common, 1);
4739: braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
4740: }
4741: else
4742: {
4743: if (opcode == OP_ONCE || opcode >= OP_SBRA)
4744: {
4745: jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
4746: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4747: /* Nothing stored during the first run. */
4748: skip = JUMP(SLJIT_JUMP);
4749: JUMPHERE(jump);
4750: /* Checking zero-length iteration. */
1.1.1.3 ! misho 4751: if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
1.1 misho 4752: {
4753: /* When we come from outside, localptr contains the previous STR_PTR. */
4754: braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4755: }
4756: else
4757: {
4758: /* Except when the whole stack frame must be saved. */
4759: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
1.1.1.3 ! misho 4760: braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w));
1.1 misho 4761: }
4762: JUMPHERE(skip);
4763: }
4764: else
4765: {
4766: jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
4767: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4768: JUMPHERE(jump);
4769: }
4770: }
4771: }
4772:
4773: if (ket == OP_KETRMIN)
1.1.1.3 ! misho 4774: BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL();
1.1 misho 4775:
4776: if (ket == OP_KETRMAX)
4777: {
4778: rmaxlabel = LABEL();
4779: if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)
1.1.1.3 ! misho 4780: BACKTRACK_AS(bracket_backtrack)->alttrypath = rmaxlabel;
1.1 misho 4781: }
4782:
4783: /* Handling capturing brackets and alternatives. */
4784: if (opcode == OP_ONCE)
4785: {
1.1.1.3 ! misho 4786: if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
1.1 misho 4787: {
4788: /* Neither capturing brackets nor recursions are not found in the block. */
4789: if (ket == OP_KETRMIN)
4790: {
4791: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4792: allocate_stack(common, 2);
4793: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4794: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4795: OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4796: }
4797: else if (ket == OP_KETRMAX || has_alternatives)
4798: {
4799: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4800: allocate_stack(common, 1);
4801: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4802: }
4803: else
4804: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4805: }
4806: else
4807: {
4808: if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)
4809: {
1.1.1.3 ! misho 4810: allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 2);
1.1 misho 4811: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
1.1.1.3 ! misho 4812: OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize + 1));
1.1 misho 4813: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4814: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4815: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
1.1.1.3 ! misho 4816: init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1, 2, FALSE);
1.1 misho 4817: }
4818: else
4819: {
1.1.1.3 ! misho 4820: allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1);
1.1 misho 4821: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
1.1.1.3 ! misho 4822: OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize));
1.1 misho 4823: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4824: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
1.1.1.3 ! misho 4825: init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize, 1, FALSE);
1.1 misho 4826: }
4827: }
4828: }
4829: else if (opcode == OP_CBRA || opcode == OP_SCBRA)
4830: {
4831: /* Saving the previous values. */
4832: allocate_stack(common, 3);
4833: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4834: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4835: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4836: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4837: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4838: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4839: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
4840: }
4841: else if (opcode == OP_SBRA || opcode == OP_SCOND)
4842: {
4843: /* Saving the previous value. */
4844: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4845: allocate_stack(common, 1);
4846: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4847: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
4848: }
4849: else if (has_alternatives)
4850: {
4851: /* Pushing the starting string pointer. */
4852: allocate_stack(common, 1);
4853: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4854: }
4855:
4856: /* Generating code for the first alternative. */
4857: if (opcode == OP_COND || opcode == OP_SCOND)
4858: {
1.1.1.3 ! misho 4859: if (*trypath == OP_CREF)
1.1 misho 4860: {
4861: SLJIT_ASSERT(has_alternatives);
1.1.1.3 ! misho 4862: add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed),
! 4863: CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(trypath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
! 4864: trypath += 1 + IMM2_SIZE;
1.1 misho 4865: }
1.1.1.3 ! misho 4866: else if (*trypath == OP_NCREF)
1.1 misho 4867: {
4868: SLJIT_ASSERT(has_alternatives);
1.1.1.3 ! misho 4869: stacksize = GET2(trypath, 1);
1.1 misho 4870: jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
4871:
4872: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
4873: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
4874: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
1.1.1.3 ! misho 4875: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_w)));
! 4876: GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0);
1.1 misho 4877: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
4878: sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector));
4879: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
1.1.1.3 ! misho 4880: add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
1.1 misho 4881:
4882: JUMPHERE(jump);
1.1.1.3 ! misho 4883: trypath += 1 + IMM2_SIZE;
1.1 misho 4884: }
1.1.1.3 ! misho 4885: else if (*trypath == OP_RREF || *trypath == OP_NRREF)
1.1 misho 4886: {
4887: /* Never has other case. */
1.1.1.3 ! misho 4888: BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;
1.1 misho 4889:
1.1.1.3 ! misho 4890: stacksize = GET2(trypath, 1);
1.1 misho 4891: if (common->currententry == NULL)
4892: stacksize = 0;
4893: else if (stacksize == RREF_ANY)
4894: stacksize = 1;
4895: else if (common->currententry->start == 0)
4896: stacksize = stacksize == 0;
4897: else
4898: stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
4899:
1.1.1.3 ! misho 4900: if (*trypath == OP_RREF || stacksize || common->currententry == NULL)
1.1 misho 4901: {
4902: SLJIT_ASSERT(!has_alternatives);
4903: if (stacksize != 0)
1.1.1.3 ! misho 4904: trypath += 1 + IMM2_SIZE;
1.1 misho 4905: else
4906: {
4907: if (*cc == OP_ALT)
4908: {
1.1.1.3 ! misho 4909: trypath = cc + 1 + LINK_SIZE;
1.1 misho 4910: cc += GET(cc, 1);
4911: }
4912: else
1.1.1.3 ! misho 4913: trypath = cc;
1.1 misho 4914: }
4915: }
4916: else
4917: {
4918: SLJIT_ASSERT(has_alternatives);
4919:
1.1.1.3 ! misho 4920: stacksize = GET2(trypath, 1);
1.1 misho 4921: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
4922: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
4923: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
4924: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE));
4925: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);
1.1.1.3 ! misho 4926: GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0);
1.1 misho 4927: OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
4928: sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups));
4929: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
1.1.1.3 ! misho 4930: add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
! 4931: trypath += 1 + IMM2_SIZE;
1.1 misho 4932: }
4933: }
4934: else
4935: {
1.1.1.3 ! misho 4936: SLJIT_ASSERT(has_alternatives && *trypath >= OP_ASSERT && *trypath <= OP_ASSERTBACK_NOT);
! 4937: /* Similar code as PUSH_BACKTRACK macro. */
! 4938: assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack));
1.1 misho 4939: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4940: return NULL;
1.1.1.3 ! misho 4941: memset(assert, 0, sizeof(assert_backtrack));
! 4942: assert->common.cc = trypath;
! 4943: BACKTRACK_AS(bracket_backtrack)->u.assert = assert;
! 4944: trypath = compile_assert_trypath(common, trypath, assert, TRUE);
1.1 misho 4945: }
4946: }
4947:
1.1.1.3 ! misho 4948: compile_trypath(common, trypath, cc, backtrack);
1.1 misho 4949: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4950: return NULL;
4951:
4952: if (opcode == OP_ONCE)
4953: {
1.1.1.3 ! misho 4954: if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
1.1 misho 4955: {
4956: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4957: /* TMP2 which is set here used by OP_KETRMAX below. */
4958: if (ket == OP_KETRMAX)
4959: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
4960: else if (ket == OP_KETRMIN)
4961: {
4962: /* Move the STR_PTR to the localptr. */
4963: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
4964: }
4965: }
4966: else
4967: {
4968: stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1;
1.1.1.3 ! misho 4969: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize) * sizeof(sljit_w));
1.1 misho 4970: if (ket == OP_KETRMAX)
4971: {
4972: /* TMP2 which is set here used by OP_KETRMAX below. */
4973: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4974: }
4975: }
4976: }
4977:
4978: stacksize = 0;
4979: if (ket != OP_KET || bra != OP_BRA)
4980: stacksize++;
4981: if (has_alternatives && opcode != OP_ONCE)
4982: stacksize++;
4983:
4984: if (stacksize > 0)
4985: allocate_stack(common, stacksize);
4986:
4987: stacksize = 0;
4988: if (ket != OP_KET)
4989: {
4990: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
4991: stacksize++;
4992: }
4993: else if (bra != OP_BRA)
4994: {
4995: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4996: stacksize++;
4997: }
4998:
4999: if (has_alternatives)
5000: {
5001: if (opcode != OP_ONCE)
5002: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
5003: if (ket != OP_KETRMAX)
1.1.1.3 ! misho 5004: BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL();
1.1 misho 5005: }
5006:
1.1.1.3 ! misho 5007: /* Must be after the trypath label. */
1.1 misho 5008: if (offset != 0)
5009: {
5010: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5011: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
5012: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
5013: }
5014:
5015: if (ket == OP_KETRMAX)
5016: {
5017: if (opcode == OP_ONCE || opcode >= OP_SBRA)
5018: {
5019: if (has_alternatives)
1.1.1.3 ! misho 5020: BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL();
1.1 misho 5021: /* Checking zero-length iteration. */
5022: if (opcode != OP_ONCE)
1.1.1.3 ! misho 5023: {
1.1 misho 5024: CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);
1.1.1.3 ! misho 5025: /* Drop STR_PTR for greedy plus quantifier. */
! 5026: if (bra != OP_BRAZERO)
! 5027: free_stack(common, 1);
! 5028: }
1.1 misho 5029: else
5030: /* TMP2 must contain the starting STR_PTR. */
5031: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);
5032: }
5033: else
5034: JUMPTO(SLJIT_JUMP, rmaxlabel);
1.1.1.3 ! misho 5035: BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL();
1.1 misho 5036: }
5037:
5038: if (bra == OP_BRAZERO)
1.1.1.3 ! misho 5039: BACKTRACK_AS(bracket_backtrack)->zerotrypath = LABEL();
1.1 misho 5040:
5041: if (bra == OP_BRAMINZERO)
5042: {
1.1.1.3 ! misho 5043: /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
! 5044: JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->trypath);
1.1 misho 5045: if (braminzerojump != NULL)
5046: {
5047: JUMPHERE(braminzerojump);
5048: /* We need to release the end pointer to perform the
1.1.1.3 ! misho 5049: backtrack for the zero-length iteration. When
1.1 misho 5050: framesize is < 0, OP_ONCE will do the release itself. */
1.1.1.3 ! misho 5051: if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0)
1.1 misho 5052: {
5053: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5054: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5055: }
5056: else if (ket == OP_KETRMIN && opcode != OP_ONCE)
5057: free_stack(common, 1);
5058: }
1.1.1.3 ! misho 5059: /* Continue to the normal backtrack. */
1.1 misho 5060: }
5061:
5062: if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
5063: decrease_call_count(common);
5064:
5065: /* Skip the other alternatives. */
5066: while (*cc == OP_ALT)
5067: cc += GET(cc, 1);
5068: cc += 1 + LINK_SIZE;
5069: return cc;
5070: }
5071:
1.1.1.3 ! misho 5072: static pcre_uchar *compile_bracketpos_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1 misho 5073: {
5074: DEFINE_COMPILER;
1.1.1.3 ! misho 5075: backtrack_common *backtrack;
1.1.1.2 misho 5076: pcre_uchar opcode;
1.1 misho 5077: int localptr;
5078: int cbraprivptr = 0;
5079: int framesize;
5080: int stacksize;
5081: int offset = 0;
5082: BOOL zero = FALSE;
1.1.1.2 misho 5083: pcre_uchar *ccbegin = NULL;
1.1 misho 5084: int stack;
5085: struct sljit_label *loop = NULL;
5086: struct jump_list *emptymatch = NULL;
5087:
1.1.1.3 ! misho 5088: PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL);
1.1 misho 5089: if (*cc == OP_BRAPOSZERO)
5090: {
5091: zero = TRUE;
5092: cc++;
5093: }
5094:
5095: opcode = *cc;
1.1.1.2 misho 5096: localptr = PRIV_DATA(cc);
1.1 misho 5097: SLJIT_ASSERT(localptr != 0);
1.1.1.3 ! misho 5098: BACKTRACK_AS(bracketpos_backtrack)->localptr = localptr;
1.1 misho 5099: switch(opcode)
5100: {
5101: case OP_BRAPOS:
5102: case OP_SBRAPOS:
5103: ccbegin = cc + 1 + LINK_SIZE;
5104: break;
5105:
5106: case OP_CBRAPOS:
5107: case OP_SCBRAPOS:
5108: offset = GET2(cc, 1 + LINK_SIZE);
5109: cbraprivptr = OVECTOR_PRIV(offset);
5110: offset <<= 1;
1.1.1.2 misho 5111: ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;
1.1 misho 5112: break;
5113:
5114: default:
5115: SLJIT_ASSERT_STOP();
5116: break;
5117: }
5118:
5119: framesize = get_framesize(common, cc, FALSE);
1.1.1.3 ! misho 5120: BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize;
1.1 misho 5121: if (framesize < 0)
5122: {
5123: stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1;
5124: if (!zero)
5125: stacksize++;
1.1.1.3 ! misho 5126: BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
1.1 misho 5127: allocate_stack(common, stacksize);
5128: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
5129:
5130: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
5131: {
5132: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
5133: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
5134: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
5135: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
5136: }
5137: else
5138: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5139:
5140: if (!zero)
5141: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1);
5142: }
5143: else
5144: {
5145: stacksize = framesize + 1;
5146: if (!zero)
5147: stacksize++;
5148: if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
5149: stacksize++;
1.1.1.3 ! misho 5150: BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
1.1 misho 5151: allocate_stack(common, stacksize);
5152:
5153: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5154: OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
5155: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
5156: stack = 0;
5157: if (!zero)
5158: {
5159: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);
5160: stack++;
5161: }
5162: if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
5163: {
5164: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);
5165: stack++;
5166: }
5167: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);
5168: init_frame(common, cc, stacksize - 1, stacksize - framesize, FALSE);
5169: }
5170:
5171: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
5172: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
5173:
5174: loop = LABEL();
5175: while (*cc != OP_KETRPOS)
5176: {
1.1.1.3 ! misho 5177: backtrack->top = NULL;
! 5178: backtrack->topbacktracks = NULL;
1.1 misho 5179: cc += GET(cc, 1);
5180:
1.1.1.3 ! misho 5181: compile_trypath(common, ccbegin, cc, backtrack);
1.1 misho 5182: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5183: return NULL;
5184:
5185: if (framesize < 0)
5186: {
5187: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5188:
5189: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
5190: {
5191: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
5192: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
5193: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
5194: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
5195: }
5196: else
5197: {
5198: if (opcode == OP_SBRAPOS)
5199: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5200: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5201: }
5202:
5203: if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
5204: add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));
5205:
5206: if (!zero)
5207: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
5208: }
5209: else
5210: {
5211: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
5212: {
5213: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, stacksize * sizeof(sljit_w));
5214: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
5215: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
5216: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
5217: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
5218: }
5219: else
5220: {
5221: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5222: OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_w));
5223: if (opcode == OP_SBRAPOS)
5224: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
5225: OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), STR_PTR, 0);
5226: }
5227:
5228: if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
5229: add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));
5230:
5231: if (!zero)
5232: {
5233: if (framesize < 0)
5234: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
5235: else
5236: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5237: }
5238: }
5239: JUMPTO(SLJIT_JUMP, loop);
5240: flush_stubs(common);
5241:
1.1.1.3 ! misho 5242: compile_backtrackpath(common, backtrack->top);
1.1 misho 5243: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5244: return NULL;
1.1.1.3 ! misho 5245: set_jumps(backtrack->topbacktracks, LABEL());
1.1 misho 5246:
5247: if (framesize < 0)
5248: {
5249: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
5250: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
5251: else
5252: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5253: }
5254: else
5255: {
5256: if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
5257: {
5258: /* Last alternative. */
5259: if (*cc == OP_KETRPOS)
5260: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5261: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
5262: }
5263: else
5264: {
5265: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5266: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
5267: }
5268: }
5269:
5270: if (*cc == OP_KETRPOS)
5271: break;
5272: ccbegin = cc + 1 + LINK_SIZE;
5273: }
5274:
1.1.1.3 ! misho 5275: backtrack->topbacktracks = NULL;
1.1 misho 5276: if (!zero)
5277: {
5278: if (framesize < 0)
1.1.1.3 ! misho 5279: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
1.1 misho 5280: else /* TMP2 is set to [localptr] above. */
1.1.1.3 ! misho 5281: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0));
1.1 misho 5282: }
5283:
5284: /* None of them matched. */
5285: set_jumps(emptymatch, LABEL());
5286: decrease_call_count(common);
5287: return cc + 1 + LINK_SIZE;
5288: }
5289:
1.1.1.2 misho 5290: static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *arg1, int *arg2, pcre_uchar **end)
1.1 misho 5291: {
5292: int class_len;
5293:
5294: *opcode = *cc;
5295: if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)
5296: {
5297: cc++;
5298: *type = OP_CHAR;
5299: }
5300: else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)
5301: {
5302: cc++;
5303: *type = OP_CHARI;
5304: *opcode -= OP_STARI - OP_STAR;
5305: }
5306: else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)
5307: {
5308: cc++;
5309: *type = OP_NOT;
5310: *opcode -= OP_NOTSTAR - OP_STAR;
5311: }
5312: else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)
5313: {
5314: cc++;
5315: *type = OP_NOTI;
5316: *opcode -= OP_NOTSTARI - OP_STAR;
5317: }
5318: else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)
5319: {
5320: cc++;
5321: *opcode -= OP_TYPESTAR - OP_STAR;
5322: *type = 0;
5323: }
5324: else
5325: {
5326: SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS);
5327: *type = *opcode;
5328: cc++;
1.1.1.2 misho 5329: class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0);
1.1 misho 5330: *opcode = cc[class_len - 1];
5331: if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)
5332: {
5333: *opcode -= OP_CRSTAR - OP_STAR;
5334: if (end != NULL)
5335: *end = cc + class_len;
5336: }
5337: else
5338: {
5339: SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE);
1.1.1.2 misho 5340: *arg1 = GET2(cc, (class_len + IMM2_SIZE));
1.1 misho 5341: *arg2 = GET2(cc, class_len);
5342:
5343: if (*arg2 == 0)
5344: {
5345: SLJIT_ASSERT(*arg1 != 0);
5346: *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : OP_MINUPTO;
5347: }
5348: if (*arg1 == *arg2)
5349: *opcode = OP_EXACT;
5350:
5351: if (end != NULL)
1.1.1.2 misho 5352: *end = cc + class_len + 2 * IMM2_SIZE;
1.1 misho 5353: }
5354: return cc;
5355: }
5356:
5357: if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO)
5358: {
5359: *arg1 = GET2(cc, 0);
1.1.1.2 misho 5360: cc += IMM2_SIZE;
1.1 misho 5361: }
5362:
5363: if (*type == 0)
5364: {
5365: *type = *cc;
5366: if (end != NULL)
5367: *end = next_opcode(common, cc);
5368: cc++;
5369: return cc;
5370: }
5371:
5372: if (end != NULL)
5373: {
5374: *end = cc + 1;
1.1.1.2 misho 5375: #ifdef SUPPORT_UTF
5376: if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);
1.1 misho 5377: #endif
5378: }
5379: return cc;
5380: }
5381:
1.1.1.3 ! misho 5382: static pcre_uchar *compile_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1 misho 5383: {
5384: DEFINE_COMPILER;
1.1.1.3 ! misho 5385: backtrack_common *backtrack;
1.1.1.2 misho 5386: pcre_uchar opcode;
5387: pcre_uchar type;
1.1 misho 5388: int arg1 = -1, arg2 = -1;
1.1.1.2 misho 5389: pcre_uchar* end;
1.1 misho 5390: jump_list *nomatch = NULL;
5391: struct sljit_jump *jump = NULL;
5392: struct sljit_label *label;
5393:
1.1.1.3 ! misho 5394: PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
1.1 misho 5395:
5396: cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end);
5397:
5398: switch(opcode)
5399: {
5400: case OP_STAR:
5401: case OP_PLUS:
5402: case OP_UPTO:
5403: case OP_CRRANGE:
5404: if (type == OP_ANYNL || type == OP_EXTUNI)
5405: {
5406: if (opcode == OP_STAR || opcode == OP_UPTO)
5407: {
5408: allocate_stack(common, 2);
5409: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5410: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
5411: }
5412: else
5413: {
5414: allocate_stack(common, 1);
5415: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5416: }
5417: if (opcode == OP_UPTO || opcode == OP_CRRANGE)
5418: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
5419:
5420: label = LABEL();
1.1.1.3 ! misho 5421: compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
1.1 misho 5422: if (opcode == OP_UPTO || opcode == OP_CRRANGE)
5423: {
5424: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
5425: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5426: if (opcode == OP_CRRANGE && arg2 > 0)
5427: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2, label);
5428: if (opcode == OP_UPTO || (opcode == OP_CRRANGE && arg1 > 0))
5429: jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, arg1);
5430: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
5431: }
5432:
5433: allocate_stack(common, 1);
5434: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5435: JUMPTO(SLJIT_JUMP, label);
5436: if (jump != NULL)
5437: JUMPHERE(jump);
5438: }
5439: else
5440: {
1.1.1.3 ! misho 5441: if (opcode == OP_PLUS)
! 5442: compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
1.1 misho 5443: allocate_stack(common, 2);
5444: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5445: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
5446: label = LABEL();
1.1.1.3 ! misho 5447: compile_char1_trypath(common, type, cc, &nomatch);
1.1 misho 5448: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5449: if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0))
5450: {
5451: OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
5452: JUMPTO(SLJIT_JUMP, label);
5453: }
5454: else
5455: {
5456: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5457: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5458: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
5459: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
5460: }
5461: set_jumps(nomatch, LABEL());
1.1.1.3 ! misho 5462: if (opcode == OP_CRRANGE)
! 5463: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1));
1.1 misho 5464: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5465: }
1.1.1.3 ! misho 5466: BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
1.1 misho 5467: break;
5468:
5469: case OP_MINSTAR:
5470: case OP_MINPLUS:
1.1.1.3 ! misho 5471: if (opcode == OP_MINPLUS)
! 5472: compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
1.1 misho 5473: allocate_stack(common, 1);
5474: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
1.1.1.3 ! misho 5475: BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
1.1 misho 5476: break;
5477:
5478: case OP_MINUPTO:
5479: case OP_CRMINRANGE:
5480: allocate_stack(common, 2);
5481: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5482: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
5483: if (opcode == OP_CRMINRANGE)
1.1.1.3 ! misho 5484: add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
! 5485: BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
1.1 misho 5486: break;
5487:
5488: case OP_QUERY:
5489: case OP_MINQUERY:
5490: allocate_stack(common, 1);
5491: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5492: if (opcode == OP_QUERY)
1.1.1.3 ! misho 5493: compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
! 5494: BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
1.1 misho 5495: break;
5496:
5497: case OP_EXACT:
5498: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
5499: label = LABEL();
1.1.1.3 ! misho 5500: compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
1.1 misho 5501: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
5502: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5503: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
5504: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
5505: break;
5506:
5507: case OP_POSSTAR:
5508: case OP_POSPLUS:
5509: case OP_POSUPTO:
5510: if (opcode != OP_POSSTAR)
5511: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
5512: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
5513: label = LABEL();
1.1.1.3 ! misho 5514: compile_char1_trypath(common, type, cc, &nomatch);
1.1 misho 5515: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
5516: if (opcode != OP_POSUPTO)
5517: {
5518: if (opcode == OP_POSPLUS)
5519: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2);
5520: JUMPTO(SLJIT_JUMP, label);
5521: }
5522: else
5523: {
5524: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
5525: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5526: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
5527: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
5528: }
5529: set_jumps(nomatch, LABEL());
5530: if (opcode == OP_POSPLUS)
1.1.1.3 ! misho 5531: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2));
1.1 misho 5532: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
5533: break;
5534:
5535: case OP_POSQUERY:
5536: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
1.1.1.3 ! misho 5537: compile_char1_trypath(common, type, cc, &nomatch);
1.1 misho 5538: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
5539: set_jumps(nomatch, LABEL());
5540: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
5541: break;
5542:
5543: default:
5544: SLJIT_ASSERT_STOP();
5545: break;
5546: }
5547:
5548: decrease_call_count(common);
5549: return end;
5550: }
5551:
1.1.1.3 ! misho 5552: static SLJIT_INLINE pcre_uchar *compile_fail_accept_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
1.1 misho 5553: {
5554: DEFINE_COMPILER;
1.1.1.3 ! misho 5555: backtrack_common *backtrack;
1.1 misho 5556:
1.1.1.3 ! misho 5557: PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);
1.1 misho 5558:
5559: if (*cc == OP_FAIL)
5560: {
1.1.1.3 ! misho 5561: add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
1.1 misho 5562: return cc + 1;
5563: }
5564:
5565: if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL)
5566: {
5567: /* No need to check notempty conditions. */
5568: if (common->acceptlabel == NULL)
5569: add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
5570: else
5571: JUMPTO(SLJIT_JUMP, common->acceptlabel);
5572: return cc + 1;
5573: }
5574:
5575: if (common->acceptlabel == NULL)
5576: add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)));
5577: else
5578: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel);
5579: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
5580: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
1.1.1.3 ! misho 5581: add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
1.1 misho 5582: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
5583: if (common->acceptlabel == NULL)
5584: add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0));
5585: else
5586: CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->acceptlabel);
5587: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
5588: if (common->acceptlabel == NULL)
5589: add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
5590: else
5591: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel);
1.1.1.3 ! misho 5592: add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
1.1 misho 5593: return cc + 1;
5594: }
5595:
1.1.1.3 ! misho 5596: static SLJIT_INLINE pcre_uchar *compile_close_trypath(compiler_common *common, pcre_uchar *cc)
1.1 misho 5597: {
5598: DEFINE_COMPILER;
5599: int offset = GET2(cc, 1);
5600:
5601: /* Data will be discarded anyway... */
5602: if (common->currententry != NULL)
1.1.1.2 misho 5603: return cc + 1 + IMM2_SIZE;
1.1 misho 5604:
5605: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset));
5606: offset <<= 1;
5607: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
5608: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
1.1.1.2 misho 5609: return cc + 1 + IMM2_SIZE;
1.1 misho 5610: }
5611:
1.1.1.3 ! misho 5612: static void compile_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
1.1 misho 5613: {
5614: DEFINE_COMPILER;
1.1.1.3 ! misho 5615: backtrack_common *backtrack;
1.1 misho 5616:
5617: while (cc < ccend)
5618: {
5619: switch(*cc)
5620: {
5621: case OP_SOD:
5622: case OP_SOM:
5623: case OP_NOT_WORD_BOUNDARY:
5624: case OP_WORD_BOUNDARY:
5625: case OP_NOT_DIGIT:
5626: case OP_DIGIT:
5627: case OP_NOT_WHITESPACE:
5628: case OP_WHITESPACE:
5629: case OP_NOT_WORDCHAR:
5630: case OP_WORDCHAR:
5631: case OP_ANY:
5632: case OP_ALLANY:
5633: case OP_ANYBYTE:
5634: case OP_NOTPROP:
5635: case OP_PROP:
5636: case OP_ANYNL:
5637: case OP_NOT_HSPACE:
5638: case OP_HSPACE:
5639: case OP_NOT_VSPACE:
5640: case OP_VSPACE:
5641: case OP_EXTUNI:
5642: case OP_EODN:
5643: case OP_EOD:
5644: case OP_CIRC:
5645: case OP_CIRCM:
5646: case OP_DOLL:
5647: case OP_DOLLM:
5648: case OP_NOT:
5649: case OP_NOTI:
5650: case OP_REVERSE:
1.1.1.3 ! misho 5651: cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
1.1 misho 5652: break;
5653:
5654: case OP_SET_SOM:
1.1.1.3 ! misho 5655: PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
! 5656: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
1.1 misho 5657: allocate_stack(common, 1);
5658: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
1.1.1.3 ! misho 5659: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
1.1 misho 5660: cc++;
5661: break;
5662:
5663: case OP_CHAR:
5664: case OP_CHARI:
1.1.1.3 ! misho 5665: if (common->mode == JIT_COMPILE)
! 5666: cc = compile_charn_trypath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
! 5667: else
! 5668: cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
1.1 misho 5669: break;
5670:
5671: case OP_STAR:
5672: case OP_MINSTAR:
5673: case OP_PLUS:
5674: case OP_MINPLUS:
5675: case OP_QUERY:
5676: case OP_MINQUERY:
5677: case OP_UPTO:
5678: case OP_MINUPTO:
5679: case OP_EXACT:
5680: case OP_POSSTAR:
5681: case OP_POSPLUS:
5682: case OP_POSQUERY:
5683: case OP_POSUPTO:
5684: case OP_STARI:
5685: case OP_MINSTARI:
5686: case OP_PLUSI:
5687: case OP_MINPLUSI:
5688: case OP_QUERYI:
5689: case OP_MINQUERYI:
5690: case OP_UPTOI:
5691: case OP_MINUPTOI:
5692: case OP_EXACTI:
5693: case OP_POSSTARI:
5694: case OP_POSPLUSI:
5695: case OP_POSQUERYI:
5696: case OP_POSUPTOI:
5697: case OP_NOTSTAR:
5698: case OP_NOTMINSTAR:
5699: case OP_NOTPLUS:
5700: case OP_NOTMINPLUS:
5701: case OP_NOTQUERY:
5702: case OP_NOTMINQUERY:
5703: case OP_NOTUPTO:
5704: case OP_NOTMINUPTO:
5705: case OP_NOTEXACT:
5706: case OP_NOTPOSSTAR:
5707: case OP_NOTPOSPLUS:
5708: case OP_NOTPOSQUERY:
5709: case OP_NOTPOSUPTO:
5710: case OP_NOTSTARI:
5711: case OP_NOTMINSTARI:
5712: case OP_NOTPLUSI:
5713: case OP_NOTMINPLUSI:
5714: case OP_NOTQUERYI:
5715: case OP_NOTMINQUERYI:
5716: case OP_NOTUPTOI:
5717: case OP_NOTMINUPTOI:
5718: case OP_NOTEXACTI:
5719: case OP_NOTPOSSTARI:
5720: case OP_NOTPOSPLUSI:
5721: case OP_NOTPOSQUERYI:
5722: case OP_NOTPOSUPTOI:
5723: case OP_TYPESTAR:
5724: case OP_TYPEMINSTAR:
5725: case OP_TYPEPLUS:
5726: case OP_TYPEMINPLUS:
5727: case OP_TYPEQUERY:
5728: case OP_TYPEMINQUERY:
5729: case OP_TYPEUPTO:
5730: case OP_TYPEMINUPTO:
5731: case OP_TYPEEXACT:
5732: case OP_TYPEPOSSTAR:
5733: case OP_TYPEPOSPLUS:
5734: case OP_TYPEPOSQUERY:
5735: case OP_TYPEPOSUPTO:
1.1.1.3 ! misho 5736: cc = compile_iterator_trypath(common, cc, parent);
1.1 misho 5737: break;
5738:
5739: case OP_CLASS:
5740: case OP_NCLASS:
1.1.1.2 misho 5741: if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE)
1.1.1.3 ! misho 5742: cc = compile_iterator_trypath(common, cc, parent);
1.1 misho 5743: else
1.1.1.3 ! misho 5744: cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
1.1 misho 5745: break;
5746:
1.1.1.2 misho 5747: #if defined SUPPORT_UTF || defined COMPILE_PCRE16
1.1 misho 5748: case OP_XCLASS:
5749: if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE)
1.1.1.3 ! misho 5750: cc = compile_iterator_trypath(common, cc, parent);
1.1 misho 5751: else
1.1.1.3 ! misho 5752: cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
1.1 misho 5753: break;
5754: #endif
5755:
5756: case OP_REF:
5757: case OP_REFI:
1.1.1.2 misho 5758: if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE)
1.1.1.3 ! misho 5759: cc = compile_ref_iterator_trypath(common, cc, parent);
1.1 misho 5760: else
1.1.1.3 ! misho 5761: cc = compile_ref_trypath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
1.1 misho 5762: break;
5763:
5764: case OP_RECURSE:
1.1.1.3 ! misho 5765: cc = compile_recurse_trypath(common, cc, parent);
1.1 misho 5766: break;
5767:
5768: case OP_ASSERT:
5769: case OP_ASSERT_NOT:
5770: case OP_ASSERTBACK:
5771: case OP_ASSERTBACK_NOT:
1.1.1.3 ! misho 5772: PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
! 5773: cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
1.1 misho 5774: break;
5775:
5776: case OP_BRAMINZERO:
1.1.1.3 ! misho 5777: PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc);
1.1 misho 5778: cc = bracketend(cc + 1);
5779: if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)
5780: {
5781: allocate_stack(common, 1);
5782: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5783: }
5784: else
5785: {
5786: allocate_stack(common, 2);
5787: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5788: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
5789: }
1.1.1.3 ! misho 5790: BACKTRACK_AS(braminzero_backtrack)->trypath = LABEL();
1.1 misho 5791: if (cc[1] > OP_ASSERTBACK_NOT)
5792: decrease_call_count(common);
5793: break;
5794:
5795: case OP_ONCE:
5796: case OP_ONCE_NC:
5797: case OP_BRA:
5798: case OP_CBRA:
5799: case OP_COND:
5800: case OP_SBRA:
5801: case OP_SCBRA:
5802: case OP_SCOND:
1.1.1.3 ! misho 5803: cc = compile_bracket_trypath(common, cc, parent);
1.1 misho 5804: break;
5805:
5806: case OP_BRAZERO:
5807: if (cc[1] > OP_ASSERTBACK_NOT)
1.1.1.3 ! misho 5808: cc = compile_bracket_trypath(common, cc, parent);
1.1 misho 5809: else
5810: {
1.1.1.3 ! misho 5811: PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
! 5812: cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
1.1 misho 5813: }
5814: break;
5815:
5816: case OP_BRAPOS:
5817: case OP_CBRAPOS:
5818: case OP_SBRAPOS:
5819: case OP_SCBRAPOS:
5820: case OP_BRAPOSZERO:
1.1.1.3 ! misho 5821: cc = compile_bracketpos_trypath(common, cc, parent);
! 5822: break;
! 5823:
! 5824: case OP_MARK:
! 5825: PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
! 5826: SLJIT_ASSERT(common->mark_ptr != 0);
! 5827: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
! 5828: allocate_stack(common, 1);
! 5829: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
! 5830: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
! 5831: OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)(cc + 2));
! 5832: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0);
! 5833: OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
! 5834: cc += 1 + 2 + cc[1];
! 5835: break;
! 5836:
! 5837: case OP_COMMIT:
! 5838: PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
! 5839: cc += 1;
1.1 misho 5840: break;
5841:
5842: case OP_FAIL:
5843: case OP_ACCEPT:
5844: case OP_ASSERT_ACCEPT:
1.1.1.3 ! misho 5845: cc = compile_fail_accept_trypath(common, cc, parent);
1.1 misho 5846: break;
5847:
5848: case OP_CLOSE:
1.1.1.3 ! misho 5849: cc = compile_close_trypath(common, cc);
1.1 misho 5850: break;
5851:
5852: case OP_SKIPZERO:
5853: cc = bracketend(cc + 1);
5854: break;
5855:
5856: default:
5857: SLJIT_ASSERT_STOP();
5858: return;
5859: }
5860: if (cc == NULL)
5861: return;
5862: }
5863: SLJIT_ASSERT(cc == ccend);
5864: }
5865:
1.1.1.3 ! misho 5866: #undef PUSH_BACKTRACK
! 5867: #undef PUSH_BACKTRACK_NOVALUE
! 5868: #undef BACKTRACK_AS
1.1 misho 5869:
1.1.1.3 ! misho 5870: #define COMPILE_BACKTRACKPATH(current) \
1.1 misho 5871: do \
5872: { \
1.1.1.3 ! misho 5873: compile_backtrackpath(common, (current)); \
1.1 misho 5874: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
5875: return; \
5876: } \
5877: while (0)
5878:
1.1.1.3 ! misho 5879: #define CURRENT_AS(type) ((type *)current)
1.1 misho 5880:
1.1.1.3 ! misho 5881: static void compile_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current)
1.1 misho 5882: {
5883: DEFINE_COMPILER;
1.1.1.2 misho 5884: pcre_uchar *cc = current->cc;
5885: pcre_uchar opcode;
5886: pcre_uchar type;
1.1 misho 5887: int arg1 = -1, arg2 = -1;
5888: struct sljit_label *label = NULL;
5889: struct sljit_jump *jump = NULL;
1.1.1.3 ! misho 5890: jump_list *jumplist = NULL;
1.1 misho 5891:
5892: cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL);
5893:
5894: switch(opcode)
5895: {
5896: case OP_STAR:
5897: case OP_PLUS:
5898: case OP_UPTO:
5899: case OP_CRRANGE:
5900: if (type == OP_ANYNL || type == OP_EXTUNI)
5901: {
1.1.1.3 ! misho 5902: set_jumps(current->topbacktracks, LABEL());
1.1 misho 5903: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5904: free_stack(common, 1);
1.1.1.3 ! misho 5905: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
1.1 misho 5906: }
5907: else
5908: {
1.1.1.3 ! misho 5909: if (opcode <= OP_PLUS || opcode == OP_UPTO)
1.1 misho 5910: arg2 = 0;
1.1.1.3 ! misho 5911: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
! 5912: jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, arg2 + 1);
! 5913: OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, SLJIT_IMM, 1);
1.1 misho 5914: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5915: skip_char_back(common);
5916: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
1.1.1.3 ! misho 5917: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
! 5918: if (opcode == OP_CRRANGE)
! 5919: set_jumps(current->topbacktracks, LABEL());
1.1 misho 5920: JUMPHERE(jump);
5921: free_stack(common, 2);
1.1.1.3 ! misho 5922: if (opcode == OP_PLUS)
! 5923: set_jumps(current->topbacktracks, LABEL());
1.1 misho 5924: }
5925: break;
5926:
5927: case OP_MINSTAR:
5928: case OP_MINPLUS:
5929: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.1.1.3 ! misho 5930: compile_char1_trypath(common, type, cc, &jumplist);
1.1 misho 5931: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
1.1.1.3 ! misho 5932: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
! 5933: set_jumps(jumplist, LABEL());
1.1 misho 5934: free_stack(common, 1);
1.1.1.3 ! misho 5935: if (opcode == OP_MINPLUS)
! 5936: set_jumps(current->topbacktracks, LABEL());
1.1 misho 5937: break;
5938:
5939: case OP_MINUPTO:
5940: case OP_CRMINRANGE:
5941: if (opcode == OP_CRMINRANGE)
5942: {
5943: label = LABEL();
1.1.1.3 ! misho 5944: set_jumps(current->topbacktracks, label);
1.1 misho 5945: }
5946: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.1.1.3 ! misho 5947: compile_char1_trypath(common, type, cc, &jumplist);
1.1 misho 5948:
5949: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5950: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5951: OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5952: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
5953:
5954: if (opcode == OP_CRMINRANGE)
5955: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label);
5956:
5957: if (opcode == OP_CRMINRANGE && arg1 == 0)
1.1.1.3 ! misho 5958: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
1.1 misho 5959: else
1.1.1.3 ! misho 5960: CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_backtrack)->trypath);
1.1 misho 5961:
1.1.1.3 ! misho 5962: set_jumps(jumplist, LABEL());
1.1 misho 5963: free_stack(common, 2);
5964: break;
5965:
5966: case OP_QUERY:
5967: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5968: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.1.1.3 ! misho 5969: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
1.1 misho 5970: jump = JUMP(SLJIT_JUMP);
1.1.1.3 ! misho 5971: set_jumps(current->topbacktracks, LABEL());
1.1 misho 5972: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5973: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.1.1.3 ! misho 5974: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
1.1 misho 5975: JUMPHERE(jump);
5976: free_stack(common, 1);
5977: break;
5978:
5979: case OP_MINQUERY:
5980: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5981: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5982: jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
1.1.1.3 ! misho 5983: compile_char1_trypath(common, type, cc, &jumplist);
! 5984: JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
! 5985: set_jumps(jumplist, LABEL());
1.1 misho 5986: JUMPHERE(jump);
5987: free_stack(common, 1);
5988: break;
5989:
5990: case OP_EXACT:
5991: case OP_POSPLUS:
1.1.1.3 ! misho 5992: set_jumps(current->topbacktracks, LABEL());
1.1 misho 5993: break;
5994:
5995: case OP_POSSTAR:
5996: case OP_POSQUERY:
5997: case OP_POSUPTO:
5998: break;
5999:
6000: default:
6001: SLJIT_ASSERT_STOP();
6002: break;
6003: }
6004: }
6005:
1.1.1.3 ! misho 6006: static void compile_ref_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current)
1.1 misho 6007: {
6008: DEFINE_COMPILER;
1.1.1.2 misho 6009: pcre_uchar *cc = current->cc;
6010: pcre_uchar type;
1.1 misho 6011:
1.1.1.2 misho 6012: type = cc[1 + IMM2_SIZE];
1.1 misho 6013: if ((type & 0x1) == 0)
6014: {
1.1.1.3 ! misho 6015: set_jumps(current->topbacktracks, LABEL());
1.1 misho 6016: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6017: free_stack(common, 1);
1.1.1.3 ! misho 6018: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
1.1 misho 6019: return;
6020: }
6021:
6022: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.1.1.3 ! misho 6023: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
! 6024: set_jumps(current->topbacktracks, LABEL());
1.1 misho 6025: free_stack(common, 2);
6026: }
6027:
1.1.1.3 ! misho 6028: static void compile_recurse_backtrackpath(compiler_common *common, struct backtrack_common *current)
1.1 misho 6029: {
6030: DEFINE_COMPILER;
6031:
1.1.1.3 ! misho 6032: set_jumps(current->topbacktracks, LABEL());
! 6033:
! 6034: if (common->has_set_som && common->mark_ptr != 0)
! 6035: {
! 6036: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
! 6037: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
! 6038: free_stack(common, 2);
! 6039: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
! 6040: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
! 6041: }
! 6042: else if (common->has_set_som || common->mark_ptr != 0)
! 6043: {
! 6044: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
! 6045: free_stack(common, 1);
! 6046: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0);
! 6047: }
1.1 misho 6048: }
6049:
1.1.1.3 ! misho 6050: static void compile_assert_backtrackpath(compiler_common *common, struct backtrack_common *current)
1.1 misho 6051: {
6052: DEFINE_COMPILER;
1.1.1.2 misho 6053: pcre_uchar *cc = current->cc;
6054: pcre_uchar bra = OP_BRA;
1.1 misho 6055: struct sljit_jump *brajump = NULL;
6056:
6057: SLJIT_ASSERT(*cc != OP_BRAMINZERO);
6058: if (*cc == OP_BRAZERO)
6059: {
6060: bra = *cc;
6061: cc++;
6062: }
6063:
6064: if (bra == OP_BRAZERO)
6065: {
1.1.1.3 ! misho 6066: SLJIT_ASSERT(current->topbacktracks == NULL);
1.1 misho 6067: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6068: }
6069:
1.1.1.3 ! misho 6070: if (CURRENT_AS(assert_backtrack)->framesize < 0)
1.1 misho 6071: {
1.1.1.3 ! misho 6072: set_jumps(current->topbacktracks, LABEL());
1.1 misho 6073:
6074: if (bra == OP_BRAZERO)
6075: {
6076: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.1.1.3 ! misho 6077: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath);
1.1 misho 6078: free_stack(common, 1);
6079: }
6080: return;
6081: }
6082:
6083: if (bra == OP_BRAZERO)
6084: {
6085: if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)
6086: {
6087: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.1.1.3 ! misho 6088: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath);
1.1 misho 6089: free_stack(common, 1);
6090: return;
6091: }
6092: free_stack(common, 1);
6093: brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
6094: }
6095:
6096: if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
6097: {
1.1.1.3 ! misho 6098: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr);
1.1 misho 6099: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
1.1.1.3 ! misho 6100: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_w));
1.1 misho 6101:
1.1.1.3 ! misho 6102: set_jumps(current->topbacktracks, LABEL());
1.1 misho 6103: }
6104: else
1.1.1.3 ! misho 6105: set_jumps(current->topbacktracks, LABEL());
1.1 misho 6106:
6107: if (bra == OP_BRAZERO)
6108: {
6109: /* We know there is enough place on the stack. */
6110: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
6111: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
1.1.1.3 ! misho 6112: JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->trypath);
1.1 misho 6113: JUMPHERE(brajump);
6114: }
6115: }
6116:
1.1.1.3 ! misho 6117: static void compile_bracket_backtrackpath(compiler_common *common, struct backtrack_common *current)
1.1 misho 6118: {
6119: DEFINE_COMPILER;
6120: int opcode;
6121: int offset = 0;
1.1.1.3 ! misho 6122: int localptr = CURRENT_AS(bracket_backtrack)->localptr;
1.1 misho 6123: int stacksize;
6124: int count;
1.1.1.2 misho 6125: pcre_uchar *cc = current->cc;
6126: pcre_uchar *ccbegin;
6127: pcre_uchar *ccprev;
1.1 misho 6128: jump_list *jumplist = NULL;
6129: jump_list *jumplistitem = NULL;
1.1.1.2 misho 6130: pcre_uchar bra = OP_BRA;
6131: pcre_uchar ket;
1.1.1.3 ! misho 6132: assert_backtrack *assert;
1.1 misho 6133: BOOL has_alternatives;
6134: struct sljit_jump *brazero = NULL;
6135: struct sljit_jump *once = NULL;
6136: struct sljit_jump *cond = NULL;
6137: struct sljit_label *rminlabel = NULL;
6138:
6139: if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
6140: {
6141: bra = *cc;
6142: cc++;
6143: }
6144:
6145: opcode = *cc;
6146: ccbegin = cc;
6147: ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);
6148: cc += GET(cc, 1);
6149: has_alternatives = *cc == OP_ALT;
6150: if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
1.1.1.3 ! misho 6151: has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL;
1.1 misho 6152: if (opcode == OP_CBRA || opcode == OP_SCBRA)
6153: offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;
6154: if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
6155: opcode = OP_SCOND;
6156: if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
6157: opcode = OP_ONCE;
6158:
6159: if (ket == OP_KETRMAX)
6160: {
1.1.1.3 ! misho 6161: if (bra == OP_BRAZERO)
1.1 misho 6162: {
6163: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6164: free_stack(common, 1);
6165: brazero = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0);
6166: }
6167: }
6168: else if (ket == OP_KETRMIN)
6169: {
6170: if (bra != OP_BRAMINZERO)
6171: {
6172: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6173: if (opcode >= OP_SBRA || opcode == OP_ONCE)
6174: {
6175: /* Checking zero-length iteration. */
1.1.1.3 ! misho 6176: if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)
! 6177: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_backtrack)->recursivetrypath);
1.1 misho 6178: else
6179: {
6180: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
1.1.1.3 ! misho 6181: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_backtrack)->recursivetrypath);
1.1 misho 6182: }
6183: if (opcode != OP_ONCE)
6184: free_stack(common, 1);
6185: }
6186: else
1.1.1.3 ! misho 6187: JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursivetrypath);
1.1 misho 6188: }
6189: rminlabel = LABEL();
6190: }
6191: else if (bra == OP_BRAZERO)
6192: {
6193: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6194: free_stack(common, 1);
6195: brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
6196: }
6197:
6198: if (SLJIT_UNLIKELY(opcode == OP_ONCE))
6199: {
1.1.1.3 ! misho 6200: if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
1.1 misho 6201: {
6202: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
6203: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
6204: }
6205: once = JUMP(SLJIT_JUMP);
6206: }
6207: else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
6208: {
6209: if (has_alternatives)
6210: {
6211: /* Always exactly one alternative. */
6212: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6213: free_stack(common, 1);
6214:
6215: jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
6216: if (SLJIT_UNLIKELY(!jumplistitem))
6217: return;
6218: jumplist = jumplistitem;
6219: jumplistitem->next = NULL;
6220: jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 1);
6221: }
6222: }
6223: else if (*cc == OP_ALT)
6224: {
6225: /* Build a jump list. Get the last successfully matched branch index. */
6226: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6227: free_stack(common, 1);
6228: count = 1;
6229: do
6230: {
6231: /* Append as the last item. */
6232: if (jumplist != NULL)
6233: {
6234: jumplistitem->next = sljit_alloc_memory(compiler, sizeof(jump_list));
6235: jumplistitem = jumplistitem->next;
6236: }
6237: else
6238: {
6239: jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
6240: jumplist = jumplistitem;
6241: }
6242:
6243: if (SLJIT_UNLIKELY(!jumplistitem))
6244: return;
6245:
6246: jumplistitem->next = NULL;
6247: jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, count++);
6248: cc += GET(cc, 1);
6249: }
6250: while (*cc == OP_ALT);
6251:
6252: cc = ccbegin + GET(ccbegin, 1);
6253: }
6254:
1.1.1.3 ! misho 6255: COMPILE_BACKTRACKPATH(current->top);
! 6256: if (current->topbacktracks)
! 6257: set_jumps(current->topbacktracks, LABEL());
1.1 misho 6258:
6259: if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
6260: {
6261: /* Conditional block always has at most one alternative. */
6262: if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)
6263: {
6264: SLJIT_ASSERT(has_alternatives);
1.1.1.3 ! misho 6265: assert = CURRENT_AS(bracket_backtrack)->u.assert;
1.1 misho 6266: if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))
6267: {
6268: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
6269: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
6270: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
6271: }
6272: cond = JUMP(SLJIT_JUMP);
1.1.1.3 ! misho 6273: set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());
1.1 misho 6274: }
1.1.1.3 ! misho 6275: else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL)
1.1 misho 6276: {
6277: SLJIT_ASSERT(has_alternatives);
6278: cond = JUMP(SLJIT_JUMP);
1.1.1.3 ! misho 6279: set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL());
1.1 misho 6280: }
6281: else
6282: SLJIT_ASSERT(!has_alternatives);
6283: }
6284:
6285: if (has_alternatives)
6286: {
6287: count = 1;
6288: do
6289: {
6290: current->top = NULL;
1.1.1.3 ! misho 6291: current->topbacktracks = NULL;
! 6292: current->nextbacktracks = NULL;
1.1 misho 6293: if (*cc == OP_ALT)
6294: {
6295: ccprev = cc + 1 + LINK_SIZE;
6296: cc += GET(cc, 1);
6297: if (opcode != OP_COND && opcode != OP_SCOND)
6298: {
6299: if (localptr != 0 && opcode != OP_ONCE)
6300: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
6301: else
6302: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6303: }
1.1.1.3 ! misho 6304: compile_trypath(common, ccprev, cc, current);
1.1 misho 6305: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6306: return;
6307: }
6308:
6309: /* Instructions after the current alternative is succesfully matched. */
1.1.1.3 ! misho 6310: /* There is a similar code in compile_bracket_trypath. */
1.1 misho 6311: if (opcode == OP_ONCE)
6312: {
1.1.1.3 ! misho 6313: if (CURRENT_AS(bracket_backtrack)->u.framesize < 0)
1.1 misho 6314: {
6315: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
6316: /* TMP2 which is set here used by OP_KETRMAX below. */
6317: if (ket == OP_KETRMAX)
6318: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
6319: else if (ket == OP_KETRMIN)
6320: {
6321: /* Move the STR_PTR to the localptr. */
6322: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
6323: }
6324: }
6325: else
6326: {
1.1.1.3 ! misho 6327: OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize + 2) * sizeof(sljit_w));
1.1 misho 6328: if (ket == OP_KETRMAX)
6329: {
6330: /* TMP2 which is set here used by OP_KETRMAX below. */
6331: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6332: }
6333: }
6334: }
6335:
6336: stacksize = 0;
6337: if (opcode != OP_ONCE)
6338: stacksize++;
6339: if (ket != OP_KET || bra != OP_BRA)
6340: stacksize++;
6341:
6342: if (stacksize > 0) {
1.1.1.3 ! misho 6343: if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
1.1 misho 6344: allocate_stack(common, stacksize);
6345: else
6346: {
6347: /* We know we have place at least for one item on the top of the stack. */
6348: SLJIT_ASSERT(stacksize == 1);
6349: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
6350: }
6351: }
6352:
6353: stacksize = 0;
6354: if (ket != OP_KET || bra != OP_BRA)
6355: {
6356: if (ket != OP_KET)
6357: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
6358: else
6359: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
6360: stacksize++;
6361: }
6362:
6363: if (opcode != OP_ONCE)
6364: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++);
6365:
6366: if (offset != 0)
6367: {
6368: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
6369: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
6370: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
6371: }
6372:
1.1.1.3 ! misho 6373: JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alttrypath);
1.1 misho 6374:
6375: if (opcode != OP_ONCE)
6376: {
6377: SLJIT_ASSERT(jumplist);
6378: JUMPHERE(jumplist->jump);
6379: jumplist = jumplist->next;
6380: }
6381:
1.1.1.3 ! misho 6382: COMPILE_BACKTRACKPATH(current->top);
! 6383: if (current->topbacktracks)
! 6384: set_jumps(current->topbacktracks, LABEL());
! 6385: SLJIT_ASSERT(!current->nextbacktracks);
1.1 misho 6386: }
6387: while (*cc == OP_ALT);
6388: SLJIT_ASSERT(!jumplist);
6389:
6390: if (cond != NULL)
6391: {
6392: SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);
1.1.1.3 ! misho 6393: assert = CURRENT_AS(bracket_backtrack)->u.assert;
1.1 misho 6394: if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)
6395:
6396: {
6397: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
6398: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
6399: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
6400: }
6401: JUMPHERE(cond);
6402: }
6403:
6404: /* Free the STR_PTR. */
6405: if (localptr == 0)
6406: free_stack(common, 1);
6407: }
6408:
6409: if (offset != 0)
6410: {
6411: /* Using both tmp register is better for instruction scheduling. */
6412: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6413: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
6414: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
6415: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
6416: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(2));
6417: free_stack(common, 3);
6418: }
6419: else if (opcode == OP_SBRA || opcode == OP_SCOND)
6420: {
6421: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(0));
6422: free_stack(common, 1);
6423: }
6424: else if (opcode == OP_ONCE)
6425: {
6426: cc = ccbegin + GET(ccbegin, 1);
1.1.1.3 ! misho 6427: if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
1.1 misho 6428: {
6429: /* Reset head and drop saved frame. */
6430: stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1;
1.1.1.3 ! misho 6431: free_stack(common, CURRENT_AS(bracket_backtrack)->u.framesize + stacksize);
1.1 misho 6432: }
6433: else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))
6434: {
6435: /* The STR_PTR must be released. */
6436: free_stack(common, 1);
6437: }
6438:
6439: JUMPHERE(once);
6440: /* Restore previous localptr */
1.1.1.3 ! misho 6441: if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
! 6442: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_w));
1.1 misho 6443: else if (ket == OP_KETRMIN)
6444: {
6445: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
6446: /* See the comment below. */
6447: free_stack(common, 2);
6448: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
6449: }
6450: }
6451:
6452: if (ket == OP_KETRMAX)
6453: {
6454: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.1.1.3 ! misho 6455: if (bra != OP_BRAZERO)
! 6456: free_stack(common, 1);
! 6457: CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursivetrypath);
1.1 misho 6458: if (bra == OP_BRAZERO)
6459: {
6460: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
1.1.1.3 ! misho 6461: JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath);
1.1 misho 6462: JUMPHERE(brazero);
1.1.1.3 ! misho 6463: free_stack(common, 1);
1.1 misho 6464: }
6465: }
6466: else if (ket == OP_KETRMIN)
6467: {
6468: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6469:
1.1.1.3 ! misho 6470: /* OP_ONCE removes everything in case of a backtrack, so we don't
1.1 misho 6471: need to explicitly release the STR_PTR. The extra release would
6472: affect badly the free_stack(2) above. */
6473: if (opcode != OP_ONCE)
6474: free_stack(common, 1);
6475: CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel);
6476: if (opcode == OP_ONCE)
6477: free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);
6478: else if (bra == OP_BRAMINZERO)
6479: free_stack(common, 1);
6480: }
6481: else if (bra == OP_BRAZERO)
6482: {
6483: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
1.1.1.3 ! misho 6484: JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath);
1.1 misho 6485: JUMPHERE(brazero);
6486: }
6487: }
6488:
1.1.1.3 ! misho 6489: static void compile_bracketpos_backtrackpath(compiler_common *common, struct backtrack_common *current)
1.1 misho 6490: {
6491: DEFINE_COMPILER;
6492: int offset;
6493: struct sljit_jump *jump;
6494:
1.1.1.3 ! misho 6495: if (CURRENT_AS(bracketpos_backtrack)->framesize < 0)
1.1 misho 6496: {
6497: if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)
6498: {
6499: offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1;
6500: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6501: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
6502: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
6503: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
6504: }
1.1.1.3 ! misho 6505: set_jumps(current->topbacktracks, LABEL());
! 6506: free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
1.1 misho 6507: return;
6508: }
6509:
1.1.1.3 ! misho 6510: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr);
1.1 misho 6511: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
6512:
1.1.1.3 ! misho 6513: if (current->topbacktracks)
1.1 misho 6514: {
6515: jump = JUMP(SLJIT_JUMP);
1.1.1.3 ! misho 6516: set_jumps(current->topbacktracks, LABEL());
1.1 misho 6517: /* Drop the stack frame. */
1.1.1.3 ! misho 6518: free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
1.1 misho 6519: JUMPHERE(jump);
6520: }
1.1.1.3 ! misho 6521: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_w));
1.1 misho 6522: }
6523:
1.1.1.3 ! misho 6524: static void compile_braminzero_backtrackpath(compiler_common *common, struct backtrack_common *current)
1.1 misho 6525: {
1.1.1.3 ! misho 6526: assert_backtrack backtrack;
1.1 misho 6527:
6528: current->top = NULL;
1.1.1.3 ! misho 6529: current->topbacktracks = NULL;
! 6530: current->nextbacktracks = NULL;
1.1 misho 6531: if (current->cc[1] > OP_ASSERTBACK_NOT)
6532: {
1.1.1.3 ! misho 6533: /* Manual call of compile_bracket_trypath and compile_bracket_backtrackpath. */
! 6534: compile_bracket_trypath(common, current->cc, current);
! 6535: compile_bracket_backtrackpath(common, current->top);
1.1 misho 6536: }
6537: else
6538: {
1.1.1.3 ! misho 6539: memset(&backtrack, 0, sizeof(backtrack));
! 6540: backtrack.common.cc = current->cc;
! 6541: backtrack.trypath = CURRENT_AS(braminzero_backtrack)->trypath;
! 6542: /* Manual call of compile_assert_trypath. */
! 6543: compile_assert_trypath(common, current->cc, &backtrack, FALSE);
1.1 misho 6544: }
1.1.1.3 ! misho 6545: SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks);
1.1 misho 6546: }
6547:
1.1.1.3 ! misho 6548: static void compile_backtrackpath(compiler_common *common, struct backtrack_common *current)
1.1 misho 6549: {
6550: DEFINE_COMPILER;
6551:
6552: while (current)
6553: {
1.1.1.3 ! misho 6554: if (current->nextbacktracks != NULL)
! 6555: set_jumps(current->nextbacktracks, LABEL());
1.1 misho 6556: switch(*current->cc)
6557: {
6558: case OP_SET_SOM:
6559: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6560: free_stack(common, 1);
6561: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP1, 0);
6562: break;
6563:
6564: case OP_STAR:
6565: case OP_MINSTAR:
6566: case OP_PLUS:
6567: case OP_MINPLUS:
6568: case OP_QUERY:
6569: case OP_MINQUERY:
6570: case OP_UPTO:
6571: case OP_MINUPTO:
6572: case OP_EXACT:
6573: case OP_POSSTAR:
6574: case OP_POSPLUS:
6575: case OP_POSQUERY:
6576: case OP_POSUPTO:
6577: case OP_STARI:
6578: case OP_MINSTARI:
6579: case OP_PLUSI:
6580: case OP_MINPLUSI:
6581: case OP_QUERYI:
6582: case OP_MINQUERYI:
6583: case OP_UPTOI:
6584: case OP_MINUPTOI:
6585: case OP_EXACTI:
6586: case OP_POSSTARI:
6587: case OP_POSPLUSI:
6588: case OP_POSQUERYI:
6589: case OP_POSUPTOI:
6590: case OP_NOTSTAR:
6591: case OP_NOTMINSTAR:
6592: case OP_NOTPLUS:
6593: case OP_NOTMINPLUS:
6594: case OP_NOTQUERY:
6595: case OP_NOTMINQUERY:
6596: case OP_NOTUPTO:
6597: case OP_NOTMINUPTO:
6598: case OP_NOTEXACT:
6599: case OP_NOTPOSSTAR:
6600: case OP_NOTPOSPLUS:
6601: case OP_NOTPOSQUERY:
6602: case OP_NOTPOSUPTO:
6603: case OP_NOTSTARI:
6604: case OP_NOTMINSTARI:
6605: case OP_NOTPLUSI:
6606: case OP_NOTMINPLUSI:
6607: case OP_NOTQUERYI:
6608: case OP_NOTMINQUERYI:
6609: case OP_NOTUPTOI:
6610: case OP_NOTMINUPTOI:
6611: case OP_NOTEXACTI:
6612: case OP_NOTPOSSTARI:
6613: case OP_NOTPOSPLUSI:
6614: case OP_NOTPOSQUERYI:
6615: case OP_NOTPOSUPTOI:
6616: case OP_TYPESTAR:
6617: case OP_TYPEMINSTAR:
6618: case OP_TYPEPLUS:
6619: case OP_TYPEMINPLUS:
6620: case OP_TYPEQUERY:
6621: case OP_TYPEMINQUERY:
6622: case OP_TYPEUPTO:
6623: case OP_TYPEMINUPTO:
6624: case OP_TYPEEXACT:
6625: case OP_TYPEPOSSTAR:
6626: case OP_TYPEPOSPLUS:
6627: case OP_TYPEPOSQUERY:
6628: case OP_TYPEPOSUPTO:
6629: case OP_CLASS:
6630: case OP_NCLASS:
1.1.1.2 misho 6631: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1.1 misho 6632: case OP_XCLASS:
1.1.1.2 misho 6633: #endif
1.1.1.3 ! misho 6634: compile_iterator_backtrackpath(common, current);
1.1 misho 6635: break;
6636:
6637: case OP_REF:
6638: case OP_REFI:
1.1.1.3 ! misho 6639: compile_ref_iterator_backtrackpath(common, current);
1.1 misho 6640: break;
6641:
6642: case OP_RECURSE:
1.1.1.3 ! misho 6643: compile_recurse_backtrackpath(common, current);
1.1 misho 6644: break;
6645:
6646: case OP_ASSERT:
6647: case OP_ASSERT_NOT:
6648: case OP_ASSERTBACK:
6649: case OP_ASSERTBACK_NOT:
1.1.1.3 ! misho 6650: compile_assert_backtrackpath(common, current);
1.1 misho 6651: break;
6652:
6653: case OP_ONCE:
6654: case OP_ONCE_NC:
6655: case OP_BRA:
6656: case OP_CBRA:
6657: case OP_COND:
6658: case OP_SBRA:
6659: case OP_SCBRA:
6660: case OP_SCOND:
1.1.1.3 ! misho 6661: compile_bracket_backtrackpath(common, current);
1.1 misho 6662: break;
6663:
6664: case OP_BRAZERO:
6665: if (current->cc[1] > OP_ASSERTBACK_NOT)
1.1.1.3 ! misho 6666: compile_bracket_backtrackpath(common, current);
1.1 misho 6667: else
1.1.1.3 ! misho 6668: compile_assert_backtrackpath(common, current);
1.1 misho 6669: break;
6670:
6671: case OP_BRAPOS:
6672: case OP_CBRAPOS:
6673: case OP_SBRAPOS:
6674: case OP_SCBRAPOS:
6675: case OP_BRAPOSZERO:
1.1.1.3 ! misho 6676: compile_bracketpos_backtrackpath(common, current);
1.1 misho 6677: break;
6678:
6679: case OP_BRAMINZERO:
1.1.1.3 ! misho 6680: compile_braminzero_backtrackpath(common, current);
! 6681: break;
! 6682:
! 6683: case OP_MARK:
! 6684: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
! 6685: free_stack(common, 1);
! 6686: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
! 6687: break;
! 6688:
! 6689: case OP_COMMIT:
! 6690: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
! 6691: if (common->leavelabel == NULL)
! 6692: add_jump(compiler, &common->leave, JUMP(SLJIT_JUMP));
! 6693: else
! 6694: JUMPTO(SLJIT_JUMP, common->leavelabel);
1.1 misho 6695: break;
6696:
6697: case OP_FAIL:
6698: case OP_ACCEPT:
6699: case OP_ASSERT_ACCEPT:
1.1.1.3 ! misho 6700: set_jumps(current->topbacktracks, LABEL());
1.1 misho 6701: break;
6702:
6703: default:
6704: SLJIT_ASSERT_STOP();
6705: break;
6706: }
6707: current = current->prev;
6708: }
6709: }
6710:
6711: static SLJIT_INLINE void compile_recurse(compiler_common *common)
6712: {
6713: DEFINE_COMPILER;
1.1.1.2 misho 6714: pcre_uchar *cc = common->start + common->currententry->start;
6715: pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);
6716: pcre_uchar *ccend = bracketend(cc);
1.1 misho 6717: int localsize = get_localsize(common, ccbegin, ccend);
6718: int framesize = get_framesize(common, cc, TRUE);
6719: int alternativesize;
6720: BOOL needsframe;
1.1.1.3 ! misho 6721: backtrack_common altbacktrack;
! 6722: struct sljit_label *save_leavelabel = common->leavelabel;
! 6723: jump_list *save_leave = common->leave;
1.1 misho 6724: struct sljit_jump *jump;
6725:
6726: SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);
6727: needsframe = framesize >= 0;
6728: if (!needsframe)
6729: framesize = 0;
6730: alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;
6731:
1.1.1.3 ! misho 6732: SLJIT_ASSERT(common->currententry->entry == NULL && common->recursive_head != 0);
1.1 misho 6733: common->currententry->entry = LABEL();
6734: set_jumps(common->currententry->calls, common->currententry->entry);
6735:
1.1.1.3 ! misho 6736: sljit_emit_fast_enter(compiler, TMP2, 0);
1.1 misho 6737: allocate_stack(common, localsize + framesize + alternativesize);
6738: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0);
6739: copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize);
1.1.1.3 ! misho 6740: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, STACK_TOP, 0);
1.1 misho 6741: if (needsframe)
1.1.1.3 ! misho 6742: init_frame(common, cc, framesize + alternativesize - 1, alternativesize, TRUE);
1.1 misho 6743:
6744: if (alternativesize > 0)
6745: OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
6746:
1.1.1.3 ! misho 6747: memset(&altbacktrack, 0, sizeof(backtrack_common));
! 6748: common->leavelabel = NULL;
1.1 misho 6749: common->acceptlabel = NULL;
1.1.1.3 ! misho 6750: common->leave = NULL;
1.1 misho 6751: common->accept = NULL;
1.1.1.3 ! misho 6752: altbacktrack.cc = ccbegin;
1.1 misho 6753: cc += GET(cc, 1);
6754: while (1)
6755: {
1.1.1.3 ! misho 6756: altbacktrack.top = NULL;
! 6757: altbacktrack.topbacktracks = NULL;
1.1 misho 6758:
1.1.1.3 ! misho 6759: if (altbacktrack.cc != ccbegin)
1.1 misho 6760: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
6761:
1.1.1.3 ! misho 6762: compile_trypath(common, altbacktrack.cc, cc, &altbacktrack);
1.1 misho 6763: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
1.1.1.3 ! misho 6764: {
! 6765: common->leavelabel = save_leavelabel;
! 6766: common->leave = save_leave;
1.1 misho 6767: return;
1.1.1.3 ! misho 6768: }
1.1 misho 6769:
6770: add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
6771:
1.1.1.3 ! misho 6772: compile_backtrackpath(common, altbacktrack.top);
1.1 misho 6773: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
1.1.1.3 ! misho 6774: {
! 6775: common->leavelabel = save_leavelabel;
! 6776: common->leave = save_leave;
1.1 misho 6777: return;
1.1.1.3 ! misho 6778: }
! 6779: set_jumps(altbacktrack.topbacktracks, LABEL());
1.1 misho 6780:
6781: if (*cc != OP_ALT)
6782: break;
6783:
1.1.1.3 ! misho 6784: altbacktrack.cc = cc + 1 + LINK_SIZE;
1.1 misho 6785: cc += GET(cc, 1);
6786: }
6787: /* None of them matched. */
1.1.1.3 ! misho 6788: if (common->leave != NULL)
! 6789: set_jumps(common->leave, LABEL());
! 6790:
1.1 misho 6791: OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
6792: jump = JUMP(SLJIT_JUMP);
6793:
6794: set_jumps(common->accept, LABEL());
1.1.1.3 ! misho 6795: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head);
1.1 misho 6796: if (needsframe)
6797: {
6798: OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
6799: add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
6800: OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
6801: }
6802: OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
6803:
6804: JUMPHERE(jump);
6805: copy_locals(common, ccbegin, ccend, FALSE, localsize + framesize + alternativesize, framesize + alternativesize);
6806: free_stack(common, localsize + framesize + alternativesize);
6807: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w));
6808: OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
1.1.1.3 ! misho 6809: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, TMP2, 0);
1.1 misho 6810: sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
1.1.1.3 ! misho 6811:
! 6812: common->leavelabel = save_leavelabel;
! 6813: common->leave = save_leave;
1.1 misho 6814: }
6815:
1.1.1.3 ! misho 6816: #undef COMPILE_BACKTRACKPATH
1.1 misho 6817: #undef CURRENT_AS
6818:
6819: void
1.1.1.3 ! misho 6820: PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode)
1.1 misho 6821: {
6822: struct sljit_compiler *compiler;
1.1.1.3 ! misho 6823: backtrack_common rootbacktrack;
1.1 misho 6824: compiler_common common_data;
6825: compiler_common *common = &common_data;
1.1.1.2 misho 6826: const pcre_uint8 *tables = re->tables;
1.1 misho 6827: pcre_study_data *study;
1.1.1.3 ! misho 6828: int localsize;
1.1.1.2 misho 6829: pcre_uchar *ccend;
1.1.1.3 ! misho 6830: executable_functions *functions;
1.1 misho 6831: void *executable_func;
6832: sljit_uw executable_size;
6833: struct sljit_label *mainloop = NULL;
6834: struct sljit_label *empty_match_found;
1.1.1.3 ! misho 6835: struct sljit_label *empty_match_backtrack;
! 6836: struct sljit_jump *jump;
1.1 misho 6837: struct sljit_jump *reqbyte_notfound = NULL;
6838: struct sljit_jump *empty_match;
6839:
6840: SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
6841: study = extra->study_data;
6842:
6843: if (!tables)
1.1.1.2 misho 6844: tables = PRIV(default_tables);
1.1 misho 6845:
1.1.1.3 ! misho 6846: memset(&rootbacktrack, 0, sizeof(backtrack_common));
! 6847: memset(common, 0, sizeof(compiler_common));
! 6848: rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
1.1 misho 6849:
1.1.1.3 ! misho 6850: common->start = rootbacktrack.cc;
1.1 misho 6851: common->fcc = tables + fcc_offset;
6852: common->lcc = (sljit_w)(tables + lcc_offset);
1.1.1.3 ! misho 6853: common->mode = mode;
1.1 misho 6854: common->nltype = NLTYPE_FIXED;
6855: switch(re->options & PCRE_NEWLINE_BITS)
6856: {
6857: case 0:
6858: /* Compile-time default */
6859: switch (NEWLINE)
6860: {
6861: case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
6862: case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
6863: default: common->newline = NEWLINE; break;
6864: }
6865: break;
6866: case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break;
6867: case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break;
6868: case PCRE_NEWLINE_CR+
6869: PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;
6870: case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
6871: case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
6872: default: return;
6873: }
6874: if ((re->options & PCRE_BSR_ANYCRLF) != 0)
6875: common->bsr_nltype = NLTYPE_ANYCRLF;
6876: else if ((re->options & PCRE_BSR_UNICODE) != 0)
6877: common->bsr_nltype = NLTYPE_ANY;
6878: else
6879: {
6880: #ifdef BSR_ANYCRLF
6881: common->bsr_nltype = NLTYPE_ANYCRLF;
6882: #else
6883: common->bsr_nltype = NLTYPE_ANY;
6884: #endif
6885: }
6886: common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
6887: common->ctypes = (sljit_w)(tables + ctypes_offset);
1.1.1.2 misho 6888: common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset);
1.1 misho 6889: common->name_count = re->name_count;
6890: common->name_entry_size = re->name_entry_size;
6891: common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
1.1.1.2 misho 6892: #ifdef SUPPORT_UTF
6893: /* PCRE_UTF16 has the same value as PCRE_UTF8. */
6894: common->utf = (re->options & PCRE_UTF8) != 0;
1.1 misho 6895: #ifdef SUPPORT_UCP
1.1.1.2 misho 6896: common->use_ucp = (re->options & PCRE_UCP) != 0;
1.1 misho 6897: #endif
1.1.1.2 misho 6898: #endif /* SUPPORT_UTF */
1.1.1.3 ! misho 6899: ccend = bracketend(rootbacktrack.cc);
! 6900:
! 6901: /* Calculate the local space size on the stack. */
! 6902: common->ovector_start = CALL_LIMIT + sizeof(sljit_w);
! 6903:
! 6904: SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
! 6905: localsize = get_localspace(common, rootbacktrack.cc, ccend);
! 6906: if (localsize < 0)
1.1 misho 6907: return;
1.1.1.3 ! misho 6908:
! 6909: /* Checking flags and updating ovector_start. */
! 6910: if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
! 6911: {
! 6912: common->req_char_ptr = common->ovector_start;
! 6913: common->ovector_start += sizeof(sljit_w);
! 6914: }
! 6915: if (mode != JIT_COMPILE)
! 6916: {
! 6917: common->start_used_ptr = common->ovector_start;
! 6918: common->ovector_start += sizeof(sljit_w);
! 6919: if (mode == JIT_PARTIAL_SOFT_COMPILE)
! 6920: {
! 6921: common->hit_start = common->ovector_start;
! 6922: common->ovector_start += sizeof(sljit_w);
! 6923: }
! 6924: }
! 6925: if ((re->options & PCRE_FIRSTLINE) != 0)
! 6926: {
! 6927: common->first_line_end = common->ovector_start;
! 6928: common->ovector_start += sizeof(sljit_w);
! 6929: }
! 6930:
! 6931: /* Aligning ovector to even number of sljit words. */
! 6932: if ((common->ovector_start & sizeof(sljit_w)) != 0)
! 6933: common->ovector_start += sizeof(sljit_w);
! 6934:
! 6935: SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
! 6936: common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w);
! 6937: localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w);
! 6938: if (localsize > SLJIT_MAX_LOCAL_SIZE)
1.1 misho 6939: return;
1.1.1.3 ! misho 6940: common->localptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(int));
1.1 misho 6941: if (!common->localptrs)
6942: return;
1.1.1.3 ! misho 6943: memset(common->localptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));
1.1 misho 6944: set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend);
6945:
6946: compiler = sljit_create_compiler();
6947: if (!compiler)
6948: {
6949: SLJIT_FREE(common->localptrs);
6950: return;
6951: }
6952: common->compiler = compiler;
6953:
6954: /* Main pcre_jit_exec entry. */
1.1.1.3 ! misho 6955: sljit_emit_enter(compiler, 1, 5, 5, localsize);
1.1 misho 6956:
6957: /* Register init. */
6958: reset_ovector(common, (re->top_bracket + 1) * 2);
1.1.1.3 ! misho 6959: if (common->req_char_ptr != 0)
! 6960: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, SLJIT_TEMPORARY_REG1, 0);
1.1 misho 6961:
1.1.1.2 misho 6962: OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0);
6963: OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0);
1.1 misho 6964: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
6965: OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
6966: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
6967: OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit));
6968: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
6969: OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
6970: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);
6971:
1.1.1.3 ! misho 6972: if (mode == JIT_PARTIAL_SOFT_COMPILE)
! 6973: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
! 6974:
1.1 misho 6975: /* Main part of the matching */
6976: if ((re->options & PCRE_ANCHORED) == 0)
6977: {
6978: mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);
6979: /* Forward search if possible. */
1.1.1.3 ! misho 6980: if ((re->options & PCRE_NO_START_OPTIMIZE) == 0)
! 6981: {
! 6982: if ((re->flags & PCRE_FIRSTSET) != 0)
! 6983: fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);
! 6984: else if ((re->flags & PCRE_STARTLINE) != 0)
! 6985: fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);
! 6986: else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
! 6987: fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
! 6988: }
1.1 misho 6989: }
1.1.1.3 ! misho 6990: if (common->req_char_ptr != 0)
! 6991: reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0);
1.1 misho 6992:
6993: /* Store the current STR_PTR in OVECTOR(0). */
6994: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
6995: /* Copy the limit of allowed recursions. */
6996: OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);
1.1.1.3 ! misho 6997: if (common->mark_ptr != 0)
! 6998: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0);
! 6999: /* Copy the beginning of the string. */
! 7000: if (mode == JIT_PARTIAL_SOFT_COMPILE)
! 7001: {
! 7002: jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
! 7003: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
! 7004: JUMPHERE(jump);
! 7005: }
! 7006: else if (mode == JIT_PARTIAL_HARD_COMPILE)
! 7007: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
1.1 misho 7008:
1.1.1.3 ! misho 7009: compile_trypath(common, rootbacktrack.cc, ccend, &rootbacktrack);
1.1 misho 7010: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
7011: {
7012: sljit_free_compiler(compiler);
7013: SLJIT_FREE(common->localptrs);
7014: return;
7015: }
7016:
7017: empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
7018: empty_match_found = LABEL();
7019:
7020: common->acceptlabel = LABEL();
7021: if (common->accept != NULL)
7022: set_jumps(common->accept, common->acceptlabel);
7023:
7024: /* This means we have a match. Update the ovector. */
7025: copy_ovector(common, re->top_bracket + 1);
1.1.1.3 ! misho 7026: common->leavelabel = LABEL();
! 7027: if (common->leave != NULL)
! 7028: set_jumps(common->leave, common->leavelabel);
1.1.1.2 misho 7029: sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);
1.1 misho 7030:
1.1.1.3 ! misho 7031: if (mode != JIT_COMPILE)
! 7032: {
! 7033: common->partialmatchlabel = LABEL();
! 7034: set_jumps(common->partialmatch, common->partialmatchlabel);
! 7035: return_with_partial_match(common, common->leavelabel);
! 7036: }
! 7037:
! 7038: empty_match_backtrack = LABEL();
! 7039: compile_backtrackpath(common, rootbacktrack.top);
1.1 misho 7040: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
7041: {
7042: sljit_free_compiler(compiler);
7043: SLJIT_FREE(common->localptrs);
7044: return;
7045: }
7046:
1.1.1.3 ! misho 7047: SLJIT_ASSERT(rootbacktrack.prev == NULL);
! 7048:
! 7049: if (mode == JIT_PARTIAL_SOFT_COMPILE)
! 7050: {
! 7051: /* Update hit_start only in the first time. */
! 7052: jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
! 7053: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr);
! 7054: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1);
! 7055: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, TMP1, 0);
! 7056: JUMPHERE(jump);
! 7057: }
1.1 misho 7058:
7059: /* Check we have remaining characters. */
7060: OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
7061:
7062: if ((re->options & PCRE_ANCHORED) == 0)
7063: {
7064: if ((re->options & PCRE_FIRSTLINE) == 0)
7065: {
1.1.1.3 ! misho 7066: if (mode == JIT_COMPILE && study != NULL && study->minlength > 1 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
1.1 misho 7067: {
1.1.1.3 ! misho 7068: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength + 1));
1.1 misho 7069: CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop);
7070: }
7071: else
7072: CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
7073: }
7074: else
7075: {
1.1.1.3 ! misho 7076: SLJIT_ASSERT(common->first_line_end != 0);
! 7077: if (mode == JIT_COMPILE && study != NULL && study->minlength > 1 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
1.1 misho 7078: {
1.1.1.3 ! misho 7079: OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength + 1));
1.1 misho 7080: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
7081: COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER);
1.1.1.3 ! misho 7082: OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
1.1 misho 7083: COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL);
7084: JUMPTO(SLJIT_C_ZERO, mainloop);
7085: }
7086: else
1.1.1.3 ! misho 7087: CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, mainloop);
1.1 misho 7088: }
7089: }
7090:
1.1.1.3 ! misho 7091: /* No more remaining characters. */
1.1 misho 7092: if (reqbyte_notfound != NULL)
7093: JUMPHERE(reqbyte_notfound);
1.1.1.3 ! misho 7094:
! 7095: if (mode == JIT_PARTIAL_SOFT_COMPILE)
! 7096: CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0, common->partialmatchlabel);
! 7097:
1.1 misho 7098: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
1.1.1.3 ! misho 7099: JUMPTO(SLJIT_JUMP, common->leavelabel);
1.1 misho 7100:
7101: flush_stubs(common);
7102:
7103: JUMPHERE(empty_match);
7104: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
7105: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
1.1.1.3 ! misho 7106: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack);
1.1 misho 7107: OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
7108: CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found);
7109: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
7110: CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found);
1.1.1.3 ! misho 7111: JUMPTO(SLJIT_JUMP, empty_match_backtrack);
1.1 misho 7112:
7113: common->currententry = common->entries;
7114: while (common->currententry != NULL)
7115: {
7116: /* Might add new entries. */
7117: compile_recurse(common);
7118: if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
7119: {
7120: sljit_free_compiler(compiler);
7121: SLJIT_FREE(common->localptrs);
7122: return;
7123: }
7124: flush_stubs(common);
7125: common->currententry = common->currententry->next;
7126: }
7127:
7128: /* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */
7129: /* This is a (really) rare case. */
7130: set_jumps(common->stackalloc, LABEL());
7131: /* RETURN_ADDR is not a saved register. */
1.1.1.3 ! misho 7132: sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
1.1 misho 7133: OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
7134: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
7135: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
7136: OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
7137: OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
7138:
7139: sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
1.1.1.3 ! misho 7140: jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
1.1 misho 7141: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
7142: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
7143: OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top));
7144: OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit));
7145: OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
7146: sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
7147:
7148: /* Allocation failed. */
1.1.1.3 ! misho 7149: JUMPHERE(jump);
1.1 misho 7150: /* We break the return address cache here, but this is a really rare case. */
7151: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
1.1.1.3 ! misho 7152: JUMPTO(SLJIT_JUMP, common->leavelabel);
1.1 misho 7153:
7154: /* Call limit reached. */
7155: set_jumps(common->calllimit, LABEL());
7156: OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
1.1.1.3 ! misho 7157: JUMPTO(SLJIT_JUMP, common->leavelabel);
1.1 misho 7158:
7159: if (common->revertframes != NULL)
7160: {
7161: set_jumps(common->revertframes, LABEL());
7162: do_revertframes(common);
7163: }
7164: if (common->wordboundary != NULL)
7165: {
7166: set_jumps(common->wordboundary, LABEL());
7167: check_wordboundary(common);
7168: }
7169: if (common->anynewline != NULL)
7170: {
7171: set_jumps(common->anynewline, LABEL());
7172: check_anynewline(common);
7173: }
7174: if (common->hspace != NULL)
7175: {
7176: set_jumps(common->hspace, LABEL());
7177: check_hspace(common);
7178: }
7179: if (common->vspace != NULL)
7180: {
7181: set_jumps(common->vspace, LABEL());
7182: check_vspace(common);
7183: }
7184: if (common->casefulcmp != NULL)
7185: {
7186: set_jumps(common->casefulcmp, LABEL());
7187: do_casefulcmp(common);
7188: }
7189: if (common->caselesscmp != NULL)
7190: {
7191: set_jumps(common->caselesscmp, LABEL());
7192: do_caselesscmp(common);
7193: }
1.1.1.2 misho 7194: #ifdef SUPPORT_UTF
7195: if (common->utfreadchar != NULL)
1.1 misho 7196: {
1.1.1.2 misho 7197: set_jumps(common->utfreadchar, LABEL());
7198: do_utfreadchar(common);
1.1 misho 7199: }
1.1.1.2 misho 7200: #ifdef COMPILE_PCRE8
7201: if (common->utfreadtype8 != NULL)
1.1 misho 7202: {
1.1.1.2 misho 7203: set_jumps(common->utfreadtype8, LABEL());
7204: do_utfreadtype8(common);
1.1 misho 7205: }
7206: #endif
1.1.1.2 misho 7207: #endif /* COMPILE_PCRE8 */
1.1 misho 7208: #ifdef SUPPORT_UCP
7209: if (common->getucd != NULL)
7210: {
7211: set_jumps(common->getucd, LABEL());
7212: do_getucd(common);
7213: }
7214: #endif
7215:
7216: SLJIT_FREE(common->localptrs);
7217: executable_func = sljit_generate_code(compiler);
7218: executable_size = sljit_get_generated_code_size(compiler);
7219: sljit_free_compiler(compiler);
7220: if (executable_func == NULL)
7221: return;
7222:
1.1.1.3 ! misho 7223: /* Reuse the function descriptor if possible. */
! 7224: if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)
! 7225: functions = (executable_functions *)extra->executable_jit;
! 7226: else
1.1 misho 7227: {
1.1.1.3 ! misho 7228: functions = SLJIT_MALLOC(sizeof(executable_functions));
! 7229: if (functions == NULL)
! 7230: {
! 7231: /* This case is highly unlikely since we just recently
! 7232: freed a lot of memory. Although not impossible. */
! 7233: sljit_free_code(executable_func);
! 7234: return;
! 7235: }
! 7236: memset(functions, 0, sizeof(executable_functions));
! 7237: extra->executable_jit = functions;
! 7238: extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
1.1 misho 7239: }
7240:
1.1.1.3 ! misho 7241: functions->executable_funcs[mode] = executable_func;
! 7242: functions->executable_sizes[mode] = executable_size;
1.1 misho 7243: }
7244:
1.1.1.3 ! misho 7245: static int jit_machine_stack_exec(jit_arguments *arguments, void* executable_func)
1.1 misho 7246: {
7247: union {
7248: void* executable_func;
7249: jit_function call_executable_func;
7250: } convert_executable_func;
1.1.1.2 misho 7251: pcre_uint8 local_area[LOCAL_SPACE_SIZE];
1.1 misho 7252: struct sljit_stack local_stack;
7253:
7254: local_stack.top = (sljit_w)&local_area;
7255: local_stack.base = local_stack.top;
7256: local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE;
7257: local_stack.max_limit = local_stack.limit;
7258: arguments->stack = &local_stack;
1.1.1.3 ! misho 7259: convert_executable_func.executable_func = executable_func;
1.1 misho 7260: return convert_executable_func.call_executable_func(arguments);
7261: }
7262:
7263: int
1.1.1.3 ! misho 7264: PRIV(jit_exec)(const REAL_PCRE *re, const PUBL(extra) *extra_data, const pcre_uchar *subject,
! 7265: int length, int start_offset, int options, int *offsets, int offsetcount)
1.1 misho 7266: {
1.1.1.3 ! misho 7267: executable_functions *functions = (executable_functions *)extra_data->executable_jit;
1.1 misho 7268: union {
7269: void* executable_func;
7270: jit_function call_executable_func;
7271: } convert_executable_func;
7272: jit_arguments arguments;
7273: int maxoffsetcount;
7274: int retval;
1.1.1.3 ! misho 7275: int mode = JIT_COMPILE;
! 7276:
! 7277: if ((options & PCRE_PARTIAL_HARD) != 0)
! 7278: mode = JIT_PARTIAL_HARD_COMPILE;
! 7279: else if ((options & PCRE_PARTIAL_SOFT) != 0)
! 7280: mode = JIT_PARTIAL_SOFT_COMPILE;
! 7281:
! 7282: if (functions->executable_funcs[mode] == NULL)
! 7283: return PCRE_ERROR_NULL;
1.1 misho 7284:
7285: /* Sanity checks should be handled by pcre_exec. */
7286: arguments.stack = NULL;
7287: arguments.str = subject + start_offset;
7288: arguments.begin = subject;
7289: arguments.end = subject + length;
1.1.1.3 ! misho 7290: arguments.mark_ptr = NULL;
! 7291: /* JIT decreases this value less frequently than the interpreter. */
! 7292: arguments.calllimit = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : extra_data->match_limit;
1.1 misho 7293: arguments.notbol = (options & PCRE_NOTBOL) != 0;
7294: arguments.noteol = (options & PCRE_NOTEOL) != 0;
7295: arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
7296: arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
7297: arguments.offsets = offsets;
7298:
7299: /* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of
7300: the output vector for storing captured strings, with the remainder used as
7301: workspace. We don't need the workspace here. For compatibility, we limit the
7302: number of captured strings in the same way as pcre_exec(), so that the user
7303: gets the same result with and without JIT. */
7304:
1.1.1.2 misho 7305: if (offsetcount != 2)
7306: offsetcount = ((offsetcount - (offsetcount % 3)) * 2) / 3;
1.1 misho 7307: maxoffsetcount = (re->top_bracket + 1) * 2;
7308: if (offsetcount > maxoffsetcount)
7309: offsetcount = maxoffsetcount;
7310: arguments.offsetcount = offsetcount;
7311:
1.1.1.3 ! misho 7312: if (functions->callback)
! 7313: arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata);
1.1 misho 7314: else
1.1.1.3 ! misho 7315: arguments.stack = (struct sljit_stack *)functions->userdata;
1.1 misho 7316:
7317: if (arguments.stack == NULL)
1.1.1.3 ! misho 7318: retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]);
1.1 misho 7319: else
7320: {
1.1.1.3 ! misho 7321: convert_executable_func.executable_func = functions->executable_funcs[mode];
1.1 misho 7322: retval = convert_executable_func.call_executable_func(&arguments);
7323: }
7324:
7325: if (retval * 2 > offsetcount)
7326: retval = 0;
1.1.1.3 ! misho 7327: if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
! 7328: *(extra_data->mark) = arguments.mark_ptr;
! 7329:
1.1 misho 7330: return retval;
7331: }
7332:
7333: void
1.1.1.3 ! misho 7334: PRIV(jit_free)(void *executable_funcs)
1.1 misho 7335: {
1.1.1.3 ! misho 7336: int i;
! 7337: executable_functions *functions = (executable_functions *)executable_funcs;
! 7338: for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
! 7339: {
! 7340: if (functions->executable_funcs[i] != NULL)
! 7341: sljit_free_code(functions->executable_funcs[i]);
! 7342: }
! 7343: SLJIT_FREE(functions);
1.1 misho 7344: }
7345:
7346: int
1.1.1.3 ! misho 7347: PRIV(jit_get_size)(void *executable_funcs)
1.1 misho 7348: {
1.1.1.3 ! misho 7349: int i;
! 7350: sljit_uw size = 0;
! 7351: sljit_uw *executable_sizes = ((executable_functions *)executable_funcs)->executable_sizes;
! 7352: for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
! 7353: size += executable_sizes[i];
! 7354: return (int)size;
1.1 misho 7355: }
7356:
1.1.1.2 misho 7357: const char*
7358: PRIV(jit_get_target)(void)
7359: {
7360: return sljit_get_platform_name();
7361: }
7362:
7363: #ifdef COMPILE_PCRE8
1.1 misho 7364: PCRE_EXP_DECL pcre_jit_stack *
7365: pcre_jit_stack_alloc(int startsize, int maxsize)
1.1.1.2 misho 7366: #else
7367: PCRE_EXP_DECL pcre16_jit_stack *
7368: pcre16_jit_stack_alloc(int startsize, int maxsize)
7369: #endif
1.1 misho 7370: {
7371: if (startsize < 1 || maxsize < 1)
7372: return NULL;
7373: if (startsize > maxsize)
7374: startsize = maxsize;
7375: startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
7376: maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
1.1.1.2 misho 7377: return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize);
1.1 misho 7378: }
7379:
1.1.1.2 misho 7380: #ifdef COMPILE_PCRE8
1.1 misho 7381: PCRE_EXP_DECL void
7382: pcre_jit_stack_free(pcre_jit_stack *stack)
1.1.1.2 misho 7383: #else
7384: PCRE_EXP_DECL void
7385: pcre16_jit_stack_free(pcre16_jit_stack *stack)
7386: #endif
1.1 misho 7387: {
1.1.1.3 ! misho 7388: sljit_free_stack((struct sljit_stack *)stack);
1.1 misho 7389: }
7390:
1.1.1.2 misho 7391: #ifdef COMPILE_PCRE8
1.1 misho 7392: PCRE_EXP_DECL void
7393: pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
1.1.1.2 misho 7394: #else
7395: PCRE_EXP_DECL void
7396: pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
7397: #endif
1.1 misho 7398: {
1.1.1.3 ! misho 7399: executable_functions *functions;
1.1 misho 7400: if (extra != NULL &&
7401: (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
7402: extra->executable_jit != NULL)
7403: {
1.1.1.3 ! misho 7404: functions = (executable_functions *)extra->executable_jit;
! 7405: functions->callback = callback;
! 7406: functions->userdata = userdata;
1.1 misho 7407: }
7408: }
7409:
7410: #else /* SUPPORT_JIT */
7411:
7412: /* These are dummy functions to avoid linking errors when JIT support is not
7413: being compiled. */
7414:
1.1.1.2 misho 7415: #ifdef COMPILE_PCRE8
1.1 misho 7416: PCRE_EXP_DECL pcre_jit_stack *
7417: pcre_jit_stack_alloc(int startsize, int maxsize)
1.1.1.2 misho 7418: #else
7419: PCRE_EXP_DECL pcre16_jit_stack *
7420: pcre16_jit_stack_alloc(int startsize, int maxsize)
7421: #endif
1.1 misho 7422: {
7423: (void)startsize;
7424: (void)maxsize;
7425: return NULL;
7426: }
7427:
1.1.1.2 misho 7428: #ifdef COMPILE_PCRE8
1.1 misho 7429: PCRE_EXP_DECL void
7430: pcre_jit_stack_free(pcre_jit_stack *stack)
1.1.1.2 misho 7431: #else
7432: PCRE_EXP_DECL void
7433: pcre16_jit_stack_free(pcre16_jit_stack *stack)
7434: #endif
1.1 misho 7435: {
7436: (void)stack;
7437: }
7438:
1.1.1.2 misho 7439: #ifdef COMPILE_PCRE8
1.1 misho 7440: PCRE_EXP_DECL void
7441: pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
1.1.1.2 misho 7442: #else
7443: PCRE_EXP_DECL void
7444: pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
7445: #endif
1.1 misho 7446: {
7447: (void)extra;
7448: (void)callback;
7449: (void)userdata;
7450: }
7451:
7452: #endif
7453:
7454: /* End of pcre_jit_compile.c */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>