6 |
and semantics are as close as possible to those of the Perl 5 language. |
and semantics are as close as possible to those of the Perl 5 language. |
7 |
|
|
8 |
Written by Philip Hazel |
Written by Philip Hazel |
9 |
Copyright (c) 1997-2012 University of Cambridge |
Copyright (c) 1997-2013 University of Cambridge |
10 |
|
|
11 |
The machine code generator part (this module) was written by Zoltan Herczeg |
The machine code generator part (this module) was written by Zoltan Herczeg |
12 |
Copyright (c) 2010-2012 |
Copyright (c) 2010-2013 |
13 |
|
|
14 |
----------------------------------------------------------------------------- |
----------------------------------------------------------------------------- |
15 |
Redistribution and use in source and binary forms, with or without |
Redistribution and use in source and binary forms, with or without |
71 |
2 - Enable capture_last_ptr (includes option 1). */ |
2 - Enable capture_last_ptr (includes option 1). */ |
72 |
/* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */ |
/* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */ |
73 |
|
|
74 |
|
/* 1 - Always have a control head. */ |
75 |
|
/* #define DEBUG_FORCE_CONTROL_HEAD 1 */ |
76 |
|
|
77 |
/* Allocate memory for the regex stack on the real machine stack. |
/* Allocate memory for the regex stack on the real machine stack. |
78 |
Fast, but limited size. */ |
Fast, but limited size. */ |
79 |
#define MACHINE_STACK_SIZE 32768 |
#define MACHINE_STACK_SIZE 32768 |
196 |
struct stub_list *next; |
struct stub_list *next; |
197 |
} stub_list; |
} stub_list; |
198 |
|
|
199 |
enum frame_types { no_frame = -1, no_stack = -2 }; |
enum frame_types { |
200 |
|
no_frame = -1, |
201 |
|
no_stack = -2 |
202 |
|
}; |
203 |
|
|
204 |
|
enum control_types { |
205 |
|
type_mark = 0, |
206 |
|
type_then_trap = 1 |
207 |
|
}; |
208 |
|
|
209 |
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); |
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); |
210 |
|
|
226 |
typedef struct assert_backtrack { |
typedef struct assert_backtrack { |
227 |
backtrack_common common; |
backtrack_common common; |
228 |
jump_list *condfailed; |
jump_list *condfailed; |
229 |
/* Less than 0 (-1) if a frame is not needed. */ |
/* Less than 0 if a frame is not needed. */ |
230 |
int framesize; |
int framesize; |
231 |
/* Points to our private memory word on the stack. */ |
/* Points to our private memory word on the stack. */ |
232 |
int private_data_ptr; |
int private_data_ptr; |
247 |
/* Both for OP_COND, OP_SCOND. */ |
/* Both for OP_COND, OP_SCOND. */ |
248 |
jump_list *condfailed; |
jump_list *condfailed; |
249 |
assert_backtrack *assert; |
assert_backtrack *assert; |
250 |
/* For OP_ONCE. -1 if not needed. */ |
/* For OP_ONCE. Less than 0 if not needed. */ |
251 |
int framesize; |
int framesize; |
252 |
} u; |
} u; |
253 |
/* Points to our private memory word on the stack. */ |
/* Points to our private memory word on the stack. */ |
282 |
/* Collects the calls until the function is not created. */ |
/* Collects the calls until the function is not created. */ |
283 |
jump_list *calls; |
jump_list *calls; |
284 |
/* Points to the starting opcode. */ |
/* Points to the starting opcode. */ |
285 |
int start; |
sljit_sw start; |
286 |
} recurse_entry; |
} recurse_entry; |
287 |
|
|
288 |
typedef struct recurse_backtrack { |
typedef struct recurse_backtrack { |
290 |
BOOL inlined_pattern; |
BOOL inlined_pattern; |
291 |
} recurse_backtrack; |
} recurse_backtrack; |
292 |
|
|
293 |
|
#define OP_THEN_TRAP OP_TABLE_LENGTH |
294 |
|
|
295 |
|
typedef struct then_trap_backtrack { |
296 |
|
backtrack_common common; |
297 |
|
/* If then_trap is not NULL, this structure contains the real |
298 |
|
then_trap for the backtracking path. */ |
299 |
|
struct then_trap_backtrack *then_trap; |
300 |
|
/* Points to the starting opcode. */ |
301 |
|
sljit_sw start; |
302 |
|
/* Exit point for the then opcodes of this alternative. */ |
303 |
|
jump_list *quit; |
304 |
|
/* Frame size of the current alternative. */ |
305 |
|
int framesize; |
306 |
|
} then_trap_backtrack; |
307 |
|
|
308 |
#define MAX_RANGE_SIZE 6 |
#define MAX_RANGE_SIZE 6 |
309 |
|
|
310 |
typedef struct compiler_common { |
typedef struct compiler_common { |
311 |
|
/* The sljit ceneric compiler. */ |
312 |
struct sljit_compiler *compiler; |
struct sljit_compiler *compiler; |
313 |
|
/* First byte code. */ |
314 |
pcre_uchar *start; |
pcre_uchar *start; |
|
|
|
315 |
/* Maps private data offset to each opcode. */ |
/* Maps private data offset to each opcode. */ |
316 |
int *private_data_ptrs; |
sljit_si *private_data_ptrs; |
317 |
/* Tells whether the capturing bracket is optimized. */ |
/* Tells whether the capturing bracket is optimized. */ |
318 |
pcre_uint8 *optimized_cbracket; |
pcre_uint8 *optimized_cbracket; |
319 |
|
/* Tells whether the starting offset is a target of then. */ |
320 |
|
pcre_uint8 *then_offsets; |
321 |
|
/* Current position where a THEN must jump. */ |
322 |
|
then_trap_backtrack *then_trap; |
323 |
/* Starting offset of private data for capturing brackets. */ |
/* Starting offset of private data for capturing brackets. */ |
324 |
int cbraptr; |
int cbra_ptr; |
325 |
/* OVector starting point. Must be divisible by 2. */ |
/* Output vector starting point. Must be divisible by 2. */ |
326 |
int ovector_start; |
int ovector_start; |
327 |
/* Last known position of the requested byte. */ |
/* Last known position of the requested byte. */ |
328 |
int req_char_ptr; |
int req_char_ptr; |
336 |
int first_line_end; |
int first_line_end; |
337 |
/* Points to the marked string. */ |
/* Points to the marked string. */ |
338 |
int mark_ptr; |
int mark_ptr; |
339 |
|
/* Recursive control verb management chain. */ |
340 |
|
int control_head_ptr; |
341 |
/* Points to the last matched capture block index. */ |
/* Points to the last matched capture block index. */ |
342 |
int capture_last_ptr; |
int capture_last_ptr; |
343 |
|
/* Points to the starting position of the current match. */ |
344 |
|
int start_ptr; |
345 |
|
|
346 |
/* Flipped and lower case tables. */ |
/* Flipped and lower case tables. */ |
347 |
const pcre_uint8 *fcc; |
const pcre_uint8 *fcc; |
348 |
sljit_sw lcc; |
sljit_sw lcc; |
349 |
/* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ |
/* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ |
350 |
int mode; |
int mode; |
351 |
|
/* \K is found in the pattern. */ |
352 |
|
BOOL has_set_som; |
353 |
|
/* (*SKIP:arg) is found in the pattern. */ |
354 |
|
BOOL has_skip_arg; |
355 |
|
/* (*THEN) is found in the pattern. */ |
356 |
|
BOOL has_then; |
357 |
|
/* Needs to know the start position anytime. */ |
358 |
|
BOOL needs_start_ptr; |
359 |
|
/* Currently in recurse or negative assert. */ |
360 |
|
BOOL local_exit; |
361 |
|
/* Currently in a positive assert. */ |
362 |
|
BOOL positive_assert; |
363 |
/* Newline control. */ |
/* Newline control. */ |
364 |
int nltype; |
int nltype; |
365 |
int newline; |
int newline; |
366 |
int bsr_nltype; |
int bsr_nltype; |
367 |
/* Dollar endonly. */ |
/* Dollar endonly. */ |
368 |
int endonly; |
int endonly; |
|
BOOL has_set_som; |
|
369 |
/* Tables. */ |
/* Tables. */ |
370 |
sljit_sw ctypes; |
sljit_sw ctypes; |
371 |
int digits[2 + MAX_RANGE_SIZE]; |
int digits[2 + MAX_RANGE_SIZE]; |
384 |
recurse_entry *currententry; |
recurse_entry *currententry; |
385 |
jump_list *partialmatch; |
jump_list *partialmatch; |
386 |
jump_list *quit; |
jump_list *quit; |
387 |
|
jump_list *positive_assert_quit; |
388 |
jump_list *forced_quit; |
jump_list *forced_quit; |
389 |
jump_list *accept; |
jump_list *accept; |
390 |
jump_list *calllimit; |
jump_list *calllimit; |
396 |
jump_list *vspace; |
jump_list *vspace; |
397 |
jump_list *casefulcmp; |
jump_list *casefulcmp; |
398 |
jump_list *caselesscmp; |
jump_list *caselesscmp; |
399 |
|
jump_list *reset_match; |
400 |
BOOL jscript_compat; |
BOOL jscript_compat; |
401 |
#ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
402 |
BOOL utf; |
BOOL utf; |
481 |
the start pointers when the end of the capturing group has not yet reached. */ |
the start pointers when the end of the capturing group has not yet reached. */ |
482 |
#define OVECTOR_START (common->ovector_start) |
#define OVECTOR_START (common->ovector_start) |
483 |
#define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_sw)) |
#define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_sw)) |
484 |
#define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_sw)) |
#define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * sizeof(sljit_sw)) |
485 |
#define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) |
#define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) |
486 |
|
|
487 |
#if defined COMPILE_PCRE8 |
#if defined COMPILE_PCRE8 |
534 |
|
|
535 |
/* Functions whose might need modification for all new supported opcodes: |
/* Functions whose might need modification for all new supported opcodes: |
536 |
next_opcode |
next_opcode |
537 |
get_private_data_length |
check_opcode_types |
538 |
set_private_data_ptrs |
set_private_data_ptrs |
539 |
get_framesize |
get_framesize |
540 |
init_frame |
init_frame |
541 |
get_private_data_length_for_copy |
get_private_data_copy_length |
542 |
copy_private_data |
copy_private_data |
543 |
compile_matchingpath |
compile_matchingpath |
544 |
compile_backtrackingpath |
compile_backtrackingpath |
620 |
case OP_BRAZERO: |
case OP_BRAZERO: |
621 |
case OP_BRAMINZERO: |
case OP_BRAMINZERO: |
622 |
case OP_BRAPOSZERO: |
case OP_BRAPOSZERO: |
623 |
|
case OP_PRUNE: |
624 |
|
case OP_SKIP: |
625 |
|
case OP_THEN: |
626 |
case OP_COMMIT: |
case OP_COMMIT: |
627 |
case OP_FAIL: |
case OP_FAIL: |
628 |
case OP_ACCEPT: |
case OP_ACCEPT: |
721 |
#endif |
#endif |
722 |
|
|
723 |
case OP_MARK: |
case OP_MARK: |
724 |
|
case OP_PRUNE_ARG: |
725 |
|
case OP_SKIP_ARG: |
726 |
|
case OP_THEN_ARG: |
727 |
return cc + 1 + 2 + cc[1]; |
return cc + 1 + 2 + cc[1]; |
728 |
|
|
729 |
default: |
default: |
730 |
|
/* All opcodes are supported now! */ |
731 |
|
SLJIT_ASSERT_STOP(); |
732 |
return NULL; |
return NULL; |
733 |
} |
} |
734 |
} |
} |
735 |
|
|
736 |
#define CASE_ITERATOR_PRIVATE_DATA_1 \ |
static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) |
|
case OP_MINSTAR: \ |
|
|
case OP_MINPLUS: \ |
|
|
case OP_QUERY: \ |
|
|
case OP_MINQUERY: \ |
|
|
case OP_MINSTARI: \ |
|
|
case OP_MINPLUSI: \ |
|
|
case OP_QUERYI: \ |
|
|
case OP_MINQUERYI: \ |
|
|
case OP_NOTMINSTAR: \ |
|
|
case OP_NOTMINPLUS: \ |
|
|
case OP_NOTQUERY: \ |
|
|
case OP_NOTMINQUERY: \ |
|
|
case OP_NOTMINSTARI: \ |
|
|
case OP_NOTMINPLUSI: \ |
|
|
case OP_NOTQUERYI: \ |
|
|
case OP_NOTMINQUERYI: |
|
|
|
|
|
#define CASE_ITERATOR_PRIVATE_DATA_2A \ |
|
|
case OP_STAR: \ |
|
|
case OP_PLUS: \ |
|
|
case OP_STARI: \ |
|
|
case OP_PLUSI: \ |
|
|
case OP_NOTSTAR: \ |
|
|
case OP_NOTPLUS: \ |
|
|
case OP_NOTSTARI: \ |
|
|
case OP_NOTPLUSI: |
|
|
|
|
|
#define CASE_ITERATOR_PRIVATE_DATA_2B \ |
|
|
case OP_UPTO: \ |
|
|
case OP_MINUPTO: \ |
|
|
case OP_UPTOI: \ |
|
|
case OP_MINUPTOI: \ |
|
|
case OP_NOTUPTO: \ |
|
|
case OP_NOTMINUPTO: \ |
|
|
case OP_NOTUPTOI: \ |
|
|
case OP_NOTMINUPTOI: |
|
|
|
|
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \ |
|
|
case OP_TYPEMINSTAR: \ |
|
|
case OP_TYPEMINPLUS: \ |
|
|
case OP_TYPEQUERY: \ |
|
|
case OP_TYPEMINQUERY: |
|
|
|
|
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \ |
|
|
case OP_TYPESTAR: \ |
|
|
case OP_TYPEPLUS: |
|
|
|
|
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \ |
|
|
case OP_TYPEUPTO: \ |
|
|
case OP_TYPEMINUPTO: |
|
|
|
|
|
static int get_class_iterator_size(pcre_uchar *cc) |
|
|
{ |
|
|
switch(*cc) |
|
|
{ |
|
|
case OP_CRSTAR: |
|
|
case OP_CRPLUS: |
|
|
return 2; |
|
|
|
|
|
case OP_CRMINSTAR: |
|
|
case OP_CRMINPLUS: |
|
|
case OP_CRQUERY: |
|
|
case OP_CRMINQUERY: |
|
|
return 1; |
|
|
|
|
|
case OP_CRRANGE: |
|
|
case OP_CRMINRANGE: |
|
|
if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE)) |
|
|
return 0; |
|
|
return 2; |
|
|
|
|
|
default: |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
static int get_private_data_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) |
|
737 |
{ |
{ |
|
int private_data_length = 0; |
|
|
pcre_uchar *alternative; |
|
738 |
pcre_uchar *name; |
pcre_uchar *name; |
739 |
pcre_uchar *end = NULL; |
pcre_uchar *name2; |
740 |
int space, size, i; |
unsigned int cbra_index; |
741 |
pcre_uint32 bracketlen; |
int i; |
742 |
|
|
743 |
/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ |
/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ |
744 |
while (cc < ccend) |
while (cc < ccend) |
745 |
{ |
{ |
|
space = 0; |
|
|
size = 0; |
|
|
bracketlen = 0; |
|
746 |
switch(*cc) |
switch(*cc) |
747 |
{ |
{ |
748 |
case OP_SET_SOM: |
case OP_SET_SOM: |
756 |
cc += 1 + IMM2_SIZE; |
cc += 1 + IMM2_SIZE; |
757 |
break; |
break; |
758 |
|
|
|
case OP_ASSERT: |
|
|
case OP_ASSERT_NOT: |
|
|
case OP_ASSERTBACK: |
|
|
case OP_ASSERTBACK_NOT: |
|
|
case OP_ONCE: |
|
|
case OP_ONCE_NC: |
|
|
case OP_BRAPOS: |
|
|
case OP_SBRA: |
|
|
case OP_SBRAPOS: |
|
|
private_data_length += sizeof(sljit_sw); |
|
|
bracketlen = 1 + LINK_SIZE; |
|
|
break; |
|
|
|
|
759 |
case OP_CBRAPOS: |
case OP_CBRAPOS: |
760 |
case OP_SCBRAPOS: |
case OP_SCBRAPOS: |
|
private_data_length += sizeof(sljit_sw); |
|
761 |
common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0; |
common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0; |
762 |
bracketlen = 1 + LINK_SIZE + IMM2_SIZE; |
cc += 1 + LINK_SIZE + IMM2_SIZE; |
763 |
break; |
break; |
764 |
|
|
765 |
case OP_COND: |
case OP_COND: |
767 |
/* Only AUTO_CALLOUT can insert this opcode. We do |
/* Only AUTO_CALLOUT can insert this opcode. We do |
768 |
not intend to support this case. */ |
not intend to support this case. */ |
769 |
if (cc[1 + LINK_SIZE] == OP_CALLOUT) |
if (cc[1 + LINK_SIZE] == OP_CALLOUT) |
770 |
return -1; |
return FALSE; |
771 |
|
cc += 1 + LINK_SIZE; |
|
if (*cc == OP_COND) |
|
|
{ |
|
|
/* Might be a hidden SCOND. */ |
|
|
alternative = cc + GET(cc, 1); |
|
|
if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) |
|
|
private_data_length += sizeof(sljit_sw); |
|
|
} |
|
|
else |
|
|
private_data_length += sizeof(sljit_sw); |
|
|
bracketlen = 1 + LINK_SIZE; |
|
772 |
break; |
break; |
773 |
|
|
774 |
case OP_CREF: |
case OP_CREF: |
778 |
break; |
break; |
779 |
|
|
780 |
case OP_NCREF: |
case OP_NCREF: |
781 |
bracketlen = GET2(cc, 1); |
cbra_index = GET2(cc, 1); |
782 |
name = (pcre_uchar *)common->name_table; |
name = (pcre_uchar *)common->name_table; |
783 |
alternative = name; |
name2 = name; |
784 |
for (i = 0; i < common->name_count; i++) |
for (i = 0; i < common->name_count; i++) |
785 |
{ |
{ |
786 |
if (GET2(name, 0) == bracketlen) break; |
if (GET2(name, 0) == cbra_index) break; |
787 |
name += common->name_entry_size; |
name += common->name_entry_size; |
788 |
} |
} |
789 |
SLJIT_ASSERT(i != common->name_count); |
SLJIT_ASSERT(i != common->name_count); |
790 |
|
|
791 |
for (i = 0; i < common->name_count; i++) |
for (i = 0; i < common->name_count; i++) |
792 |
{ |
{ |
793 |
if (STRCMP_UC_UC(alternative + IMM2_SIZE, name + IMM2_SIZE) == 0) |
if (STRCMP_UC_UC(name2 + IMM2_SIZE, name + IMM2_SIZE) == 0) |
794 |
common->optimized_cbracket[GET2(alternative, 0)] = 0; |
common->optimized_cbracket[GET2(name2, 0)] = 0; |
795 |
alternative += common->name_entry_size; |
name2 += common->name_entry_size; |
796 |
} |
} |
|
bracketlen = 0; |
|
797 |
cc += 1 + IMM2_SIZE; |
cc += 1 + IMM2_SIZE; |
798 |
break; |
break; |
799 |
|
|
|
case OP_BRA: |
|
|
bracketlen = 1 + LINK_SIZE; |
|
|
break; |
|
|
|
|
|
case OP_CBRA: |
|
|
case OP_SCBRA: |
|
|
bracketlen = 1 + LINK_SIZE + IMM2_SIZE; |
|
|
break; |
|
|
|
|
|
CASE_ITERATOR_PRIVATE_DATA_1 |
|
|
space = 1; |
|
|
size = -2; |
|
|
break; |
|
|
|
|
|
CASE_ITERATOR_PRIVATE_DATA_2A |
|
|
space = 2; |
|
|
size = -2; |
|
|
break; |
|
|
|
|
|
CASE_ITERATOR_PRIVATE_DATA_2B |
|
|
space = 2; |
|
|
size = -(2 + IMM2_SIZE); |
|
|
break; |
|
|
|
|
|
CASE_ITERATOR_TYPE_PRIVATE_DATA_1 |
|
|
space = 1; |
|
|
size = 1; |
|
|
break; |
|
|
|
|
|
CASE_ITERATOR_TYPE_PRIVATE_DATA_2A |
|
|
if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI) |
|
|
space = 2; |
|
|
size = 1; |
|
|
break; |
|
|
|
|
|
CASE_ITERATOR_TYPE_PRIVATE_DATA_2B |
|
|
if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) |
|
|
space = 2; |
|
|
size = 1 + IMM2_SIZE; |
|
|
break; |
|
|
|
|
|
case OP_CLASS: |
|
|
case OP_NCLASS: |
|
|
size += 1 + 32 / sizeof(pcre_uchar); |
|
|
space = get_class_iterator_size(cc + size); |
|
|
break; |
|
|
|
|
|
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
|
|
case OP_XCLASS: |
|
|
size = GET(cc, 1); |
|
|
space = get_class_iterator_size(cc + size); |
|
|
break; |
|
|
#endif |
|
|
|
|
800 |
case OP_RECURSE: |
case OP_RECURSE: |
801 |
/* Set its value only once. */ |
/* Set its value only once. */ |
802 |
if (common->recursive_head_ptr == 0) |
if (common->recursive_head_ptr == 0) |
816 |
cc += 2 + 2 * LINK_SIZE; |
cc += 2 + 2 * LINK_SIZE; |
817 |
break; |
break; |
818 |
|
|
819 |
|
case OP_THEN_ARG: |
820 |
|
common->has_then = TRUE; |
821 |
|
common->control_head_ptr = 1; |
822 |
|
/* Fall through. */ |
823 |
|
|
824 |
|
case OP_PRUNE_ARG: |
825 |
|
common->needs_start_ptr = TRUE; |
826 |
|
/* Fall through. */ |
827 |
|
|
828 |
case OP_MARK: |
case OP_MARK: |
829 |
if (common->mark_ptr == 0) |
if (common->mark_ptr == 0) |
830 |
{ |
{ |
834 |
cc += 1 + 2 + cc[1]; |
cc += 1 + 2 + cc[1]; |
835 |
break; |
break; |
836 |
|
|
837 |
|
case OP_THEN: |
838 |
|
common->has_then = TRUE; |
839 |
|
common->control_head_ptr = 1; |
840 |
|
/* Fall through. */ |
841 |
|
|
842 |
|
case OP_PRUNE: |
843 |
|
case OP_SKIP: |
844 |
|
common->needs_start_ptr = TRUE; |
845 |
|
cc += 1; |
846 |
|
break; |
847 |
|
|
848 |
|
case OP_SKIP_ARG: |
849 |
|
common->control_head_ptr = 1; |
850 |
|
common->has_skip_arg = TRUE; |
851 |
|
cc += 1 + 2 + cc[1]; |
852 |
|
break; |
853 |
|
|
854 |
default: |
default: |
855 |
cc = next_opcode(common, cc); |
cc = next_opcode(common, cc); |
856 |
if (cc == NULL) |
if (cc == NULL) |
857 |
return -1; |
return FALSE; |
858 |
break; |
break; |
859 |
} |
} |
860 |
|
} |
861 |
|
return TRUE; |
862 |
|
} |
863 |
|
|
864 |
if (space > 0 && cc >= end) |
static int get_class_iterator_size(pcre_uchar *cc) |
865 |
private_data_length += sizeof(sljit_sw) * space; |
{ |
866 |
|
switch(*cc) |
867 |
|
{ |
868 |
|
case OP_CRSTAR: |
869 |
|
case OP_CRPLUS: |
870 |
|
return 2; |
871 |
|
|
872 |
if (size != 0) |
case OP_CRMINSTAR: |
873 |
|
case OP_CRMINPLUS: |
874 |
|
case OP_CRQUERY: |
875 |
|
case OP_CRMINQUERY: |
876 |
|
return 1; |
877 |
|
|
878 |
|
case OP_CRRANGE: |
879 |
|
case OP_CRMINRANGE: |
880 |
|
if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE)) |
881 |
|
return 0; |
882 |
|
return 2; |
883 |
|
|
884 |
|
default: |
885 |
|
return 0; |
886 |
|
} |
887 |
|
} |
888 |
|
|
889 |
|
static BOOL detect_repeat(compiler_common *common, pcre_uchar *begin) |
890 |
|
{ |
891 |
|
pcre_uchar *end = bracketend(begin); |
892 |
|
pcre_uchar *next; |
893 |
|
pcre_uchar *next_end; |
894 |
|
pcre_uchar *max_end; |
895 |
|
pcre_uchar type; |
896 |
|
sljit_sw length = end - begin; |
897 |
|
int min, max, i; |
898 |
|
|
899 |
|
/* Detect fixed iterations first. */ |
900 |
|
if (end[-(1 + LINK_SIZE)] != OP_KET) |
901 |
|
return FALSE; |
902 |
|
|
903 |
|
/* Already detected repeat. */ |
904 |
|
if (common->private_data_ptrs[end - common->start - LINK_SIZE] != 0) |
905 |
|
return TRUE; |
906 |
|
|
907 |
|
next = end; |
908 |
|
min = 1; |
909 |
|
while (1) |
910 |
|
{ |
911 |
|
if (*next != *begin) |
912 |
|
break; |
913 |
|
next_end = bracketend(next); |
914 |
|
if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0) |
915 |
|
break; |
916 |
|
next = next_end; |
917 |
|
min++; |
918 |
|
} |
919 |
|
|
920 |
|
if (min == 2) |
921 |
|
return FALSE; |
922 |
|
|
923 |
|
max = 0; |
924 |
|
max_end = next; |
925 |
|
if (*next == OP_BRAZERO || *next == OP_BRAMINZERO) |
926 |
|
{ |
927 |
|
type = *next; |
928 |
|
while (1) |
929 |
{ |
{ |
930 |
if (size < 0) |
if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin) |
931 |
{ |
break; |
932 |
cc += -size; |
next_end = bracketend(next + 2 + LINK_SIZE); |
933 |
#ifdef SUPPORT_UTF |
if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0) |
934 |
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); |
break; |
935 |
#endif |
next = next_end; |
936 |
} |
max++; |
|
else |
|
|
cc += size; |
|
937 |
} |
} |
938 |
|
|
939 |
if (bracketlen != 0) |
if (next[0] == type && next[1] == *begin && max >= 1) |
940 |
{ |
{ |
941 |
if (cc >= end) |
next_end = bracketend(next + 1); |
942 |
|
if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0) |
943 |
{ |
{ |
944 |
end = bracketend(cc); |
for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE) |
945 |
if (end[-1 - LINK_SIZE] == OP_KET) |
if (*next_end != OP_KET) |
946 |
end = NULL; |
break; |
947 |
|
|
948 |
|
if (i == max) |
949 |
|
{ |
950 |
|
common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end; |
951 |
|
common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO; |
952 |
|
/* +2 the original and the last. */ |
953 |
|
common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2; |
954 |
|
if (min == 1) |
955 |
|
return TRUE; |
956 |
|
min--; |
957 |
|
max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE); |
958 |
|
} |
959 |
} |
} |
|
cc += bracketlen; |
|
960 |
} |
} |
961 |
} |
} |
962 |
return private_data_length; |
|
963 |
|
if (min >= 3) |
964 |
|
{ |
965 |
|
common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end; |
966 |
|
common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT; |
967 |
|
common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min; |
968 |
|
return TRUE; |
969 |
|
} |
970 |
|
|
971 |
|
return FALSE; |
972 |
} |
} |
973 |
|
|
974 |
static void set_private_data_ptrs(compiler_common *common, int private_data_ptr, pcre_uchar *ccend) |
#define CASE_ITERATOR_PRIVATE_DATA_1 \ |
975 |
|
case OP_MINSTAR: \ |
976 |
|
case OP_MINPLUS: \ |
977 |
|
case OP_QUERY: \ |
978 |
|
case OP_MINQUERY: \ |
979 |
|
case OP_MINSTARI: \ |
980 |
|
case OP_MINPLUSI: \ |
981 |
|
case OP_QUERYI: \ |
982 |
|
case OP_MINQUERYI: \ |
983 |
|
case OP_NOTMINSTAR: \ |
984 |
|
case OP_NOTMINPLUS: \ |
985 |
|
case OP_NOTQUERY: \ |
986 |
|
case OP_NOTMINQUERY: \ |
987 |
|
case OP_NOTMINSTARI: \ |
988 |
|
case OP_NOTMINPLUSI: \ |
989 |
|
case OP_NOTQUERYI: \ |
990 |
|
case OP_NOTMINQUERYI: |
991 |
|
|
992 |
|
#define CASE_ITERATOR_PRIVATE_DATA_2A \ |
993 |
|
case OP_STAR: \ |
994 |
|
case OP_PLUS: \ |
995 |
|
case OP_STARI: \ |
996 |
|
case OP_PLUSI: \ |
997 |
|
case OP_NOTSTAR: \ |
998 |
|
case OP_NOTPLUS: \ |
999 |
|
case OP_NOTSTARI: \ |
1000 |
|
case OP_NOTPLUSI: |
1001 |
|
|
1002 |
|
#define CASE_ITERATOR_PRIVATE_DATA_2B \ |
1003 |
|
case OP_UPTO: \ |
1004 |
|
case OP_MINUPTO: \ |
1005 |
|
case OP_UPTOI: \ |
1006 |
|
case OP_MINUPTOI: \ |
1007 |
|
case OP_NOTUPTO: \ |
1008 |
|
case OP_NOTMINUPTO: \ |
1009 |
|
case OP_NOTUPTOI: \ |
1010 |
|
case OP_NOTMINUPTOI: |
1011 |
|
|
1012 |
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \ |
1013 |
|
case OP_TYPEMINSTAR: \ |
1014 |
|
case OP_TYPEMINPLUS: \ |
1015 |
|
case OP_TYPEQUERY: \ |
1016 |
|
case OP_TYPEMINQUERY: |
1017 |
|
|
1018 |
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \ |
1019 |
|
case OP_TYPESTAR: \ |
1020 |
|
case OP_TYPEPLUS: |
1021 |
|
|
1022 |
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \ |
1023 |
|
case OP_TYPEUPTO: \ |
1024 |
|
case OP_TYPEMINUPTO: |
1025 |
|
|
1026 |
|
static void set_private_data_ptrs(compiler_common *common, int *private_data_start, pcre_uchar *ccend) |
1027 |
{ |
{ |
1028 |
pcre_uchar *cc = common->start; |
pcre_uchar *cc = common->start; |
1029 |
pcre_uchar *alternative; |
pcre_uchar *alternative; |
1030 |
pcre_uchar *end = NULL; |
pcre_uchar *end = NULL; |
1031 |
|
int private_data_ptr = *private_data_start; |
1032 |
int space, size, bracketlen; |
int space, size, bracketlen; |
1033 |
|
|
1034 |
while (cc < ccend) |
while (cc < ccend) |
1036 |
space = 0; |
space = 0; |
1037 |
size = 0; |
size = 0; |
1038 |
bracketlen = 0; |
bracketlen = 0; |
1039 |
|
if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) |
1040 |
|
return; |
1041 |
|
|
1042 |
|
if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND) |
1043 |
|
if (detect_repeat(common, cc)) |
1044 |
|
{ |
1045 |
|
/* These brackets are converted to repeats, so no global |
1046 |
|
based single character repeat is allowed. */ |
1047 |
|
if (cc >= end) |
1048 |
|
end = bracketend(cc); |
1049 |
|
} |
1050 |
|
|
1051 |
switch(*cc) |
switch(*cc) |
1052 |
{ |
{ |
1053 |
|
case OP_KET: |
1054 |
|
if (common->private_data_ptrs[cc + 1 - common->start] != 0) |
1055 |
|
{ |
1056 |
|
common->private_data_ptrs[cc - common->start] = private_data_ptr; |
1057 |
|
private_data_ptr += sizeof(sljit_sw); |
1058 |
|
cc += common->private_data_ptrs[cc + 1 - common->start]; |
1059 |
|
} |
1060 |
|
cc += 1 + LINK_SIZE; |
1061 |
|
break; |
1062 |
|
|
1063 |
case OP_ASSERT: |
case OP_ASSERT: |
1064 |
case OP_ASSERT_NOT: |
case OP_ASSERT_NOT: |
1065 |
case OP_ASSERTBACK: |
case OP_ASSERTBACK: |
1153 |
break; |
break; |
1154 |
} |
} |
1155 |
|
|
1156 |
|
/* Character iterators, which are not inside a repeated bracket, |
1157 |
|
gets a private slot instead of allocating it on the stack. */ |
1158 |
if (space > 0 && cc >= end) |
if (space > 0 && cc >= end) |
1159 |
{ |
{ |
1160 |
common->private_data_ptrs[cc - common->start] = private_data_ptr; |
common->private_data_ptrs[cc - common->start] = private_data_ptr; |
1185 |
cc += bracketlen; |
cc += bracketlen; |
1186 |
} |
} |
1187 |
} |
} |
1188 |
|
*private_data_start = private_data_ptr; |
1189 |
} |
} |
1190 |
|
|
1191 |
/* Returns with a frame_types (always < 0) if no need for frame. */ |
/* Returns with a frame_types (always < 0) if no need for frame. */ |
1192 |
static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive) |
static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL* needs_control_head) |
1193 |
{ |
{ |
|
pcre_uchar *ccend = bracketend(cc) - (1 + LINK_SIZE); |
|
1194 |
int length = 0; |
int length = 0; |
1195 |
int possessive = 0; |
int possessive = 0; |
1196 |
BOOL stack_restore = FALSE; |
BOOL stack_restore = FALSE; |
1199 |
/* The last capture is a local variable even for recursions. */ |
/* The last capture is a local variable even for recursions. */ |
1200 |
BOOL capture_last_found = FALSE; |
BOOL capture_last_found = FALSE; |
1201 |
|
|
1202 |
if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) |
#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD |
1203 |
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
1204 |
|
*needs_control_head = TRUE; |
1205 |
|
#else |
1206 |
|
*needs_control_head = FALSE; |
1207 |
|
#endif |
1208 |
|
|
1209 |
|
if (ccend == NULL) |
1210 |
{ |
{ |
1211 |
possessive = length = (common->capture_last_ptr != 0) ? 5 : 3; |
ccend = bracketend(cc) - (1 + LINK_SIZE); |
1212 |
/* This is correct regardless of common->capture_last_ptr. */ |
if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) |
1213 |
capture_last_found = TRUE; |
{ |
1214 |
|
possessive = length = (common->capture_last_ptr != 0) ? 5 : 3; |
1215 |
|
/* This is correct regardless of common->capture_last_ptr. */ |
1216 |
|
capture_last_found = TRUE; |
1217 |
|
} |
1218 |
|
cc = next_opcode(common, cc); |
1219 |
} |
} |
1220 |
|
|
|
cc = next_opcode(common, cc); |
|
1221 |
SLJIT_ASSERT(cc != NULL); |
SLJIT_ASSERT(cc != NULL); |
1222 |
while (cc < ccend) |
while (cc < ccend) |
1223 |
switch(*cc) |
switch(*cc) |
1234 |
break; |
break; |
1235 |
|
|
1236 |
case OP_MARK: |
case OP_MARK: |
1237 |
|
case OP_PRUNE_ARG: |
1238 |
|
case OP_THEN_ARG: |
1239 |
SLJIT_ASSERT(common->mark_ptr != 0); |
SLJIT_ASSERT(common->mark_ptr != 0); |
1240 |
stack_restore = TRUE; |
stack_restore = TRUE; |
1241 |
if (!setmark_found) |
if (!setmark_found) |
1243 |
length += 2; |
length += 2; |
1244 |
setmark_found = TRUE; |
setmark_found = TRUE; |
1245 |
} |
} |
1246 |
|
if (common->control_head_ptr != 0) |
1247 |
|
*needs_control_head = TRUE; |
1248 |
cc += 1 + 2 + cc[1]; |
cc += 1 + 2 + cc[1]; |
1249 |
break; |
break; |
1250 |
|
|
1364 |
return stack_restore ? no_frame : no_stack; |
return stack_restore ? no_frame : no_stack; |
1365 |
} |
} |
1366 |
|
|
1367 |
static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive) |
static void init_frame(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, int stackpos, int stacktop, BOOL recursive) |
1368 |
{ |
{ |
1369 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
|
pcre_uchar *ccend = bracketend(cc) - (1 + LINK_SIZE); |
|
1370 |
BOOL setsom_found = recursive; |
BOOL setsom_found = recursive; |
1371 |
BOOL setmark_found = recursive; |
BOOL setmark_found = recursive; |
1372 |
/* The last capture is a local variable even for recursions. */ |
/* The last capture is a local variable even for recursions. */ |
1378 |
SLJIT_ASSERT(stackpos >= stacktop + 2); |
SLJIT_ASSERT(stackpos >= stacktop + 2); |
1379 |
|
|
1380 |
stackpos = STACK(stackpos); |
stackpos = STACK(stackpos); |
1381 |
if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) |
if (ccend == NULL) |
1382 |
cc = next_opcode(common, cc); |
{ |
1383 |
|
ccend = bracketend(cc) - (1 + LINK_SIZE); |
1384 |
|
if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) |
1385 |
|
cc = next_opcode(common, cc); |
1386 |
|
} |
1387 |
|
|
1388 |
SLJIT_ASSERT(cc != NULL); |
SLJIT_ASSERT(cc != NULL); |
1389 |
while (cc < ccend) |
while (cc < ccend) |
1390 |
switch(*cc) |
switch(*cc) |
1404 |
break; |
break; |
1405 |
|
|
1406 |
case OP_MARK: |
case OP_MARK: |
1407 |
|
case OP_PRUNE_ARG: |
1408 |
|
case OP_THEN_ARG: |
1409 |
SLJIT_ASSERT(common->mark_ptr != 0); |
SLJIT_ASSERT(common->mark_ptr != 0); |
1410 |
if (!setmark_found) |
if (!setmark_found) |
1411 |
{ |
{ |
1486 |
SLJIT_ASSERT(stackpos == STACK(stacktop)); |
SLJIT_ASSERT(stackpos == STACK(stacktop)); |
1487 |
} |
} |
1488 |
|
|
1489 |
static SLJIT_INLINE int get_private_data_length_for_copy(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) |
static SLJIT_INLINE int get_private_data_copy_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL needs_control_head) |
1490 |
{ |
{ |
1491 |
int private_data_length = 2; |
int private_data_length = needs_control_head ? 3 : 2; |
1492 |
int size; |
int size; |
1493 |
pcre_uchar *alternative; |
pcre_uchar *alternative; |
1494 |
/* Calculate the sum of the private machine words. */ |
/* Calculate the sum of the private machine words. */ |
1497 |
size = 0; |
size = 0; |
1498 |
switch(*cc) |
switch(*cc) |
1499 |
{ |
{ |
1500 |
|
case OP_KET: |
1501 |
|
if (PRIVATE_DATA(cc) != 0) |
1502 |
|
private_data_length++; |
1503 |
|
cc += 1 + LINK_SIZE; |
1504 |
|
break; |
1505 |
|
|
1506 |
case OP_ASSERT: |
case OP_ASSERT: |
1507 |
case OP_ASSERT_NOT: |
case OP_ASSERT_NOT: |
1508 |
case OP_ASSERTBACK: |
case OP_ASSERTBACK: |
1607 |
} |
} |
1608 |
|
|
1609 |
static void copy_private_data(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, |
static void copy_private_data(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, |
1610 |
BOOL save, int stackptr, int stacktop) |
BOOL save, int stackptr, int stacktop, BOOL needs_control_head) |
1611 |
{ |
{ |
1612 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
1613 |
int srcw[2]; |
int srcw[2]; |
1628 |
|
|
1629 |
if (!save) |
if (!save) |
1630 |
{ |
{ |
1631 |
stackptr += sizeof(sljit_sw); |
stackptr += (needs_control_head ? 2 : 1) * sizeof(sljit_sw); |
1632 |
if (stackptr < stacktop) |
if (stackptr < stacktop) |
1633 |
{ |
{ |
1634 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); |
1644 |
/* The tmp1next must be TRUE in either way. */ |
/* The tmp1next must be TRUE in either way. */ |
1645 |
} |
} |
1646 |
|
|
1647 |
while (status != end) |
do |
1648 |
{ |
{ |
1649 |
count = 0; |
count = 0; |
1650 |
switch(status) |
switch(status) |
1653 |
SLJIT_ASSERT(save && common->recursive_head_ptr != 0); |
SLJIT_ASSERT(save && common->recursive_head_ptr != 0); |
1654 |
count = 1; |
count = 1; |
1655 |
srcw[0] = common->recursive_head_ptr; |
srcw[0] = common->recursive_head_ptr; |
1656 |
|
if (needs_control_head) |
1657 |
|
{ |
1658 |
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
1659 |
|
count = 2; |
1660 |
|
srcw[1] = common->control_head_ptr; |
1661 |
|
} |
1662 |
status = loop; |
status = loop; |
1663 |
break; |
break; |
1664 |
|
|
1671 |
|
|
1672 |
switch(*cc) |
switch(*cc) |
1673 |
{ |
{ |
1674 |
|
case OP_KET: |
1675 |
|
if (PRIVATE_DATA(cc) != 0) |
1676 |
|
{ |
1677 |
|
count = 1; |
1678 |
|
srcw[0] = PRIVATE_DATA(cc); |
1679 |
|
} |
1680 |
|
cc += 1 + LINK_SIZE; |
1681 |
|
break; |
1682 |
|
|
1683 |
case OP_ASSERT: |
case OP_ASSERT: |
1684 |
case OP_ASSERT_NOT: |
case OP_ASSERT_NOT: |
1685 |
case OP_ASSERTBACK: |
case OP_ASSERTBACK: |
1892 |
} |
} |
1893 |
} |
} |
1894 |
} |
} |
1895 |
|
while (status != end); |
1896 |
|
|
1897 |
if (save) |
if (save) |
1898 |
{ |
{ |
1926 |
SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); |
SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); |
1927 |
} |
} |
1928 |
|
|
1929 |
|
static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, pcre_uint8 *current_offset) |
1930 |
|
{ |
1931 |
|
pcre_uchar *end = bracketend(cc); |
1932 |
|
BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT; |
1933 |
|
|
1934 |
|
/* Assert captures then. */ |
1935 |
|
if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) |
1936 |
|
current_offset = NULL; |
1937 |
|
/* Conditional block does not. */ |
1938 |
|
if (*cc == OP_COND || *cc == OP_SCOND) |
1939 |
|
has_alternatives = FALSE; |
1940 |
|
|
1941 |
|
cc = next_opcode(common, cc); |
1942 |
|
if (has_alternatives) |
1943 |
|
current_offset = common->then_offsets + (cc - common->start); |
1944 |
|
|
1945 |
|
while (cc < end) |
1946 |
|
{ |
1947 |
|
if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)) |
1948 |
|
cc = set_then_offsets(common, cc, current_offset); |
1949 |
|
else |
1950 |
|
{ |
1951 |
|
if (*cc == OP_ALT && has_alternatives) |
1952 |
|
current_offset = common->then_offsets + (cc + 1 + LINK_SIZE - common->start); |
1953 |
|
if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL) |
1954 |
|
*current_offset = 1; |
1955 |
|
cc = next_opcode(common, cc); |
1956 |
|
} |
1957 |
|
} |
1958 |
|
|
1959 |
|
return end; |
1960 |
|
} |
1961 |
|
|
1962 |
#undef CASE_ITERATOR_PRIVATE_DATA_1 |
#undef CASE_ITERATOR_PRIVATE_DATA_1 |
1963 |
#undef CASE_ITERATOR_PRIVATE_DATA_2A |
#undef CASE_ITERATOR_PRIVATE_DATA_2A |
1964 |
#undef CASE_ITERATOR_PRIVATE_DATA_2B |
#undef CASE_ITERATOR_PRIVATE_DATA_2B |
2052 |
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); |
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); |
2053 |
} |
} |
2054 |
|
|
2055 |
static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) |
static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) |
2056 |
|
{ |
2057 |
|
DEFINE_COMPILER; |
2058 |
|
struct sljit_label *loop; |
2059 |
|
int i; |
2060 |
|
|
2061 |
|
/* At this point we can freely use all temporary registers. */ |
2062 |
|
SLJIT_ASSERT(length > 1); |
2063 |
|
/* TMP1 returns with begin - 1. */ |
2064 |
|
OP2(SLJIT_SUB, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); |
2065 |
|
if (length < 8) |
2066 |
|
{ |
2067 |
|
for (i = 1; i < length; i++) |
2068 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_SCRATCH_REG1, 0); |
2069 |
|
} |
2070 |
|
else |
2071 |
|
{ |
2072 |
|
GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, OVECTOR_START); |
2073 |
|
OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, length - 1); |
2074 |
|
loop = LABEL(); |
2075 |
|
OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(sljit_sw), SLJIT_SCRATCH_REG1, 0); |
2076 |
|
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 1); |
2077 |
|
JUMPTO(SLJIT_C_NOT_ZERO, loop); |
2078 |
|
} |
2079 |
|
} |
2080 |
|
|
2081 |
|
static SLJIT_INLINE void do_reset_match(compiler_common *common, int length) |
2082 |
{ |
{ |
2083 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
2084 |
struct sljit_label *loop; |
struct sljit_label *loop; |
2085 |
int i; |
int i; |
2086 |
/* At this point we can freely use all temporary registers. */ |
|
2087 |
/* TMP1 returns with begin - 1. */ |
SLJIT_ASSERT(length > 1); |
2088 |
OP2(SLJIT_SUB, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); |
/* OVECTOR(1) contains the "string begin - 1" constant. */ |
2089 |
|
if (length > 2) |
2090 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
2091 |
if (length < 8) |
if (length < 8) |
2092 |
{ |
{ |
2093 |
for (i = 0; i < length; i++) |
for (i = 2; i < length; i++) |
2094 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_SCRATCH_REG1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), TMP1, 0); |
2095 |
} |
} |
2096 |
else |
else |
2097 |
{ |
{ |
2098 |
GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, OVECTOR_START - sizeof(sljit_sw)); |
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw)); |
2099 |
OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, length); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); |
2100 |
loop = LABEL(); |
loop = LABEL(); |
2101 |
OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(sljit_sw), SLJIT_SCRATCH_REG1, 0); |
OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); |
2102 |
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 1); |
OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); |
2103 |
JUMPTO(SLJIT_C_NOT_ZERO, loop); |
JUMPTO(SLJIT_C_NOT_ZERO, loop); |
2104 |
} |
} |
2105 |
|
|
2106 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); |
2107 |
|
if (common->mark_ptr != 0) |
2108 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); |
2109 |
|
if (common->control_head_ptr != 0) |
2110 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
2111 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); |
2112 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); |
2113 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); |
2114 |
|
} |
2115 |
|
|
2116 |
|
static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg) |
2117 |
|
{ |
2118 |
|
while (current != NULL) |
2119 |
|
{ |
2120 |
|
switch (current[-2]) |
2121 |
|
{ |
2122 |
|
case type_then_trap: |
2123 |
|
break; |
2124 |
|
|
2125 |
|
case type_mark: |
2126 |
|
if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0) |
2127 |
|
return current[-4]; |
2128 |
|
break; |
2129 |
|
|
2130 |
|
default: |
2131 |
|
SLJIT_ASSERT_STOP(); |
2132 |
|
break; |
2133 |
|
} |
2134 |
|
current = (sljit_sw*)current[-1]; |
2135 |
|
} |
2136 |
|
return -1; |
2137 |
} |
} |
2138 |
|
|
2139 |
static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) |
static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) |
2192 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
2193 |
|
|
2194 |
SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); |
SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); |
2195 |
SLJIT_ASSERT(common->start_used_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); |
SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0 |
2196 |
|
&& (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); |
2197 |
|
|
2198 |
OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0); |
2199 |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); |
2205 |
OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); |
OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); |
2206 |
|
|
2207 |
jump = CMP(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 3); |
jump = CMP(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 3); |
2208 |
OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), (common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start) + sizeof(sljit_sw), SLJIT_SAVED_REG1, 0); |
OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_SAVED_REG1, 0); |
2209 |
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2210 |
OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); |
OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); |
2211 |
#endif |
#endif |
2388 |
jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); |
jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); |
2389 |
|
|
2390 |
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2391 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
2392 |
else |
else |
2393 |
{ |
{ |
2394 |
if (common->partialmatchlabel != NULL) |
if (common->partialmatchlabel != NULL) |
2401 |
JUMPHERE(jump); |
JUMPHERE(jump); |
2402 |
} |
} |
2403 |
|
|
2404 |
static struct sljit_jump *check_str_end(compiler_common *common) |
static void check_str_end(compiler_common *common, jump_list **end_reached) |
2405 |
{ |
{ |
2406 |
/* Does not affect registers. Usually used in a tight spot. */ |
/* Does not affect registers. Usually used in a tight spot. */ |
2407 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
2408 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
|
struct sljit_jump *nohit; |
|
|
struct sljit_jump *return_value; |
|
2409 |
|
|
2410 |
if (common->mode == JIT_COMPILE) |
if (common->mode == JIT_COMPILE) |
2411 |
return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
{ |
2412 |
|
add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
2413 |
|
return; |
2414 |
|
} |
2415 |
|
|
2416 |
jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); |
jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); |
2417 |
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2418 |
{ |
{ |
2419 |
nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); |
add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); |
2420 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
2421 |
JUMPHERE(nohit); |
add_jump(compiler, end_reached, JUMP(SLJIT_JUMP)); |
|
return_value = JUMP(SLJIT_JUMP); |
|
2422 |
} |
} |
2423 |
else |
else |
2424 |
{ |
{ |
2425 |
return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); |
add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); |
2426 |
if (common->partialmatchlabel != NULL) |
if (common->partialmatchlabel != NULL) |
2427 |
JUMPTO(SLJIT_JUMP, common->partialmatchlabel); |
JUMPTO(SLJIT_JUMP, common->partialmatchlabel); |
2428 |
else |
else |
2429 |
add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); |
add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); |
2430 |
} |
} |
2431 |
JUMPHERE(jump); |
JUMPHERE(jump); |
|
return return_value; |
|
2432 |
} |
} |
2433 |
|
|
2434 |
static void detect_partial_match(compiler_common *common, jump_list **backtracks) |
static void detect_partial_match(compiler_common *common, jump_list **backtracks) |
2447 |
add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); |
add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); |
2448 |
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2449 |
{ |
{ |
2450 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
2451 |
add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
2452 |
} |
} |
2453 |
else |
else |
3395 |
{ |
{ |
3396 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
3397 |
struct sljit_jump *skipread; |
struct sljit_jump *skipread; |
3398 |
|
jump_list *skipread_list = NULL; |
3399 |
#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF |
#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF |
3400 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
3401 |
#endif |
#endif |
3453 |
JUMPHERE(skipread); |
JUMPHERE(skipread); |
3454 |
|
|
3455 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
3456 |
skipread = check_str_end(common); |
check_str_end(common, &skipread_list); |
3457 |
peek_char(common); |
peek_char(common); |
3458 |
|
|
3459 |
/* Testing char type. This is a code duplication. */ |
/* Testing char type. This is a code duplication. */ |
3494 |
JUMPHERE(jump); |
JUMPHERE(jump); |
3495 |
#endif /* COMPILE_PCRE8 */ |
#endif /* COMPILE_PCRE8 */ |
3496 |
} |
} |
3497 |
JUMPHERE(skipread); |
set_jumps(skipread_list, LABEL()); |
3498 |
|
|
3499 |
OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
3500 |
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
4134 |
break; |
break; |
4135 |
|
|
4136 |
case PT_CLIST: |
case PT_CLIST: |
4137 |
|
case PT_UCNC: |
4138 |
needschar = TRUE; |
needschar = TRUE; |
4139 |
break; |
break; |
4140 |
|
|
4400 |
} |
} |
4401 |
jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
4402 |
break; |
break; |
4403 |
|
|
4404 |
|
case PT_UCNC: |
4405 |
|
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_DOLLAR_SIGN - charoffset); |
4406 |
|
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
4407 |
|
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_COMMERCIAL_AT - charoffset); |
4408 |
|
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
4409 |
|
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_GRAVE_ACCENT - charoffset); |
4410 |
|
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
4411 |
|
|
4412 |
|
SET_CHAR_OFFSET(0xa0); |
4413 |
|
OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd7ff - charoffset); |
4414 |
|
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); |
4415 |
|
SET_CHAR_OFFSET(0); |
4416 |
|
OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0); |
4417 |
|
OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_GREATER_EQUAL); |
4418 |
|
jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
4419 |
|
break; |
4420 |
} |
} |
4421 |
cc += 2; |
cc += 2; |
4422 |
} |
} |
4442 |
unsigned int c, oc, bit; |
unsigned int c, oc, bit; |
4443 |
compare_context context; |
compare_context context; |
4444 |
struct sljit_jump *jump[4]; |
struct sljit_jump *jump[4]; |
4445 |
|
jump_list *end_list; |
4446 |
#ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
4447 |
struct sljit_label *label; |
struct sljit_label *label; |
4448 |
#ifdef SUPPORT_UCP |
#ifdef SUPPORT_UCP |
4511 |
if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
4512 |
{ |
{ |
4513 |
jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); |
jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); |
4514 |
|
end_list = NULL; |
4515 |
if (common->mode != JIT_PARTIAL_HARD_COMPILE) |
if (common->mode != JIT_PARTIAL_HARD_COMPILE) |
4516 |
jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
add_jump(compiler, &end_list, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
4517 |
else |
else |
4518 |
jump[1] = check_str_end(common); |
check_str_end(common, &end_list); |
4519 |
|
|
4520 |
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
4521 |
add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); |
add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); |
4522 |
if (jump[1] != NULL) |
set_jumps(end_list, LABEL()); |
|
JUMPHERE(jump[1]); |
|
4523 |
JUMPHERE(jump[0]); |
JUMPHERE(jump[0]); |
4524 |
} |
} |
4525 |
else |
else |
4578 |
read_char(common); |
read_char(common); |
4579 |
jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); |
jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); |
4580 |
/* We don't need to handle soft partial matching case. */ |
/* We don't need to handle soft partial matching case. */ |
4581 |
|
end_list = NULL; |
4582 |
if (common->mode != JIT_PARTIAL_HARD_COMPILE) |
if (common->mode != JIT_PARTIAL_HARD_COMPILE) |
4583 |
jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
add_jump(compiler, &end_list, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
4584 |
else |
else |
4585 |
jump[1] = check_str_end(common); |
check_str_end(common, &end_list); |
4586 |
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
4587 |
jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); |
jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); |
4588 |
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
4589 |
jump[3] = JUMP(SLJIT_JUMP); |
jump[2] = JUMP(SLJIT_JUMP); |
4590 |
JUMPHERE(jump[0]); |
JUMPHERE(jump[0]); |
4591 |
check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); |
check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); |
4592 |
|
set_jumps(end_list, LABEL()); |
4593 |
JUMPHERE(jump[1]); |
JUMPHERE(jump[1]); |
4594 |
JUMPHERE(jump[2]); |
JUMPHERE(jump[2]); |
|
JUMPHERE(jump[3]); |
|
4595 |
return cc; |
return cc; |
4596 |
|
|
4597 |
case OP_NOT_HSPACE: |
case OP_NOT_HSPACE: |
5341 |
backtrack_common *backtrack; |
backtrack_common *backtrack; |
5342 |
recurse_entry *entry = common->entries; |
recurse_entry *entry = common->entries; |
5343 |
recurse_entry *prev = NULL; |
recurse_entry *prev = NULL; |
5344 |
int start = GET(cc, 1); |
sljit_sw start = GET(cc, 1); |
5345 |
pcre_uchar *start_cc; |
pcre_uchar *start_cc; |
5346 |
|
BOOL needs_control_head; |
5347 |
|
|
5348 |
PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL); |
PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL); |
5349 |
|
|
5350 |
/* Inlining simple patterns. */ |
/* Inlining simple patterns. */ |
5351 |
if (get_framesize(common, common->start + start, TRUE) == no_stack) |
if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack) |
5352 |
{ |
{ |
5353 |
start_cc = common->start + start; |
start_cc = common->start + start; |
5354 |
compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack); |
compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack); |
5467 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); |
5468 |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
5469 |
SLJIT_ASSERT(common->capture_last_ptr != 0); |
SLJIT_ASSERT(common->capture_last_ptr != 0); |
5470 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]); |
OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]); |
5471 |
OP1(SLJIT_MOV_UI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0); |
OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0); |
5472 |
|
|
5473 |
/* These pointer sized fields temporarly stores internal variables. */ |
/* These pointer sized fields temporarly stores internal variables. */ |
5474 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
5477 |
|
|
5478 |
if (common->mark_ptr != 0) |
if (common->mark_ptr != 0) |
5479 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr)); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr)); |
5480 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2)); |
OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2)); |
5481 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE)); |
OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE)); |
5482 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0); |
5483 |
|
|
5484 |
/* Needed to save important temporary registers. */ |
/* Needed to save important temporary registers. */ |
5507 |
{ |
{ |
5508 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
5509 |
int framesize; |
int framesize; |
5510 |
|
int extrasize; |
5511 |
|
BOOL needs_control_head; |
5512 |
int private_data_ptr; |
int private_data_ptr; |
5513 |
backtrack_common altbacktrack; |
backtrack_common altbacktrack; |
5514 |
pcre_uchar *ccbegin; |
pcre_uchar *ccbegin; |
5518 |
jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; |
jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; |
5519 |
jump_list **found; |
jump_list **found; |
5520 |
/* Saving previous accept variables. */ |
/* Saving previous accept variables. */ |
5521 |
|
BOOL save_local_exit = common->local_exit; |
5522 |
|
BOOL save_positive_assert = common->positive_assert; |
5523 |
|
then_trap_backtrack *save_then_trap = common->then_trap; |
5524 |
struct sljit_label *save_quit_label = common->quit_label; |
struct sljit_label *save_quit_label = common->quit_label; |
5525 |
struct sljit_label *save_accept_label = common->accept_label; |
struct sljit_label *save_accept_label = common->accept_label; |
5526 |
jump_list *save_quit = common->quit; |
jump_list *save_quit = common->quit; |
5527 |
|
jump_list *save_positive_assert_quit = common->positive_assert_quit; |
5528 |
jump_list *save_accept = common->accept; |
jump_list *save_accept = common->accept; |
5529 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
5530 |
struct sljit_jump *brajump = NULL; |
struct sljit_jump *brajump = NULL; |
5531 |
|
|
5532 |
|
/* Assert captures then. */ |
5533 |
|
common->then_trap = NULL; |
5534 |
|
|
5535 |
if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
5536 |
{ |
{ |
5537 |
SLJIT_ASSERT(!conditional); |
SLJIT_ASSERT(!conditional); |
5540 |
} |
} |
5541 |
private_data_ptr = PRIVATE_DATA(cc); |
private_data_ptr = PRIVATE_DATA(cc); |
5542 |
SLJIT_ASSERT(private_data_ptr != 0); |
SLJIT_ASSERT(private_data_ptr != 0); |
5543 |
framesize = get_framesize(common, cc, FALSE); |
framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head); |
5544 |
backtrack->framesize = framesize; |
backtrack->framesize = framesize; |
5545 |
backtrack->private_data_ptr = private_data_ptr; |
backtrack->private_data_ptr = private_data_ptr; |
5546 |
opcode = *cc; |
opcode = *cc; |
5559 |
|
|
5560 |
if (framesize < 0) |
if (framesize < 0) |
5561 |
{ |
{ |
5562 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); |
extrasize = needs_control_head ? 2 : 1; |
5563 |
allocate_stack(common, 1); |
if (framesize == no_frame) |
5564 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); |
5565 |
|
allocate_stack(common, extrasize); |
5566 |
|
if (needs_control_head) |
5567 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
5568 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
5569 |
|
if (needs_control_head) |
5570 |
|
{ |
5571 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
5572 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); |
5573 |
|
} |
5574 |
} |
} |
5575 |
else |
else |
5576 |
{ |
{ |
5577 |
allocate_stack(common, framesize + 2); |
extrasize = needs_control_head ? 3 : 2; |
5578 |
|
allocate_stack(common, framesize + extrasize); |
5579 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
5580 |
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1)); |
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); |
5581 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
5582 |
|
if (needs_control_head) |
5583 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
5584 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
5585 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); |
if (needs_control_head) |
5586 |
init_frame(common, ccbegin, framesize + 1, 2, FALSE); |
{ |
5587 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); |
5588 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); |
5589 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
5590 |
|
} |
5591 |
|
else |
5592 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); |
5593 |
|
init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE); |
5594 |
} |
} |
5595 |
|
|
5596 |
memset(&altbacktrack, 0, sizeof(backtrack_common)); |
memset(&altbacktrack, 0, sizeof(backtrack_common)); |
5597 |
common->quit_label = NULL; |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5598 |
common->quit = NULL; |
{ |
5599 |
|
/* Negative assert is stronger than positive assert. */ |
5600 |
|
common->local_exit = TRUE; |
5601 |
|
common->quit_label = NULL; |
5602 |
|
common->quit = NULL; |
5603 |
|
common->positive_assert = FALSE; |
5604 |
|
} |
5605 |
|
else |
5606 |
|
common->positive_assert = TRUE; |
5607 |
|
common->positive_assert_quit = NULL; |
5608 |
|
|
5609 |
while (1) |
while (1) |
5610 |
{ |
{ |
5611 |
common->accept_label = NULL; |
common->accept_label = NULL; |
5620 |
compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); |
compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); |
5621 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5622 |
{ |
{ |
5623 |
common->quit_label = save_quit_label; |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5624 |
|
{ |
5625 |
|
common->local_exit = save_local_exit; |
5626 |
|
common->quit_label = save_quit_label; |
5627 |
|
common->quit = save_quit; |
5628 |
|
} |
5629 |
|
common->positive_assert = save_positive_assert; |
5630 |
|
common->then_trap = save_then_trap; |
5631 |
common->accept_label = save_accept_label; |
common->accept_label = save_accept_label; |
5632 |
common->quit = save_quit; |
common->positive_assert_quit = save_positive_assert_quit; |
5633 |
common->accept = save_accept; |
common->accept = save_accept; |
5634 |
return NULL; |
return NULL; |
5635 |
} |
} |
5639 |
|
|
5640 |
/* Reset stack. */ |
/* Reset stack. */ |
5641 |
if (framesize < 0) |
if (framesize < 0) |
5642 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
{ |
5643 |
else { |
if (framesize == no_frame) |
5644 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
5645 |
|
else |
5646 |
|
free_stack(common, extrasize); |
5647 |
|
if (needs_control_head) |
5648 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); |
5649 |
|
} |
5650 |
|
else |
5651 |
|
{ |
5652 |
if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) |
if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) |
5653 |
{ |
{ |
5654 |
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
5655 |
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); |
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); |
5656 |
|
if (needs_control_head) |
5657 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); |
5658 |
} |
} |
5659 |
else |
else |
5660 |
{ |
{ |
5661 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
5662 |
|
if (needs_control_head) |
5663 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw)); |
5664 |
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
5665 |
} |
} |
5666 |
} |
} |
5667 |
|
|
5668 |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5669 |
{ |
{ |
5670 |
/* We know that STR_PTR was stored on the top of the stack. */ |
/* We know that STR_PTR was stored on the top of the stack. */ |
5671 |
if (conditional) |
if (conditional) |
5672 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0); |
5673 |
else if (bra == OP_BRAZERO) |
else if (bra == OP_BRAZERO) |
5674 |
{ |
{ |
5675 |
if (framesize < 0) |
if (framesize < 0) |
5676 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw)); |
5677 |
else |
else |
5678 |
{ |
{ |
5679 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); |
5680 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + extrasize - 1) * sizeof(sljit_sw)); |
5681 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
5682 |
} |
} |
5683 |
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
5694 |
compile_backtrackingpath(common, altbacktrack.top); |
compile_backtrackingpath(common, altbacktrack.top); |
5695 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5696 |
{ |
{ |
5697 |
common->quit_label = save_quit_label; |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5698 |
|
{ |
5699 |
|
common->local_exit = save_local_exit; |
5700 |
|
common->quit_label = save_quit_label; |
5701 |
|
common->quit = save_quit; |
5702 |
|
} |
5703 |
|
common->positive_assert = save_positive_assert; |
5704 |
|
common->then_trap = save_then_trap; |
5705 |
common->accept_label = save_accept_label; |
common->accept_label = save_accept_label; |
5706 |
common->quit = save_quit; |
common->positive_assert_quit = save_positive_assert_quit; |
5707 |
common->accept = save_accept; |
common->accept = save_accept; |
5708 |
return NULL; |
return NULL; |
5709 |
} |
} |
5715 |
ccbegin = cc; |
ccbegin = cc; |
5716 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
5717 |
} |
} |
5718 |
|
|
5719 |
|
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5720 |
|
{ |
5721 |
|
SLJIT_ASSERT(common->positive_assert_quit == NULL); |
5722 |
|
/* Makes the check less complicated below. */ |
5723 |
|
common->positive_assert_quit = common->quit; |
5724 |
|
} |
5725 |
|
|
5726 |
/* None of them matched. */ |
/* None of them matched. */ |
5727 |
if (common->quit != NULL) |
if (common->positive_assert_quit != NULL) |
5728 |
set_jumps(common->quit, LABEL()); |
{ |
5729 |
|
jump = JUMP(SLJIT_JUMP); |
5730 |
|
set_jumps(common->positive_assert_quit, LABEL()); |
5731 |
|
SLJIT_ASSERT(framesize != no_stack); |
5732 |
|
if (framesize < 0) |
5733 |
|
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); |
5734 |
|
else |
5735 |
|
{ |
5736 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
5737 |
|
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
5738 |
|
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); |
5739 |
|
} |
5740 |
|
JUMPHERE(jump); |
5741 |
|
} |
5742 |
|
|
5743 |
|
if (needs_control_head) |
5744 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1)); |
5745 |
|
|
5746 |
if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) |
if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) |
5747 |
{ |
{ |
5753 |
{ |
{ |
5754 |
/* The topmost item should be 0. */ |
/* The topmost item should be 0. */ |
5755 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
5756 |
|
{ |
5757 |
|
if (extrasize == 2) |
5758 |
|
free_stack(common, 1); |
5759 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5760 |
|
} |
5761 |
else |
else |
5762 |
free_stack(common, 1); |
free_stack(common, extrasize); |
5763 |
} |
} |
5764 |
else |
else |
5765 |
{ |
{ |
5766 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1)); |
5767 |
/* The topmost item should be 0. */ |
/* The topmost item should be 0. */ |
5768 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
5769 |
{ |
{ |
5770 |
free_stack(common, framesize + 1); |
free_stack(common, framesize + extrasize - 1); |
5771 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5772 |
} |
} |
5773 |
else |
else |
5774 |
free_stack(common, framesize + 2); |
free_stack(common, framesize + extrasize); |
5775 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
5776 |
} |
} |
5777 |
jump = JUMP(SLJIT_JUMP); |
jump = JUMP(SLJIT_JUMP); |
5783 |
if (framesize < 0) |
if (framesize < 0) |
5784 |
{ |
{ |
5785 |
/* We know that STR_PTR was stored on the top of the stack. */ |
/* We know that STR_PTR was stored on the top of the stack. */ |
5786 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw)); |
5787 |
/* Keep the STR_PTR on the top of the stack. */ |
/* Keep the STR_PTR on the top of the stack. */ |
5788 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
5789 |
|
{ |
5790 |
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
5791 |
|
if (extrasize == 2) |
5792 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
5793 |
|
} |
5794 |
else if (bra == OP_BRAMINZERO) |
else if (bra == OP_BRAMINZERO) |
5795 |
{ |
{ |
5796 |
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
5803 |
{ |
{ |
5804 |
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
5805 |
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); |
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); |
5806 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 2) * sizeof(sljit_sw)); |
5807 |
} |
} |
5808 |
else |
else |
5809 |
{ |
{ |
5810 |
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
/* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
5811 |
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); |
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); |
5812 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
if (extrasize == 2) |
5813 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); |
{ |
5814 |
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
5815 |
|
if (bra == OP_BRAMINZERO) |
5816 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5817 |
|
} |
5818 |
|
else |
5819 |
|
{ |
5820 |
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); |
5821 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); |
5822 |
|
} |
5823 |
} |
} |
5824 |
} |
} |
5825 |
|
|
5848 |
{ |
{ |
5849 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
5850 |
if (bra != OP_BRA) |
if (bra != OP_BRA) |
5851 |
|
{ |
5852 |
|
if (extrasize == 2) |
5853 |
|
free_stack(common, 1); |
5854 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5855 |
|
} |
5856 |
else |
else |
5857 |
free_stack(common, 1); |
free_stack(common, extrasize); |
5858 |
} |
} |
5859 |
else |
else |
5860 |
{ |
{ |
5861 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
5862 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1)); |
5863 |
/* The topmost item should be 0. */ |
/* The topmost item should be 0. */ |
5864 |
if (bra != OP_BRA) |
if (bra != OP_BRA) |
5865 |
{ |
{ |
5866 |
free_stack(common, framesize + 1); |
free_stack(common, framesize + extrasize - 1); |
5867 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5868 |
} |
} |
5869 |
else |
else |
5870 |
free_stack(common, framesize + 2); |
free_stack(common, framesize + extrasize); |
5871 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
5872 |
} |
} |
5873 |
|
|
5887 |
} |
} |
5888 |
} |
} |
5889 |
|
|
5890 |
common->quit_label = save_quit_label; |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5891 |
|
{ |
5892 |
|
common->local_exit = save_local_exit; |
5893 |
|
common->quit_label = save_quit_label; |
5894 |
|
common->quit = save_quit; |
5895 |
|
} |
5896 |
|
common->positive_assert = save_positive_assert; |
5897 |
|
common->then_trap = save_then_trap; |
5898 |
common->accept_label = save_accept_label; |
common->accept_label = save_accept_label; |
5899 |
common->quit = save_quit; |
common->positive_assert_quit = save_positive_assert_quit; |
5900 |
common->accept = save_accept; |
common->accept = save_accept; |
5901 |
return cc + 1 + LINK_SIZE; |
return cc + 1 + LINK_SIZE; |
5902 |
} |
} |
6011 |
return condition; |
return condition; |
6012 |
} |
} |
6013 |
|
|
6014 |
|
static SLJIT_INLINE void match_once_common(compiler_common *common, pcre_uchar ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head) |
6015 |
|
{ |
6016 |
|
DEFINE_COMPILER; |
6017 |
|
int stacksize; |
6018 |
|
|
6019 |
|
if (framesize < 0) |
6020 |
|
{ |
6021 |
|
if (framesize == no_frame) |
6022 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
6023 |
|
else |
6024 |
|
{ |
6025 |
|
stacksize = needs_control_head ? 1 : 0; |
6026 |
|
if (ket != OP_KET || has_alternatives) |
6027 |
|
stacksize++; |
6028 |
|
free_stack(common, stacksize); |
6029 |
|
} |
6030 |
|
|
6031 |
|
if (needs_control_head) |
6032 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? sizeof(sljit_sw) : 0); |
6033 |
|
|
6034 |
|
/* TMP2 which is set here used by OP_KETRMAX below. */ |
6035 |
|
if (ket == OP_KETRMAX) |
6036 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); |
6037 |
|
else if (ket == OP_KETRMIN) |
6038 |
|
{ |
6039 |
|
/* Move the STR_PTR to the private_data_ptr. */ |
6040 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); |
6041 |
|
} |
6042 |
|
} |
6043 |
|
else |
6044 |
|
{ |
6045 |
|
stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1; |
6046 |
|
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw)); |
6047 |
|
if (needs_control_head) |
6048 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 0); |
6049 |
|
|
6050 |
|
if (ket == OP_KETRMAX) |
6051 |
|
{ |
6052 |
|
/* TMP2 which is set here used by OP_KETRMAX below. */ |
6053 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
6054 |
|
} |
6055 |
|
} |
6056 |
|
if (needs_control_head) |
6057 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0); |
6058 |
|
} |
6059 |
|
|
6060 |
|
static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr) |
6061 |
|
{ |
6062 |
|
DEFINE_COMPILER; |
6063 |
|
|
6064 |
|
if (common->capture_last_ptr != 0) |
6065 |
|
{ |
6066 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); |
6067 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); |
6068 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
6069 |
|
stacksize++; |
6070 |
|
} |
6071 |
|
if (common->optimized_cbracket[offset >> 1] == 0) |
6072 |
|
{ |
6073 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
6074 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
6075 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
6076 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
6077 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); |
6078 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); |
6079 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
6080 |
|
stacksize += 2; |
6081 |
|
} |
6082 |
|
return stacksize; |
6083 |
|
} |
6084 |
|
|
6085 |
/* |
/* |
6086 |
Handling bracketed expressions is probably the most complex part. |
Handling bracketed expressions is probably the most complex part. |
6087 |
|
|
6144 |
int private_data_ptr = 0; |
int private_data_ptr = 0; |
6145 |
int offset = 0; |
int offset = 0; |
6146 |
int stacksize; |
int stacksize; |
6147 |
|
int repeat_ptr = 0, repeat_length = 0; |
6148 |
|
int repeat_type = 0, repeat_count = 0; |
6149 |
pcre_uchar *ccbegin; |
pcre_uchar *ccbegin; |
6150 |
pcre_uchar *matchingpath; |
pcre_uchar *matchingpath; |
6151 |
pcre_uchar bra = OP_BRA; |
pcre_uchar bra = OP_BRA; |
6152 |
pcre_uchar ket; |
pcre_uchar ket; |
6153 |
assert_backtrack *assert; |
assert_backtrack *assert; |
6154 |
BOOL has_alternatives; |
BOOL has_alternatives; |
6155 |
|
BOOL needs_control_head = FALSE; |
6156 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
6157 |
struct sljit_jump *skip; |
struct sljit_jump *skip; |
6158 |
struct sljit_label *rmaxlabel = NULL; |
struct sljit_label *rmax_label = NULL; |
6159 |
struct sljit_jump *braminzerojump = NULL; |
struct sljit_jump *braminzero = NULL; |
6160 |
|
|
6161 |
PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); |
PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); |
6162 |
|
|
6169 |
|
|
6170 |
opcode = *cc; |
opcode = *cc; |
6171 |
ccbegin = cc; |
ccbegin = cc; |
6172 |
matchingpath = ccbegin + 1 + LINK_SIZE; |
matchingpath = bracketend(cc) - 1 - LINK_SIZE; |
6173 |
|
ket = *matchingpath; |
6174 |
|
if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0) |
6175 |
|
{ |
6176 |
|
repeat_ptr = PRIVATE_DATA(matchingpath); |
6177 |
|
repeat_length = PRIVATE_DATA(matchingpath + 1); |
6178 |
|
repeat_type = PRIVATE_DATA(matchingpath + 2); |
6179 |
|
repeat_count = PRIVATE_DATA(matchingpath + 3); |
6180 |
|
SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0); |
6181 |
|
if (repeat_type == OP_UPTO) |
6182 |
|
ket = OP_KETRMAX; |
6183 |
|
if (repeat_type == OP_MINUPTO) |
6184 |
|
ket = OP_KETRMIN; |
6185 |
|
} |
6186 |
|
|
6187 |
if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) |
if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) |
6188 |
{ |
{ |
6189 |
/* Drop this bracket_backtrack. */ |
/* Drop this bracket_backtrack. */ |
6190 |
parent->top = backtrack->prev; |
parent->top = backtrack->prev; |
6191 |
return bracketend(cc); |
return matchingpath + 1 + LINK_SIZE + repeat_length; |
6192 |
} |
} |
6193 |
|
|
6194 |
ket = *(bracketend(cc) - 1 - LINK_SIZE); |
matchingpath = ccbegin + 1 + LINK_SIZE; |
6195 |
SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); |
SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); |
6196 |
SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX))); |
SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX))); |
6197 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
6241 |
SLJIT_ASSERT(private_data_ptr != 0); |
SLJIT_ASSERT(private_data_ptr != 0); |
6242 |
BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr; |
BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr; |
6243 |
if (opcode == OP_ONCE) |
if (opcode == OP_ONCE) |
6244 |
BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, FALSE); |
BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, NULL, FALSE, &needs_control_head); |
6245 |
} |
} |
6246 |
|
|
6247 |
/* Instructions before the first alternative. */ |
/* Instructions before the first alternative. */ |
6248 |
stacksize = 0; |
stacksize = 0; |
6249 |
if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) |
if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) |
6250 |
stacksize++; |
stacksize++; |
6251 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
6252 |
stacksize++; |
stacksize++; |
6255 |
allocate_stack(common, stacksize); |
allocate_stack(common, stacksize); |
6256 |
|
|
6257 |
stacksize = 0; |
stacksize = 0; |
6258 |
if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) |
if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) |
6259 |
{ |
{ |
6260 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); |
6261 |
stacksize++; |
stacksize++; |
6271 |
if (ket != OP_KETRMIN) |
if (ket != OP_KETRMIN) |
6272 |
{ |
{ |
6273 |
free_stack(common, 1); |
free_stack(common, 1); |
6274 |
braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); |
braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); |
6275 |
} |
} |
6276 |
else |
else |
6277 |
{ |
{ |
6286 |
if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
6287 |
{ |
{ |
6288 |
/* When we come from outside, private_data_ptr contains the previous STR_PTR. */ |
/* When we come from outside, private_data_ptr contains the previous STR_PTR. */ |
6289 |
braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
6290 |
} |
} |
6291 |
else |
else |
6292 |
{ |
{ |
6293 |
/* Except when the whole stack frame must be saved. */ |
/* Except when the whole stack frame must be saved. */ |
6294 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
6295 |
braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw)); |
braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw)); |
6296 |
} |
} |
6297 |
JUMPHERE(skip); |
JUMPHERE(skip); |
6298 |
} |
} |
6305 |
} |
} |
6306 |
} |
} |
6307 |
|
|
6308 |
|
if (repeat_type != 0) |
6309 |
|
{ |
6310 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, repeat_count); |
6311 |
|
if (repeat_type == OP_EXACT) |
6312 |
|
rmax_label = LABEL(); |
6313 |
|
} |
6314 |
|
|
6315 |
if (ket == OP_KETRMIN) |
if (ket == OP_KETRMIN) |
6316 |
BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
6317 |
|
|
6318 |
if (ket == OP_KETRMAX) |
if (ket == OP_KETRMAX) |
6319 |
{ |
{ |
6320 |
rmaxlabel = LABEL(); |
rmax_label = LABEL(); |
6321 |
if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA) |
if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0) |
6322 |
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmaxlabel; |
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label; |
6323 |
} |
} |
6324 |
|
|
6325 |
/* Handling capturing brackets and alternatives. */ |
/* Handling capturing brackets and alternatives. */ |
6326 |
if (opcode == OP_ONCE) |
if (opcode == OP_ONCE) |
6327 |
{ |
{ |
6328 |
|
stacksize = 0; |
6329 |
|
if (needs_control_head) |
6330 |
|
{ |
6331 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
6332 |
|
stacksize++; |
6333 |
|
} |
6334 |
|
|
6335 |
if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
6336 |
{ |
{ |
6337 |
/* Neither capturing brackets nor recursions are not found in the block. */ |
/* Neither capturing brackets nor recursions are found in the block. */ |
6338 |
if (ket == OP_KETRMIN) |
if (ket == OP_KETRMIN) |
6339 |
{ |
{ |
6340 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
stacksize += 2; |
6341 |
allocate_stack(common, 2); |
if (!needs_control_head) |
6342 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); |
|
|
OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
|
6343 |
} |
} |
6344 |
else if (ket == OP_KETRMAX || has_alternatives) |
else |
6345 |
{ |
{ |
6346 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); |
if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) |
6347 |
allocate_stack(common, 1); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); |
6348 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
if (ket == OP_KETRMAX || has_alternatives) |
6349 |
|
stacksize++; |
6350 |
} |
} |
6351 |
else |
|
6352 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); |
if (stacksize > 0) |
6353 |
|
allocate_stack(common, stacksize); |
6354 |
|
|
6355 |
|
stacksize = 0; |
6356 |
|
if (needs_control_head) |
6357 |
|
{ |
6358 |
|
stacksize++; |
6359 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
6360 |
|
} |
6361 |
|
|
6362 |
|
if (ket == OP_KETRMIN) |
6363 |
|
{ |
6364 |
|
if (needs_control_head) |
6365 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
6366 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); |
6367 |
|
if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) |
6368 |
|
OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw)); |
6369 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); |
6370 |
|
} |
6371 |
|
else if (ket == OP_KETRMAX || has_alternatives) |
6372 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); |
6373 |
} |
} |
6374 |
else |
else |
6375 |
{ |
{ |
6376 |
if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) |
if (ket != OP_KET || has_alternatives) |
6377 |
|
stacksize++; |
6378 |
|
|
6379 |
|
stacksize += BACKTRACK_AS(bracket_backtrack)->u.framesize + 1; |
6380 |
|
allocate_stack(common, stacksize); |
6381 |
|
|
6382 |
|
if (needs_control_head) |
6383 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
6384 |
|
|
6385 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
6386 |
|
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); |
6387 |
|
|
6388 |
|
stacksize = needs_control_head ? 1 : 0; |
6389 |
|
if (ket != OP_KET || has_alternatives) |
6390 |
{ |
{ |
6391 |
allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 2); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
|
|
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize + 1)); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
|
6392 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
6393 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); |
stacksize++; |
6394 |
init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1, 2, FALSE); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
6395 |
} |
} |
6396 |
else |
else |
6397 |
{ |
{ |
|
allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1); |
|
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
|
|
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize)); |
|
6398 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
6399 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
|
init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize, 1, FALSE); |
|
6400 |
} |
} |
6401 |
|
init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1, FALSE); |
6402 |
} |
} |
6403 |
} |
} |
6404 |
else if (opcode == OP_CBRA || opcode == OP_SCBRA) |
else if (opcode == OP_CBRA || opcode == OP_SCBRA) |
6534 |
return NULL; |
return NULL; |
6535 |
|
|
6536 |
if (opcode == OP_ONCE) |
if (opcode == OP_ONCE) |
6537 |
{ |
match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); |
|
if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
|
|
{ |
|
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
|
|
/* TMP2 which is set here used by OP_KETRMAX below. */ |
|
|
if (ket == OP_KETRMAX) |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); |
|
|
else if (ket == OP_KETRMIN) |
|
|
{ |
|
|
/* Move the STR_PTR to the private_data_ptr. */ |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; |
|
|
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize) * sizeof(sljit_sw)); |
|
|
if (ket == OP_KETRMAX) |
|
|
{ |
|
|
/* TMP2 which is set here used by OP_KETRMAX below. */ |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
|
|
} |
|
|
} |
|
|
} |
|
6538 |
|
|
6539 |
stacksize = 0; |
stacksize = 0; |
6540 |
|
if (repeat_type == OP_MINUPTO) |
6541 |
|
{ |
6542 |
|
/* We need to preserve the counter. TMP2 will be used below. */ |
6543 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); |
6544 |
|
stacksize++; |
6545 |
|
} |
6546 |
if (ket != OP_KET || bra != OP_BRA) |
if (ket != OP_KET || bra != OP_BRA) |
6547 |
stacksize++; |
stacksize++; |
6548 |
if (offset != 0) |
if (offset != 0) |
6559 |
allocate_stack(common, stacksize); |
allocate_stack(common, stacksize); |
6560 |
|
|
6561 |
stacksize = 0; |
stacksize = 0; |
6562 |
|
if (repeat_type == OP_MINUPTO) |
6563 |
|
{ |
6564 |
|
/* TMP2 was set above. */ |
6565 |
|
OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1); |
6566 |
|
stacksize++; |
6567 |
|
} |
6568 |
|
|
6569 |
if (ket != OP_KET || bra != OP_BRA) |
if (ket != OP_KET || bra != OP_BRA) |
6570 |
{ |
{ |
6571 |
if (ket != OP_KET) |
if (ket != OP_KET) |
6576 |
} |
} |
6577 |
|
|
6578 |
if (offset != 0) |
if (offset != 0) |
6579 |
{ |
stacksize = match_capture_common(common, stacksize, offset, private_data_ptr); |
|
if (common->capture_last_ptr != 0) |
|
|
{ |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0); |
|
|
stacksize++; |
|
|
} |
|
|
if (common->optimized_cbracket[offset >> 1] == 0) |
|
|
{ |
|
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
|
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
|
|
stacksize += 2; |
|
|
} |
|
|
} |
|
6580 |
|
|
6581 |
if (has_alternatives) |
if (has_alternatives) |
6582 |
{ |
{ |
6595 |
|
|
6596 |
if (ket == OP_KETRMAX) |
if (ket == OP_KETRMAX) |
6597 |
{ |
{ |
6598 |
if (opcode == OP_ONCE || opcode >= OP_SBRA) |
if (repeat_type != 0) |
6599 |
|
{ |
6600 |
|
if (has_alternatives) |
6601 |
|
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); |
6602 |
|
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
6603 |
|
JUMPTO(SLJIT_C_NOT_ZERO, rmax_label); |
6604 |
|
/* Drop STR_PTR for greedy plus quantifier. */ |
6605 |
|
if (opcode != OP_ONCE) |
6606 |
|
free_stack(common, 1); |
6607 |
|
} |
6608 |
|
else if (opcode == OP_ONCE || opcode >= OP_SBRA) |
6609 |
{ |
{ |
6610 |
if (has_alternatives) |
if (has_alternatives) |
6611 |
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); |
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); |
6612 |
/* Checking zero-length iteration. */ |
/* Checking zero-length iteration. */ |
6613 |
if (opcode != OP_ONCE) |
if (opcode != OP_ONCE) |
6614 |
{ |
{ |
6615 |
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0, rmaxlabel); |
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0, rmax_label); |
6616 |
/* Drop STR_PTR for greedy plus quantifier. */ |
/* Drop STR_PTR for greedy plus quantifier. */ |
6617 |
if (bra != OP_BRAZERO) |
if (bra != OP_BRAZERO) |
6618 |
free_stack(common, 1); |
free_stack(common, 1); |
6619 |
} |
} |
6620 |
else |
else |
6621 |
/* TMP2 must contain the starting STR_PTR. */ |
/* TMP2 must contain the starting STR_PTR. */ |
6622 |
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel); |
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label); |
6623 |
} |
} |
6624 |
else |
else |
6625 |
JUMPTO(SLJIT_JUMP, rmaxlabel); |
JUMPTO(SLJIT_JUMP, rmax_label); |
6626 |
BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
6627 |
} |
} |
6628 |
|
|
6629 |
|
if (repeat_type == OP_EXACT) |
6630 |
|
{ |
6631 |
|
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
6632 |
|
JUMPTO(SLJIT_C_NOT_ZERO, rmax_label); |
6633 |
|
} |
6634 |
|
else if (repeat_type == OP_UPTO) |
6635 |
|
{ |
6636 |
|
/* We need to preserve the counter. */ |
6637 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); |
6638 |
|
allocate_stack(common, 1); |
6639 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
6640 |
|
} |
6641 |
|
|
6642 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
6643 |
BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL(); |
BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL(); |
6644 |
|
|
6646 |
{ |
{ |
6647 |
/* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */ |
/* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */ |
6648 |
JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath); |
JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath); |
6649 |
if (braminzerojump != NULL) |
if (braminzero != NULL) |
6650 |
{ |
{ |
6651 |
JUMPHERE(braminzerojump); |
JUMPHERE(braminzero); |
6652 |
/* We need to release the end pointer to perform the |
/* We need to release the end pointer to perform the |
6653 |
backtrack for the zero-length iteration. When |
backtrack for the zero-length iteration. When |
6654 |
framesize is < 0, OP_ONCE will do the release itself. */ |
framesize is < 0, OP_ONCE will do the release itself. */ |
6670 |
while (*cc == OP_ALT) |
while (*cc == OP_ALT) |
6671 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
6672 |
cc += 1 + LINK_SIZE; |
cc += 1 + LINK_SIZE; |
6673 |
return cc; |
|
6674 |
|
/* Temporarily encoding the needs_control_head in framesize. */ |
6675 |
|
if (opcode == OP_ONCE) |
6676 |
|
BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0); |
6677 |
|
return cc + repeat_length; |
6678 |
} |
} |
6679 |
|
|
6680 |
static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
6684 |
pcre_uchar opcode; |
pcre_uchar opcode; |
6685 |
int private_data_ptr; |
int private_data_ptr; |
6686 |
int cbraprivptr = 0; |
int cbraprivptr = 0; |
6687 |
|
BOOL needs_control_head; |
6688 |
int framesize; |
int framesize; |
6689 |
int stacksize; |
int stacksize; |
6690 |
int offset = 0; |
int offset = 0; |
6691 |
BOOL zero = FALSE; |
BOOL zero = FALSE; |
6692 |
pcre_uchar *ccbegin = NULL; |
pcre_uchar *ccbegin = NULL; |
6693 |
int stack; |
int stack; /* Also contains the offset of control head. */ |
6694 |
struct sljit_label *loop = NULL; |
struct sljit_label *loop = NULL; |
6695 |
struct jump_list *emptymatch = NULL; |
struct jump_list *emptymatch = NULL; |
6696 |
|
|
6728 |
break; |
break; |
6729 |
} |
} |
6730 |
|
|
6731 |
framesize = get_framesize(common, cc, FALSE); |
framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head); |
6732 |
BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize; |
BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize; |
6733 |
if (framesize < 0) |
if (framesize < 0) |
6734 |
{ |
{ |
6741 |
else |
else |
6742 |
stacksize = 1; |
stacksize = 1; |
6743 |
|
|
6744 |
|
if (needs_control_head) |
6745 |
|
stacksize++; |
6746 |
if (!zero) |
if (!zero) |
6747 |
stacksize++; |
stacksize++; |
6748 |
|
|
6751 |
if (framesize == no_frame) |
if (framesize == no_frame) |
6752 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); |
6753 |
|
|
6754 |
|
stack = 0; |
6755 |
if (offset != 0) |
if (offset != 0) |
6756 |
{ |
{ |
6757 |
|
stack = 2; |
6758 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
6759 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
6760 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); |
6761 |
if (common->capture_last_ptr != 0) |
if (common->capture_last_ptr != 0) |
6762 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); |
6763 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); |
6764 |
|
if (needs_control_head) |
6765 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
6766 |
if (common->capture_last_ptr != 0) |
if (common->capture_last_ptr != 0) |
6767 |
|
{ |
6768 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); |
6769 |
|
stack = 3; |
6770 |
|
} |
6771 |
} |
} |
6772 |
else |
else |
6773 |
|
{ |
6774 |
|
if (needs_control_head) |
6775 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
6776 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
6777 |
|
stack = 1; |
6778 |
|
} |
6779 |
|
|
6780 |
|
if (needs_control_head) |
6781 |
|
stack++; |
6782 |
if (!zero) |
if (!zero) |
6783 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), SLJIT_IMM, 1); |
6784 |
|
if (needs_control_head) |
6785 |
|
{ |
6786 |
|
stack--; |
6787 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0); |
6788 |
|
} |
6789 |
} |
} |
6790 |
else |
else |
6791 |
{ |
{ |
6792 |
stacksize = framesize + 1; |
stacksize = framesize + 1; |
6793 |
if (!zero) |
if (!zero) |
6794 |
stacksize++; |
stacksize++; |
6795 |
if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) |
if (needs_control_head) |
6796 |
|
stacksize++; |
6797 |
|
if (offset == 0) |
6798 |
stacksize++; |
stacksize++; |
6799 |
BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; |
BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; |
6800 |
|
|
6801 |
allocate_stack(common, stacksize); |
allocate_stack(common, stacksize); |
6802 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
6803 |
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); |
if (needs_control_head) |
6804 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
6805 |
|
OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); |
6806 |
|
|
6807 |
stack = 0; |
stack = 0; |
6808 |
if (!zero) |
if (!zero) |
6809 |
{ |
{ |
6810 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1); |
6811 |
|
stack = 1; |
6812 |
|
} |
6813 |
|
if (needs_control_head) |
6814 |
|
{ |
6815 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0); |
6816 |
stack++; |
stack++; |
6817 |
} |
} |
6818 |
if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) |
if (offset == 0) |
6819 |
{ |
{ |
6820 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0); |
6821 |
stack++; |
stack++; |
6822 |
} |
} |
6823 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0); |
6824 |
init_frame(common, cc, stacksize - 1, stacksize - framesize, FALSE); |
init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize, FALSE); |
6825 |
|
stack -= 1 + (offset == 0); |
6826 |
} |
} |
6827 |
|
|
6828 |
if (offset != 0) |
if (offset != 0) |
6898 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
6899 |
} |
} |
6900 |
} |
} |
6901 |
|
|
6902 |
|
if (needs_control_head) |
6903 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); |
6904 |
|
|
6905 |
JUMPTO(SLJIT_JUMP, loop); |
JUMPTO(SLJIT_JUMP, loop); |
6906 |
flush_stubs(common); |
flush_stubs(common); |
6907 |
|
|
6938 |
ccbegin = cc + 1 + LINK_SIZE; |
ccbegin = cc + 1 + LINK_SIZE; |
6939 |
} |
} |
6940 |
|
|
6941 |
|
/* We don't have to restore the control head in case of a failed match. */ |
6942 |
|
|
6943 |
backtrack->topbacktracks = NULL; |
backtrack->topbacktracks = NULL; |
6944 |
if (!zero) |
if (!zero) |
6945 |
{ |
{ |
7328 |
return cc + 1 + IMM2_SIZE; |
return cc + 1 + IMM2_SIZE; |
7329 |
} |
} |
7330 |
|
|
7331 |
|
static SLJIT_INLINE pcre_uchar *compile_control_verb_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) |
7332 |
|
{ |
7333 |
|
DEFINE_COMPILER; |
7334 |
|
backtrack_common *backtrack; |
7335 |
|
pcre_uchar opcode = *cc; |
7336 |
|
pcre_uchar *ccend = cc + 1; |
7337 |
|
|
7338 |
|
if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG) |
7339 |
|
ccend += 2 + cc[1]; |
7340 |
|
|
7341 |
|
PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); |
7342 |
|
|
7343 |
|
if (opcode == OP_SKIP) |
7344 |
|
{ |
7345 |
|
allocate_stack(common, 1); |
7346 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
7347 |
|
return ccend; |
7348 |
|
} |
7349 |
|
|
7350 |
|
if (opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG) |
7351 |
|
{ |
7352 |
|
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
7353 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); |
7354 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); |
7355 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); |
7356 |
|
} |
7357 |
|
|
7358 |
|
return ccend; |
7359 |
|
} |
7360 |
|
|
7361 |
|
static pcre_uchar then_trap_opcode[1] = { OP_THEN_TRAP }; |
7362 |
|
|
7363 |
|
static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) |
7364 |
|
{ |
7365 |
|
DEFINE_COMPILER; |
7366 |
|
backtrack_common *backtrack; |
7367 |
|
BOOL needs_control_head; |
7368 |
|
int size; |
7369 |
|
|
7370 |
|
PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc); |
7371 |
|
common->then_trap = BACKTRACK_AS(then_trap_backtrack); |
7372 |
|
BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode; |
7373 |
|
BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start); |
7374 |
|
BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head); |
7375 |
|
|
7376 |
|
size = BACKTRACK_AS(then_trap_backtrack)->framesize; |
7377 |
|
size = 3 + (size < 0 ? 0 : size); |
7378 |
|
|
7379 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
7380 |
|
allocate_stack(common, size); |
7381 |
|
if (size > 3) |
7382 |
|
OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw)); |
7383 |
|
else |
7384 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); |
7385 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start); |
7386 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap); |
7387 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0); |
7388 |
|
|
7389 |
|
size = BACKTRACK_AS(then_trap_backtrack)->framesize; |
7390 |
|
if (size >= 0) |
7391 |
|
init_frame(common, cc, ccend, size - 1, 0, FALSE); |
7392 |
|
} |
7393 |
|
|
7394 |
static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) |
static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) |
7395 |
{ |
{ |
7396 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
7397 |
backtrack_common *backtrack; |
backtrack_common *backtrack; |
7398 |
|
BOOL has_then_trap = FALSE; |
7399 |
|
then_trap_backtrack *save_then_trap = NULL; |
7400 |
|
|
7401 |
|
SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS)); |
7402 |
|
|
7403 |
|
if (common->has_then && common->then_offsets[cc - common->start] != 0) |
7404 |
|
{ |
7405 |
|
SLJIT_ASSERT(*ccend != OP_END && common->control_head_ptr != 0); |
7406 |
|
has_then_trap = TRUE; |
7407 |
|
save_then_trap = common->then_trap; |
7408 |
|
/* Tail item on backtrack. */ |
7409 |
|
compile_then_trap_matchingpath(common, cc, ccend, parent); |
7410 |
|
} |
7411 |
|
|
7412 |
while (cc < ccend) |
while (cc < ccend) |
7413 |
{ |
{ |
7624 |
PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); |
PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); |
7625 |
SLJIT_ASSERT(common->mark_ptr != 0); |
SLJIT_ASSERT(common->mark_ptr != 0); |
7626 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); |
7627 |
allocate_stack(common, 1); |
allocate_stack(common, common->has_skip_arg ? 5 : 1); |
7628 |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
7629 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0); |
7630 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); |
7631 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); |
7632 |
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); |
7633 |
|
if (common->has_skip_arg) |
7634 |
|
{ |
7635 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
7636 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); |
7637 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark); |
7638 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2)); |
7639 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0); |
7640 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); |
7641 |
|
} |
7642 |
cc += 1 + 2 + cc[1]; |
cc += 1 + 2 + cc[1]; |
7643 |
break; |
break; |
7644 |
|
|
7645 |
|
case OP_PRUNE: |
7646 |
|
case OP_PRUNE_ARG: |
7647 |
|
case OP_SKIP: |
7648 |
|
case OP_SKIP_ARG: |
7649 |
|
case OP_THEN: |
7650 |
|
case OP_THEN_ARG: |
7651 |
case OP_COMMIT: |
case OP_COMMIT: |
7652 |
PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); |
cc = compile_control_verb_matchingpath(common, cc, parent); |
|
cc += 1; |
|
7653 |
break; |
break; |
7654 |
|
|
7655 |
case OP_FAIL: |
case OP_FAIL: |
7673 |
if (cc == NULL) |
if (cc == NULL) |
7674 |
return; |
return; |
7675 |
} |
} |
7676 |
|
|
7677 |
|
if (has_then_trap) |
7678 |
|
{ |
7679 |
|
/* Head item on backtrack. */ |
7680 |
|
PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc); |
7681 |
|
BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode; |
7682 |
|
BACKTRACK_AS(then_trap_backtrack)->then_trap = common->then_trap; |
7683 |
|
common->then_trap = save_then_trap; |
7684 |
|
} |
7685 |
SLJIT_ASSERT(cc == ccend); |
SLJIT_ASSERT(cc == ccend); |
7686 |
} |
} |
7687 |
|
|
7843 |
} |
} |
7844 |
} |
} |
7845 |
|
|
7846 |
static void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
7847 |
{ |
{ |
7848 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
7849 |
pcre_uchar *cc = current->cc; |
pcre_uchar *cc = current->cc; |
7865 |
free_stack(common, 2); |
free_stack(common, 2); |
7866 |
} |
} |
7867 |
|
|
7868 |
static void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
7869 |
{ |
{ |
7870 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
7871 |
|
|
7961 |
static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
7962 |
{ |
{ |
7963 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
7964 |
int opcode; |
int opcode, stacksize, count; |
7965 |
int offset = 0; |
int offset = 0; |
7966 |
int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr; |
int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr; |
7967 |
int stacksize; |
int repeat_ptr = 0, repeat_type = 0, repeat_count = 0; |
|
int count; |
|
7968 |
pcre_uchar *cc = current->cc; |
pcre_uchar *cc = current->cc; |
7969 |
pcre_uchar *ccbegin; |
pcre_uchar *ccbegin; |
7970 |
pcre_uchar *ccprev; |
pcre_uchar *ccprev; |
7974 |
pcre_uchar ket; |
pcre_uchar ket; |
7975 |
assert_backtrack *assert; |
assert_backtrack *assert; |
7976 |
BOOL has_alternatives; |
BOOL has_alternatives; |
7977 |
|
BOOL needs_control_head = FALSE; |
7978 |
struct sljit_jump *brazero = NULL; |
struct sljit_jump *brazero = NULL; |
7979 |
struct sljit_jump *once = NULL; |
struct sljit_jump *once = NULL; |
7980 |
struct sljit_jump *cond = NULL; |
struct sljit_jump *cond = NULL; |
7981 |
struct sljit_label *rminlabel = NULL; |
struct sljit_label *rmin_label = NULL; |
7982 |
|
struct sljit_label *exact_label = NULL; |
7983 |
|
|
7984 |
if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
7985 |
{ |
{ |
7988 |
} |
} |
7989 |
|
|
7990 |
opcode = *cc; |
opcode = *cc; |
7991 |
|
ccbegin = bracketend(cc) - 1 - LINK_SIZE; |
7992 |
|
ket = *ccbegin; |
7993 |
|
if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0) |
7994 |
|
{ |
7995 |
|
repeat_ptr = PRIVATE_DATA(ccbegin); |
7996 |
|
repeat_type = PRIVATE_DATA(ccbegin + 2); |
7997 |
|
repeat_count = PRIVATE_DATA(ccbegin + 3); |
7998 |
|
SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0); |
7999 |
|
if (repeat_type == OP_UPTO) |
8000 |
|
ket = OP_KETRMAX; |
8001 |
|
if (repeat_type == OP_MINUPTO) |
8002 |
|
ket = OP_KETRMIN; |
8003 |
|
} |
8004 |
ccbegin = cc; |
ccbegin = cc; |
|
ket = *(bracketend(ccbegin) - 1 - LINK_SIZE); |
|
8005 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
8006 |
has_alternatives = *cc == OP_ALT; |
has_alternatives = *cc == OP_ALT; |
8007 |
if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) |
if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) |
8013 |
if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) |
if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) |
8014 |
opcode = OP_ONCE; |
opcode = OP_ONCE; |
8015 |
|
|
8016 |
|
/* Decoding the needs_control_head in framesize. */ |
8017 |
|
if (opcode == OP_ONCE) |
8018 |
|
{ |
8019 |
|
needs_control_head = (CURRENT_AS(bracket_backtrack)->u.framesize & 0x1) != 0; |
8020 |
|
CURRENT_AS(bracket_backtrack)->u.framesize >>= 1; |
8021 |
|
} |
8022 |
|
|
8023 |
|
if (ket != OP_KET && repeat_type != 0) |
8024 |
|
{ |
8025 |
|
/* TMP1 is used in OP_KETRMIN below. */ |
8026 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8027 |
|
free_stack(common, 1); |
8028 |
|
if (repeat_type == OP_UPTO) |
8029 |
|
OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0, SLJIT_IMM, 1); |
8030 |
|
else |
8031 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0); |
8032 |
|
} |
8033 |
|
|
8034 |
if (ket == OP_KETRMAX) |
if (ket == OP_KETRMAX) |
8035 |
{ |
{ |
8036 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
8045 |
if (bra != OP_BRAMINZERO) |
if (bra != OP_BRAMINZERO) |
8046 |
{ |
{ |
8047 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8048 |
if (opcode >= OP_SBRA || opcode == OP_ONCE) |
if (repeat_type != 0) |
8049 |
|
{ |
8050 |
|
/* TMP1 was set a few lines above. */ |
8051 |
|
CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
8052 |
|
/* Drop STR_PTR for non-greedy plus quantifier. */ |
8053 |
|
if (opcode != OP_ONCE) |
8054 |
|
free_stack(common, 1); |
8055 |
|
} |
8056 |
|
else if (opcode >= OP_SBRA || opcode == OP_ONCE) |
8057 |
{ |
{ |
8058 |
/* Checking zero-length iteration. */ |
/* Checking zero-length iteration. */ |
8059 |
if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0) |
if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0) |
8063 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
8064 |
CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
8065 |
} |
} |
8066 |
|
/* Drop STR_PTR for non-greedy plus quantifier. */ |
8067 |
if (opcode != OP_ONCE) |
if (opcode != OP_ONCE) |
8068 |
free_stack(common, 1); |
free_stack(common, 1); |
8069 |
} |
} |
8070 |
else |
else |
8071 |
JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
8072 |
} |
} |
8073 |
rminlabel = LABEL(); |
rmin_label = LABEL(); |
8074 |
|
if (repeat_type != 0) |
8075 |
|
OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
8076 |
} |
} |
8077 |
else if (bra == OP_BRAZERO) |
else if (bra == OP_BRAZERO) |
8078 |
{ |
{ |
8080 |
free_stack(common, 1); |
free_stack(common, 1); |
8081 |
brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); |
brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); |
8082 |
} |
} |
8083 |
|
else if (repeat_type == OP_EXACT) |
8084 |
|
{ |
8085 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
8086 |
|
exact_label = LABEL(); |
8087 |
|
} |
8088 |
|
|
8089 |
if (offset != 0) |
if (offset != 0) |
8090 |
{ |
{ |
8204 |
current->top = NULL; |
current->top = NULL; |
8205 |
current->topbacktracks = NULL; |
current->topbacktracks = NULL; |
8206 |
current->nextbacktracks = NULL; |
current->nextbacktracks = NULL; |
8207 |
|
/* Conditional blocks always have an additional alternative, even if it is empty. */ |
8208 |
if (*cc == OP_ALT) |
if (*cc == OP_ALT) |
8209 |
{ |
{ |
8210 |
ccprev = cc + 1 + LINK_SIZE; |
ccprev = cc + 1 + LINK_SIZE; |
8211 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
8212 |
if (opcode != OP_COND && opcode != OP_SCOND) |
if (opcode != OP_COND && opcode != OP_SCOND) |
8213 |
{ |
{ |
8214 |
if (private_data_ptr != 0 && opcode != OP_ONCE) |
if (opcode != OP_ONCE) |
8215 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
{ |
8216 |
|
if (private_data_ptr != 0) |
8217 |
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
8218 |
|
else |
8219 |
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8220 |
|
} |
8221 |
else |
else |
8222 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0)); |
8223 |
} |
} |
8224 |
compile_matchingpath(common, ccprev, cc, current); |
compile_matchingpath(common, ccprev, cc, current); |
8225 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
8229 |
/* Instructions after the current alternative is succesfully matched. */ |
/* Instructions after the current alternative is succesfully matched. */ |
8230 |
/* There is a similar code in compile_bracket_matchingpath. */ |
/* There is a similar code in compile_bracket_matchingpath. */ |
8231 |
if (opcode == OP_ONCE) |
if (opcode == OP_ONCE) |
8232 |
{ |
match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); |
|
if (CURRENT_AS(bracket_backtrack)->u.framesize < 0) |
|
|
{ |
|
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
|
|
/* TMP2 which is set here used by OP_KETRMAX below. */ |
|
|
if (ket == OP_KETRMAX) |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); |
|
|
else if (ket == OP_KETRMIN) |
|
|
{ |
|
|
/* Move the STR_PTR to the private_data_ptr. */ |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize + 2) * sizeof(sljit_sw)); |
|
|
if (ket == OP_KETRMAX) |
|
|
{ |
|
|
/* TMP2 which is set here used by OP_KETRMAX below. */ |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
|
|
} |
|
|
} |
|
|
} |
|
8233 |
|
|
8234 |
stacksize = 0; |
stacksize = 0; |
8235 |
|
if (repeat_type == OP_MINUPTO) |
8236 |
|
{ |
8237 |
|
/* We need to preserve the counter. TMP2 will be used below. */ |
8238 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); |
8239 |
|
stacksize++; |
8240 |
|
} |
8241 |
if (ket != OP_KET || bra != OP_BRA) |
if (ket != OP_KET || bra != OP_BRA) |
8242 |
stacksize++; |
stacksize++; |
8243 |
if (offset != 0) |
if (offset != 0) |
8250 |
if (opcode != OP_ONCE) |
if (opcode != OP_ONCE) |
8251 |
stacksize++; |
stacksize++; |
8252 |
|
|
8253 |
if (stacksize > 0) { |
if (stacksize > 0) |
8254 |
if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
allocate_stack(common, stacksize); |
|
allocate_stack(common, stacksize); |
|
|
else |
|
|
{ |
|
|
/* We know we have place at least for one item on the top of the stack. */ |
|
|
SLJIT_ASSERT(stacksize == 1); |
|
|
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
|
|
} |
|
|
} |
|
8255 |
|
|
8256 |
stacksize = 0; |
stacksize = 0; |
8257 |
|
if (repeat_type == OP_MINUPTO) |
8258 |
|
{ |
8259 |
|
/* TMP2 was set above. */ |
8260 |
|
OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1); |
8261 |
|
stacksize++; |
8262 |
|
} |
8263 |
|
|
8264 |
if (ket != OP_KET || bra != OP_BRA) |
if (ket != OP_KET || bra != OP_BRA) |
8265 |
{ |
{ |
8266 |
if (ket != OP_KET) |
if (ket != OP_KET) |
8271 |
} |
} |
8272 |
|
|
8273 |
if (offset != 0) |
if (offset != 0) |
8274 |
{ |
stacksize = match_capture_common(common, stacksize, offset, private_data_ptr); |
|
if (common->capture_last_ptr != 0) |
|
|
{ |
|
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
|
|
stacksize++; |
|
|
} |
|
|
if (common->optimized_cbracket[offset >> 1] == 0) |
|
|
{ |
|
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
|
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
|
|
stacksize += 2; |
|
|
} |
|
|
} |
|
8275 |
|
|
8276 |
if (opcode != OP_ONCE) |
if (opcode != OP_ONCE) |
8277 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++); |
8305 |
SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); |
SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); |
8306 |
assert = CURRENT_AS(bracket_backtrack)->u.assert; |
assert = CURRENT_AS(bracket_backtrack)->u.assert; |
8307 |
if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) |
if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) |
|
|
|
8308 |
{ |
{ |
8309 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr); |
8310 |
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
8344 |
else if (opcode == OP_ONCE) |
else if (opcode == OP_ONCE) |
8345 |
{ |
{ |
8346 |
cc = ccbegin + GET(ccbegin, 1); |
cc = ccbegin + GET(ccbegin, 1); |
8347 |
|
stacksize = needs_control_head ? 1 : 0; |
8348 |
|
|
8349 |
if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
8350 |
{ |
{ |
8351 |
/* Reset head and drop saved frame. */ |
/* Reset head and drop saved frame. */ |
8352 |
stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1; |
stacksize += CURRENT_AS(bracket_backtrack)->u.framesize + ((ket != OP_KET || *cc == OP_ALT) ? 2 : 1); |
|
free_stack(common, CURRENT_AS(bracket_backtrack)->u.framesize + stacksize); |
|
8353 |
} |
} |
8354 |
else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) |
else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) |
8355 |
{ |
{ |
8356 |
/* The STR_PTR must be released. */ |
/* The STR_PTR must be released. */ |
8357 |
free_stack(common, 1); |
stacksize++; |
8358 |
} |
} |
8359 |
|
free_stack(common, stacksize); |
8360 |
|
|
8361 |
JUMPHERE(once); |
JUMPHERE(once); |
8362 |
/* Restore previous private_data_ptr */ |
/* Restore previous private_data_ptr */ |
8371 |
} |
} |
8372 |
} |
} |
8373 |
|
|
8374 |
if (ket == OP_KETRMAX) |
if (repeat_type == OP_EXACT) |
8375 |
|
{ |
8376 |
|
OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
8377 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0); |
8378 |
|
CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label); |
8379 |
|
} |
8380 |
|
else if (ket == OP_KETRMAX) |
8381 |
{ |
{ |
8382 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8383 |
if (bra != OP_BRAZERO) |
if (bra != OP_BRAZERO) |
8384 |
free_stack(common, 1); |
free_stack(common, 1); |
8385 |
|
|
8386 |
CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
8387 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
8388 |
{ |
{ |
8401 |
affect badly the free_stack(2) above. */ |
affect badly the free_stack(2) above. */ |
8402 |
if (opcode != OP_ONCE) |
if (opcode != OP_ONCE) |
8403 |
free_stack(common, 1); |
free_stack(common, 1); |
8404 |
CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel); |
CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label); |
8405 |
if (opcode == OP_ONCE) |
if (opcode == OP_ONCE) |
8406 |
free_stack(common, bra == OP_BRAMINZERO ? 2 : 1); |
free_stack(common, bra == OP_BRAMINZERO ? 2 : 1); |
8407 |
else if (bra == OP_BRAMINZERO) |
else if (bra == OP_BRAMINZERO) |
8415 |
} |
} |
8416 |
} |
} |
8417 |
|
|
8418 |
static void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static SLJIT_INLINE void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8419 |
{ |
{ |
8420 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
8421 |
int offset; |
int offset; |
8454 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_sw)); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_sw)); |
8455 |
} |
} |
8456 |
|
|
8457 |
static void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8458 |
{ |
{ |
8459 |
assert_backtrack backtrack; |
assert_backtrack backtrack; |
8460 |
|
|
8478 |
SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks); |
SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks); |
8479 |
} |
} |
8480 |
|
|
8481 |
|
static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8482 |
|
{ |
8483 |
|
DEFINE_COMPILER; |
8484 |
|
pcre_uchar opcode = *current->cc; |
8485 |
|
struct sljit_label *loop; |
8486 |
|
struct sljit_jump *jump; |
8487 |
|
|
8488 |
|
if (opcode == OP_THEN || opcode == OP_THEN_ARG) |
8489 |
|
{ |
8490 |
|
if (common->then_trap != NULL) |
8491 |
|
{ |
8492 |
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
8493 |
|
|
8494 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
8495 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap); |
8496 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start); |
8497 |
|
jump = JUMP(SLJIT_JUMP); |
8498 |
|
|
8499 |
|
loop = LABEL(); |
8500 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw)); |
8501 |
|
JUMPHERE(jump); |
8502 |
|
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop); |
8503 |
|
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop); |
8504 |
|
add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP)); |
8505 |
|
return; |
8506 |
|
} |
8507 |
|
else if (common->positive_assert) |
8508 |
|
{ |
8509 |
|
add_jump(compiler, &common->positive_assert_quit, JUMP(SLJIT_JUMP)); |
8510 |
|
return; |
8511 |
|
} |
8512 |
|
} |
8513 |
|
|
8514 |
|
if (common->local_exit) |
8515 |
|
{ |
8516 |
|
if (common->quit_label == NULL) |
8517 |
|
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
8518 |
|
else |
8519 |
|
JUMPTO(SLJIT_JUMP, common->quit_label); |
8520 |
|
return; |
8521 |
|
} |
8522 |
|
|
8523 |
|
if (opcode == OP_SKIP_ARG) |
8524 |
|
{ |
8525 |
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
8526 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
8527 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
8528 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); |
8529 |
|
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark)); |
8530 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
8531 |
|
|
8532 |
|
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); |
8533 |
|
add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); |
8534 |
|
return; |
8535 |
|
} |
8536 |
|
|
8537 |
|
if (opcode == OP_SKIP) |
8538 |
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8539 |
|
else |
8540 |
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0); |
8541 |
|
add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP)); |
8542 |
|
} |
8543 |
|
|
8544 |
|
static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8545 |
|
{ |
8546 |
|
DEFINE_COMPILER; |
8547 |
|
struct sljit_jump *jump; |
8548 |
|
int size; |
8549 |
|
|
8550 |
|
if (CURRENT_AS(then_trap_backtrack)->then_trap) |
8551 |
|
{ |
8552 |
|
common->then_trap = CURRENT_AS(then_trap_backtrack)->then_trap; |
8553 |
|
return; |
8554 |
|
} |
8555 |
|
|
8556 |
|
size = CURRENT_AS(then_trap_backtrack)->framesize; |
8557 |
|
size = 3 + (size < 0 ? 0 : size); |
8558 |
|
|
8559 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 3)); |
8560 |
|
free_stack(common, size); |
8561 |
|
jump = JUMP(SLJIT_JUMP); |
8562 |
|
|
8563 |
|
set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL()); |
8564 |
|
/* STACK_TOP is set by THEN. */ |
8565 |
|
if (CURRENT_AS(then_trap_backtrack)->framesize >= 0) |
8566 |
|
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
8567 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8568 |
|
free_stack(common, 3); |
8569 |
|
|
8570 |
|
JUMPHERE(jump); |
8571 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0); |
8572 |
|
} |
8573 |
|
|
8574 |
static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8575 |
{ |
{ |
8576 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
8577 |
|
then_trap_backtrack *save_then_trap = common->then_trap; |
8578 |
|
|
8579 |
while (current) |
while (current) |
8580 |
{ |
{ |
8708 |
break; |
break; |
8709 |
|
|
8710 |
case OP_MARK: |
case OP_MARK: |
8711 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0)); |
8712 |
free_stack(common, 1); |
if (common->has_skip_arg) |
8713 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8714 |
|
free_stack(common, common->has_skip_arg ? 5 : 1); |
8715 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0); |
8716 |
|
if (common->has_skip_arg) |
8717 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP2, 0); |
8718 |
|
break; |
8719 |
|
|
8720 |
|
case OP_THEN: |
8721 |
|
case OP_THEN_ARG: |
8722 |
|
case OP_PRUNE: |
8723 |
|
case OP_PRUNE_ARG: |
8724 |
|
case OP_SKIP: |
8725 |
|
case OP_SKIP_ARG: |
8726 |
|
compile_control_verb_backtrackingpath(common, current); |
8727 |
break; |
break; |
8728 |
|
|
8729 |
case OP_COMMIT: |
case OP_COMMIT: |
8730 |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
if (!common->local_exit) |
8731 |
|
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
8732 |
if (common->quit_label == NULL) |
if (common->quit_label == NULL) |
8733 |
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
8734 |
else |
else |
8742 |
set_jumps(current->topbacktracks, LABEL()); |
set_jumps(current->topbacktracks, LABEL()); |
8743 |
break; |
break; |
8744 |
|
|
8745 |
|
case OP_THEN_TRAP: |
8746 |
|
/* A virtual opcode for then traps. */ |
8747 |
|
compile_then_trap_backtrackingpath(common, current); |
8748 |
|
break; |
8749 |
|
|
8750 |
default: |
default: |
8751 |
SLJIT_ASSERT_STOP(); |
SLJIT_ASSERT_STOP(); |
8752 |
break; |
break; |
8753 |
} |
} |
8754 |
current = current->prev; |
current = current->prev; |
8755 |
} |
} |
8756 |
|
common->then_trap = save_then_trap; |
8757 |
} |
} |
8758 |
|
|
8759 |
static SLJIT_INLINE void compile_recurse(compiler_common *common) |
static SLJIT_INLINE void compile_recurse(compiler_common *common) |
8762 |
pcre_uchar *cc = common->start + common->currententry->start; |
pcre_uchar *cc = common->start + common->currententry->start; |
8763 |
pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE); |
pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE); |
8764 |
pcre_uchar *ccend = bracketend(cc); |
pcre_uchar *ccend = bracketend(cc); |
8765 |
int private_data_size = get_private_data_length_for_copy(common, ccbegin, ccend); |
BOOL needs_control_head; |
8766 |
int framesize = get_framesize(common, cc, TRUE); |
int framesize = get_framesize(common, cc, NULL, TRUE, &needs_control_head); |
8767 |
|
int private_data_size = get_private_data_copy_length(common, ccbegin, ccend, needs_control_head); |
8768 |
int alternativesize; |
int alternativesize; |
8769 |
BOOL needsframe; |
BOOL needs_frame; |
8770 |
backtrack_common altbacktrack; |
backtrack_common altbacktrack; |
|
struct sljit_label *save_quit_label = common->quit_label; |
|
|
jump_list *save_quit = common->quit; |
|
8771 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
8772 |
|
|
8773 |
|
/* Recurse captures then. */ |
8774 |
|
common->then_trap = NULL; |
8775 |
|
|
8776 |
SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS); |
SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS); |
8777 |
needsframe = framesize >= 0; |
needs_frame = framesize >= 0; |
8778 |
if (!needsframe) |
if (!needs_frame) |
8779 |
framesize = 0; |
framesize = 0; |
8780 |
alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0; |
alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0; |
8781 |
|
|
8786 |
sljit_emit_fast_enter(compiler, TMP2, 0); |
sljit_emit_fast_enter(compiler, TMP2, 0); |
8787 |
allocate_stack(common, private_data_size + framesize + alternativesize); |
allocate_stack(common, private_data_size + framesize + alternativesize); |
8788 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0); |
8789 |
copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize); |
copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head); |
8790 |
|
if (needs_control_head) |
8791 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
8792 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, STACK_TOP, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, STACK_TOP, 0); |
8793 |
if (needsframe) |
if (needs_frame) |
8794 |
init_frame(common, cc, framesize + alternativesize - 1, alternativesize, TRUE); |
init_frame(common, cc, NULL, framesize + alternativesize - 1, alternativesize, TRUE); |
8795 |
|
|
8796 |
if (alternativesize > 0) |
if (alternativesize > 0) |
8797 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
8813 |
|
|
8814 |
compile_matchingpath(common, altbacktrack.cc, cc, &altbacktrack); |
compile_matchingpath(common, altbacktrack.cc, cc, &altbacktrack); |
8815 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
|
{ |
|
|
common->quit_label = save_quit_label; |
|
|
common->quit = save_quit; |
|
8816 |
return; |
return; |
|
} |
|
8817 |
|
|
8818 |
add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); |
add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); |
8819 |
|
|
8820 |
compile_backtrackingpath(common, altbacktrack.top); |
compile_backtrackingpath(common, altbacktrack.top); |
8821 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
|
{ |
|
|
common->quit_label = save_quit_label; |
|
|
common->quit = save_quit; |
|
8822 |
return; |
return; |
|
} |
|
8823 |
set_jumps(altbacktrack.topbacktracks, LABEL()); |
set_jumps(altbacktrack.topbacktracks, LABEL()); |
8824 |
|
|
8825 |
if (*cc != OP_ALT) |
if (*cc != OP_ALT) |
8828 |
altbacktrack.cc = cc + 1 + LINK_SIZE; |
altbacktrack.cc = cc + 1 + LINK_SIZE; |
8829 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
8830 |
} |
} |
|
/* None of them matched. */ |
|
|
if (common->quit != NULL) |
|
|
set_jumps(common->quit, LABEL()); |
|
8831 |
|
|
8832 |
|
/* None of them matched. */ |
8833 |
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); |
8834 |
jump = JUMP(SLJIT_JUMP); |
jump = JUMP(SLJIT_JUMP); |
8835 |
|
|
8836 |
|
if (common->quit != NULL) |
8837 |
|
{ |
8838 |
|
set_jumps(common->quit, LABEL()); |
8839 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr); |
8840 |
|
if (needs_frame) |
8841 |
|
{ |
8842 |
|
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); |
8843 |
|
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
8844 |
|
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); |
8845 |
|
} |
8846 |
|
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); |
8847 |
|
common->quit = NULL; |
8848 |
|
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
8849 |
|
} |
8850 |
|
|
8851 |
set_jumps(common->accept, LABEL()); |
set_jumps(common->accept, LABEL()); |
8852 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr); |
8853 |
if (needsframe) |
if (needs_frame) |
8854 |
{ |
{ |
8855 |
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); |
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); |
8856 |
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
8859 |
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); |
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); |
8860 |
|
|
8861 |
JUMPHERE(jump); |
JUMPHERE(jump); |
8862 |
copy_private_data(common, ccbegin, ccend, FALSE, private_data_size + framesize + alternativesize, framesize + alternativesize); |
if (common->quit != NULL) |
8863 |
|
set_jumps(common->quit, LABEL()); |
8864 |
|
copy_private_data(common, ccbegin, ccend, FALSE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head); |
8865 |
free_stack(common, private_data_size + framesize + alternativesize); |
free_stack(common, private_data_size + framesize + alternativesize); |
8866 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw)); |
if (needs_control_head) |
8867 |
OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); |
{ |
8868 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, TMP2, 0); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 2 * sizeof(sljit_sw)); |
8869 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw)); |
8870 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, TMP1, 0); |
8871 |
|
OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); |
8872 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP2, 0); |
8873 |
|
} |
8874 |
|
else |
8875 |
|
{ |
8876 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw)); |
8877 |
|
OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); |
8878 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, TMP2, 0); |
8879 |
|
} |
8880 |
sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0); |
sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0); |
|
|
|
|
common->quit_label = save_quit_label; |
|
|
common->quit = save_quit; |
|
8881 |
} |
} |
8882 |
|
|
8883 |
#undef COMPILE_BACKTRACKINGPATH |
#undef COMPILE_BACKTRACKINGPATH |
8897 |
executable_functions *functions; |
executable_functions *functions; |
8898 |
void *executable_func; |
void *executable_func; |
8899 |
sljit_uw executable_size; |
sljit_uw executable_size; |
8900 |
struct sljit_label *mainloop = NULL; |
struct sljit_label *mainloop_label = NULL; |
8901 |
struct sljit_label *empty_match_found; |
struct sljit_label *continue_match_label; |
8902 |
struct sljit_label *empty_match_backtrack; |
struct sljit_label *empty_match_found_label; |
8903 |
|
struct sljit_label *empty_match_backtrack_label; |
8904 |
|
struct sljit_label *reset_match_label; |
8905 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
8906 |
struct sljit_jump *minlength_check_failed = NULL; |
struct sljit_jump *minlength_check_failed = NULL; |
8907 |
struct sljit_jump *reqbyte_notfound = NULL; |
struct sljit_jump *reqbyte_notfound = NULL; |
8908 |
struct sljit_jump *empty_match; |
struct sljit_jump *empty_match; |
8909 |
|
struct sljit_label *quit_label; |
8910 |
|
|
8911 |
SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0); |
SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0); |
8912 |
study = extra->study_data; |
study = extra->study_data; |
8986 |
common->capture_last_ptr = common->ovector_start; |
common->capture_last_ptr = common->ovector_start; |
8987 |
common->ovector_start += sizeof(sljit_sw); |
common->ovector_start += sizeof(sljit_sw); |
8988 |
#endif |
#endif |
8989 |
private_data_size = get_private_data_length(common, rootbacktrack.cc, ccend); |
if (!check_opcode_types(common, rootbacktrack.cc, ccend)) |
|
if (private_data_size < 0) |
|
8990 |
{ |
{ |
8991 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
8992 |
return; |
return; |
9001 |
if (mode != JIT_COMPILE) |
if (mode != JIT_COMPILE) |
9002 |
{ |
{ |
9003 |
common->start_used_ptr = common->ovector_start; |
common->start_used_ptr = common->ovector_start; |
9004 |
common->ovector_start += 2 * sizeof(sljit_sw); |
common->ovector_start += sizeof(sljit_sw); |
9005 |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
9006 |
{ |
{ |
9007 |
common->hit_start = common->ovector_start; |
common->hit_start = common->ovector_start; |
9008 |
common->ovector_start += 2 * sizeof(sljit_sw); |
common->ovector_start += 2 * sizeof(sljit_sw); |
9009 |
} |
} |
9010 |
|
else |
9011 |
|
{ |
9012 |
|
SLJIT_ASSERT(mode == JIT_PARTIAL_HARD_COMPILE); |
9013 |
|
common->needs_start_ptr = TRUE; |
9014 |
|
} |
9015 |
} |
} |
9016 |
if ((re->options & PCRE_FIRSTLINE) != 0) |
if ((re->options & PCRE_FIRSTLINE) != 0) |
9017 |
{ |
{ |
9018 |
common->first_line_end = common->ovector_start; |
common->first_line_end = common->ovector_start; |
9019 |
common->ovector_start += sizeof(sljit_sw); |
common->ovector_start += sizeof(sljit_sw); |
9020 |
} |
} |
9021 |
|
#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD |
9022 |
|
common->control_head_ptr = 1; |
9023 |
|
#endif |
9024 |
|
if (common->control_head_ptr != 0) |
9025 |
|
{ |
9026 |
|
common->control_head_ptr = common->ovector_start; |
9027 |
|
common->ovector_start += sizeof(sljit_sw); |
9028 |
|
} |
9029 |
|
if (common->needs_start_ptr && common->has_set_som) |
9030 |
|
{ |
9031 |
|
/* Saving the real start pointer is necessary. */ |
9032 |
|
common->start_ptr = common->ovector_start; |
9033 |
|
common->ovector_start += sizeof(sljit_sw); |
9034 |
|
} |
9035 |
|
else |
9036 |
|
common->needs_start_ptr = FALSE; |
9037 |
|
|
9038 |
/* Aligning ovector to even number of sljit words. */ |
/* Aligning ovector to even number of sljit words. */ |
9039 |
if ((common->ovector_start & sizeof(sljit_sw)) != 0) |
if ((common->ovector_start & sizeof(sljit_sw)) != 0) |
9040 |
common->ovector_start += sizeof(sljit_sw); |
common->ovector_start += sizeof(sljit_sw); |
9041 |
|
|
9042 |
|
if (common->start_ptr == 0) |
9043 |
|
common->start_ptr = OVECTOR(0); |
9044 |
|
|
9045 |
/* Capturing brackets cannot be optimized if callouts are allowed. */ |
/* Capturing brackets cannot be optimized if callouts are allowed. */ |
9046 |
if (common->capture_last_ptr != 0) |
if (common->capture_last_ptr != 0) |
9047 |
memset(common->optimized_cbracket, 0, re->top_bracket + 1); |
memset(common->optimized_cbracket, 0, re->top_bracket + 1); |
9048 |
|
|
9049 |
SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); |
SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); |
9050 |
common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw); |
common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw); |
9051 |
private_data_size += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_sw); |
|
9052 |
if (private_data_size > SLJIT_MAX_LOCAL_SIZE) |
common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(sljit_si)); |
9053 |
|
if (!common->private_data_ptrs) |
9054 |
{ |
{ |
9055 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9056 |
return; |
return; |
9057 |
} |
} |
9058 |
common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(int)); |
memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int)); |
9059 |
if (!common->private_data_ptrs) |
|
9060 |
|
private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw); |
9061 |
|
set_private_data_ptrs(common, &private_data_size, ccend); |
9062 |
|
if (private_data_size > SLJIT_MAX_LOCAL_SIZE) |
9063 |
{ |
{ |
9064 |
|
SLJIT_FREE(common->private_data_ptrs); |
9065 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9066 |
return; |
return; |
9067 |
} |
} |
9068 |
memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int)); |
|
9069 |
set_private_data_ptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_sw), ccend); |
if (common->has_then) |
9070 |
|
{ |
9071 |
|
common->then_offsets = (pcre_uint8 *)SLJIT_MALLOC(ccend - rootbacktrack.cc); |
9072 |
|
if (!common->then_offsets) |
9073 |
|
{ |
9074 |
|
SLJIT_FREE(common->optimized_cbracket); |
9075 |
|
SLJIT_FREE(common->private_data_ptrs); |
9076 |
|
return; |
9077 |
|
} |
9078 |
|
memset(common->then_offsets, 0, ccend - rootbacktrack.cc); |
9079 |
|
set_then_offsets(common, rootbacktrack.cc, NULL); |
9080 |
|
} |
9081 |
|
|
9082 |
compiler = sljit_create_compiler(); |
compiler = sljit_create_compiler(); |
9083 |
if (!compiler) |
if (!compiler) |
9084 |
{ |
{ |
9085 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9086 |
SLJIT_FREE(common->private_data_ptrs); |
SLJIT_FREE(common->private_data_ptrs); |
9087 |
|
if (common->has_then) |
9088 |
|
SLJIT_FREE(common->then_offsets); |
9089 |
return; |
return; |
9090 |
} |
} |
9091 |
common->compiler = compiler; |
common->compiler = compiler; |
9109 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0); |
9110 |
|
|
9111 |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
9112 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); |
9113 |
|
if (common->mark_ptr != 0) |
9114 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); |
9115 |
|
if (common->control_head_ptr != 0) |
9116 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
9117 |
|
|
9118 |
/* Main part of the matching */ |
/* Main part of the matching */ |
9119 |
if ((re->options & PCRE_ANCHORED) == 0) |
if ((re->options & PCRE_ANCHORED) == 0) |
9120 |
{ |
{ |
9121 |
mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0); |
mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0); |
9122 |
|
continue_match_label = LABEL(); |
9123 |
/* Forward search if possible. */ |
/* Forward search if possible. */ |
9124 |
if ((re->options & PCRE_NO_START_OPTIMIZE) == 0) |
if ((re->options & PCRE_NO_START_OPTIMIZE) == 0) |
9125 |
{ |
{ |
9133 |
fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0); |
fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0); |
9134 |
} |
} |
9135 |
} |
} |
9136 |
|
else |
9137 |
|
continue_match_label = LABEL(); |
9138 |
|
|
9139 |
if (mode == JIT_COMPILE && study->minlength > 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) |
if (mode == JIT_COMPILE && study->minlength > 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) |
9140 |
{ |
{ |
9141 |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
9149 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); |
9150 |
/* Copy the limit of allowed recursions. */ |
/* Copy the limit of allowed recursions. */ |
9151 |
OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT); |
OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT); |
|
if (common->mark_ptr != 0) |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); |
|
9152 |
if (common->capture_last_ptr != 0) |
if (common->capture_last_ptr != 0) |
9153 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, -1); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, -1); |
9154 |
|
|
9155 |
|
if (common->needs_start_ptr) |
9156 |
|
{ |
9157 |
|
SLJIT_ASSERT(common->start_ptr != OVECTOR(0)); |
9158 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr, STR_PTR, 0); |
9159 |
|
} |
9160 |
|
else |
9161 |
|
SLJIT_ASSERT(common->start_ptr == OVECTOR(0)); |
9162 |
|
|
9163 |
/* Copy the beginning of the string. */ |
/* Copy the beginning of the string. */ |
9164 |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
9165 |
{ |
{ |
9166 |
jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); |
9167 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); |
9168 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr + sizeof(sljit_sw), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start + sizeof(sljit_sw), STR_PTR, 0); |
9169 |
JUMPHERE(jump); |
JUMPHERE(jump); |
9170 |
} |
} |
9171 |
else if (mode == JIT_PARTIAL_HARD_COMPILE) |
else if (mode == JIT_PARTIAL_HARD_COMPILE) |
|
{ |
|
9172 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr + sizeof(sljit_sw), STR_PTR, 0); |
|
|
} |
|
9173 |
|
|
9174 |
compile_matchingpath(common, rootbacktrack.cc, ccend, &rootbacktrack); |
compile_matchingpath(common, rootbacktrack.cc, ccend, &rootbacktrack); |
9175 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
9177 |
sljit_free_compiler(compiler); |
sljit_free_compiler(compiler); |
9178 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9179 |
SLJIT_FREE(common->private_data_ptrs); |
SLJIT_FREE(common->private_data_ptrs); |
9180 |
|
if (common->has_then) |
9181 |
|
SLJIT_FREE(common->then_offsets); |
9182 |
return; |
return; |
9183 |
} |
} |
9184 |
|
|
9185 |
empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
9186 |
empty_match_found = LABEL(); |
empty_match_found_label = LABEL(); |
9187 |
|
|
9188 |
common->accept_label = LABEL(); |
common->accept_label = LABEL(); |
9189 |
if (common->accept != NULL) |
if (common->accept != NULL) |
9207 |
return_with_partial_match(common, common->quit_label); |
return_with_partial_match(common, common->quit_label); |
9208 |
} |
} |
9209 |
|
|
9210 |
empty_match_backtrack = LABEL(); |
empty_match_backtrack_label = LABEL(); |
9211 |
compile_backtrackingpath(common, rootbacktrack.top); |
compile_backtrackingpath(common, rootbacktrack.top); |
9212 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
9213 |
{ |
{ |
9214 |
sljit_free_compiler(compiler); |
sljit_free_compiler(compiler); |
9215 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9216 |
SLJIT_FREE(common->private_data_ptrs); |
SLJIT_FREE(common->private_data_ptrs); |
9217 |
|
if (common->has_then) |
9218 |
|
SLJIT_FREE(common->then_offsets); |
9219 |
return; |
return; |
9220 |
} |
} |
9221 |
|
|
9222 |
SLJIT_ASSERT(rootbacktrack.prev == NULL); |
SLJIT_ASSERT(rootbacktrack.prev == NULL); |
9223 |
|
reset_match_label = LABEL(); |
9224 |
|
|
9225 |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
9226 |
{ |
{ |
9227 |
/* Update hit_start only in the first time. */ |
/* Update hit_start only in the first time. */ |
9228 |
jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); |
jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
9229 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr); |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr + sizeof(sljit_sw)); |
|
9230 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); |
9231 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, TMP1, 0); |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start + sizeof(sljit_sw), TMP2, 0); |
|
9232 |
JUMPHERE(jump); |
JUMPHERE(jump); |
9233 |
} |
} |
9234 |
|
|
9238 |
SLJIT_ASSERT(common->first_line_end != 0); |
SLJIT_ASSERT(common->first_line_end != 0); |
9239 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); |
9240 |
} |
} |
9241 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
|
9242 |
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); |
9243 |
|
|
9244 |
if ((re->options & PCRE_ANCHORED) == 0) |
if ((re->options & PCRE_ANCHORED) == 0) |
9245 |
{ |
{ |
9246 |
if ((re->options & PCRE_FIRSTLINE) == 0) |
if ((re->options & PCRE_FIRSTLINE) == 0) |
9247 |
CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); |
CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop_label); |
9248 |
else |
else |
9249 |
CMPTO(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0, mainloop); |
CMPTO(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0, mainloop_label); |
9250 |
} |
} |
9251 |
|
|
9252 |
/* No more remaining characters. */ |
/* No more remaining characters. */ |
9254 |
JUMPHERE(reqbyte_notfound); |
JUMPHERE(reqbyte_notfound); |
9255 |
|
|
9256 |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
if (mode == JIT_PARTIAL_SOFT_COMPILE) |
9257 |
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0, common->partialmatchlabel); |
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel); |
9258 |
|
|
9259 |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
9260 |
JUMPTO(SLJIT_JUMP, common->quit_label); |
JUMPTO(SLJIT_JUMP, common->quit_label); |
9264 |
JUMPHERE(empty_match); |
JUMPHERE(empty_match); |
9265 |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
9266 |
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); |
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); |
9267 |
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack); |
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label); |
9268 |
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); |
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); |
9269 |
CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found); |
CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label); |
9270 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); |
9271 |
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found); |
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label); |
9272 |
JUMPTO(SLJIT_JUMP, empty_match_backtrack); |
JUMPTO(SLJIT_JUMP, empty_match_backtrack_label); |
9273 |
|
|
9274 |
common->currententry = common->entries; |
common->currententry = common->entries; |
9275 |
|
common->local_exit = TRUE; |
9276 |
|
quit_label = common->quit_label; |
9277 |
while (common->currententry != NULL) |
while (common->currententry != NULL) |
9278 |
{ |
{ |
9279 |
/* Might add new entries. */ |
/* Might add new entries. */ |
9283 |
sljit_free_compiler(compiler); |
sljit_free_compiler(compiler); |
9284 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9285 |
SLJIT_FREE(common->private_data_ptrs); |
SLJIT_FREE(common->private_data_ptrs); |
9286 |
|
if (common->has_then) |
9287 |
|
SLJIT_FREE(common->then_offsets); |
9288 |
return; |
return; |
9289 |
} |
} |
9290 |
flush_stubs(common); |
flush_stubs(common); |
9291 |
common->currententry = common->currententry->next; |
common->currententry = common->currententry->next; |
9292 |
} |
} |
9293 |
|
common->local_exit = FALSE; |
9294 |
|
common->quit_label = quit_label; |
9295 |
|
|
9296 |
/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */ |
/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */ |
9297 |
/* This is a (really) rare case. */ |
/* This is a (really) rare case. */ |
9359 |
set_jumps(common->caselesscmp, LABEL()); |
set_jumps(common->caselesscmp, LABEL()); |
9360 |
do_caselesscmp(common); |
do_caselesscmp(common); |
9361 |
} |
} |
9362 |
|
if (common->reset_match != NULL) |
9363 |
|
{ |
9364 |
|
set_jumps(common->reset_match, LABEL()); |
9365 |
|
do_reset_match(common, (re->top_bracket + 1) * 2); |
9366 |
|
CMPTO(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label); |
9367 |
|
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); |
9368 |
|
JUMPTO(SLJIT_JUMP, reset_match_label); |
9369 |
|
} |
9370 |
#ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
9371 |
#ifndef COMPILE_PCRE32 |
#ifndef COMPILE_PCRE32 |
9372 |
if (common->utfreadchar != NULL) |
if (common->utfreadchar != NULL) |
9393 |
|
|
9394 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9395 |
SLJIT_FREE(common->private_data_ptrs); |
SLJIT_FREE(common->private_data_ptrs); |
9396 |
|
if (common->has_then) |
9397 |
|
SLJIT_FREE(common->then_offsets); |
9398 |
|
|
9399 |
executable_func = sljit_generate_code(compiler); |
executable_func = sljit_generate_code(compiler); |
9400 |
executable_size = sljit_get_generated_code_size(compiler); |
executable_size = sljit_get_generated_code_size(compiler); |
9401 |
sljit_free_compiler(compiler); |
sljit_free_compiler(compiler); |