196 |
struct stub_list *next; |
struct stub_list *next; |
197 |
} stub_list; |
} stub_list; |
198 |
|
|
|
enum bytecode_flag_types { |
|
|
flag_optimized_cbracket = 1, |
|
|
flag_then_start = 2, |
|
|
}; |
|
|
|
|
199 |
enum frame_types { |
enum frame_types { |
200 |
no_frame = -1, |
no_frame = -1, |
201 |
no_stack = -2 |
no_stack = -2 |
202 |
}; |
}; |
203 |
|
|
204 |
enum control_types { |
enum control_types { |
205 |
type_commit = 0, |
type_mark = 0, |
206 |
type_prune = 1, |
type_then_trap = 1 |
|
type_skip = 2, |
|
|
type_skip_arg = 3, |
|
|
type_mark = 4, |
|
|
type_then_trap = 5 |
|
207 |
}; |
}; |
208 |
|
|
209 |
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); |
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); |
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 { |
typedef struct then_trap_backtrack { |
296 |
backtrack_common common; |
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; |
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; |
jump_list *quit; |
304 |
|
/* Frame size of the current alternative. */ |
305 |
int framesize; |
int framesize; |
306 |
} then_trap_backtrack; |
} then_trap_backtrack; |
307 |
|
|
313 |
/* First byte code. */ |
/* 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. */ |
/* Tells whether the starting offset is a target of then. */ |
356 |
BOOL has_then; |
BOOL has_then; |
357 |
/* Needs to know the start position anytime. */ |
/* Needs to know the start position anytime. */ |
358 |
BOOL needs_start_ptr; |
BOOL needs_start_ptr; |
359 |
/* Currently in recurse or assert. */ |
/* Currently in recurse or negative assert. */ |
360 |
BOOL local_exit; |
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; |
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; |
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 |
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; |
int i, cbra_index; |
|
pcre_uint32 bracketlen; |
|
741 |
|
|
742 |
/* 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. */ |
743 |
while (cc < ccend) |
while (cc < ccend) |
744 |
{ |
{ |
|
space = 0; |
|
|
size = 0; |
|
|
bracketlen = 0; |
|
745 |
switch(*cc) |
switch(*cc) |
746 |
{ |
{ |
747 |
case OP_SET_SOM: |
case OP_SET_SOM: |
755 |
cc += 1 + IMM2_SIZE; |
cc += 1 + IMM2_SIZE; |
756 |
break; |
break; |
757 |
|
|
|
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; |
|
|
|
|
758 |
case OP_CBRAPOS: |
case OP_CBRAPOS: |
759 |
case OP_SCBRAPOS: |
case OP_SCBRAPOS: |
|
private_data_length += sizeof(sljit_sw); |
|
760 |
common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0; |
common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0; |
761 |
bracketlen = 1 + LINK_SIZE + IMM2_SIZE; |
cc += 1 + LINK_SIZE + IMM2_SIZE; |
762 |
break; |
break; |
763 |
|
|
764 |
case OP_COND: |
case OP_COND: |
766 |
/* Only AUTO_CALLOUT can insert this opcode. We do |
/* Only AUTO_CALLOUT can insert this opcode. We do |
767 |
not intend to support this case. */ |
not intend to support this case. */ |
768 |
if (cc[1 + LINK_SIZE] == OP_CALLOUT) |
if (cc[1 + LINK_SIZE] == OP_CALLOUT) |
769 |
return -1; |
return FALSE; |
770 |
|
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; |
|
771 |
break; |
break; |
772 |
|
|
773 |
case OP_CREF: |
case OP_CREF: |
777 |
break; |
break; |
778 |
|
|
779 |
case OP_NCREF: |
case OP_NCREF: |
780 |
bracketlen = GET2(cc, 1); |
cbra_index = GET2(cc, 1); |
781 |
name = (pcre_uchar *)common->name_table; |
name = (pcre_uchar *)common->name_table; |
782 |
alternative = name; |
name2 = name; |
783 |
for (i = 0; i < common->name_count; i++) |
for (i = 0; i < common->name_count; i++) |
784 |
{ |
{ |
785 |
if (GET2(name, 0) == bracketlen) break; |
if (GET2(name, 0) == cbra_index) break; |
786 |
name += common->name_entry_size; |
name += common->name_entry_size; |
787 |
} |
} |
788 |
SLJIT_ASSERT(i != common->name_count); |
SLJIT_ASSERT(i != common->name_count); |
789 |
|
|
790 |
for (i = 0; i < common->name_count; i++) |
for (i = 0; i < common->name_count; i++) |
791 |
{ |
{ |
792 |
if (STRCMP_UC_UC(alternative + IMM2_SIZE, name + IMM2_SIZE) == 0) |
if (STRCMP_UC_UC(name2 + IMM2_SIZE, name + IMM2_SIZE) == 0) |
793 |
common->optimized_cbracket[GET2(alternative, 0)] = 0; |
common->optimized_cbracket[GET2(name2, 0)] = 0; |
794 |
alternative += common->name_entry_size; |
name2 += common->name_entry_size; |
795 |
} |
} |
|
bracketlen = 0; |
|
796 |
cc += 1 + IMM2_SIZE; |
cc += 1 + IMM2_SIZE; |
797 |
break; |
break; |
798 |
|
|
|
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 |
|
|
|
|
799 |
case OP_RECURSE: |
case OP_RECURSE: |
800 |
/* Set its value only once. */ |
/* Set its value only once. */ |
801 |
if (common->recursive_head_ptr == 0) |
if (common->recursive_head_ptr == 0) |
817 |
|
|
818 |
case OP_THEN_ARG: |
case OP_THEN_ARG: |
819 |
common->has_then = TRUE; |
common->has_then = TRUE; |
820 |
|
common->control_head_ptr = 1; |
821 |
/* Fall through. */ |
/* Fall through. */ |
822 |
|
|
823 |
case OP_PRUNE_ARG: |
case OP_PRUNE_ARG: |
824 |
common->needs_start_ptr = TRUE; |
common->needs_start_ptr = TRUE; |
|
common->control_head_ptr = 1; |
|
825 |
/* Fall through. */ |
/* Fall through. */ |
826 |
|
|
827 |
case OP_MARK: |
case OP_MARK: |
835 |
|
|
836 |
case OP_THEN: |
case OP_THEN: |
837 |
common->has_then = TRUE; |
common->has_then = TRUE; |
838 |
|
common->control_head_ptr = 1; |
839 |
/* Fall through. */ |
/* Fall through. */ |
840 |
|
|
841 |
case OP_PRUNE: |
case OP_PRUNE: |
842 |
case OP_SKIP: |
case OP_SKIP: |
843 |
common->needs_start_ptr = TRUE; |
common->needs_start_ptr = TRUE; |
|
common->control_head_ptr = 1; |
|
844 |
cc += 1; |
cc += 1; |
845 |
break; |
break; |
846 |
|
|
853 |
default: |
default: |
854 |
cc = next_opcode(common, cc); |
cc = next_opcode(common, cc); |
855 |
if (cc == NULL) |
if (cc == NULL) |
856 |
return -1; |
return FALSE; |
857 |
break; |
break; |
858 |
} |
} |
859 |
|
} |
860 |
|
return TRUE; |
861 |
|
} |
862 |
|
|
863 |
if (space > 0 && cc >= end) |
static int get_class_iterator_size(pcre_uchar *cc) |
864 |
private_data_length += sizeof(sljit_sw) * space; |
{ |
865 |
|
switch(*cc) |
866 |
|
{ |
867 |
|
case OP_CRSTAR: |
868 |
|
case OP_CRPLUS: |
869 |
|
return 2; |
870 |
|
|
871 |
if (size != 0) |
case OP_CRMINSTAR: |
872 |
|
case OP_CRMINPLUS: |
873 |
|
case OP_CRQUERY: |
874 |
|
case OP_CRMINQUERY: |
875 |
|
return 1; |
876 |
|
|
877 |
|
case OP_CRRANGE: |
878 |
|
case OP_CRMINRANGE: |
879 |
|
if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE)) |
880 |
|
return 0; |
881 |
|
return 2; |
882 |
|
|
883 |
|
default: |
884 |
|
return 0; |
885 |
|
} |
886 |
|
} |
887 |
|
|
888 |
|
static BOOL detect_repeat(compiler_common *common, pcre_uchar *begin) |
889 |
|
{ |
890 |
|
pcre_uchar *end = bracketend(begin); |
891 |
|
pcre_uchar *next; |
892 |
|
pcre_uchar *next_end; |
893 |
|
pcre_uchar *max_end; |
894 |
|
pcre_uchar type; |
895 |
|
sljit_uw length = end - begin; |
896 |
|
int min, max, i; |
897 |
|
|
898 |
|
/* Detect fixed iterations first. */ |
899 |
|
if (end[-(1 + LINK_SIZE)] != OP_KET) |
900 |
|
return FALSE; |
901 |
|
|
902 |
|
/* Already detected repeat. */ |
903 |
|
if (common->private_data_ptrs[end - common->start - LINK_SIZE] != 0) |
904 |
|
return TRUE; |
905 |
|
|
906 |
|
next = end; |
907 |
|
min = 1; |
908 |
|
while (1) |
909 |
|
{ |
910 |
|
if (*next != *begin) |
911 |
|
break; |
912 |
|
next_end = bracketend(next); |
913 |
|
if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0) |
914 |
|
break; |
915 |
|
next = next_end; |
916 |
|
min++; |
917 |
|
} |
918 |
|
|
919 |
|
if (min == 2) |
920 |
|
return FALSE; |
921 |
|
|
922 |
|
max = 0; |
923 |
|
max_end = next; |
924 |
|
if (*next == OP_BRAZERO || *next == OP_BRAMINZERO) |
925 |
|
{ |
926 |
|
type = *next; |
927 |
|
while (1) |
928 |
{ |
{ |
929 |
if (size < 0) |
if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin) |
930 |
{ |
break; |
931 |
cc += -size; |
next_end = bracketend(next + 2 + LINK_SIZE); |
932 |
#ifdef SUPPORT_UTF |
if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0) |
933 |
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); |
break; |
934 |
#endif |
next = next_end; |
935 |
} |
max++; |
|
else |
|
|
cc += size; |
|
936 |
} |
} |
937 |
|
|
938 |
if (bracketlen != 0) |
if (next[0] == type && next[1] == *begin && max >= 1) |
939 |
{ |
{ |
940 |
if (cc >= end) |
next_end = bracketend(next + 1); |
941 |
|
if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0) |
942 |
{ |
{ |
943 |
end = bracketend(cc); |
for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE) |
944 |
if (end[-1 - LINK_SIZE] == OP_KET) |
if (*next_end != OP_KET) |
945 |
end = NULL; |
break; |
946 |
|
|
947 |
|
if (i == max) |
948 |
|
{ |
949 |
|
common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end; |
950 |
|
common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO; |
951 |
|
/* +2 the original and the last. */ |
952 |
|
common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2; |
953 |
|
if (min == 1) |
954 |
|
return TRUE; |
955 |
|
min--; |
956 |
|
max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE); |
957 |
|
} |
958 |
} |
} |
|
cc += bracketlen; |
|
959 |
} |
} |
960 |
} |
} |
961 |
return private_data_length; |
|
962 |
|
if (min >= 3) |
963 |
|
{ |
964 |
|
common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end; |
965 |
|
common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT; |
966 |
|
common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min; |
967 |
|
return TRUE; |
968 |
|
} |
969 |
|
|
970 |
|
return FALSE; |
971 |
} |
} |
972 |
|
|
973 |
static void set_private_data_ptrs(compiler_common *common, int private_data_ptr, pcre_uchar *ccend) |
#define CASE_ITERATOR_PRIVATE_DATA_1 \ |
974 |
|
case OP_MINSTAR: \ |
975 |
|
case OP_MINPLUS: \ |
976 |
|
case OP_QUERY: \ |
977 |
|
case OP_MINQUERY: \ |
978 |
|
case OP_MINSTARI: \ |
979 |
|
case OP_MINPLUSI: \ |
980 |
|
case OP_QUERYI: \ |
981 |
|
case OP_MINQUERYI: \ |
982 |
|
case OP_NOTMINSTAR: \ |
983 |
|
case OP_NOTMINPLUS: \ |
984 |
|
case OP_NOTQUERY: \ |
985 |
|
case OP_NOTMINQUERY: \ |
986 |
|
case OP_NOTMINSTARI: \ |
987 |
|
case OP_NOTMINPLUSI: \ |
988 |
|
case OP_NOTQUERYI: \ |
989 |
|
case OP_NOTMINQUERYI: |
990 |
|
|
991 |
|
#define CASE_ITERATOR_PRIVATE_DATA_2A \ |
992 |
|
case OP_STAR: \ |
993 |
|
case OP_PLUS: \ |
994 |
|
case OP_STARI: \ |
995 |
|
case OP_PLUSI: \ |
996 |
|
case OP_NOTSTAR: \ |
997 |
|
case OP_NOTPLUS: \ |
998 |
|
case OP_NOTSTARI: \ |
999 |
|
case OP_NOTPLUSI: |
1000 |
|
|
1001 |
|
#define CASE_ITERATOR_PRIVATE_DATA_2B \ |
1002 |
|
case OP_UPTO: \ |
1003 |
|
case OP_MINUPTO: \ |
1004 |
|
case OP_UPTOI: \ |
1005 |
|
case OP_MINUPTOI: \ |
1006 |
|
case OP_NOTUPTO: \ |
1007 |
|
case OP_NOTMINUPTO: \ |
1008 |
|
case OP_NOTUPTOI: \ |
1009 |
|
case OP_NOTMINUPTOI: |
1010 |
|
|
1011 |
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \ |
1012 |
|
case OP_TYPEMINSTAR: \ |
1013 |
|
case OP_TYPEMINPLUS: \ |
1014 |
|
case OP_TYPEQUERY: \ |
1015 |
|
case OP_TYPEMINQUERY: |
1016 |
|
|
1017 |
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \ |
1018 |
|
case OP_TYPESTAR: \ |
1019 |
|
case OP_TYPEPLUS: |
1020 |
|
|
1021 |
|
#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \ |
1022 |
|
case OP_TYPEUPTO: \ |
1023 |
|
case OP_TYPEMINUPTO: |
1024 |
|
|
1025 |
|
static void set_private_data_ptrs(compiler_common *common, int *private_data_start, pcre_uchar *ccend) |
1026 |
{ |
{ |
1027 |
pcre_uchar *cc = common->start; |
pcre_uchar *cc = common->start; |
1028 |
pcre_uchar *alternative; |
pcre_uchar *alternative; |
1029 |
pcre_uchar *end = NULL; |
pcre_uchar *end = NULL; |
1030 |
|
int private_data_ptr = *private_data_start; |
1031 |
int space, size, bracketlen; |
int space, size, bracketlen; |
1032 |
|
|
1033 |
while (cc < ccend) |
while (cc < ccend) |
1035 |
space = 0; |
space = 0; |
1036 |
size = 0; |
size = 0; |
1037 |
bracketlen = 0; |
bracketlen = 0; |
1038 |
|
if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) |
1039 |
|
return; |
1040 |
|
|
1041 |
|
if (*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_ONCE || *cc == OP_ONCE_NC) |
1042 |
|
if (detect_repeat(common, cc)) |
1043 |
|
{ |
1044 |
|
/* These brackets are converted to repeats, so no global |
1045 |
|
based single character repeat is allowed. */ |
1046 |
|
if (cc >= end) |
1047 |
|
end = bracketend(cc); |
1048 |
|
} |
1049 |
|
|
1050 |
switch(*cc) |
switch(*cc) |
1051 |
{ |
{ |
1052 |
|
case OP_KET: |
1053 |
|
if (common->private_data_ptrs[cc + 1 - common->start] != 0) |
1054 |
|
{ |
1055 |
|
common->private_data_ptrs[cc - common->start] = private_data_ptr; |
1056 |
|
private_data_ptr += sizeof(sljit_sw); |
1057 |
|
cc += common->private_data_ptrs[cc + 1 - common->start]; |
1058 |
|
} |
1059 |
|
cc += 1 + LINK_SIZE; |
1060 |
|
break; |
1061 |
|
|
1062 |
case OP_ASSERT: |
case OP_ASSERT: |
1063 |
case OP_ASSERT_NOT: |
case OP_ASSERT_NOT: |
1064 |
case OP_ASSERTBACK: |
case OP_ASSERTBACK: |
1152 |
break; |
break; |
1153 |
} |
} |
1154 |
|
|
1155 |
|
/* Character iterators, which are not inside a repeated bracket, |
1156 |
|
gets a private slot instead of allocating it on the stack. */ |
1157 |
if (space > 0 && cc >= end) |
if (space > 0 && cc >= end) |
1158 |
{ |
{ |
1159 |
common->private_data_ptrs[cc - common->start] = private_data_ptr; |
common->private_data_ptrs[cc - common->start] = private_data_ptr; |
1184 |
cc += bracketlen; |
cc += bracketlen; |
1185 |
} |
} |
1186 |
} |
} |
1187 |
|
*private_data_start = private_data_ptr; |
1188 |
} |
} |
1189 |
|
|
1190 |
/* Returns with a frame_types (always < 0) if no need for frame. */ |
/* Returns with a frame_types (always < 0) if no need for frame. */ |
1281 |
cc += 1 + LINK_SIZE + IMM2_SIZE; |
cc += 1 + LINK_SIZE + IMM2_SIZE; |
1282 |
break; |
break; |
1283 |
|
|
|
case OP_PRUNE: |
|
|
case OP_SKIP: |
|
|
case OP_SKIP_ARG: |
|
|
case OP_COMMIT: |
|
|
if (common->control_head_ptr != 0) |
|
|
*needs_control_head = TRUE; |
|
|
/* Fall through. */ |
|
|
|
|
1284 |
default: |
default: |
1285 |
stack_restore = TRUE; |
stack_restore = TRUE; |
1286 |
/* Fall through. */ |
/* Fall through. */ |
2090 |
OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); |
OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); |
2091 |
if (common->mark_ptr != 0) |
if (common->mark_ptr != 0) |
2092 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); |
2093 |
SLJIT_ASSERT(common->control_head_ptr != 0); |
if (common->control_head_ptr != 0) |
2094 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); |
2095 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); |
2096 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); |
2097 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); |
2098 |
} |
} |
2099 |
|
|
2100 |
static sljit_sw SLJIT_CALL do_check_control_chain(sljit_sw *current) |
static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg) |
2101 |
{ |
{ |
2102 |
sljit_sw return_value = 0; |
while (current != NULL) |
|
const pcre_uchar *skip_arg = NULL; |
|
|
|
|
|
SLJIT_ASSERT(current != NULL); |
|
|
do |
|
2103 |
{ |
{ |
2104 |
switch (current[-2]) |
switch (current[-2]) |
2105 |
{ |
{ |
|
case type_commit: |
|
|
/* Commit overwrites all. */ |
|
|
return -1; |
|
|
|
|
|
case type_prune: |
|
2106 |
case type_then_trap: |
case type_then_trap: |
2107 |
break; |
break; |
2108 |
|
|
|
case type_skip: |
|
|
/* Overwrites prune, but not other skips. */ |
|
|
if (return_value == 0 && skip_arg == NULL) |
|
|
return_value = current[-3]; |
|
|
break; |
|
|
|
|
|
case type_skip_arg: |
|
|
if (return_value == 0 && skip_arg == NULL) |
|
|
skip_arg = (pcre_uchar *)current[-3]; |
|
|
break; |
|
|
|
|
2109 |
case type_mark: |
case type_mark: |
2110 |
if (return_value == 0 && skip_arg != NULL) |
if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0) |
2111 |
if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0) |
return current[-4]; |
|
return_value = current[-4]; |
|
2112 |
break; |
break; |
2113 |
|
|
2114 |
default: |
default: |
2117 |
} |
} |
2118 |
current = (sljit_sw*)current[-1]; |
current = (sljit_sw*)current[-1]; |
2119 |
} |
} |
2120 |
while (current != NULL); |
return -1; |
|
return (return_value != 0 || skip_arg == NULL) ? return_value : -2; |
|
|
} |
|
|
|
|
|
static sljit_sw SLJIT_CALL do_search_then_trap(sljit_sw *current) |
|
|
{ |
|
|
do |
|
|
{ |
|
|
switch (current[-2]) |
|
|
{ |
|
|
case type_commit: |
|
|
/* Commit overwrites all. */ |
|
|
return 0; |
|
|
|
|
|
case type_then_trap: |
|
|
return (sljit_sw)current; |
|
|
|
|
|
case type_prune: |
|
|
case type_skip: |
|
|
case type_skip_arg: |
|
|
case type_mark: |
|
|
break; |
|
|
|
|
|
default: |
|
|
SLJIT_ASSERT_STOP(); |
|
|
break; |
|
|
} |
|
|
current = (sljit_sw*)current[-1]; |
|
|
SLJIT_ASSERT(current != NULL); |
|
|
} |
|
|
while (TRUE); |
|
2121 |
} |
} |
2122 |
|
|
2123 |
static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) |
static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) |
5325 |
backtrack_common *backtrack; |
backtrack_common *backtrack; |
5326 |
recurse_entry *entry = common->entries; |
recurse_entry *entry = common->entries; |
5327 |
recurse_entry *prev = NULL; |
recurse_entry *prev = NULL; |
5328 |
int start = GET(cc, 1); |
sljit_sw start = GET(cc, 1); |
5329 |
pcre_uchar *start_cc; |
pcre_uchar *start_cc; |
5330 |
BOOL needs_control_head; |
BOOL needs_control_head; |
5331 |
|
|
5503 |
jump_list **found; |
jump_list **found; |
5504 |
/* Saving previous accept variables. */ |
/* Saving previous accept variables. */ |
5505 |
BOOL save_local_exit = common->local_exit; |
BOOL save_local_exit = common->local_exit; |
5506 |
|
BOOL save_positive_assert = common->positive_assert; |
5507 |
then_trap_backtrack *save_then_trap = common->then_trap; |
then_trap_backtrack *save_then_trap = common->then_trap; |
5508 |
struct sljit_label *save_quit_label = common->quit_label; |
struct sljit_label *save_quit_label = common->quit_label; |
5509 |
struct sljit_label *save_accept_label = common->accept_label; |
struct sljit_label *save_accept_label = common->accept_label; |
5510 |
jump_list *save_quit = common->quit; |
jump_list *save_quit = common->quit; |
5511 |
|
jump_list *save_positive_assert_quit = common->positive_assert_quit; |
5512 |
jump_list *save_accept = common->accept; |
jump_list *save_accept = common->accept; |
5513 |
struct sljit_jump *jump; |
struct sljit_jump *jump; |
5514 |
struct sljit_jump *brajump = NULL; |
struct sljit_jump *brajump = NULL; |
5578 |
} |
} |
5579 |
|
|
5580 |
memset(&altbacktrack, 0, sizeof(backtrack_common)); |
memset(&altbacktrack, 0, sizeof(backtrack_common)); |
5581 |
common->local_exit = TRUE; |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5582 |
common->quit_label = NULL; |
{ |
5583 |
common->quit = NULL; |
/* Negative assert is stronger than positive assert. */ |
5584 |
|
common->local_exit = TRUE; |
5585 |
|
common->quit_label = NULL; |
5586 |
|
common->quit = NULL; |
5587 |
|
common->positive_assert = FALSE; |
5588 |
|
} |
5589 |
|
else |
5590 |
|
common->positive_assert = TRUE; |
5591 |
|
common->positive_assert_quit = NULL; |
5592 |
|
|
5593 |
while (1) |
while (1) |
5594 |
{ |
{ |
5595 |
common->accept_label = NULL; |
common->accept_label = NULL; |
5604 |
compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); |
compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); |
5605 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5606 |
{ |
{ |
5607 |
common->local_exit = save_local_exit; |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5608 |
|
{ |
5609 |
|
common->local_exit = save_local_exit; |
5610 |
|
common->quit_label = save_quit_label; |
5611 |
|
common->quit = save_quit; |
5612 |
|
} |
5613 |
|
common->positive_assert = save_positive_assert; |
5614 |
common->then_trap = save_then_trap; |
common->then_trap = save_then_trap; |
|
common->quit_label = save_quit_label; |
|
5615 |
common->accept_label = save_accept_label; |
common->accept_label = save_accept_label; |
5616 |
common->quit = save_quit; |
common->positive_assert_quit = save_positive_assert_quit; |
5617 |
common->accept = save_accept; |
common->accept = save_accept; |
5618 |
return NULL; |
return NULL; |
5619 |
} |
} |
5678 |
compile_backtrackingpath(common, altbacktrack.top); |
compile_backtrackingpath(common, altbacktrack.top); |
5679 |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5680 |
{ |
{ |
5681 |
common->local_exit = save_local_exit; |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5682 |
|
{ |
5683 |
|
common->local_exit = save_local_exit; |
5684 |
|
common->quit_label = save_quit_label; |
5685 |
|
common->quit = save_quit; |
5686 |
|
} |
5687 |
|
common->positive_assert = save_positive_assert; |
5688 |
common->then_trap = save_then_trap; |
common->then_trap = save_then_trap; |
|
common->quit_label = save_quit_label; |
|
5689 |
common->accept_label = save_accept_label; |
common->accept_label = save_accept_label; |
5690 |
common->quit = save_quit; |
common->positive_assert_quit = save_positive_assert_quit; |
5691 |
common->accept = save_accept; |
common->accept = save_accept; |
5692 |
return NULL; |
return NULL; |
5693 |
} |
} |
5700 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
5701 |
} |
} |
5702 |
|
|
5703 |
|
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5704 |
|
{ |
5705 |
|
SLJIT_ASSERT(common->positive_assert_quit == NULL); |
5706 |
|
/* Makes the check less complicated below. */ |
5707 |
|
common->positive_assert_quit = common->quit; |
5708 |
|
} |
5709 |
|
|
5710 |
/* None of them matched. */ |
/* None of them matched. */ |
5711 |
if (common->quit != NULL) |
if (common->positive_assert_quit != NULL) |
5712 |
{ |
{ |
5713 |
jump = JUMP(SLJIT_JUMP); |
jump = JUMP(SLJIT_JUMP); |
5714 |
set_jumps(common->quit, LABEL()); |
set_jumps(common->positive_assert_quit, LABEL()); |
5715 |
SLJIT_ASSERT(framesize != no_stack); |
SLJIT_ASSERT(framesize != no_stack); |
5716 |
if (framesize < 0) |
if (framesize < 0) |
5717 |
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); |
OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); |
5871 |
} |
} |
5872 |
} |
} |
5873 |
|
|
5874 |
common->local_exit = save_local_exit; |
if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5875 |
|
{ |
5876 |
|
common->local_exit = save_local_exit; |
5877 |
|
common->quit_label = save_quit_label; |
5878 |
|
common->quit = save_quit; |
5879 |
|
} |
5880 |
|
common->positive_assert = save_positive_assert; |
5881 |
common->then_trap = save_then_trap; |
common->then_trap = save_then_trap; |
|
common->quit_label = save_quit_label; |
|
5882 |
common->accept_label = save_accept_label; |
common->accept_label = save_accept_label; |
5883 |
common->quit = save_quit; |
common->positive_assert_quit = save_positive_assert_quit; |
5884 |
common->accept = save_accept; |
common->accept = save_accept; |
5885 |
return cc + 1 + LINK_SIZE; |
return cc + 1 + LINK_SIZE; |
5886 |
} |
} |
6128 |
int private_data_ptr = 0; |
int private_data_ptr = 0; |
6129 |
int offset = 0; |
int offset = 0; |
6130 |
int stacksize; |
int stacksize; |
6131 |
|
int repeat_ptr = 0, repeat_length = 0; |
6132 |
|
int repeat_type = 0, repeat_count = 0; |
6133 |
pcre_uchar *ccbegin; |
pcre_uchar *ccbegin; |
6134 |
pcre_uchar *matchingpath; |
pcre_uchar *matchingpath; |
6135 |
pcre_uchar bra = OP_BRA; |
pcre_uchar bra = OP_BRA; |
6153 |
|
|
6154 |
opcode = *cc; |
opcode = *cc; |
6155 |
ccbegin = cc; |
ccbegin = cc; |
6156 |
matchingpath = ccbegin + 1 + LINK_SIZE; |
matchingpath = bracketend(cc) - 1 - LINK_SIZE; |
6157 |
|
ket = *matchingpath; |
6158 |
|
if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0) |
6159 |
|
{ |
6160 |
|
repeat_ptr = PRIVATE_DATA(matchingpath); |
6161 |
|
repeat_length = PRIVATE_DATA(matchingpath + 1); |
6162 |
|
repeat_type = PRIVATE_DATA(matchingpath + 2); |
6163 |
|
repeat_count = PRIVATE_DATA(matchingpath + 3); |
6164 |
|
SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0); |
6165 |
|
if (repeat_type == OP_UPTO) |
6166 |
|
ket = OP_KETRMAX; |
6167 |
|
if (repeat_type == OP_MINUPTO) |
6168 |
|
ket = OP_KETRMIN; |
6169 |
|
} |
6170 |
|
|
6171 |
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) |
6172 |
{ |
{ |
6173 |
/* Drop this bracket_backtrack. */ |
/* Drop this bracket_backtrack. */ |
6174 |
parent->top = backtrack->prev; |
parent->top = backtrack->prev; |
6175 |
return bracketend(cc); |
return matchingpath + 1 + LINK_SIZE + repeat_length; |
6176 |
} |
} |
6177 |
|
|
6178 |
ket = *(bracketend(cc) - 1 - LINK_SIZE); |
matchingpath = ccbegin + 1 + LINK_SIZE; |
6179 |
SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); |
SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); |
6180 |
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))); |
6181 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
6289 |
} |
} |
6290 |
} |
} |
6291 |
|
|
6292 |
|
if (repeat_type != 0) |
6293 |
|
{ |
6294 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, repeat_count); |
6295 |
|
if (repeat_type == OP_EXACT) |
6296 |
|
rmaxlabel = LABEL(); |
6297 |
|
} |
6298 |
|
|
6299 |
if (ket == OP_KETRMIN) |
if (ket == OP_KETRMIN) |
6300 |
BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
6301 |
|
|
6302 |
if (ket == OP_KETRMAX) |
if (ket == OP_KETRMAX) |
6303 |
{ |
{ |
6304 |
rmaxlabel = LABEL(); |
rmaxlabel = LABEL(); |
6305 |
if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA) |
if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0) |
6306 |
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmaxlabel; |
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmaxlabel; |
6307 |
} |
} |
6308 |
|
|
6521 |
match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); |
match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); |
6522 |
|
|
6523 |
stacksize = 0; |
stacksize = 0; |
6524 |
|
if (repeat_type == OP_MINUPTO) |
6525 |
|
{ |
6526 |
|
/* We need to preserve the counter. TMP2 will be used below. */ |
6527 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); |
6528 |
|
stacksize++; |
6529 |
|
} |
6530 |
if (ket != OP_KET || bra != OP_BRA) |
if (ket != OP_KET || bra != OP_BRA) |
6531 |
stacksize++; |
stacksize++; |
6532 |
if (offset != 0) |
if (offset != 0) |
6543 |
allocate_stack(common, stacksize); |
allocate_stack(common, stacksize); |
6544 |
|
|
6545 |
stacksize = 0; |
stacksize = 0; |
6546 |
|
if (repeat_type == OP_MINUPTO) |
6547 |
|
{ |
6548 |
|
/* TMP2 was set above. */ |
6549 |
|
OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1); |
6550 |
|
stacksize++; |
6551 |
|
} |
6552 |
|
|
6553 |
if (ket != OP_KET || bra != OP_BRA) |
if (ket != OP_KET || bra != OP_BRA) |
6554 |
{ |
{ |
6555 |
if (ket != OP_KET) |
if (ket != OP_KET) |
6579 |
|
|
6580 |
if (ket == OP_KETRMAX) |
if (ket == OP_KETRMAX) |
6581 |
{ |
{ |
6582 |
if (opcode == OP_ONCE || opcode >= OP_SBRA) |
if (repeat_type != 0) |
6583 |
|
{ |
6584 |
|
if (has_alternatives) |
6585 |
|
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); |
6586 |
|
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
6587 |
|
JUMPTO(SLJIT_C_NOT_ZERO, rmaxlabel); |
6588 |
|
/* Drop STR_PTR for greedy plus quantifier. */ |
6589 |
|
if (opcode != OP_ONCE) |
6590 |
|
free_stack(common, 1); |
6591 |
|
} |
6592 |
|
else if (opcode == OP_ONCE || opcode >= OP_SBRA) |
6593 |
{ |
{ |
6594 |
if (has_alternatives) |
if (has_alternatives) |
6595 |
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); |
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); |
6610 |
BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); |
6611 |
} |
} |
6612 |
|
|
6613 |
|
if (repeat_type == OP_EXACT) |
6614 |
|
{ |
6615 |
|
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
6616 |
|
JUMPTO(SLJIT_C_NOT_ZERO, rmaxlabel); |
6617 |
|
} |
6618 |
|
else if (repeat_type == OP_UPTO) |
6619 |
|
{ |
6620 |
|
/* We need to preserve the counter. */ |
6621 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); |
6622 |
|
allocate_stack(common, 1); |
6623 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
6624 |
|
} |
6625 |
|
|
6626 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
6627 |
BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL(); |
BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL(); |
6628 |
|
|
6658 |
/* Temporarily encoding the needs_control_head in framesize. */ |
/* Temporarily encoding the needs_control_head in framesize. */ |
6659 |
if (opcode == OP_ONCE) |
if (opcode == OP_ONCE) |
6660 |
BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0); |
BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0); |
6661 |
return cc; |
return cc + repeat_length; |
6662 |
} |
} |
6663 |
|
|
6664 |
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) |
7319 |
pcre_uchar opcode = *cc; |
pcre_uchar opcode = *cc; |
7320 |
pcre_uchar *ccend = cc + 1; |
pcre_uchar *ccend = cc + 1; |
7321 |
|
|
|
SLJIT_ASSERT(common->control_head_ptr != 0 || *cc == OP_COMMIT); |
|
|
|
|
7322 |
if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG) |
if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG) |
7323 |
ccend += 2 + cc[1]; |
ccend += 2 + cc[1]; |
7324 |
|
|
7325 |
PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); |
PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); |
7326 |
|
|
7327 |
if (opcode == OP_SKIP || opcode == OP_SKIP_ARG) |
if (opcode == OP_SKIP) |
7328 |
{ |
{ |
7329 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
allocate_stack(common, 1); |
7330 |
allocate_stack(common, 3); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, *cc == OP_SKIP ? type_skip : type_skip_arg); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), (opcode == OP_SKIP) ? STR_PTR : SLJIT_IMM, (opcode == OP_SKIP) ? 0 : (sljit_sw)(cc + 2)); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
|
7331 |
return ccend; |
return ccend; |
7332 |
} |
} |
7333 |
|
|
7339 |
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); |
7340 |
} |
} |
7341 |
|
|
|
if (common->control_head_ptr != 0 && ((opcode != OP_THEN && opcode != OP_THEN_ARG) || common->then_trap == NULL)) |
|
|
{ |
|
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
|
|
allocate_stack(common, 2); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, *cc == OP_COMMIT ? type_commit : type_prune); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); |
|
|
} |
|
|
|
|
7342 |
return ccend; |
return ccend; |
7343 |
} |
} |
7344 |
|
|
7345 |
static pcre_uchar then_trap_opcode[1] = { OP_TABLE_LENGTH }; |
static pcre_uchar then_trap_opcode[1] = { OP_THEN_TRAP }; |
7346 |
|
|
7347 |
static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) |
static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) |
7348 |
{ |
{ |
7354 |
PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc); |
PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc); |
7355 |
common->then_trap = BACKTRACK_AS(then_trap_backtrack); |
common->then_trap = BACKTRACK_AS(then_trap_backtrack); |
7356 |
BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode; |
BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode; |
7357 |
|
BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start); |
7358 |
BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head); |
BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head); |
7359 |
|
|
7360 |
size = BACKTRACK_AS(then_trap_backtrack)->framesize; |
size = BACKTRACK_AS(then_trap_backtrack)->framesize; |
7361 |
size = 2 + (size < 0 ? 0 : size); |
size = 3 + (size < 0 ? 0 : size); |
7362 |
|
|
7363 |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
7364 |
allocate_stack(common, size); |
allocate_stack(common, size); |
7365 |
if (size > 2) |
if (size > 3) |
7366 |
OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 2) * sizeof(sljit_sw)); |
OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw)); |
7367 |
else |
else |
7368 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); |
7369 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, type_then_trap); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start); |
7370 |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap); |
7371 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0); |
7372 |
|
|
7373 |
size = BACKTRACK_AS(then_trap_backtrack)->framesize; |
size = BACKTRACK_AS(then_trap_backtrack)->framesize; |
7374 |
if (size >= 0) |
if (size >= 0) |
7945 |
static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
7946 |
{ |
{ |
7947 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
7948 |
int opcode; |
int opcode, stacksize, count; |
7949 |
int offset = 0; |
int offset = 0; |
7950 |
int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr; |
int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr; |
7951 |
int stacksize; |
int repeat_ptr = 0, repeat_type = 0, repeat_count = 0; |
|
int count; |
|
7952 |
pcre_uchar *cc = current->cc; |
pcre_uchar *cc = current->cc; |
7953 |
pcre_uchar *ccbegin; |
pcre_uchar *ccbegin; |
7954 |
pcre_uchar *ccprev; |
pcre_uchar *ccprev; |
7963 |
struct sljit_jump *once = NULL; |
struct sljit_jump *once = NULL; |
7964 |
struct sljit_jump *cond = NULL; |
struct sljit_jump *cond = NULL; |
7965 |
struct sljit_label *rminlabel = NULL; |
struct sljit_label *rminlabel = NULL; |
7966 |
|
struct sljit_label *exact_label = NULL; |
7967 |
|
|
7968 |
if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
7969 |
{ |
{ |
7972 |
} |
} |
7973 |
|
|
7974 |
opcode = *cc; |
opcode = *cc; |
7975 |
|
ccbegin = bracketend(cc) - 1 - LINK_SIZE; |
7976 |
|
ket = *ccbegin; |
7977 |
|
if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0) |
7978 |
|
{ |
7979 |
|
repeat_ptr = PRIVATE_DATA(ccbegin); |
7980 |
|
repeat_type = PRIVATE_DATA(ccbegin + 2); |
7981 |
|
repeat_count = PRIVATE_DATA(ccbegin + 3); |
7982 |
|
SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0); |
7983 |
|
if (repeat_type == OP_UPTO) |
7984 |
|
ket = OP_KETRMAX; |
7985 |
|
if (repeat_type == OP_MINUPTO) |
7986 |
|
ket = OP_KETRMIN; |
7987 |
|
} |
7988 |
ccbegin = cc; |
ccbegin = cc; |
|
ket = *(bracketend(ccbegin) - 1 - LINK_SIZE); |
|
7989 |
cc += GET(cc, 1); |
cc += GET(cc, 1); |
7990 |
has_alternatives = *cc == OP_ALT; |
has_alternatives = *cc == OP_ALT; |
7991 |
if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) |
if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) |
8004 |
CURRENT_AS(bracket_backtrack)->u.framesize >>= 1; |
CURRENT_AS(bracket_backtrack)->u.framesize >>= 1; |
8005 |
} |
} |
8006 |
|
|
8007 |
|
if (ket != OP_KET && repeat_type != 0) |
8008 |
|
{ |
8009 |
|
/* TMP1 is used in OP_KETRMIN below. */ |
8010 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8011 |
|
free_stack(common, 1); |
8012 |
|
if (repeat_type == OP_UPTO) |
8013 |
|
OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0, SLJIT_IMM, 1); |
8014 |
|
else |
8015 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0); |
8016 |
|
} |
8017 |
|
|
8018 |
if (ket == OP_KETRMAX) |
if (ket == OP_KETRMAX) |
8019 |
{ |
{ |
8020 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
8029 |
if (bra != OP_BRAMINZERO) |
if (bra != OP_BRAMINZERO) |
8030 |
{ |
{ |
8031 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8032 |
if (opcode >= OP_SBRA || opcode == OP_ONCE) |
if (repeat_type != 0) |
8033 |
|
{ |
8034 |
|
/* TMP1 was set a few lines above. */ |
8035 |
|
CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
8036 |
|
/* Drop STR_PTR for non-greedy plus quantifier. */ |
8037 |
|
if (opcode != OP_ONCE) |
8038 |
|
free_stack(common, 1); |
8039 |
|
} |
8040 |
|
else if (opcode >= OP_SBRA || opcode == OP_ONCE) |
8041 |
{ |
{ |
8042 |
/* Checking zero-length iteration. */ |
/* Checking zero-length iteration. */ |
8043 |
if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0) |
if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0) |
8047 |
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); |
8048 |
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); |
8049 |
} |
} |
8050 |
|
/* Drop STR_PTR for non-greedy plus quantifier. */ |
8051 |
if (opcode != OP_ONCE) |
if (opcode != OP_ONCE) |
8052 |
free_stack(common, 1); |
free_stack(common, 1); |
8053 |
} |
} |
8055 |
JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); |
8056 |
} |
} |
8057 |
rminlabel = LABEL(); |
rminlabel = LABEL(); |
8058 |
|
if (repeat_type != 0) |
8059 |
|
OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
8060 |
} |
} |
8061 |
else if (bra == OP_BRAZERO) |
else if (bra == OP_BRAZERO) |
8062 |
{ |
{ |
8064 |
free_stack(common, 1); |
free_stack(common, 1); |
8065 |
brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); |
brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); |
8066 |
} |
} |
8067 |
|
else if (repeat_type == OP_EXACT) |
8068 |
|
{ |
8069 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
8070 |
|
exact_label = LABEL(); |
8071 |
|
} |
8072 |
|
|
8073 |
if (offset != 0) |
if (offset != 0) |
8074 |
{ |
{ |
8216 |
match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); |
match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); |
8217 |
|
|
8218 |
stacksize = 0; |
stacksize = 0; |
8219 |
|
if (repeat_type == OP_MINUPTO) |
8220 |
|
{ |
8221 |
|
/* We need to preserve the counter. TMP2 will be used below. */ |
8222 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); |
8223 |
|
stacksize++; |
8224 |
|
} |
8225 |
if (ket != OP_KET || bra != OP_BRA) |
if (ket != OP_KET || bra != OP_BRA) |
8226 |
stacksize++; |
stacksize++; |
8227 |
if (offset != 0) |
if (offset != 0) |
8235 |
stacksize++; |
stacksize++; |
8236 |
|
|
8237 |
if (stacksize > 0) |
if (stacksize > 0) |
8238 |
|
allocate_stack(common, stacksize); |
8239 |
|
|
8240 |
|
stacksize = 0; |
8241 |
|
if (repeat_type == OP_MINUPTO) |
8242 |
{ |
{ |
8243 |
if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
/* TMP2 was set above. */ |
8244 |
allocate_stack(common, stacksize); |
OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1); |
8245 |
else |
stacksize++; |
|
{ |
|
|
/* 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)); |
|
|
} |
|
8246 |
} |
} |
8247 |
|
|
|
stacksize = 0; |
|
8248 |
if (ket != OP_KET || bra != OP_BRA) |
if (ket != OP_KET || bra != OP_BRA) |
8249 |
{ |
{ |
8250 |
if (ket != OP_KET) |
if (ket != OP_KET) |
8355 |
} |
} |
8356 |
} |
} |
8357 |
|
|
8358 |
if (ket == OP_KETRMAX) |
if (repeat_type == OP_EXACT) |
8359 |
|
{ |
8360 |
|
OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); |
8361 |
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0); |
8362 |
|
CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label); |
8363 |
|
} |
8364 |
|
else if (ket == OP_KETRMAX) |
8365 |
{ |
{ |
8366 |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8367 |
if (bra != OP_BRAZERO) |
if (bra != OP_BRAZERO) |
8368 |
free_stack(common, 1); |
free_stack(common, 1); |
8369 |
|
|
8370 |
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); |
8371 |
if (bra == OP_BRAZERO) |
if (bra == OP_BRAZERO) |
8372 |
{ |
{ |
8466 |
{ |
{ |
8467 |
DEFINE_COMPILER; |
DEFINE_COMPILER; |
8468 |
pcre_uchar opcode = *current->cc; |
pcre_uchar opcode = *current->cc; |
8469 |
|
struct sljit_label *loop; |
8470 |
|
struct sljit_jump *jump; |
8471 |
|
|
8472 |
SLJIT_ASSERT(common->control_head_ptr != 0); |
if (opcode == OP_THEN || opcode == OP_THEN_ARG) |
|
|
|
|
if ((opcode == OP_THEN || opcode == OP_THEN_ARG) && common->then_trap != NULL) |
|
8473 |
{ |
{ |
8474 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
if (common->then_trap != NULL) |
8475 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
{ |
8476 |
sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_then_trap)); |
SLJIT_ASSERT(common->control_head_ptr != 0); |
8477 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
|
8478 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
8479 |
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap); |
8480 |
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start); |
8481 |
|
jump = JUMP(SLJIT_JUMP); |
8482 |
|
|
8483 |
|
loop = LABEL(); |
8484 |
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw)); |
8485 |
|
JUMPHERE(jump); |
8486 |
|
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop); |
8487 |
|
CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop); |
8488 |
|
add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP)); |
8489 |
|
return; |
8490 |
|
} |
8491 |
|
else if (common->positive_assert) |
8492 |
|
{ |
8493 |
|
add_jump(compiler, &common->positive_assert_quit, JUMP(SLJIT_JUMP)); |
8494 |
|
return; |
8495 |
|
} |
8496 |
|
} |
8497 |
|
|
8498 |
|
if (common->local_exit) |
8499 |
|
{ |
8500 |
if (common->quit_label == NULL) |
if (common->quit_label == NULL) |
8501 |
add_jump(compiler, &common->quit, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0)); |
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
8502 |
else |
else |
8503 |
CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0, common->quit_label); |
JUMPTO(SLJIT_JUMP, common->quit_label); |
|
|
|
|
OP1(SLJIT_MOV, STACK_TOP, 0, TMP1, 0); |
|
|
add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP)); |
|
8504 |
return; |
return; |
8505 |
} |
} |
8506 |
|
|
8507 |
if (!common->local_exit) |
if (opcode == OP_SKIP_ARG) |
8508 |
{ |
{ |
8509 |
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
8510 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
8511 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
8512 |
sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_check_control_chain)); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); |
8513 |
|
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark)); |
8514 |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
8515 |
|
|
8516 |
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); |
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); |
8517 |
add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); |
add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); |
8518 |
|
return; |
|
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
|
8519 |
} |
} |
8520 |
|
|
8521 |
/* Commit or in recurse or accept. */ |
if (opcode == OP_SKIP) |
8522 |
if (common->quit_label == NULL) |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
|
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
|
8523 |
else |
else |
8524 |
JUMPTO(SLJIT_JUMP, common->quit_label); |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0); |
8525 |
|
add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP)); |
8526 |
} |
} |
8527 |
|
|
8528 |
static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8538 |
} |
} |
8539 |
|
|
8540 |
size = CURRENT_AS(then_trap_backtrack)->framesize; |
size = CURRENT_AS(then_trap_backtrack)->framesize; |
8541 |
size = 2 + (size < 0 ? 0 : size); |
size = 3 + (size < 0 ? 0 : size); |
8542 |
|
|
8543 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 2)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 3)); |
8544 |
free_stack(common, size); |
free_stack(common, size); |
8545 |
jump = JUMP(SLJIT_JUMP); |
jump = JUMP(SLJIT_JUMP); |
8546 |
|
|
8549 |
if (CURRENT_AS(then_trap_backtrack)->framesize >= 0) |
if (CURRENT_AS(then_trap_backtrack)->framesize >= 0) |
8550 |
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
8551 |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8552 |
free_stack(common, 2); |
free_stack(common, 3); |
8553 |
|
|
8554 |
JUMPHERE(jump); |
JUMPHERE(jump); |
8555 |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0); |
8706 |
case OP_PRUNE: |
case OP_PRUNE: |
8707 |
case OP_PRUNE_ARG: |
case OP_PRUNE_ARG: |
8708 |
case OP_SKIP: |
case OP_SKIP: |
|
compile_control_verb_backtrackingpath(common, current); |
|
|
break; |
|
|
|
|
8709 |
case OP_SKIP_ARG: |
case OP_SKIP_ARG: |
8710 |
if (!common->local_exit) |
compile_control_verb_backtrackingpath(common, current); |
|
{ |
|
|
SLJIT_ASSERT(common->control_head_ptr != 0); |
|
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
|
|
sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_check_control_chain)); |
|
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
|
|
|
|
|
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); |
|
|
add_jump(compiler, &common->reset_match, CMP(SLJIT_C_LESS, STR_PTR, 0, SLJIT_IMM, -2)); |
|
|
|
|
|
/* May not find suitable mark. */ |
|
|
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); |
|
|
if (common->quit_label == NULL) |
|
|
add_jump(compiler, &common->quit, CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); |
|
|
else |
|
|
CMPTO(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, -1, common->quit_label); |
|
|
|
|
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
|
|
free_stack(common, 3); |
|
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0); |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* In recurse or accept. */ |
|
|
if (common->quit_label == NULL) |
|
|
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); |
|
|
else |
|
|
JUMPTO(SLJIT_JUMP, common->quit_label); |
|
|
} |
|
8711 |
break; |
break; |
8712 |
|
|
8713 |
case OP_COMMIT: |
case OP_COMMIT: |
8726 |
set_jumps(current->topbacktracks, LABEL()); |
set_jumps(current->topbacktracks, LABEL()); |
8727 |
break; |
break; |
8728 |
|
|
8729 |
case OP_TABLE_LENGTH: |
case OP_THEN_TRAP: |
8730 |
/* A virtual opcode for then traps. */ |
/* A virtual opcode for then traps. */ |
8731 |
compile_then_trap_backtrackingpath(common, current); |
compile_then_trap_backtrackingpath(common, current); |
8732 |
break; |
break; |
8970 |
common->capture_last_ptr = common->ovector_start; |
common->capture_last_ptr = common->ovector_start; |
8971 |
common->ovector_start += sizeof(sljit_sw); |
common->ovector_start += sizeof(sljit_sw); |
8972 |
#endif |
#endif |
8973 |
private_data_size = get_private_data_length(common, rootbacktrack.cc, ccend); |
if (!check_opcode_types(common, rootbacktrack.cc, ccend)) |
|
if (private_data_size < 0) |
|
8974 |
{ |
{ |
8975 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
8976 |
return; |
return; |
9032 |
|
|
9033 |
SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); |
SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); |
9034 |
common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw); |
common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw); |
9035 |
private_data_size += common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw); |
|
9036 |
if (private_data_size > SLJIT_MAX_LOCAL_SIZE) |
common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(sljit_si)); |
9037 |
|
if (!common->private_data_ptrs) |
9038 |
{ |
{ |
9039 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9040 |
return; |
return; |
9041 |
} |
} |
9042 |
|
memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int)); |
9043 |
|
|
9044 |
common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(int)); |
private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw); |
9045 |
if (!common->private_data_ptrs) |
set_private_data_ptrs(common, &private_data_size, ccend); |
9046 |
|
if (private_data_size > SLJIT_MAX_LOCAL_SIZE) |
9047 |
{ |
{ |
9048 |
|
SLJIT_FREE(common->private_data_ptrs); |
9049 |
SLJIT_FREE(common->optimized_cbracket); |
SLJIT_FREE(common->optimized_cbracket); |
9050 |
return; |
return; |
9051 |
} |
} |
|
memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int)); |
|
|
set_private_data_ptrs(common, common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw), ccend); |
|
9052 |
|
|
9053 |
if (common->has_then) |
if (common->has_then) |
9054 |
{ |
{ |