xref: /netbsd-src/sys/external/bsd/sljit/dist/regex_src/regexJIT.c (revision 06eb4e7bdb1e14f0c368bf8554cee763517c4736)
177d68377Salnsn /*
277d68377Salnsn  *    Stack-less Just-In-Time compiler
377d68377Salnsn  *
4*06eb4e7bSalnsn  *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
577d68377Salnsn  *
677d68377Salnsn  * Redistribution and use in source and binary forms, with or without modification, are
777d68377Salnsn  * permitted provided that the following conditions are met:
877d68377Salnsn  *
977d68377Salnsn  *   1. Redistributions of source code must retain the above copyright notice, this list of
1077d68377Salnsn  *      conditions and the following disclaimer.
1177d68377Salnsn  *
1277d68377Salnsn  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
1377d68377Salnsn  *      of conditions and the following disclaimer in the documentation and/or other materials
1477d68377Salnsn  *      provided with the distribution.
1577d68377Salnsn  *
1677d68377Salnsn  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
1777d68377Salnsn  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1877d68377Salnsn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
1977d68377Salnsn  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2077d68377Salnsn  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2177d68377Salnsn  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2277d68377Salnsn  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2377d68377Salnsn  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2477d68377Salnsn  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2577d68377Salnsn  */
2677d68377Salnsn 
2777d68377Salnsn #include "sljitLir.h"
2877d68377Salnsn #include "regexJIT.h"
2977d68377Salnsn 
30*06eb4e7bSalnsn #include <stdlib.h>
31*06eb4e7bSalnsn 
3277d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
3377d68377Salnsn #include <stdio.h>
3477d68377Salnsn #endif
3577d68377Salnsn 
3677d68377Salnsn /* Extra, hidden flags:
3777d68377Salnsn    {id!} where id > 0 found in the code. */
3877d68377Salnsn #define REGEX_ID_CHECK		0x100
3977d68377Salnsn /* When REGEX_NEWLINE && REGEX_MATCH_BEGIN defined, the pattern turn to a normal search,
4077d68377Salnsn    which starts with [\r\n] character range. */
4177d68377Salnsn #define REGEX_FAKE_MATCH_BEGIN	0x200
4277d68377Salnsn /* When REGEX_NEWLINE && REGEX_MATCH_END defined, the pattern turn to a normal search,
4377d68377Salnsn    which ends with [\r\n] character range. */
4477d68377Salnsn #define REGEX_FAKE_MATCH_END	0x400
4577d68377Salnsn 
4677d68377Salnsn /* Check match completition after every (FINISH_TEST + 1) steps. */
4777d68377Salnsn #define FINISH_TEST	0x7
4877d68377Salnsn 
4977d68377Salnsn /* --------------------------------------------------------------------- */
5077d68377Salnsn /*  Structures for JIT-ed pattern matching                               */
5177d68377Salnsn /* --------------------------------------------------------------------- */
5277d68377Salnsn 
5377d68377Salnsn struct regex_machine
5477d68377Salnsn {
5577d68377Salnsn 	/* flags. */
5677d68377Salnsn 	int flags;
5777d68377Salnsn 	/* Number of state descriptors for one term. */
58e5292e6bSalnsn 	sljit_sw no_states;
5977d68377Salnsn 	/* Total size. */
60e5292e6bSalnsn 	sljit_sw size;
6177d68377Salnsn 
6277d68377Salnsn 	union {
6377d68377Salnsn 		void *init_match;
64e5292e6bSalnsn 		sljit_sw (SLJIT_CALL *call_init)(void *next, void* match);
6577d68377Salnsn 	} u;
6677d68377Salnsn #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
6777d68377Salnsn 	struct sljit_function_context context;
6877d68377Salnsn #endif
6977d68377Salnsn 
7077d68377Salnsn 	void *continue_match;
7177d68377Salnsn 
7277d68377Salnsn 	/* Variable sized array to contain the handler addresses. */
7377d68377Salnsn 	sljit_uw entry_addrs[1];
7477d68377Salnsn };
7577d68377Salnsn 
7677d68377Salnsn struct regex_match
7777d68377Salnsn {
7877d68377Salnsn 	/* Current and next state array. */
79e5292e6bSalnsn 	sljit_sw *current;
80e5292e6bSalnsn 	sljit_sw *next;
8177d68377Salnsn 	/* Starting. */
82e5292e6bSalnsn 	sljit_sw head;
8377d68377Salnsn 	/* String character index (ever increasing). */
84e5292e6bSalnsn 	sljit_sw index;
8577d68377Salnsn 	/* Best match found so far (members in priority order). */
86e5292e6bSalnsn 	sljit_sw best_begin;
87e5292e6bSalnsn 	sljit_sw best_end;
88e5292e6bSalnsn 	sljit_sw best_id;
8977d68377Salnsn 	/* Bool flags (encoded as word). */
90e5292e6bSalnsn 	sljit_sw fast_quit;
91e5292e6bSalnsn 	sljit_sw fast_forward;
9277d68377Salnsn 	/* Machine. */
9377d68377Salnsn 	struct regex_machine *machine;
9477d68377Salnsn 
9577d68377Salnsn 	union {
9677d68377Salnsn 		void *continue_match;
9777d68377Salnsn 		void (SLJIT_CALL *call_continue)(struct regex_match *match, const regex_char_t *input_string, int length);
9877d68377Salnsn 	} u;
9977d68377Salnsn 
10077d68377Salnsn 	/* Variable sized array to contain the state arrays. */
101e5292e6bSalnsn 	sljit_sw states[1];
10277d68377Salnsn };
10377d68377Salnsn 
10477d68377Salnsn /* State vector
10577d68377Salnsn     ITEM[0] - pointer to the address inside the machine code
10677d68377Salnsn     ITEM[1] - next pointer
10777d68377Salnsn     ITEM[2] - string started from (optional)
10877d68377Salnsn     ITEM[3] - max ID (optional) */
10977d68377Salnsn 
11077d68377Salnsn /* Register allocation. */
11177d68377Salnsn /* Current state array (loaded & stored: regex_match->current). */
11299e10043Salnsn #define R_CURR_STATE	SLJIT_S0
11377d68377Salnsn /* Next state array (loaded & stored: regex_match->next). */
11499e10043Salnsn #define R_NEXT_STATE	SLJIT_S1
11577d68377Salnsn /* Head (loaded & stored: regex_match->head). */
11699e10043Salnsn #define R_NEXT_HEAD	SLJIT_S2
11777d68377Salnsn /* String fragment pointer. */
11899e10043Salnsn #define R_STRING	SLJIT_S3
11977d68377Salnsn /* String fragment length. */
12099e10043Salnsn #define R_LENGTH	SLJIT_S4
12177d68377Salnsn /* 'struct regex_match*' */
12299e10043Salnsn #define R_REGEX_MATCH	SLJIT_R0
12377d68377Salnsn /* Current character. */
12499e10043Salnsn #define R_CURR_CHAR	SLJIT_R1
12577d68377Salnsn /* Temporary register. */
12699e10043Salnsn #define R_TEMP		SLJIT_R2
12777d68377Salnsn /* Caches the regex_match->best_begin. */
12899e10043Salnsn #define R_BEST_BEGIN	SLJIT_R3
12977d68377Salnsn /* Current character index. */
13099e10043Salnsn #define R_CURR_INDEX	SLJIT_R4
13177d68377Salnsn 
13277d68377Salnsn /* --------------------------------------------------------------------- */
13377d68377Salnsn /*  Stack management                                                     */
13477d68377Salnsn /* --------------------------------------------------------------------- */
13577d68377Salnsn 
13677d68377Salnsn /* Try to allocate 2^n blocks. */
13777d68377Salnsn #define STACK_FRAGMENT_SIZE (((64 * sizeof(struct stack_item)) - (sizeof(struct stack_fragment_data))) / (sizeof(struct stack_item)))
13877d68377Salnsn 
13977d68377Salnsn struct stack_item {
14077d68377Salnsn 	int type;
14177d68377Salnsn 	int value;
14277d68377Salnsn };
14377d68377Salnsn 
14477d68377Salnsn struct stack_fragment_data {
14577d68377Salnsn 	struct stack_fragment *next;
14677d68377Salnsn 	struct stack_fragment *prev;
14777d68377Salnsn };
14877d68377Salnsn 
14977d68377Salnsn struct stack_fragment {
15077d68377Salnsn 	struct stack_fragment_data data;
15177d68377Salnsn 	struct stack_item items[STACK_FRAGMENT_SIZE];
15277d68377Salnsn };
15377d68377Salnsn 
15477d68377Salnsn struct stack {
15577d68377Salnsn 	struct stack_fragment *first;
15677d68377Salnsn 	struct stack_fragment *last;
15777d68377Salnsn 	int index;
15877d68377Salnsn 	int count;
15977d68377Salnsn };
16077d68377Salnsn 
16177d68377Salnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
16277d68377Salnsn 
stack_check(struct stack * stack)16377d68377Salnsn static void stack_check(struct stack *stack)
16477d68377Salnsn {
16577d68377Salnsn 	struct stack_fragment *curr;
16677d68377Salnsn 	int found;
16777d68377Salnsn 
16877d68377Salnsn 	if (!stack)
16977d68377Salnsn 		return;
17077d68377Salnsn 
17177d68377Salnsn 	SLJIT_ASSERT(stack->index >= 0 && stack->index < STACK_FRAGMENT_SIZE);
17277d68377Salnsn 
17377d68377Salnsn 	if (stack->first == NULL) {
17477d68377Salnsn 		SLJIT_ASSERT(stack->first == NULL && stack->last == NULL);
17577d68377Salnsn 		SLJIT_ASSERT(stack->index == STACK_FRAGMENT_SIZE - 1 && stack->count == 0);
17677d68377Salnsn 		return;
17777d68377Salnsn 	}
17877d68377Salnsn 
17977d68377Salnsn 	found = 0;
18077d68377Salnsn 	if (stack->last == NULL) {
18177d68377Salnsn 		SLJIT_ASSERT(stack->index == STACK_FRAGMENT_SIZE - 1 && stack->count == 0);
18277d68377Salnsn 		found = 1;
18377d68377Salnsn 	}
18477d68377Salnsn 	else
18577d68377Salnsn 		SLJIT_ASSERT(stack->index >= 0 && stack->count >= 0);
18677d68377Salnsn 
18777d68377Salnsn 	SLJIT_ASSERT(stack->first->data.prev == NULL);
18877d68377Salnsn 	curr = stack->first;
18977d68377Salnsn 	while (curr) {
19077d68377Salnsn 		if (curr == stack->last)
19177d68377Salnsn 			found = 1;
19277d68377Salnsn 		if (curr->data.next)
19377d68377Salnsn 			SLJIT_ASSERT(curr->data.next->data.prev == curr);
19477d68377Salnsn 		curr = curr->data.next;
19577d68377Salnsn 	}
19677d68377Salnsn 	SLJIT_ASSERT(found);
19777d68377Salnsn }
19877d68377Salnsn 
19977d68377Salnsn #endif
20077d68377Salnsn 
stack_init(struct stack * stack)20177d68377Salnsn static void stack_init(struct stack *stack)
20277d68377Salnsn {
20377d68377Salnsn 	stack->first = NULL;
20477d68377Salnsn 	stack->last = NULL;
20577d68377Salnsn 	stack->index = STACK_FRAGMENT_SIZE - 1;
20677d68377Salnsn 	stack->count = 0;
20777d68377Salnsn }
20877d68377Salnsn 
stack_destroy(struct stack * stack)20977d68377Salnsn static void stack_destroy(struct stack *stack)
21077d68377Salnsn {
21177d68377Salnsn 	struct stack_fragment *curr = stack->first;
21277d68377Salnsn 	struct stack_fragment *prev;
21377d68377Salnsn 
21477d68377Salnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
21577d68377Salnsn 	stack_check(stack);
21677d68377Salnsn #endif
21777d68377Salnsn 
21877d68377Salnsn 	while (curr) {
21977d68377Salnsn 		prev = curr;
22077d68377Salnsn 		curr = curr->data.next;
22199e10043Salnsn 		SLJIT_FREE(prev, NULL);
22277d68377Salnsn 	}
22377d68377Salnsn }
22477d68377Salnsn 
stack_top(struct stack * stack)22577d68377Salnsn static SLJIT_INLINE struct stack_item* stack_top(struct stack *stack)
22677d68377Salnsn {
22777d68377Salnsn 	SLJIT_ASSERT(stack->last);
22877d68377Salnsn 	return stack->last->items + stack->index;
22977d68377Salnsn }
23077d68377Salnsn 
stack_push(struct stack * stack,int type,int value)23177d68377Salnsn static int stack_push(struct stack *stack, int type, int value)
23277d68377Salnsn {
23377d68377Salnsn 	if (stack->last) {
23477d68377Salnsn 		stack->index++;
23577d68377Salnsn 		if (stack->index >= STACK_FRAGMENT_SIZE) {
23677d68377Salnsn 			stack->index = 0;
23777d68377Salnsn 			if (!stack->last->data.next) {
23899e10043Salnsn 				stack->last->data.next = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);
23977d68377Salnsn 				if (!stack->last->data.next)
24077d68377Salnsn 					return 1;
24177d68377Salnsn 				stack->last->data.next->data.next = NULL;
24277d68377Salnsn 				stack->last->data.next->data.prev = stack->last;
24377d68377Salnsn 			}
24477d68377Salnsn 			stack->last = stack->last->data.next;
24577d68377Salnsn 		}
24677d68377Salnsn 	}
24777d68377Salnsn 	else if (!stack->first) {
24899e10043Salnsn 		stack->last = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);
24977d68377Salnsn 		if (!stack->last)
25077d68377Salnsn 			return 1;
25177d68377Salnsn 		stack->last->data.prev = NULL;
25277d68377Salnsn 		stack->last->data.next = NULL;
25377d68377Salnsn 		stack->first = stack->last;
25477d68377Salnsn 		stack->index = 0;
25577d68377Salnsn 	}
25677d68377Salnsn 	else {
25777d68377Salnsn 		stack->last = stack->first;
25877d68377Salnsn 		stack->index = 0;
25977d68377Salnsn 	}
26077d68377Salnsn 	stack->last->items[stack->index].type = type;
26177d68377Salnsn 	stack->last->items[stack->index].value = value;
26277d68377Salnsn 	stack->count++;
26377d68377Salnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
26477d68377Salnsn 	stack_check(stack);
26577d68377Salnsn #endif
26677d68377Salnsn 	return 0;
26777d68377Salnsn }
26877d68377Salnsn 
stack_pop(struct stack * stack)26977d68377Salnsn static struct stack_item* stack_pop(struct stack *stack)
27077d68377Salnsn {
27177d68377Salnsn 	struct stack_item *ret = stack_top(stack);
27277d68377Salnsn 
27377d68377Salnsn 	if (stack->index > 0)
27477d68377Salnsn 		stack->index--;
27577d68377Salnsn 	else {
27677d68377Salnsn 		stack->last = stack->last->data.prev;
27777d68377Salnsn 		stack->index = STACK_FRAGMENT_SIZE - 1;
27877d68377Salnsn 	}
27977d68377Salnsn 
28077d68377Salnsn 	stack->count--;
28177d68377Salnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
28277d68377Salnsn 	stack_check(stack);
28377d68377Salnsn #endif
28477d68377Salnsn 	return ret;
28577d68377Salnsn }
28677d68377Salnsn 
stack_clone(struct stack * src,struct stack * dst)28777d68377Salnsn static SLJIT_INLINE void stack_clone(struct stack *src, struct stack *dst)
28877d68377Salnsn {
28977d68377Salnsn 	*dst = *src;
29077d68377Salnsn }
29177d68377Salnsn 
stack_push_copy(struct stack * stack,int items,int length)29277d68377Salnsn static int stack_push_copy(struct stack *stack, int items, int length)
29377d68377Salnsn {
29477d68377Salnsn 	struct stack_fragment *frag1;
29577d68377Salnsn 	int ind1;
29677d68377Salnsn 	struct stack_fragment *frag2;
29777d68377Salnsn 	int ind2;
29877d68377Salnsn 	int counter;
29977d68377Salnsn 
30077d68377Salnsn 	SLJIT_ASSERT(stack->count >= length && items <= length && items > 0);
30177d68377Salnsn 
30277d68377Salnsn 	/* Allocate the necessary elements. */
30377d68377Salnsn 	counter = items;
30477d68377Salnsn 	frag1 = stack->last;
30577d68377Salnsn 	ind1 = stack->index;
30677d68377Salnsn 	while (counter > 0) {
30777d68377Salnsn 		if (stack->index + counter >= STACK_FRAGMENT_SIZE) {
30877d68377Salnsn 			counter -= STACK_FRAGMENT_SIZE - stack->index - 1 + 1;
30977d68377Salnsn 			stack->index = 0;
31077d68377Salnsn 			if (!stack->last->data.next) {
31199e10043Salnsn 				stack->last->data.next = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);
31277d68377Salnsn 				if (!stack->last->data.next)
31377d68377Salnsn 					return 1;
31477d68377Salnsn 				stack->last->data.next->data.next = NULL;
31577d68377Salnsn 				stack->last->data.next->data.prev = stack->last;
31677d68377Salnsn 			}
31777d68377Salnsn 			stack->last = stack->last->data.next;
31877d68377Salnsn 		}
31977d68377Salnsn 		else {
32077d68377Salnsn 			stack->index += counter;
32177d68377Salnsn 			counter = 0;
32277d68377Salnsn 		}
32377d68377Salnsn 	}
32477d68377Salnsn 
32577d68377Salnsn 	frag2 = stack->last;
32677d68377Salnsn 	ind2 = stack->index;
32777d68377Salnsn 	while (length > 0) {
32877d68377Salnsn 		frag2->items[ind2--] = frag1->items[ind1--];
32977d68377Salnsn 		if (ind1 < 0) {
33077d68377Salnsn 			ind1 = STACK_FRAGMENT_SIZE - 1;
33177d68377Salnsn 			frag1 = frag1->data.prev;
33277d68377Salnsn 		}
33377d68377Salnsn 		if (ind2 < 0) {
33477d68377Salnsn 			ind2 = STACK_FRAGMENT_SIZE - 1;
33577d68377Salnsn 			frag2 = frag2->data.prev;
33677d68377Salnsn 		}
33777d68377Salnsn 		length--;
33877d68377Salnsn 	}
33977d68377Salnsn 
34077d68377Salnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
34177d68377Salnsn 	stack_check(stack);
34277d68377Salnsn #endif
34377d68377Salnsn 	stack->count += items;
34477d68377Salnsn 	return 0;
34577d68377Salnsn }
34677d68377Salnsn 
34777d68377Salnsn /* --------------------------------------------------------------------- */
34877d68377Salnsn /*  Parser                                                               */
34977d68377Salnsn /* --------------------------------------------------------------------- */
35077d68377Salnsn 
35177d68377Salnsn enum {
35277d68377Salnsn 	/* Common. */
35377d68377Salnsn 	type_begin,
35477d68377Salnsn 	type_end,
35577d68377Salnsn 	type_char,
35677d68377Salnsn 	type_newline,
35777d68377Salnsn 	type_id,
35877d68377Salnsn 	type_rng_start,
35977d68377Salnsn 	type_rng_end,
36077d68377Salnsn 	type_rng_char,
36177d68377Salnsn 	type_rng_left,
36277d68377Salnsn 	type_rng_right,
36377d68377Salnsn 
36477d68377Salnsn 	/* generator only. */
36577d68377Salnsn 	type_branch,
36677d68377Salnsn 	type_jump,
36777d68377Salnsn 
36877d68377Salnsn 	/* Parser only. */
36977d68377Salnsn 	type_open_br,
37077d68377Salnsn 	type_close_br,
37177d68377Salnsn 	type_select,
37277d68377Salnsn 	type_asterisk,
37377d68377Salnsn 	type_plus_sign,
37477d68377Salnsn 	type_qestion_mark
37577d68377Salnsn };
37677d68377Salnsn 
37777d68377Salnsn struct compiler_common {
37877d68377Salnsn 	/* Temporary stacks. */
37977d68377Salnsn 	struct stack stack;
38077d68377Salnsn 	struct stack depth;
38177d68377Salnsn 	/* REGEX_ flags. */
38277d68377Salnsn 	int flags;
38377d68377Salnsn 	/* Encoded size of the dfa representation. */
384e5292e6bSalnsn 	sljit_sw dfa_size;
38577d68377Salnsn 	/* Number of terms. */
386e5292e6bSalnsn 	sljit_sw terms_size;
38777d68377Salnsn 	/* Number of state descriptors for one term (same as machine->no_states). */
388e5292e6bSalnsn 	sljit_sw no_states;
38977d68377Salnsn 	/* Number of type_rng_(char|left)-s in the longest character range. */
390e5292e6bSalnsn 	sljit_sw longest_range_size;
39177d68377Salnsn 
39277d68377Salnsn 	/* DFA linear representation (size: dfa_size). */
39377d68377Salnsn 	struct stack_item *dfa_transitions;
39477d68377Salnsn 	/* Term id and search state pairs (size: dfa_size). */
39577d68377Salnsn 	struct stack_item *search_states;
39677d68377Salnsn 
39777d68377Salnsn 	/* sljit compiler */
39877d68377Salnsn 	struct sljit_compiler *compiler;
39977d68377Salnsn 	/* Machine data, which must be kept for later use. */
40077d68377Salnsn 	struct regex_machine *machine;
40177d68377Salnsn 	/* Temporary space for jumps (size: longest_range_size). */
40277d68377Salnsn 	struct sljit_jump **range_jump_list;
40377d68377Salnsn };
40477d68377Salnsn 
decode_number(const regex_char_t * regex_string,int length,int * result)40577d68377Salnsn static const regex_char_t* decode_number(const regex_char_t *regex_string, int length, int *result)
40677d68377Salnsn {
40777d68377Salnsn 	int value = 0;
40877d68377Salnsn 
40977d68377Salnsn 	SLJIT_ASSERT(length > 0);
41077d68377Salnsn 	if (*regex_string < '0' || *regex_string > '9') {
41177d68377Salnsn 		*result = -1;
41277d68377Salnsn 		return regex_string;
41377d68377Salnsn 	}
41477d68377Salnsn 
41577d68377Salnsn 	while (length > 0 && *regex_string >= '0' && *regex_string <= '9') {
41677d68377Salnsn 		value = value * 10 + (*regex_string - '0');
41777d68377Salnsn 		length--;
41877d68377Salnsn 		regex_string++;
41977d68377Salnsn 	}
42077d68377Salnsn 
42177d68377Salnsn 	*result = value;
42277d68377Salnsn 	return regex_string;
42377d68377Salnsn }
42477d68377Salnsn 
iterate(struct stack * stack,int min,int max)42577d68377Salnsn static int iterate(struct stack *stack, int min, int max)
42677d68377Salnsn {
42777d68377Salnsn 	struct stack it;
42877d68377Salnsn 	struct stack_item *item;
42977d68377Salnsn 	int count = -1;
43077d68377Salnsn 	int len = 0;
43177d68377Salnsn 	int depth = 0;
43277d68377Salnsn 
43377d68377Salnsn 	stack_clone(stack, &it);
43477d68377Salnsn 
43577d68377Salnsn 	/* Calculate size. */
43677d68377Salnsn 	while (count < 0) {
43777d68377Salnsn 		item = stack_pop(&it);
43877d68377Salnsn 		switch (item->type) {
43977d68377Salnsn 		case type_id:
44077d68377Salnsn 		case type_rng_end:
44177d68377Salnsn 		case type_rng_char:
44277d68377Salnsn 		case type_rng_left:
44377d68377Salnsn 		case type_rng_right:
44477d68377Salnsn 		case type_plus_sign:
44577d68377Salnsn 		case type_qestion_mark:
44677d68377Salnsn 			len++;
44777d68377Salnsn 			break;
44877d68377Salnsn 
44977d68377Salnsn 		case type_asterisk:
45077d68377Salnsn 			len += 2;
45177d68377Salnsn 			break;
45277d68377Salnsn 
45377d68377Salnsn 		case type_close_br:
45477d68377Salnsn 			depth++;
45577d68377Salnsn 			break;
45677d68377Salnsn 
45777d68377Salnsn 		case type_open_br:
45877d68377Salnsn 			SLJIT_ASSERT(depth > 0);
45977d68377Salnsn 			depth--;
46077d68377Salnsn 			if (depth == 0)
46177d68377Salnsn 				count = it.count;
46277d68377Salnsn 			break;
46377d68377Salnsn 
46477d68377Salnsn 		case type_select:
46577d68377Salnsn 			SLJIT_ASSERT(depth > 0);
46677d68377Salnsn 			len += 2;
46777d68377Salnsn 			break;
46877d68377Salnsn 
46977d68377Salnsn 		default:
47077d68377Salnsn 			SLJIT_ASSERT(item->type != type_begin && item->type != type_end);
47177d68377Salnsn 			if (depth == 0)
47277d68377Salnsn 				count = it.count;
47377d68377Salnsn 			len++;
47477d68377Salnsn 			break;
47577d68377Salnsn 		}
47677d68377Salnsn 	}
47777d68377Salnsn 
47877d68377Salnsn 	if (min == 0 && max == 0) {
47977d68377Salnsn 		/* {0,0} case, not {0,} case: delete subtree. */
48077d68377Salnsn 		stack_clone(&it, stack);
48177d68377Salnsn 		/* and put an empty bracket expression instead of it. */
48277d68377Salnsn 		if (stack_push(stack, type_open_br, 0))
48377d68377Salnsn 			return REGEX_MEMORY_ERROR;
48477d68377Salnsn 		if (stack_push(stack, type_close_br, 0))
48577d68377Salnsn 			return REGEX_MEMORY_ERROR;
48677d68377Salnsn 		return len;
48777d68377Salnsn 	}
48877d68377Salnsn 
48977d68377Salnsn 	count = stack->count - count;
49077d68377Salnsn 
49177d68377Salnsn 	/* Put an open bracket before the sequence. */
49277d68377Salnsn 	if (stack_push_copy(stack, 1, count))
49377d68377Salnsn 		return -1;
49477d68377Salnsn 
49577d68377Salnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
49677d68377Salnsn 	SLJIT_ASSERT(stack_push(&it, type_open_br, 0) == 0);
49777d68377Salnsn #else
49877d68377Salnsn 	stack_push(&it, type_open_br, 0);
49977d68377Salnsn #endif
50077d68377Salnsn 
50177d68377Salnsn 	/* Copy the data. */
50277d68377Salnsn 	if (max > 0) {
50377d68377Salnsn 		len = len * (max - 1);
50477d68377Salnsn 		max -= min;
50577d68377Salnsn 		/* Insert ? operators. */
50677d68377Salnsn 		len += max;
50777d68377Salnsn 
50877d68377Salnsn 		if (min > 0) {
50977d68377Salnsn 			min--;
51077d68377Salnsn 			while (min > 0) {
51177d68377Salnsn 				if (stack_push_copy(stack, count, count))
51277d68377Salnsn 					return -1;
51377d68377Salnsn 				min--;
51477d68377Salnsn 			}
51577d68377Salnsn 			if (max > 0) {
51677d68377Salnsn 				if (stack_push_copy(stack, count, count))
51777d68377Salnsn 					return -1;
51877d68377Salnsn 				if (stack_push(stack, type_qestion_mark, 0))
51977d68377Salnsn 					return REGEX_MEMORY_ERROR;
52077d68377Salnsn 				count++;
52177d68377Salnsn 				max--;
52277d68377Salnsn 			}
52377d68377Salnsn 		}
52477d68377Salnsn 		else {
52577d68377Salnsn 			SLJIT_ASSERT(max > 0);
52677d68377Salnsn 			max--;
52777d68377Salnsn 			count++;
52877d68377Salnsn 			if (stack_push(stack, type_qestion_mark, 0))
52977d68377Salnsn 				return REGEX_MEMORY_ERROR;
53077d68377Salnsn 		}
53177d68377Salnsn 
53277d68377Salnsn 		while (max > 0) {
53377d68377Salnsn 			if (stack_push_copy(stack, count, count))
53477d68377Salnsn 				return -1;
53577d68377Salnsn 			max--;
53677d68377Salnsn 		}
53777d68377Salnsn 	}
53877d68377Salnsn 	else {
53977d68377Salnsn 		SLJIT_ASSERT(min > 0);
54077d68377Salnsn 		min--;
54177d68377Salnsn 		/* Insert + operator. */
54277d68377Salnsn 		len = len * min + 1;
54377d68377Salnsn 		while (min > 0) {
54477d68377Salnsn 			if (stack_push_copy(stack, count, count))
54577d68377Salnsn 				return -1;
54677d68377Salnsn 			min--;
54777d68377Salnsn 		}
54877d68377Salnsn 
54977d68377Salnsn 		if (stack_push(stack, type_plus_sign, 0))
55077d68377Salnsn 			return REGEX_MEMORY_ERROR;
55177d68377Salnsn 	}
55277d68377Salnsn 
55377d68377Salnsn 	/* Close the opened bracket. */
55477d68377Salnsn 	if (stack_push(stack, type_close_br, 0))
55577d68377Salnsn 		return REGEX_MEMORY_ERROR;
55677d68377Salnsn 
55777d68377Salnsn 	return len;
55877d68377Salnsn }
55977d68377Salnsn 
parse_iterator(const regex_char_t * regex_string,int length,struct stack * stack,sljit_sw * dfa_size,int begin)560e5292e6bSalnsn static int parse_iterator(const regex_char_t *regex_string, int length, struct stack *stack, sljit_sw *dfa_size, int begin)
56177d68377Salnsn {
56277d68377Salnsn 	/* We only know that *regex_string == { . */
56377d68377Salnsn 	int val1, val2;
56477d68377Salnsn 	const regex_char_t *base_from = regex_string;
56577d68377Salnsn 	const regex_char_t *from;
56677d68377Salnsn 
56777d68377Salnsn 	length--;
56877d68377Salnsn 	regex_string++;
56977d68377Salnsn 
57077d68377Salnsn 	/* Decode left value. */
57177d68377Salnsn 	val2 = -1;
57277d68377Salnsn 	if (length == 0)
57377d68377Salnsn 		return -2;
57477d68377Salnsn 	if (*regex_string == ',') {
57577d68377Salnsn 		val1 = 0;
57677d68377Salnsn 		length--;
57777d68377Salnsn 		regex_string++;
57877d68377Salnsn 	}
57977d68377Salnsn 	else {
58077d68377Salnsn 		from = regex_string;
58177d68377Salnsn 		regex_string = decode_number(regex_string, length, &val1);
58277d68377Salnsn 		if (val1 < 0)
58377d68377Salnsn 			return -2;
58477d68377Salnsn 		length -= regex_string - from;
58577d68377Salnsn 
58677d68377Salnsn 		if (length == 0)
58777d68377Salnsn 			return -2;
58877d68377Salnsn 		if (*regex_string == '}') {
58977d68377Salnsn 			val2 = val1;
59077d68377Salnsn 			if (val1 == 0)
59177d68377Salnsn 				val1 = -1;
59277d68377Salnsn 		}
59377d68377Salnsn 		else if (length >= 2 && *regex_string == '!' && regex_string[1] == '}') {
59477d68377Salnsn 			/* Non posix extension. */
59577d68377Salnsn 			if (stack_push(stack, type_id, val1))
59677d68377Salnsn 				return -1;
59777d68377Salnsn 			(*dfa_size)++;
59877d68377Salnsn 			return (regex_string - base_from) + 1;
59977d68377Salnsn 		}
60077d68377Salnsn 		else {
60177d68377Salnsn 			if (*regex_string != ',')
60277d68377Salnsn 				return -2;
60377d68377Salnsn 			length--;
60477d68377Salnsn 			regex_string++;
60577d68377Salnsn 		}
60677d68377Salnsn 	}
60777d68377Salnsn 
60877d68377Salnsn 	if (begin)
60977d68377Salnsn 		return -2;
61077d68377Salnsn 
61177d68377Salnsn 	/* Decode right value. */
61277d68377Salnsn 	if (val2 == -1) {
61377d68377Salnsn 		if (length == 0)
61477d68377Salnsn 			return -2;
61577d68377Salnsn 		if (*regex_string == '}')
61677d68377Salnsn 			val2 = 0;
61777d68377Salnsn 		else {
61877d68377Salnsn 			from = regex_string;
61977d68377Salnsn 			regex_string = decode_number(regex_string, length, &val2);
62077d68377Salnsn 			length -= regex_string - from;
62177d68377Salnsn 			if (val2 < 0 || length == 0 || *regex_string != '}' || val2 < val1)
62277d68377Salnsn 				return -2;
62377d68377Salnsn 			if (val2 == 0) {
62477d68377Salnsn 				SLJIT_ASSERT(val1 == 0);
62577d68377Salnsn 				val1 = -1;
62677d68377Salnsn 			}
62777d68377Salnsn 		}
62877d68377Salnsn 	}
62977d68377Salnsn 
63077d68377Salnsn 	/* Fast cases. */
63177d68377Salnsn 	if (val1 > 1 || val2 > 1) {
63277d68377Salnsn 		val1 = iterate(stack, val1, val2);
63377d68377Salnsn 		if (val1 < 0)
63477d68377Salnsn 			return -1;
63577d68377Salnsn 		*dfa_size += val1;
63677d68377Salnsn 	}
63777d68377Salnsn 	else if (val1 == 0 && val2 == 0) {
63877d68377Salnsn 		if (stack_push(stack, type_asterisk, 0))
63977d68377Salnsn 			return -1;
64077d68377Salnsn 		*dfa_size += 2;
64177d68377Salnsn 	}
64277d68377Salnsn 	else if (val1 == 1 && val2 == 0) {
64377d68377Salnsn 		if (stack_push(stack, type_plus_sign, 0))
64477d68377Salnsn 			return -1;
64577d68377Salnsn 		(*dfa_size)++;
64677d68377Salnsn 	}
64777d68377Salnsn 	else if (val1 == 0 && val2 == 1) {
64877d68377Salnsn 		if (stack_push(stack, type_qestion_mark, 0))
64977d68377Salnsn 			return -1;
65077d68377Salnsn 		(*dfa_size)++;
65177d68377Salnsn 	}
65277d68377Salnsn 	else if (val1 == -1) {
65377d68377Salnsn 		val1 = iterate(stack, 0, 0);
65477d68377Salnsn 		if (val1 < 0)
65577d68377Salnsn 			return -1;
65677d68377Salnsn 		*dfa_size -= val1;
65777d68377Salnsn 		SLJIT_ASSERT(*dfa_size >= 2);
65877d68377Salnsn 	}
65977d68377Salnsn 	else {
66077d68377Salnsn 		/* Ignore. */
66177d68377Salnsn 		SLJIT_ASSERT(val1 == 1 && val2 == 1);
66277d68377Salnsn 	}
66377d68377Salnsn 	return regex_string - base_from;
66477d68377Salnsn }
66577d68377Salnsn 
parse_char_range(const regex_char_t * regex_string,int length,struct compiler_common * compiler_common)66677d68377Salnsn static int parse_char_range(const regex_char_t *regex_string, int length, struct compiler_common *compiler_common)
66777d68377Salnsn {
66877d68377Salnsn 	struct stack* stack = &compiler_common->stack;
66977d68377Salnsn 	const regex_char_t *base_from = regex_string;
67077d68377Salnsn 	regex_char_t left_char, right_char, tmp_char;
67177d68377Salnsn 
67277d68377Salnsn 	length--;
67377d68377Salnsn 	regex_string++;
67477d68377Salnsn 
67577d68377Salnsn 	if (length == 0)
67677d68377Salnsn 		return -2;
67777d68377Salnsn 
67877d68377Salnsn 	if (*regex_string != '^') {
67977d68377Salnsn 		if (stack_push(stack, type_rng_start, 0))
68077d68377Salnsn 			return -1;
68177d68377Salnsn 	}
68277d68377Salnsn 	else {
68377d68377Salnsn 		length--;
68477d68377Salnsn 		regex_string++;
68577d68377Salnsn 
68677d68377Salnsn 		if (length == 0)
68777d68377Salnsn 			return -2;
68877d68377Salnsn 
68977d68377Salnsn 		if (stack_push(stack, type_rng_start, 1))
69077d68377Salnsn 			return -1;
69177d68377Salnsn 	}
69277d68377Salnsn 	/* For both the type_rng_start & type_rng_end. */
69377d68377Salnsn 	compiler_common->dfa_size += 2;
69477d68377Salnsn 
69577d68377Salnsn 	/* Range must be at least 1 character. */
69677d68377Salnsn 	if (*regex_string == ']') {
69777d68377Salnsn 		length--;
69877d68377Salnsn 		regex_string++;
69977d68377Salnsn 		if (stack_push(stack, type_rng_char, ']'))
70077d68377Salnsn 			return -1;
70177d68377Salnsn 		compiler_common->dfa_size++;
70277d68377Salnsn 	}
70377d68377Salnsn 
70477d68377Salnsn 	while (1) {
70577d68377Salnsn 		if (length == 0)
70677d68377Salnsn 			return -2;
70777d68377Salnsn 
70877d68377Salnsn 		if (*regex_string == ']')
70977d68377Salnsn 			break;
71077d68377Salnsn 
71177d68377Salnsn 		if (*regex_string != '\\')
71277d68377Salnsn 			left_char = *regex_string;
71377d68377Salnsn 		else {
71477d68377Salnsn 			regex_string++;
71577d68377Salnsn 			length--;
71677d68377Salnsn 			if (length == 0)
71777d68377Salnsn 				return -2;
71877d68377Salnsn 			left_char = *regex_string;
71977d68377Salnsn 		}
72077d68377Salnsn 		regex_string++;
72177d68377Salnsn 		length--;
72277d68377Salnsn 
72377d68377Salnsn 		/* Is a range here? */
72477d68377Salnsn 		if (length >= 3 && *regex_string == '-' && *(regex_string + 1) != ']') {
72577d68377Salnsn 			regex_string++;
72677d68377Salnsn 			length--;
72777d68377Salnsn 
72877d68377Salnsn 			if (*regex_string != '\\')
72977d68377Salnsn 				right_char = *regex_string;
73077d68377Salnsn 			else {
73177d68377Salnsn 				regex_string++;
73277d68377Salnsn 				length--;
73377d68377Salnsn 				if (length == 0)
73477d68377Salnsn 					return -2;
73577d68377Salnsn 				right_char = *regex_string;
73677d68377Salnsn 			}
73777d68377Salnsn 			regex_string++;
73877d68377Salnsn 			length--;
73977d68377Salnsn 
74077d68377Salnsn 			if (left_char > right_char) {
74177d68377Salnsn 				/* Swap if necessary. */
74277d68377Salnsn 				tmp_char = left_char;
74377d68377Salnsn 				left_char = right_char;
74477d68377Salnsn 				right_char = tmp_char;
74577d68377Salnsn 			}
74677d68377Salnsn 
74777d68377Salnsn 			if (stack_push(stack, type_rng_left, left_char))
74877d68377Salnsn 				return -1;
74977d68377Salnsn 			if (stack_push(stack, type_rng_right, right_char))
75077d68377Salnsn 				return -1;
75177d68377Salnsn 			compiler_common->dfa_size += 2;
75277d68377Salnsn 		}
75377d68377Salnsn 		else {
75477d68377Salnsn 			if (stack_push(stack, type_rng_char, left_char))
75577d68377Salnsn 				return -1;
75677d68377Salnsn 			compiler_common->dfa_size++;
75777d68377Salnsn 		}
75877d68377Salnsn 	}
75977d68377Salnsn 
76077d68377Salnsn 	if (stack_push(stack, type_rng_end, 0))
76177d68377Salnsn 		return -1;
76277d68377Salnsn 	return regex_string - base_from;
76377d68377Salnsn }
76477d68377Salnsn 
parse(const regex_char_t * regex_string,int length,struct compiler_common * compiler_common)76577d68377Salnsn static int parse(const regex_char_t *regex_string, int length, struct compiler_common *compiler_common)
76677d68377Salnsn {
76777d68377Salnsn 	/* Depth of bracketed expressions. */
76877d68377Salnsn 	int depth = 0;
76977d68377Salnsn 	/* Have we already found a term? '1' if not yet. */
77077d68377Salnsn 	int begin = 1;
77177d68377Salnsn 	/* Cache stack pointer. */
77277d68377Salnsn 	struct stack* stack = &compiler_common->stack;
77377d68377Salnsn 	int tmp;
77477d68377Salnsn 
77577d68377Salnsn 	/* Type_begin and type_end. */
77677d68377Salnsn 	compiler_common->dfa_size = 2;
77777d68377Salnsn 	stack_init(stack);
77877d68377Salnsn 	if (stack_push(stack, type_begin, 0))
77977d68377Salnsn 		return REGEX_MEMORY_ERROR;
78077d68377Salnsn 
78177d68377Salnsn 	if (length > 0 && *regex_string == '^') {
78277d68377Salnsn 		compiler_common->flags |= REGEX_MATCH_BEGIN;
78377d68377Salnsn 		length--;
78477d68377Salnsn 		regex_string++;
78577d68377Salnsn 	}
78677d68377Salnsn 
78777d68377Salnsn 	if ((compiler_common->flags & (REGEX_MATCH_BEGIN | REGEX_NEWLINE)) == (REGEX_MATCH_BEGIN | REGEX_NEWLINE)) {
78877d68377Salnsn 		/* Replace REGEX_MATCH_BEGIN flag to REGEX_FAKE_MATCH_BEGIN */
78977d68377Salnsn 		compiler_common->flags &= ~REGEX_MATCH_BEGIN;
79077d68377Salnsn 		compiler_common->flags |= REGEX_FAKE_MATCH_BEGIN;
79177d68377Salnsn 		/* and append a new-line search. */
79277d68377Salnsn 		if (stack_push(stack, type_newline, 0))
79377d68377Salnsn 			return REGEX_MEMORY_ERROR;
79477d68377Salnsn 		compiler_common->dfa_size++;
79577d68377Salnsn 		/* Begin intentionally kept as 1. */
79677d68377Salnsn 	}
79777d68377Salnsn 
79877d68377Salnsn 	while (length > 0) {
79977d68377Salnsn 		switch (*regex_string) {
80077d68377Salnsn 		case '\\' :
80177d68377Salnsn 			length--;
80277d68377Salnsn 			regex_string++;
80377d68377Salnsn 			if (length == 0)
80477d68377Salnsn 				return REGEX_INVALID_REGEX;
80577d68377Salnsn 			if (stack_push(stack, type_char, *regex_string))
80677d68377Salnsn 				return REGEX_MEMORY_ERROR;
80777d68377Salnsn 			begin = 0;
80877d68377Salnsn 			compiler_common->dfa_size++;
80977d68377Salnsn 			break;
81077d68377Salnsn 
81177d68377Salnsn 		case '.' :
81277d68377Salnsn 			if (stack_push(stack, type_rng_start, 1))
81377d68377Salnsn 				return REGEX_MEMORY_ERROR;
81477d68377Salnsn 			if (compiler_common->flags & REGEX_NEWLINE) {
81577d68377Salnsn 				if (stack_push(stack, type_rng_char, '\n'))
81677d68377Salnsn 					return REGEX_MEMORY_ERROR;
81777d68377Salnsn 				if (stack_push(stack, type_rng_char, '\r'))
81877d68377Salnsn 					return REGEX_MEMORY_ERROR;
81977d68377Salnsn 				compiler_common->dfa_size += 2;
82077d68377Salnsn 			}
82177d68377Salnsn 			if (stack_push(stack, type_rng_end, 1))
82277d68377Salnsn 				return REGEX_MEMORY_ERROR;
82377d68377Salnsn 			begin = 0;
82477d68377Salnsn 			compiler_common->dfa_size += 2;
82577d68377Salnsn 			break;
82677d68377Salnsn 
82777d68377Salnsn 		case '(' :
82877d68377Salnsn 			depth++;
82977d68377Salnsn 			if (stack_push(stack, type_open_br, 0))
83077d68377Salnsn 				return REGEX_MEMORY_ERROR;
83177d68377Salnsn 			begin = 1;
83277d68377Salnsn 			break;
83377d68377Salnsn 
83477d68377Salnsn 		case ')' :
83577d68377Salnsn 			if (depth == 0)
83677d68377Salnsn 				return REGEX_INVALID_REGEX;
83777d68377Salnsn 			depth--;
83877d68377Salnsn 			if (stack_push(stack, type_close_br, 0))
83977d68377Salnsn 				return REGEX_MEMORY_ERROR;
84077d68377Salnsn 			begin = 0;
84177d68377Salnsn 			break;
84277d68377Salnsn 
84377d68377Salnsn 		case '|' :
84477d68377Salnsn 			if (stack_push(stack, type_select, 0))
84577d68377Salnsn 				return REGEX_MEMORY_ERROR;
84677d68377Salnsn 			begin = 1;
84777d68377Salnsn 			compiler_common->dfa_size += 2;
84877d68377Salnsn 			break;
84977d68377Salnsn 
85077d68377Salnsn 		case '*' :
85177d68377Salnsn 			if (begin)
85277d68377Salnsn 				return REGEX_INVALID_REGEX;
85377d68377Salnsn 			if (stack_push(stack, type_asterisk, 0))
85477d68377Salnsn 				return REGEX_MEMORY_ERROR;
85577d68377Salnsn 			compiler_common->dfa_size += 2;
85677d68377Salnsn 			break;
85777d68377Salnsn 
85877d68377Salnsn 		case '?' :
85977d68377Salnsn 		case '+' :
86077d68377Salnsn 			if (begin)
86177d68377Salnsn 				return REGEX_INVALID_REGEX;
86277d68377Salnsn 			if (stack_push(stack, (*regex_string == '+') ? type_plus_sign : type_qestion_mark, 0))
86377d68377Salnsn 				return REGEX_MEMORY_ERROR;
86477d68377Salnsn 			compiler_common->dfa_size++;
86577d68377Salnsn 			break;
86677d68377Salnsn 
86777d68377Salnsn 		case '{' :
86877d68377Salnsn 			tmp = parse_iterator(regex_string, length, stack, &compiler_common->dfa_size, begin);
86977d68377Salnsn 
87077d68377Salnsn 			if (tmp >= 0) {
87177d68377Salnsn 				length -= tmp;
87277d68377Salnsn 				regex_string += tmp;
87377d68377Salnsn 			}
87477d68377Salnsn 			else if (tmp == -1)
87577d68377Salnsn 				return REGEX_MEMORY_ERROR;
87677d68377Salnsn 			else {
87777d68377Salnsn 				/* Not a valid range expression. */
87877d68377Salnsn 				SLJIT_ASSERT(tmp == -2);
87977d68377Salnsn 				if (stack_push(stack, type_char, '{'))
88077d68377Salnsn 					return REGEX_MEMORY_ERROR;
88177d68377Salnsn 				compiler_common->dfa_size++;
88277d68377Salnsn 			}
88377d68377Salnsn 			break;
88477d68377Salnsn 
88577d68377Salnsn 		case '[' :
88677d68377Salnsn 			tmp = parse_char_range(regex_string, length, compiler_common);
88777d68377Salnsn 			if (tmp >= 0) {
88877d68377Salnsn 				length -= tmp;
88977d68377Salnsn 				regex_string += tmp;
89077d68377Salnsn 			}
89177d68377Salnsn 			else if (tmp == -1)
89277d68377Salnsn 				return REGEX_MEMORY_ERROR;
89377d68377Salnsn 			else {
89477d68377Salnsn 				SLJIT_ASSERT(tmp == -2);
89577d68377Salnsn 				return REGEX_INVALID_REGEX;
89677d68377Salnsn 			}
89777d68377Salnsn 			begin = 0;
89877d68377Salnsn 			break;
89977d68377Salnsn 
90077d68377Salnsn 		default:
90177d68377Salnsn 			if (length == 1 && *regex_string == '$') {
90277d68377Salnsn 				compiler_common->flags |= REGEX_MATCH_END;
90377d68377Salnsn 				break;
90477d68377Salnsn 			}
90577d68377Salnsn 			if (stack_push(stack, type_char, *regex_string))
90677d68377Salnsn 				return REGEX_MEMORY_ERROR;
90777d68377Salnsn 			begin = 0;
90877d68377Salnsn 			compiler_common->dfa_size++;
90977d68377Salnsn 			break;
91077d68377Salnsn 		}
91177d68377Salnsn 		length--;
91277d68377Salnsn 		regex_string++;
91377d68377Salnsn 	}
91477d68377Salnsn 
91577d68377Salnsn 	if (depth != 0)
91677d68377Salnsn 		return REGEX_INVALID_REGEX;
91777d68377Salnsn 
91877d68377Salnsn 	if ((compiler_common->flags & (REGEX_MATCH_END | REGEX_NEWLINE)) == (REGEX_MATCH_END | REGEX_NEWLINE)) {
91977d68377Salnsn 		/* Replace REGEX_MATCH_END flag to REGEX_FAKE_MATCH_END */
92077d68377Salnsn 		compiler_common->flags &= ~REGEX_MATCH_END;
92177d68377Salnsn 		compiler_common->flags |= REGEX_FAKE_MATCH_END;
92277d68377Salnsn 		/* and append a new-line search. */
92377d68377Salnsn 		if (stack_push(stack, type_newline, 1))
92477d68377Salnsn 			return REGEX_MEMORY_ERROR;
92577d68377Salnsn 		compiler_common->dfa_size++;
92677d68377Salnsn 		/* Begin intentionally kept as 1. */
92777d68377Salnsn 	}
92877d68377Salnsn 
92977d68377Salnsn 	if (stack_push(stack, type_end, 0))
93077d68377Salnsn 		return REGEX_MEMORY_ERROR;
93177d68377Salnsn 
93277d68377Salnsn 	return REGEX_NO_ERROR;
93377d68377Salnsn }
93477d68377Salnsn 
93577d68377Salnsn /* --------------------------------------------------------------------- */
93677d68377Salnsn /*  Generating machine state transitions                                 */
93777d68377Salnsn /* --------------------------------------------------------------------- */
93877d68377Salnsn 
93977d68377Salnsn #define PUT_TRANSITION(typ, val) \
94077d68377Salnsn 	do { \
94177d68377Salnsn 		--transitions_ptr; \
94277d68377Salnsn 		transitions_ptr->type = typ; \
94377d68377Salnsn 		transitions_ptr->value = val; \
94477d68377Salnsn 	} while (0)
94577d68377Salnsn 
handle_iteratives(struct stack_item * transitions_ptr,struct stack_item * transitions,struct stack * depth)94677d68377Salnsn static struct stack_item* handle_iteratives(struct stack_item *transitions_ptr, struct stack_item *transitions, struct stack *depth)
94777d68377Salnsn {
94877d68377Salnsn 	struct stack_item *item;
94977d68377Salnsn 
95077d68377Salnsn 	while (1) {
95177d68377Salnsn 		item = stack_top(depth);
95277d68377Salnsn 
95377d68377Salnsn 		switch (item->type) {
95477d68377Salnsn 		case type_asterisk:
95577d68377Salnsn 			SLJIT_ASSERT(transitions[item->value].type == type_branch);
95677d68377Salnsn 			transitions[item->value].value = transitions_ptr - transitions;
95777d68377Salnsn 			PUT_TRANSITION(type_branch, item->value + 1);
95877d68377Salnsn 			break;
95977d68377Salnsn 
96077d68377Salnsn 		case type_plus_sign:
96177d68377Salnsn 			SLJIT_ASSERT(transitions[item->value].type == type_branch);
96277d68377Salnsn 			transitions[item->value].value = transitions_ptr - transitions;
96377d68377Salnsn 			break;
96477d68377Salnsn 
96577d68377Salnsn 		case type_qestion_mark:
96677d68377Salnsn 			PUT_TRANSITION(type_branch, item->value);
96777d68377Salnsn 			break;
96877d68377Salnsn 
96977d68377Salnsn 		default:
97077d68377Salnsn 			return transitions_ptr;
97177d68377Salnsn 		}
97277d68377Salnsn 		stack_pop(depth);
97377d68377Salnsn 	}
97477d68377Salnsn }
97577d68377Salnsn 
generate_transitions(struct compiler_common * compiler_common)97677d68377Salnsn static int generate_transitions(struct compiler_common *compiler_common)
97777d68377Salnsn {
97877d68377Salnsn 	struct stack *stack = &compiler_common->stack;
97977d68377Salnsn 	struct stack *depth = &compiler_common->depth;
98077d68377Salnsn 	struct stack_item *transitions_ptr;
98177d68377Salnsn 	struct stack_item *item;
98277d68377Salnsn 
98377d68377Salnsn 	stack_init(depth);
98499e10043Salnsn 	compiler_common->dfa_transitions = SLJIT_MALLOC(sizeof(struct stack_item) * compiler_common->dfa_size, NULL);
98577d68377Salnsn 	if (!compiler_common->dfa_transitions)
98677d68377Salnsn 		return REGEX_MEMORY_ERROR;
98777d68377Salnsn 
98877d68377Salnsn 	/* Go through the items of the stack and generate the necessary branches and jumps (edges of DFA). */
98977d68377Salnsn 	transitions_ptr = compiler_common->dfa_transitions + compiler_common->dfa_size;
99077d68377Salnsn 	while (stack->count > 0) {
99177d68377Salnsn 		item = stack_pop(stack);
99277d68377Salnsn 		switch (item->type) {
99377d68377Salnsn 		case type_begin:
99477d68377Salnsn 		case type_open_br:
99577d68377Salnsn 			item = stack_pop(depth);
99677d68377Salnsn 			if (item->type == type_select)
99777d68377Salnsn 				PUT_TRANSITION(type_branch, item->value + 1);
99877d68377Salnsn 			else
99977d68377Salnsn 				SLJIT_ASSERT(item->type == type_close_br);
100077d68377Salnsn 			if (stack->count == 0)
100177d68377Salnsn 				PUT_TRANSITION(type_begin, 0);
100277d68377Salnsn 			else
100377d68377Salnsn 				transitions_ptr = handle_iteratives(transitions_ptr, compiler_common->dfa_transitions, depth);
100477d68377Salnsn 			break;
100577d68377Salnsn 
100677d68377Salnsn 		case type_end:
100777d68377Salnsn 		case type_close_br:
100877d68377Salnsn 			if (item->type == type_end)
100977d68377Salnsn 				*--transitions_ptr = *item;
101077d68377Salnsn 			if (stack_push(depth, type_close_br, transitions_ptr - compiler_common->dfa_transitions))
101177d68377Salnsn 				return REGEX_MEMORY_ERROR;
101277d68377Salnsn 			break;
101377d68377Salnsn 
101477d68377Salnsn 		case type_select:
101577d68377Salnsn 			item = stack_top(depth);
101677d68377Salnsn 			if (item->type == type_select) {
101777d68377Salnsn 				SLJIT_ASSERT(compiler_common->dfa_transitions[item->value].type == type_jump);
101877d68377Salnsn 				PUT_TRANSITION(type_branch, item->value + 1);
101977d68377Salnsn 				PUT_TRANSITION(type_jump, item->value);
102077d68377Salnsn 				item->value = transitions_ptr - compiler_common->dfa_transitions;
102177d68377Salnsn 			}
102277d68377Salnsn 			else {
102377d68377Salnsn 				SLJIT_ASSERT(item->type == type_close_br);
102477d68377Salnsn 				item->type = type_select;
102577d68377Salnsn 				PUT_TRANSITION(type_jump, item->value);
102677d68377Salnsn 				item->value = transitions_ptr - compiler_common->dfa_transitions;
102777d68377Salnsn 			}
102877d68377Salnsn 			break;
102977d68377Salnsn 
103077d68377Salnsn 		case type_asterisk:
103177d68377Salnsn 		case type_plus_sign:
103277d68377Salnsn 		case type_qestion_mark:
103377d68377Salnsn 			if (item->type != type_qestion_mark)
103477d68377Salnsn 				PUT_TRANSITION(type_branch, 0);
103577d68377Salnsn 			if (stack_push(depth, item->type, transitions_ptr - compiler_common->dfa_transitions))
103677d68377Salnsn 				return REGEX_MEMORY_ERROR;
103777d68377Salnsn 			break;
103877d68377Salnsn 
103977d68377Salnsn 		case type_char:
104077d68377Salnsn 		case type_newline:
104177d68377Salnsn 		case type_rng_start:
104277d68377Salnsn 			/* Requires handle_iteratives. */
104377d68377Salnsn 			*--transitions_ptr = *item;
104477d68377Salnsn 			transitions_ptr = handle_iteratives(transitions_ptr, compiler_common->dfa_transitions, depth);
104577d68377Salnsn 			break;
104677d68377Salnsn 
104777d68377Salnsn 		default:
104877d68377Salnsn 			*--transitions_ptr = *item;
104977d68377Salnsn 			break;
105077d68377Salnsn 		}
105177d68377Salnsn 	}
105277d68377Salnsn 
105377d68377Salnsn 	SLJIT_ASSERT(compiler_common->dfa_transitions == transitions_ptr);
105477d68377Salnsn 	SLJIT_ASSERT(depth->count == 0);
105577d68377Salnsn 	return REGEX_NO_ERROR;
105677d68377Salnsn }
105777d68377Salnsn 
105877d68377Salnsn #undef PUT_TRANSITION
105977d68377Salnsn 
106077d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
106177d68377Salnsn 
verbose_transitions(struct compiler_common * compiler_common)106277d68377Salnsn static void verbose_transitions(struct compiler_common *compiler_common)
106377d68377Salnsn {
106477d68377Salnsn 	struct stack_item *transitions_ptr = compiler_common->dfa_transitions;
106577d68377Salnsn 	struct stack_item *transitions_end = transitions_ptr + compiler_common->dfa_size;
106677d68377Salnsn 	struct stack_item *search_states_ptr = compiler_common->search_states;
106777d68377Salnsn 	int pos;
106877d68377Salnsn 
106977d68377Salnsn 	printf("-----------------\nTransitions\n-----------------\n");
107077d68377Salnsn 	pos = 0;
107177d68377Salnsn 	while (transitions_ptr < transitions_end) {
107277d68377Salnsn 		printf("[%3d] ", pos++);
107377d68377Salnsn 		if (search_states_ptr->type >= 0)
107477d68377Salnsn 			printf("(%3d) ", search_states_ptr->type);
107577d68377Salnsn 		switch (transitions_ptr->type) {
107677d68377Salnsn 		case type_begin:
107777d68377Salnsn 			printf("type_begin\n");
107877d68377Salnsn 			break;
107977d68377Salnsn 
108077d68377Salnsn 		case type_end:
108177d68377Salnsn 			printf("type_end\n");
108277d68377Salnsn 			break;
108377d68377Salnsn 
108477d68377Salnsn 		case type_char:
108577d68377Salnsn 			if (transitions_ptr->value >= ' ')
108677d68377Salnsn 				printf("type_char '%c'\n", transitions_ptr->value);
108777d68377Salnsn 			else
108877d68377Salnsn 				printf("type_char 0x%x\n", transitions_ptr->value);
108977d68377Salnsn 			break;
109077d68377Salnsn 
109177d68377Salnsn 		case type_newline:
109277d68377Salnsn 			printf("type_newline %s\n", transitions_ptr->value ? "(end)" : "(begin)");
109377d68377Salnsn 			break;
109477d68377Salnsn 
109577d68377Salnsn 		case type_id:
109677d68377Salnsn 			printf("type_id %d\n", transitions_ptr->value);
109777d68377Salnsn 			break;
109877d68377Salnsn 
109977d68377Salnsn 		case type_rng_start:
110077d68377Salnsn 			printf("type_rng_start %s\n", transitions_ptr->value ? "(invert)" : "(normal)");
110177d68377Salnsn 			break;
110277d68377Salnsn 
110377d68377Salnsn 		case type_rng_end:
110477d68377Salnsn 			printf("type_rng_end\n");
110577d68377Salnsn 			break;
110677d68377Salnsn 
110777d68377Salnsn 		case type_rng_char:
110877d68377Salnsn 			if (transitions_ptr->value >= ' ')
110977d68377Salnsn 				printf("type_rng_char '%c'\n", transitions_ptr->value);
111077d68377Salnsn 			else
111177d68377Salnsn 				printf("type_rng_char 0x%x\n", transitions_ptr->value);
111277d68377Salnsn 			break;
111377d68377Salnsn 
111477d68377Salnsn 		case type_rng_left:
111577d68377Salnsn 			if (transitions_ptr->value >= ' ')
111677d68377Salnsn 				printf("type_rng_left '%c'\n", transitions_ptr->value);
111777d68377Salnsn 			else
111877d68377Salnsn 				printf("type_rng_left 0x%x\n", transitions_ptr->value);
111977d68377Salnsn 			break;
112077d68377Salnsn 
112177d68377Salnsn 		case type_rng_right:
112277d68377Salnsn 			if (transitions_ptr->value >= ' ')
112377d68377Salnsn 				printf("type_rng_right '%c'\n", transitions_ptr->value);
112477d68377Salnsn 			else
112577d68377Salnsn 				printf("type_rng_right 0x%x\n", transitions_ptr->value);
112677d68377Salnsn 			break;
112777d68377Salnsn 
112877d68377Salnsn 		case type_branch:
112977d68377Salnsn 			printf("type_branch -> %d\n", transitions_ptr->value);
113077d68377Salnsn 			break;
113177d68377Salnsn 
113277d68377Salnsn 		case type_jump:
113377d68377Salnsn 			printf("type_jump -> %d\n", transitions_ptr->value);
113477d68377Salnsn 			break;
113577d68377Salnsn 
113677d68377Salnsn 		default:
113777d68377Salnsn 			printf("UNEXPECTED TYPE\n");
113877d68377Salnsn 			break;
113977d68377Salnsn 		}
114077d68377Salnsn 		transitions_ptr++;
114177d68377Salnsn 		search_states_ptr++;
114277d68377Salnsn 	}
114377d68377Salnsn 	printf("flags: ");
114477d68377Salnsn 	if (!(compiler_common->flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_NEWLINE | REGEX_ID_CHECK | REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)))
114577d68377Salnsn 		printf("none ");
114677d68377Salnsn 	if (compiler_common->flags & REGEX_MATCH_BEGIN)
114777d68377Salnsn 		printf("REGEX_MATCH_BEGIN ");
114877d68377Salnsn 	if (compiler_common->flags & REGEX_MATCH_END)
114977d68377Salnsn 		printf("REGEX_MATCH_END ");
115077d68377Salnsn 	if (compiler_common->flags & REGEX_NEWLINE)
115177d68377Salnsn 		printf("REGEX_NEWLINE ");
115277d68377Salnsn 	if (compiler_common->flags & REGEX_ID_CHECK)
115377d68377Salnsn 		printf("REGEX_ID_CHECK ");
115477d68377Salnsn 	if (compiler_common->flags & REGEX_FAKE_MATCH_BEGIN)
115577d68377Salnsn 		printf("REGEX_FAKE_MATCH_BEGIN ");
115677d68377Salnsn 	if (compiler_common->flags & REGEX_FAKE_MATCH_END)
115777d68377Salnsn 		printf("REGEX_FAKE_MATCH_END ");
115877d68377Salnsn 	if (compiler_common->longest_range_size > 0)
115977d68377Salnsn 		printf("(longest range: %ld) ", (long)compiler_common->longest_range_size);
116077d68377Salnsn 	printf("\n");
116177d68377Salnsn }
116277d68377Salnsn 
116377d68377Salnsn #endif
116477d68377Salnsn 
116577d68377Salnsn /* --------------------------------------------------------------------- */
116677d68377Salnsn /*  Utilities                                                            */
116777d68377Salnsn /* --------------------------------------------------------------------- */
116877d68377Salnsn 
generate_search_states(struct compiler_common * compiler_common)116977d68377Salnsn static int generate_search_states(struct compiler_common *compiler_common)
117077d68377Salnsn {
117177d68377Salnsn 	struct stack_item *transitions_ptr = compiler_common->dfa_transitions;
117277d68377Salnsn 	struct stack_item *transitions_end = transitions_ptr + compiler_common->dfa_size;
117377d68377Salnsn 	struct stack_item *search_states_ptr;
117477d68377Salnsn 	struct stack_item *rng_start = NULL;
117577d68377Salnsn 
117677d68377Salnsn 	compiler_common->terms_size = !(compiler_common->flags & REGEX_FAKE_MATCH_END) ? 1 : 2;
117777d68377Salnsn 	compiler_common->longest_range_size = 0;
117899e10043Salnsn 	compiler_common->search_states = SLJIT_MALLOC(sizeof(struct stack_item) * compiler_common->dfa_size, NULL);
117977d68377Salnsn 	if (!compiler_common->search_states)
118077d68377Salnsn 		return REGEX_MEMORY_ERROR;
118177d68377Salnsn 
118277d68377Salnsn 	search_states_ptr = compiler_common->search_states;
118377d68377Salnsn 	while (transitions_ptr < transitions_end) {
118477d68377Salnsn 		switch (transitions_ptr->type) {
118577d68377Salnsn 		case type_begin:
118677d68377Salnsn 		case type_end:
118777d68377Salnsn 			search_states_ptr->type = 0;
118877d68377Salnsn 			break;
118977d68377Salnsn 
119077d68377Salnsn 		case type_char:
119177d68377Salnsn 			search_states_ptr->type = compiler_common->terms_size++;
119277d68377Salnsn 			break;
119377d68377Salnsn 
119477d68377Salnsn 		case type_newline:
119577d68377Salnsn 			if (transitions_ptr->value)
119677d68377Salnsn 				search_states_ptr->type = 1;
119777d68377Salnsn 			else
119877d68377Salnsn 				search_states_ptr->type = compiler_common->terms_size++;
119977d68377Salnsn 			SLJIT_ASSERT(search_states_ptr->type == 1 || search_states_ptr->type == 2);
120077d68377Salnsn 			break;
120177d68377Salnsn 
120277d68377Salnsn 		case type_id:
120377d68377Salnsn 			if (transitions_ptr->value > 0)
120477d68377Salnsn 				compiler_common->flags |= REGEX_ID_CHECK;
120577d68377Salnsn 			search_states_ptr->type = -1;
120677d68377Salnsn 			break;
120777d68377Salnsn 
120877d68377Salnsn 		case type_rng_start:
120977d68377Salnsn 			search_states_ptr->type = compiler_common->terms_size;
121077d68377Salnsn 			rng_start = search_states_ptr;
121177d68377Salnsn 			break;
121277d68377Salnsn 
121377d68377Salnsn 		case type_rng_end:
121477d68377Salnsn 			search_states_ptr->type = compiler_common->terms_size++;
121577d68377Salnsn 			/* Ok, this is a blunt over estimation :) */
121677d68377Salnsn 			if (compiler_common->longest_range_size < search_states_ptr - rng_start)
121777d68377Salnsn 				compiler_common->longest_range_size = search_states_ptr - rng_start;
121877d68377Salnsn 			break;
121977d68377Salnsn 
122077d68377Salnsn 		default:
122177d68377Salnsn 			search_states_ptr->type = -1;
122277d68377Salnsn 			break;
122377d68377Salnsn 		}
122477d68377Salnsn 		search_states_ptr->value = -1;
122577d68377Salnsn 		search_states_ptr++;
122677d68377Salnsn 		transitions_ptr++;
122777d68377Salnsn 	}
122877d68377Salnsn 	return REGEX_NO_ERROR;
122977d68377Salnsn }
123077d68377Salnsn 
trace_transitions(int from,struct compiler_common * compiler_common)123177d68377Salnsn static int trace_transitions(int from, struct compiler_common *compiler_common)
123277d68377Salnsn {
123377d68377Salnsn 	int id = 0;
123477d68377Salnsn 	struct stack *stack = &compiler_common->stack;
123577d68377Salnsn 	struct stack *depth = &compiler_common->depth;
123677d68377Salnsn 	struct stack_item *dfa_transitions = compiler_common->dfa_transitions;
123777d68377Salnsn 	struct stack_item *search_states = compiler_common->search_states;
123877d68377Salnsn 
123977d68377Salnsn 	SLJIT_ASSERT(search_states[from].type >= 0);
124077d68377Salnsn 
124177d68377Salnsn 	from++;
124277d68377Salnsn 
124377d68377Salnsn 	/* Be prepared for any paths (loops, etc). */
124477d68377Salnsn 	while (1) {
124577d68377Salnsn 		if (dfa_transitions[from].type == type_id)
124677d68377Salnsn 			if (id < dfa_transitions[from].value)
124777d68377Salnsn 				id = dfa_transitions[from].value;
124877d68377Salnsn 
124977d68377Salnsn 		if (search_states[from].value < id) {
125077d68377Salnsn 			/* Forward step. */
125177d68377Salnsn 			if (search_states[from].value == -1)
125277d68377Salnsn 				if (stack_push(stack, 0, from))
125377d68377Salnsn 					return REGEX_MEMORY_ERROR;
125477d68377Salnsn 			search_states[from].value = id;
125577d68377Salnsn 
125677d68377Salnsn 			if (dfa_transitions[from].type == type_branch) {
125777d68377Salnsn 				if (stack_push(depth, id, from))
125877d68377Salnsn 					return REGEX_MEMORY_ERROR;
125977d68377Salnsn 				from++;
126077d68377Salnsn 				continue;
126177d68377Salnsn 			}
126277d68377Salnsn 			else if (dfa_transitions[from].type == type_jump) {
126377d68377Salnsn 				from = dfa_transitions[from].value;
126477d68377Salnsn 				continue;
126577d68377Salnsn 			}
126677d68377Salnsn 			else if (search_states[from].type < 0) {
126777d68377Salnsn 				from++;
126877d68377Salnsn 				continue;
126977d68377Salnsn 			}
127077d68377Salnsn 		}
127177d68377Salnsn 
127277d68377Salnsn 		/* Back tracking. */
127377d68377Salnsn 		if (depth->count > 0) {
127477d68377Salnsn 			id = stack_top(depth)->type;
127577d68377Salnsn 			from = dfa_transitions[stack_pop(depth)->value].value;
127677d68377Salnsn 			continue;
127777d68377Salnsn 		}
127877d68377Salnsn 		return 0;
127977d68377Salnsn 	}
128077d68377Salnsn }
128177d68377Salnsn 
128277d68377Salnsn /* --------------------------------------------------------------------- */
128377d68377Salnsn /*  Code generator                                                       */
128477d68377Salnsn /* --------------------------------------------------------------------- */
128577d68377Salnsn 
1286e5292e6bSalnsn #define TERM_OFFSET_OF(index, offs)	(((index) * no_states + (offs)) * sizeof(sljit_sw))
1287e5292e6bSalnsn #define TERM_REL_OFFSET_OF(base, offs)	((base) + ((offs) * sizeof(sljit_sw)))
128877d68377Salnsn 
128977d68377Salnsn #define EMIT_OP1(type, arg1, arg2, arg3, arg4) \
129077d68377Salnsn 	CHECK(sljit_emit_op1(compiler, type, arg1, arg2, arg3, arg4))
129177d68377Salnsn 
129277d68377Salnsn #define EMIT_OP2(type, arg1, arg2, arg3, arg4, arg5, arg6) \
129377d68377Salnsn 	CHECK(sljit_emit_op2(compiler, type, arg1, arg2, arg3, arg4, arg5, arg6))
129477d68377Salnsn 
129577d68377Salnsn #define EMIT_LABEL(label) \
129677d68377Salnsn 	label = sljit_emit_label(compiler); \
129777d68377Salnsn 	CHECK(!label)
129877d68377Salnsn 
129977d68377Salnsn #define EMIT_JUMP(jump, type) \
130077d68377Salnsn 	jump = sljit_emit_jump(compiler, type); \
130177d68377Salnsn 	CHECK(!jump)
130277d68377Salnsn 
130377d68377Salnsn #define EMIT_CMP(jump, type, arg1, arg2, arg3, arg4) \
130477d68377Salnsn 	jump = sljit_emit_cmp(compiler, type, arg1, arg2, arg3, arg4); \
130577d68377Salnsn 	CHECK(!jump)
130677d68377Salnsn 
130777d68377Salnsn /* CHECK depends on the use case. */
130877d68377Salnsn 
130977d68377Salnsn #define CHECK(exp) \
131077d68377Salnsn 	if (SLJIT_UNLIKELY(exp)) \
131177d68377Salnsn 		return REGEX_MEMORY_ERROR
131277d68377Salnsn 
compile_uncond_tran(struct compiler_common * compiler_common,int reg)131377d68377Salnsn static int compile_uncond_tran(struct compiler_common *compiler_common, int reg)
131477d68377Salnsn {
131577d68377Salnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
131677d68377Salnsn 	struct stack *stack = &compiler_common->stack;
131777d68377Salnsn 	struct stack_item *search_states = compiler_common->search_states;
131877d68377Salnsn 	int flags = compiler_common->flags;
1319e5292e6bSalnsn 	sljit_sw no_states = compiler_common->no_states;
132077d68377Salnsn 	sljit_uw head = 0;
1321e5292e6bSalnsn 	sljit_sw offset, value;
132277d68377Salnsn 
132377d68377Salnsn 	if (reg != R_CURR_STATE || !(compiler_common->flags & REGEX_FAKE_MATCH_BEGIN)) {
132477d68377Salnsn 		CHECK(trace_transitions(0, compiler_common));
132577d68377Salnsn 	}
132677d68377Salnsn 	else {
132777d68377Salnsn 		CHECK(trace_transitions(1, compiler_common));
132877d68377Salnsn 	}
132977d68377Salnsn 
133077d68377Salnsn 	while (stack->count > 0) {
133177d68377Salnsn 		value = stack_pop(stack)->value;
133277d68377Salnsn 		if (search_states[value].type >= 0) {
133377d68377Salnsn 			offset = TERM_OFFSET_OF(search_states[value].type, 0);
133477d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 1), SLJIT_IMM, head);
133577d68377Salnsn 			if (offset > 0)
133677d68377Salnsn 				head = offset;
133777d68377Salnsn 
133877d68377Salnsn 			if (!(flags & REGEX_MATCH_BEGIN)) {
133977d68377Salnsn 				EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), R_TEMP, 0);
134077d68377Salnsn 				if (flags & REGEX_ID_CHECK) {
134177d68377Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 3), SLJIT_IMM, search_states[value].value);
134277d68377Salnsn 				}
134377d68377Salnsn 			}
134477d68377Salnsn 			else if (flags & REGEX_ID_CHECK) {
134577d68377Salnsn 				EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), SLJIT_IMM, search_states[value].value);
134677d68377Salnsn 			}
134777d68377Salnsn 		}
134877d68377Salnsn 		search_states[value].value = -1;
134977d68377Salnsn 	}
135077d68377Salnsn 	if (reg == R_NEXT_STATE) {
135177d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);
135277d68377Salnsn 	}
135377d68377Salnsn 	else if (flags & REGEX_FAKE_MATCH_BEGIN) {
135477d68377Salnsn 		SLJIT_ASSERT(compiler_common->dfa_transitions[1].type == type_newline && !compiler_common->dfa_transitions[1].value);
135577d68377Salnsn 		offset = TERM_OFFSET_OF(search_states[1].type, 0);
135677d68377Salnsn 
135777d68377Salnsn 		SLJIT_ASSERT(!(flags & REGEX_MATCH_BEGIN));
135877d68377Salnsn 
135977d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 1), SLJIT_IMM, head);
136077d68377Salnsn 		head = offset;
136177d68377Salnsn 
136277d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), SLJIT_IMM, 1);
136377d68377Salnsn 		if (flags & REGEX_ID_CHECK) {
136477d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 3), SLJIT_IMM, 0);
136577d68377Salnsn 		}
136677d68377Salnsn 	}
136777d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, head);
136877d68377Salnsn 	return REGEX_NO_ERROR;
136977d68377Salnsn }
137077d68377Salnsn 
compile_cond_tran(struct compiler_common * compiler_common,sljit_sw curr_index)1371e5292e6bSalnsn static int compile_cond_tran(struct compiler_common *compiler_common, sljit_sw curr_index)
137277d68377Salnsn {
137377d68377Salnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
137477d68377Salnsn 	struct stack *stack = &compiler_common->stack;
137577d68377Salnsn 	struct stack_item *search_states = compiler_common->search_states;
1376e5292e6bSalnsn 	sljit_sw offset;
137777d68377Salnsn 	int flags;
1378e5292e6bSalnsn 	sljit_sw no_states;
1379e5292e6bSalnsn 	sljit_sw value;
138077d68377Salnsn 	struct sljit_jump *jump1;
138177d68377Salnsn 	struct sljit_jump *jump2;
138277d68377Salnsn 	struct sljit_jump *jump3;
138377d68377Salnsn 	struct sljit_jump *jump4;
138477d68377Salnsn 	struct sljit_jump *jump5;
138577d68377Salnsn 	struct sljit_label *label1;
138677d68377Salnsn 
138777d68377Salnsn 	flags = compiler_common->flags;
138877d68377Salnsn 	no_states = compiler_common->no_states;
138977d68377Salnsn 
139077d68377Salnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);
139177d68377Salnsn 	if (!(flags & (REGEX_ID_CHECK | REGEX_MATCH_BEGIN))) {
139277d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));
139377d68377Salnsn 	}
139477d68377Salnsn 
139577d68377Salnsn 	while (stack->count > 0) {
139677d68377Salnsn 		value = stack_pop(stack)->value;
139777d68377Salnsn 		if (search_states[value].type >= 0) {
139877d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
139977d68377Salnsn 			if (flags & REGEX_MATCH_VERBOSE)
140077d68377Salnsn 				printf("-> (%3d:%3d) ", search_states[value].type, search_states[value].value);
140177d68377Salnsn #endif
140277d68377Salnsn 			offset = TERM_OFFSET_OF(search_states[value].type, 0);
140377d68377Salnsn 
140477d68377Salnsn 			if (!(flags & REGEX_ID_CHECK)) {
140577d68377Salnsn 				if (!(flags & REGEX_MATCH_BEGIN)) {
140677d68377Salnsn 					/* Check whether item is inserted. */
140799e10043Salnsn 					EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), SLJIT_IMM, -1);
1408e5292e6bSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), R_NEXT_HEAD, 0);
140977d68377Salnsn 					if (offset > 0) {
141077d68377Salnsn 						EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);
141177d68377Salnsn 					}
141277d68377Salnsn 					EMIT_JUMP(jump2, SLJIT_JUMP);
141377d68377Salnsn 
141477d68377Salnsn 					/* Check whether old index <= index. */
141577d68377Salnsn 					EMIT_LABEL(label1);
141677d68377Salnsn 					sljit_set_label(jump1, label1);
141777d68377Salnsn 
141899e10043Salnsn 					EMIT_CMP(jump1, SLJIT_LESS_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
141977d68377Salnsn 
142077d68377Salnsn 					EMIT_LABEL(label1);
142177d68377Salnsn 					sljit_set_label(jump2, label1);
1422e5292e6bSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
142377d68377Salnsn 
142477d68377Salnsn 					EMIT_LABEL(label1);
142577d68377Salnsn 					sljit_set_label(jump1, label1);
142677d68377Salnsn 				}
142777d68377Salnsn 				else {
142877d68377Salnsn 					/* Check whether item is inserted. */
142999e10043Salnsn 					EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), SLJIT_IMM, -1);
1430e5292e6bSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), R_NEXT_HEAD, 0);
143177d68377Salnsn 					if (offset > 0) {
143277d68377Salnsn 						EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);
143377d68377Salnsn 					}
143477d68377Salnsn 					EMIT_LABEL(label1);
143577d68377Salnsn 					sljit_set_label(jump1, label1);
143677d68377Salnsn 				}
143777d68377Salnsn 			}
143877d68377Salnsn 			else {
143977d68377Salnsn 				if (!(flags & REGEX_MATCH_BEGIN)) {
144077d68377Salnsn 					EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));
144177d68377Salnsn 
144277d68377Salnsn 					/* Check whether item is inserted. */
144399e10043Salnsn 					EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), SLJIT_IMM, -1);
1444e5292e6bSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), R_NEXT_HEAD, 0);
144577d68377Salnsn 					if (offset > 0) {
144677d68377Salnsn 						EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);
144777d68377Salnsn 					}
144877d68377Salnsn 					EMIT_JUMP(jump2, SLJIT_JUMP);
144977d68377Salnsn 
145077d68377Salnsn 					/* Check whether old index != index. */
145177d68377Salnsn 					EMIT_LABEL(label1);
145277d68377Salnsn 					sljit_set_label(jump1, label1);
145377d68377Salnsn 
1454*06eb4e7bSalnsn 					EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
145599e10043Salnsn 					EMIT_JUMP(jump1, SLJIT_LESS);
1456*06eb4e7bSalnsn 					EMIT_JUMP(jump3, SLJIT_NOT_EQUAL); /* Greater. */
145777d68377Salnsn 
145877d68377Salnsn 					/* Old index == index. */
145977d68377Salnsn 					EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 3));
146077d68377Salnsn 					if (search_states[value].value > 0) {
146199e10043Salnsn 						EMIT_CMP(jump4, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
146277d68377Salnsn 
146377d68377Salnsn 						EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
146477d68377Salnsn 						EMIT_LABEL(label1);
146577d68377Salnsn 						sljit_set_label(jump4, label1);
146677d68377Salnsn 					}
146777d68377Salnsn 
1468*06eb4e7bSalnsn 					EMIT_OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, SLJIT_MEM1(R_NEXT_STATE), offset + 3 * sizeof(sljit_sw), R_TEMP, 0);
146999e10043Salnsn 					EMIT_JUMP(jump4, SLJIT_GREATER_EQUAL);
147077d68377Salnsn 					EMIT_JUMP(jump5, SLJIT_JUMP);
147177d68377Salnsn 
147277d68377Salnsn 					/* Overwrite index & id. */
147377d68377Salnsn 					EMIT_LABEL(label1);
147477d68377Salnsn 					sljit_set_label(jump3, label1);
147577d68377Salnsn 					sljit_set_label(jump2, label1);
1476e5292e6bSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
147777d68377Salnsn 
147877d68377Salnsn 					EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 3));
147977d68377Salnsn 					if (search_states[value].value > 0) {
148099e10043Salnsn 						EMIT_CMP(jump3, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
148177d68377Salnsn 
148277d68377Salnsn 						EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
148377d68377Salnsn 						EMIT_LABEL(label1);
148477d68377Salnsn 						sljit_set_label(jump3, label1);
148577d68377Salnsn 					}
148677d68377Salnsn 
148777d68377Salnsn 					EMIT_LABEL(label1);
148877d68377Salnsn 					sljit_set_label(jump5, label1);
1489e5292e6bSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 3 * sizeof(sljit_sw), R_TEMP, 0);
149077d68377Salnsn 
149177d68377Salnsn 					/* Exit. */
149277d68377Salnsn 					EMIT_LABEL(label1);
149377d68377Salnsn 					sljit_set_label(jump1, label1);
149477d68377Salnsn 					sljit_set_label(jump4, label1);
149577d68377Salnsn 				}
149677d68377Salnsn 				else {
149777d68377Salnsn 					EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));
149877d68377Salnsn 
149977d68377Salnsn 					if (search_states[value].value > 0) {
150099e10043Salnsn 						EMIT_CMP(jump1, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
150177d68377Salnsn 
150277d68377Salnsn 						EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
150377d68377Salnsn 						EMIT_LABEL(label1);
150477d68377Salnsn 						sljit_set_label(jump1, label1);
150577d68377Salnsn 					}
150677d68377Salnsn 
150777d68377Salnsn 					/* Check whether item is inserted. */
150899e10043Salnsn 					EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), SLJIT_IMM, -1);
1509e5292e6bSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), R_NEXT_HEAD, 0);
151077d68377Salnsn 					if (offset > 0) {
151177d68377Salnsn 						EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);
151277d68377Salnsn 					}
151377d68377Salnsn 					EMIT_JUMP(jump2, SLJIT_JUMP);
151477d68377Salnsn 
151577d68377Salnsn 					/* Check whether old id >= id. */
151677d68377Salnsn 					EMIT_LABEL(label1);
151777d68377Salnsn 					sljit_set_label(jump1, label1);
151877d68377Salnsn 
151999e10043Salnsn 					EMIT_CMP(jump1, SLJIT_GREATER_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
152077d68377Salnsn 
152177d68377Salnsn 					EMIT_LABEL(label1);
152277d68377Salnsn 					sljit_set_label(jump2, label1);
1523e5292e6bSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
152477d68377Salnsn 
152577d68377Salnsn 					EMIT_LABEL(label1);
152677d68377Salnsn 					sljit_set_label(jump1, label1);
152777d68377Salnsn 				}
152877d68377Salnsn 			}
152977d68377Salnsn 		}
153077d68377Salnsn 		search_states[value].value = -1;
153177d68377Salnsn 	}
153277d68377Salnsn 
153377d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
153477d68377Salnsn 	if (flags & REGEX_MATCH_VERBOSE)
153577d68377Salnsn 		printf("\n");
153677d68377Salnsn #endif
153777d68377Salnsn 	return REGEX_NO_ERROR;
153877d68377Salnsn }
153977d68377Salnsn 
compile_end_check(struct compiler_common * compiler_common,struct sljit_label * end_check_label)154077d68377Salnsn static int compile_end_check(struct compiler_common *compiler_common, struct sljit_label *end_check_label)
154177d68377Salnsn {
154277d68377Salnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
154377d68377Salnsn 	struct sljit_jump *jump;
154477d68377Salnsn 	struct sljit_jump *clear_states_jump;
154577d68377Salnsn 	struct sljit_label *label;
154677d68377Salnsn 	struct sljit_label *leave_label;
154777d68377Salnsn 	struct sljit_label *begin_loop_label;
154877d68377Salnsn 
154977d68377Salnsn 	/* Priority order: best_begin > best_end > best_id.
155077d68377Salnsn 	   In other words:
155177d68377Salnsn 	       if (new best_begin > old test_begin) do nothing
155277d68377Salnsn 	       otherwise we know that new_end > old_end, since R_CURR_INDEX ever increasing
155377d68377Salnsn 	       therefore we must overwrite all best_* variables (new_id also contains the highest id for this turn). */
155477d68377Salnsn 
155577d68377Salnsn 	/* Both R_CURR_CHAR and R_BEST_BEGIN used as temporary registers. */
155677d68377Salnsn 
155777d68377Salnsn 	if (!(compiler_common->flags & REGEX_MATCH_BEGIN)) {
155877d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2));
155999e10043Salnsn 		EMIT_CMP(jump, !(compiler_common->flags & REGEX_MATCH_NON_GREEDY) ? SLJIT_LESS : SLJIT_LESS_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), R_CURR_CHAR, 0);
156077d68377Salnsn 		sljit_set_label(jump, end_check_label);
156177d68377Salnsn 
156277d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), R_CURR_CHAR, 0);
156377d68377Salnsn 		if (!(compiler_common->flags & (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END))) {
156477d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);
156577d68377Salnsn 		}
156677d68377Salnsn 		else {
156777d68377Salnsn 			if ((compiler_common->flags & (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)) == (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)) {
156877d68377Salnsn 				EMIT_OP2(SLJIT_SUB, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0, SLJIT_IMM, 2);
156977d68377Salnsn 			}
157077d68377Salnsn 			else {
157177d68377Salnsn 				EMIT_OP2(SLJIT_SUB, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0, SLJIT_IMM, 1);
157277d68377Salnsn 			}
157377d68377Salnsn 		}
157477d68377Salnsn 		if (compiler_common->flags & REGEX_ID_CHECK) {
157577d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 3));
157677d68377Salnsn 		}
157777d68377Salnsn 
157899e10043Salnsn 		EMIT_CMP(clear_states_jump, SLJIT_LESS, R_CURR_CHAR, 0, R_BEST_BEGIN, 0);
157977d68377Salnsn 
158077d68377Salnsn 		EMIT_LABEL(leave_label);
158177d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, R_CURR_CHAR, 0);
158277d68377Salnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
158377d68377Salnsn 		sljit_set_label(jump, end_check_label);
158477d68377Salnsn 
158577d68377Salnsn 		/* A loop to clear all states, which are > (or >=) than R_CURR_CHAR. */
158677d68377Salnsn 		EMIT_LABEL(label);
158777d68377Salnsn 		sljit_set_label(clear_states_jump, label);
158877d68377Salnsn 
158977d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);
159077d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
159177d68377Salnsn 
159277d68377Salnsn 		/* Begin of the loop. */
159377d68377Salnsn 		EMIT_LABEL(begin_loop_label);
159499e10043Salnsn 		EMIT_CMP(jump, SLJIT_EQUAL, R_TEMP, 0, SLJIT_IMM, 0);
159577d68377Salnsn 		sljit_set_label(jump, leave_label);
159677d68377Salnsn 
159777d68377Salnsn 		EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, R_CURR_STATE, 0);
1598e5292e6bSalnsn 		EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw));
159999e10043Salnsn 		EMIT_CMP(clear_states_jump, !(compiler_common->flags & REGEX_MATCH_NON_GREEDY) ? SLJIT_GREATER : SLJIT_GREATER_EQUAL, SLJIT_MEM1(R_TEMP), 2 * sizeof(sljit_sw), R_CURR_CHAR, 0);
160077d68377Salnsn 
160177d68377Salnsn 		/* Case 1: keep this case. */
1602e5292e6bSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw), R_NEXT_HEAD, 0);
160377d68377Salnsn 		EMIT_OP2(SLJIT_SUB, R_NEXT_HEAD, 0, R_TEMP, 0, R_CURR_STATE, 0);
160477d68377Salnsn 
160577d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_BEST_BEGIN, 0);
160677d68377Salnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
160777d68377Salnsn 		sljit_set_label(jump, begin_loop_label);
160877d68377Salnsn 
160977d68377Salnsn 		/* Case 2: remove this case. */
161077d68377Salnsn 		EMIT_LABEL(label);
161177d68377Salnsn 		sljit_set_label(clear_states_jump, label);
161277d68377Salnsn 
1613e5292e6bSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw), SLJIT_IMM, -1);
161477d68377Salnsn 
161577d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_BEST_BEGIN, 0);
161677d68377Salnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
161777d68377Salnsn 		sljit_set_label(jump, begin_loop_label);
161877d68377Salnsn 	}
161977d68377Salnsn 	else {
162077d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_IMM, 0);
162177d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);
162277d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);
162377d68377Salnsn 		if (compiler_common->flags & REGEX_ID_CHECK) {
162477d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2));
162577d68377Salnsn 		}
162677d68377Salnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
162777d68377Salnsn 		sljit_set_label(jump, end_check_label);
162877d68377Salnsn 	}
162977d68377Salnsn 	return REGEX_NO_ERROR;
163077d68377Salnsn }
163177d68377Salnsn 
compile_leave_fast_forward(struct compiler_common * compiler_common,struct sljit_label * fast_forward_label)163277d68377Salnsn static int compile_leave_fast_forward(struct compiler_common *compiler_common, struct sljit_label *fast_forward_label)
163377d68377Salnsn {
163477d68377Salnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
163577d68377Salnsn 	struct stack *stack = &compiler_common->stack;
163677d68377Salnsn 	struct stack_item *dfa_transitions = compiler_common->dfa_transitions;
163777d68377Salnsn 	struct stack_item *search_states = compiler_common->search_states;
163877d68377Salnsn 	int ind;
163977d68377Salnsn 	struct sljit_jump *jump;
164077d68377Salnsn 	int init_range = 1, prev_value = 0;
164177d68377Salnsn 
164277d68377Salnsn 	while (stack->count > 0) {
164377d68377Salnsn 		ind = stack_pop(stack)->value;
164477d68377Salnsn 		search_states[ind].value = -1;
164577d68377Salnsn 		if (search_states[ind].type >= 0) {
164677d68377Salnsn 			if (dfa_transitions[ind].type == type_char) {
164799e10043Salnsn 				EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);
164877d68377Salnsn 				sljit_set_label(jump, fast_forward_label);
164977d68377Salnsn 			}
165077d68377Salnsn 			else if (dfa_transitions[ind].type == type_rng_start) {
165177d68377Salnsn 				SLJIT_ASSERT(!dfa_transitions[ind].value);
165277d68377Salnsn 				ind++;
165377d68377Salnsn 				while (dfa_transitions[ind].type != type_rng_end) {
165477d68377Salnsn 					if (dfa_transitions[ind].type == type_rng_char) {
165599e10043Salnsn 						EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);
165677d68377Salnsn 						sljit_set_label(jump, fast_forward_label);
165777d68377Salnsn 					}
165877d68377Salnsn 					else {
165977d68377Salnsn 						SLJIT_ASSERT(dfa_transitions[ind].type == type_rng_left);
166077d68377Salnsn 						if (init_range) {
166177d68377Salnsn 							EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_CHAR, 0);
166277d68377Salnsn 							init_range = 0;
166377d68377Salnsn 						}
166477d68377Salnsn 						if (dfa_transitions[ind].value != prev_value) {
166577d68377Salnsn 							/* Best compatibility to all archs. */
166677d68377Salnsn 							prev_value -= dfa_transitions[ind].value;
166777d68377Salnsn 							if (prev_value < 0) {
166877d68377Salnsn 								EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, -prev_value);
166977d68377Salnsn 							}
167077d68377Salnsn 							else {
167177d68377Salnsn 								EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, prev_value);
167277d68377Salnsn 							}
167377d68377Salnsn 							prev_value = dfa_transitions[ind].value;
167477d68377Salnsn 						}
167599e10043Salnsn 						EMIT_CMP(jump, SLJIT_LESS_EQUAL, R_TEMP, 0, SLJIT_IMM, dfa_transitions[ind + 1].value - dfa_transitions[ind].value);
167677d68377Salnsn 						sljit_set_label(jump, fast_forward_label);
167777d68377Salnsn 						ind++;
167877d68377Salnsn 					}
167977d68377Salnsn 					ind++;
168077d68377Salnsn 				}
168177d68377Salnsn 			}
168277d68377Salnsn 			else {
168377d68377Salnsn 				SLJIT_ASSERT(dfa_transitions[ind].type == type_newline);
168499e10043Salnsn 				EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\n');
168577d68377Salnsn 				sljit_set_label(jump, fast_forward_label);
168699e10043Salnsn 				EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\r');
168777d68377Salnsn 				sljit_set_label(jump, fast_forward_label);
168877d68377Salnsn 			}
168977d68377Salnsn 		}
169077d68377Salnsn 	}
169177d68377Salnsn 	return REGEX_NO_ERROR;
169277d68377Salnsn }
169377d68377Salnsn 
compile_newline_check(struct compiler_common * compiler_common,sljit_sw ind)1694e5292e6bSalnsn static int compile_newline_check(struct compiler_common *compiler_common, sljit_sw ind)
169577d68377Salnsn {
169677d68377Salnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
169777d68377Salnsn 	struct sljit_jump *jump1;
169877d68377Salnsn 	struct sljit_jump *jump2;
169977d68377Salnsn 	struct sljit_label *label;
1700e5292e6bSalnsn 	sljit_sw no_states;
1701e5292e6bSalnsn 	sljit_sw offset;
170277d68377Salnsn 
170377d68377Salnsn 	/* Check whether a new-line character is found. */
170499e10043Salnsn 	EMIT_CMP(jump1, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\n');
170599e10043Salnsn 	EMIT_CMP(jump2, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\r');
170677d68377Salnsn 
170777d68377Salnsn 	no_states = compiler_common->no_states;
170877d68377Salnsn 	offset = TERM_OFFSET_OF(compiler_common->search_states[ind].type, 1);
170977d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), offset);
171077d68377Salnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), offset, SLJIT_IMM, -1);
171177d68377Salnsn 	CHECK(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
171277d68377Salnsn 
171377d68377Salnsn 	EMIT_LABEL(label);
171477d68377Salnsn 	sljit_set_label(jump1, label);
171577d68377Salnsn 	sljit_set_label(jump2, label);
171677d68377Salnsn 	return REGEX_NO_ERROR;
171777d68377Salnsn }
171877d68377Salnsn 
171977d68377Salnsn #undef CHECK
172077d68377Salnsn 
172177d68377Salnsn #define CHECK(exp) \
172277d68377Salnsn 	if (SLJIT_UNLIKELY(exp)) \
172377d68377Salnsn 		return 0
172477d68377Salnsn 
range_set_label(struct sljit_jump ** range_jump_list,struct sljit_label * label)172577d68377Salnsn static SLJIT_INLINE void range_set_label(struct sljit_jump **range_jump_list, struct sljit_label *label)
172677d68377Salnsn {
172777d68377Salnsn 	while (*range_jump_list) {
172877d68377Salnsn 		sljit_set_label(*range_jump_list, label);
172977d68377Salnsn 		range_jump_list++;
173077d68377Salnsn 	}
173177d68377Salnsn }
173277d68377Salnsn 
compile_range_check(struct compiler_common * compiler_common,sljit_sw ind)1733e5292e6bSalnsn static sljit_sw compile_range_check(struct compiler_common *compiler_common, sljit_sw ind)
173477d68377Salnsn {
173577d68377Salnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
173677d68377Salnsn 	struct stack_item *dfa_transitions = compiler_common->dfa_transitions;
173777d68377Salnsn 	struct sljit_jump **range_jump_list = compiler_common->range_jump_list;
173877d68377Salnsn 	int invert = dfa_transitions[ind].value;
173977d68377Salnsn 	struct sljit_label *label;
1740e5292e6bSalnsn 	sljit_sw no_states;
1741e5292e6bSalnsn 	sljit_sw offset;
174277d68377Salnsn 	int init_range = 1, prev_value = 0;
174377d68377Salnsn 
174477d68377Salnsn 	ind++;
174577d68377Salnsn 
174677d68377Salnsn 	while (dfa_transitions[ind].type != type_rng_end) {
174777d68377Salnsn 		if (dfa_transitions[ind].type == type_rng_char) {
174899e10043Salnsn 			EMIT_CMP(*range_jump_list, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);
174977d68377Salnsn 			range_jump_list++;
175077d68377Salnsn 		}
175177d68377Salnsn 		else {
175277d68377Salnsn 			SLJIT_ASSERT(dfa_transitions[ind].type == type_rng_left);
175377d68377Salnsn 			if (init_range) {
175477d68377Salnsn 				EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_CHAR, 0);
175577d68377Salnsn 				init_range = 0;
175677d68377Salnsn 			}
175777d68377Salnsn 			if (dfa_transitions[ind].value != prev_value) {
175877d68377Salnsn 				/* Best compatibility to all archs. */
175977d68377Salnsn 				prev_value -= dfa_transitions[ind].value;
176077d68377Salnsn 				if (prev_value < 0) {
176177d68377Salnsn 					EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, -prev_value);
176277d68377Salnsn 				}
176377d68377Salnsn 				else {
176477d68377Salnsn 					EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, prev_value);
176577d68377Salnsn 				}
176677d68377Salnsn 				prev_value = dfa_transitions[ind].value;
176777d68377Salnsn 			}
176899e10043Salnsn 			EMIT_CMP(*range_jump_list, SLJIT_LESS_EQUAL, R_TEMP, 0, SLJIT_IMM, dfa_transitions[ind + 1].value - dfa_transitions[ind].value);
176977d68377Salnsn 			range_jump_list++;
177077d68377Salnsn 			ind++;
177177d68377Salnsn 		}
177277d68377Salnsn 		ind++;
177377d68377Salnsn 	}
177477d68377Salnsn 
177577d68377Salnsn 	*range_jump_list = NULL;
177677d68377Salnsn 
177777d68377Salnsn 	if (!invert) {
177877d68377Salnsn 		no_states = compiler_common->no_states;
177977d68377Salnsn 		offset = TERM_OFFSET_OF(compiler_common->search_states[ind].type, 1);
178077d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), offset);
178177d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), offset, SLJIT_IMM, -1);
178277d68377Salnsn 		CHECK(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
178377d68377Salnsn 
178477d68377Salnsn 		EMIT_LABEL(label);
178577d68377Salnsn 		range_set_label(compiler_common->range_jump_list, label);
178677d68377Salnsn 		/* Clears the jump list. */
178777d68377Salnsn 		*compiler_common->range_jump_list = NULL;
178877d68377Salnsn 	}
178977d68377Salnsn 	return ind;
179077d68377Salnsn }
179177d68377Salnsn 
179277d68377Salnsn #undef TERM_OFFSET_OF
179377d68377Salnsn #undef EMIT_OP1
179477d68377Salnsn #undef EMIT_OP2
179577d68377Salnsn #undef EMIT_LABEL
179677d68377Salnsn #undef EMIT_JUMP
179777d68377Salnsn #undef EMIT_CMP
179877d68377Salnsn #undef CHECK
179977d68377Salnsn 
180077d68377Salnsn /* --------------------------------------------------------------------- */
180177d68377Salnsn /*  Main compiler                                                        */
180277d68377Salnsn /* --------------------------------------------------------------------- */
180377d68377Salnsn 
1804e5292e6bSalnsn #define TERM_OFFSET_OF(ind, offs) (((ind) * compiler_common.no_states + (offs)) * sizeof(sljit_sw))
180577d68377Salnsn 
180677d68377Salnsn #define EMIT_OP1(type, arg1, arg2, arg3, arg4) \
180777d68377Salnsn 	CHECK(sljit_emit_op1(compiler_common.compiler, type, arg1, arg2, arg3, arg4))
180877d68377Salnsn 
180977d68377Salnsn #define EMIT_OP2(type, arg1, arg2, arg3, arg4, arg5, arg6) \
181077d68377Salnsn 	CHECK(sljit_emit_op2(compiler_common.compiler, type, arg1, arg2, arg3, arg4, arg5, arg6))
181177d68377Salnsn 
181277d68377Salnsn #define EMIT_LABEL(label) \
181377d68377Salnsn 	label = sljit_emit_label(compiler_common.compiler); \
181477d68377Salnsn 	CHECK(!label)
181577d68377Salnsn 
181677d68377Salnsn #define EMIT_JUMP(jump, type) \
181777d68377Salnsn 	jump = sljit_emit_jump(compiler_common.compiler, type); \
181877d68377Salnsn 	CHECK(!jump)
181977d68377Salnsn 
182077d68377Salnsn #define EMIT_CMP(jump, type, arg1, arg2, arg3, arg4) \
182177d68377Salnsn 	jump = sljit_emit_cmp(compiler_common.compiler, type, arg1, arg2, arg3, arg4); \
182277d68377Salnsn 	CHECK(!jump)
182377d68377Salnsn 
182477d68377Salnsn /* A do {} while(0) expression helps to avoid goto statements. */
182577d68377Salnsn #define BEGIN_GUARD \
182677d68377Salnsn 	do {
182777d68377Salnsn 
182877d68377Salnsn #define END_GUARD \
182977d68377Salnsn 	} while(0);
183077d68377Salnsn 
183177d68377Salnsn #define CHECK(exp) \
183277d68377Salnsn 	if (SLJIT_UNLIKELY(exp)) \
183377d68377Salnsn 		break;
183477d68377Salnsn 
regex_compile(const regex_char_t * regex_string,int length,int re_flags,int * error)183577d68377Salnsn struct regex_machine* regex_compile(const regex_char_t *regex_string, int length, int re_flags, int *error)
183677d68377Salnsn {
183777d68377Salnsn 	struct compiler_common compiler_common;
1838e5292e6bSalnsn 	sljit_sw ind;
183977d68377Salnsn 	int error_code, done, suggest_fast_forward;
184077d68377Salnsn 	/* ID of an empty match (-1 if not reachable). */
184177d68377Salnsn 	int empty_match_id;
184277d68377Salnsn 
184377d68377Salnsn 	struct sljit_jump *jump;
184477d68377Salnsn 	struct sljit_jump *best_match_found_jump;
184577d68377Salnsn 	struct sljit_jump *fast_forward_jump = NULL;
184677d68377Salnsn 	struct sljit_jump *length_is_zero_jump;
184777d68377Salnsn 	struct sljit_jump *end_check_jump = NULL;
184877d68377Salnsn 	struct sljit_jump *best_match_check_jump = NULL;
184977d68377Salnsn 	struct sljit_jump *non_greedy_end_jump = NULL;
185077d68377Salnsn 	struct sljit_label *label;
185177d68377Salnsn 	struct sljit_label *end_check_label = NULL;
185277d68377Salnsn 	struct sljit_label *start_label;
185377d68377Salnsn 	struct sljit_label *fast_forward_label;
185477d68377Salnsn 	struct sljit_label *fast_forward_return_label;
185577d68377Salnsn 
185677d68377Salnsn 	if (error)
185777d68377Salnsn 		*error = REGEX_NO_ERROR;
185877d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
185977d68377Salnsn 	compiler_common.flags = re_flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_MATCH_NON_GREEDY | REGEX_NEWLINE | REGEX_MATCH_VERBOSE);
186077d68377Salnsn #else
186177d68377Salnsn 	compiler_common.flags = re_flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_MATCH_NON_GREEDY | REGEX_NEWLINE);
186277d68377Salnsn #endif
186377d68377Salnsn 
186477d68377Salnsn 	/* Step 1: parsing (Left->Right).
186577d68377Salnsn 	   Syntax check and AST generator. */
186677d68377Salnsn 	error_code = parse(regex_string, length, &compiler_common);
186777d68377Salnsn 	if (error_code) {
186877d68377Salnsn 		stack_destroy(&compiler_common.stack);
186977d68377Salnsn 		if (error)
187077d68377Salnsn 			*error = error_code;
187177d68377Salnsn 		return NULL;
187277d68377Salnsn 	}
187377d68377Salnsn 
187477d68377Salnsn 	/* Step 2: generating branches (Right->Left). */
187577d68377Salnsn 	error_code = generate_transitions(&compiler_common);
187677d68377Salnsn 	stack_destroy(&compiler_common.stack);
187777d68377Salnsn 	stack_destroy(&compiler_common.depth);
187877d68377Salnsn 	if (error_code) {
187977d68377Salnsn 		if (compiler_common.dfa_transitions)
188099e10043Salnsn 			SLJIT_FREE(compiler_common.dfa_transitions, NULL);
188177d68377Salnsn 		if (error)
188277d68377Salnsn 			*error = error_code;
188377d68377Salnsn 		return NULL;
188477d68377Salnsn 	}
188577d68377Salnsn 
188677d68377Salnsn 	/* Step 3: Generate necessary data for depth-first search (Left->Right). */
188777d68377Salnsn 	error_code = generate_search_states(&compiler_common);
188877d68377Salnsn 	if (error_code) {
188999e10043Salnsn 		SLJIT_FREE(compiler_common.dfa_transitions, NULL);
189077d68377Salnsn 		if (error)
189177d68377Salnsn 			*error = error_code;
189277d68377Salnsn 		return NULL;
189377d68377Salnsn 	}
189477d68377Salnsn 
189577d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
189677d68377Salnsn 	if (compiler_common.flags & REGEX_MATCH_VERBOSE)
189777d68377Salnsn 		verbose_transitions(&compiler_common);
189877d68377Salnsn #endif
189977d68377Salnsn 
190077d68377Salnsn 	/* Step 4: Left->Right generate code. */
190177d68377Salnsn 	stack_init(&compiler_common.stack);
190277d68377Salnsn 	stack_init(&compiler_common.depth);
190377d68377Salnsn 	done = 0;
190477d68377Salnsn 	compiler_common.machine = NULL;
190577d68377Salnsn 	compiler_common.compiler = NULL;
190677d68377Salnsn 	compiler_common.range_jump_list = NULL;
190777d68377Salnsn 
190877d68377Salnsn 	BEGIN_GUARD
190977d68377Salnsn 
191099e10043Salnsn 	compiler_common.machine = (struct regex_machine*)SLJIT_MALLOC(sizeof(struct regex_machine) + (compiler_common.terms_size - 1) * sizeof(sljit_uw), NULL);
191177d68377Salnsn 	CHECK(!compiler_common.machine);
191277d68377Salnsn 
191399e10043Salnsn 	compiler_common.compiler = sljit_create_compiler(NULL);
191477d68377Salnsn 	CHECK(!compiler_common.compiler);
191577d68377Salnsn 
191677d68377Salnsn 	if (compiler_common.longest_range_size > 0) {
191799e10043Salnsn 		compiler_common.range_jump_list = (struct sljit_jump**)SLJIT_MALLOC(sizeof(struct sljit_jump*) * compiler_common.longest_range_size, NULL);
191877d68377Salnsn 		CHECK(!compiler_common.range_jump_list);
191977d68377Salnsn 	}
192077d68377Salnsn 
192177d68377Salnsn 	if ((compiler_common.flags & REGEX_ID_CHECK) && !(compiler_common.flags & REGEX_MATCH_BEGIN))
192277d68377Salnsn 		compiler_common.no_states = 4;
192377d68377Salnsn 	else if (!(compiler_common.flags & REGEX_ID_CHECK) && (compiler_common.flags & REGEX_MATCH_BEGIN))
192477d68377Salnsn 		compiler_common.no_states = 2;
192577d68377Salnsn 	else
192677d68377Salnsn 		compiler_common.no_states = 3;
192777d68377Salnsn 
192877d68377Salnsn 	compiler_common.machine->flags = compiler_common.flags;
192977d68377Salnsn 	compiler_common.machine->no_states = compiler_common.no_states;
193077d68377Salnsn 	compiler_common.machine->size = compiler_common.machine->no_states * compiler_common.terms_size;
193177d68377Salnsn 
193277d68377Salnsn 	/* Study the regular expression. */
193377d68377Salnsn 	empty_match_id = -1;
193477d68377Salnsn 	suggest_fast_forward = 1;
193577d68377Salnsn 	if (!(compiler_common.flags & REGEX_FAKE_MATCH_BEGIN)) {
193677d68377Salnsn 		CHECK(trace_transitions(0, &compiler_common));
193777d68377Salnsn 		while (compiler_common.stack.count > 0) {
193877d68377Salnsn 			ind = stack_pop(&compiler_common.stack)->value;
193977d68377Salnsn 			if (compiler_common.search_states[ind].type == 0) {
194077d68377Salnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_end);
194177d68377Salnsn 				suggest_fast_forward = 0;
194277d68377Salnsn 				empty_match_id = compiler_common.search_states[ind].value;
194377d68377Salnsn 			}
194477d68377Salnsn 			else if (compiler_common.search_states[ind].type > 0) {
194577d68377Salnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type != type_end);
194677d68377Salnsn 				if (compiler_common.dfa_transitions[ind].type == type_rng_start && compiler_common.dfa_transitions[ind].value)
194777d68377Salnsn 					suggest_fast_forward = 0;
194877d68377Salnsn 			}
194977d68377Salnsn 			compiler_common.search_states[ind].value = -1;
195077d68377Salnsn 		}
195177d68377Salnsn 	}
195277d68377Salnsn 	else {
195377d68377Salnsn 		SLJIT_ASSERT(compiler_common.dfa_transitions[1].type == type_newline);
195477d68377Salnsn 		CHECK(trace_transitions(1, &compiler_common));
195577d68377Salnsn 		while (compiler_common.stack.count > 0) {
195677d68377Salnsn 			ind = stack_pop(&compiler_common.stack)->value;
195777d68377Salnsn 			if (compiler_common.search_states[ind].type == 0) {
195877d68377Salnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_end);
195977d68377Salnsn 				suggest_fast_forward = 0;
196077d68377Salnsn 				empty_match_id = compiler_common.search_states[ind].value;
196177d68377Salnsn 			}
196277d68377Salnsn 			compiler_common.search_states[ind].value = -1;
196377d68377Salnsn 		}
196477d68377Salnsn 	}
196577d68377Salnsn 
196677d68377Salnsn 	/* Step 4.1: Generate entry. */
196799e10043Salnsn 	CHECK(sljit_emit_enter(compiler_common.compiler, 0, 3, 5, 5, 0, 0, 0));
196877d68377Salnsn 
196977d68377Salnsn 	/* Copy arguments to their place. */
197099e10043Salnsn 	EMIT_OP1(SLJIT_MOV, R_REGEX_MATCH, 0, SLJIT_S0, 0);
197199e10043Salnsn 	EMIT_OP1(SLJIT_MOV, R_STRING, 0, SLJIT_S1, 0);
197299e10043Salnsn 	EMIT_OP2(SLJIT_ADD, R_LENGTH, 0, SLJIT_S2, 0, SLJIT_IMM, 1);
197377d68377Salnsn 
197477d68377Salnsn 	/* Init global registers. */
197577d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current));
197677d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next));
197777d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head));
197877d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin));
197977d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_CURR_INDEX, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index));
198077d68377Salnsn 
198177d68377Salnsn 	/* Check whether the best match has already found in a previous frame. */
198299e10043Salnsn 	EMIT_CMP(jump, SLJIT_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 0);
198377d68377Salnsn 	EMIT_JUMP(best_match_found_jump, SLJIT_JUMP);
198477d68377Salnsn 
198577d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
198677d68377Salnsn 	if (compiler_common.flags & REGEX_MATCH_VERBOSE)
198777d68377Salnsn 		printf("\n-----------------\nTrace\n-----------------\n");
198877d68377Salnsn #endif
198977d68377Salnsn 
199077d68377Salnsn 	/* Step 4.2: Generate code for state 0. */
199177d68377Salnsn 	EMIT_LABEL(label);
199277d68377Salnsn 	compiler_common.machine->entry_addrs[0] = (sljit_uw)label;
199377d68377Salnsn 
199477d68377Salnsn 	/* Swapping current and next. */
199577d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_STATE, 0);
199677d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, R_NEXT_STATE, 0);
199777d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, R_TEMP, 0);
199877d68377Salnsn 
199977d68377Salnsn 	/* Checking whether the best case needs to be updated. */
200077d68377Salnsn 	if (!(compiler_common.flags & REGEX_MATCH_END)) {
200199e10043Salnsn 		EMIT_CMP(end_check_jump, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 1), SLJIT_IMM, -1);
200277d68377Salnsn 		EMIT_LABEL(end_check_label);
200377d68377Salnsn 	}
200477d68377Salnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), TERM_REL_OFFSET_OF(0, 1), SLJIT_IMM, -1);
200577d68377Salnsn 	EMIT_OP2(SLJIT_ADD, R_CURR_INDEX, 0, R_CURR_INDEX, 0, SLJIT_IMM, 1);
200677d68377Salnsn 
200777d68377Salnsn 	/* Checking whether best case has already found. */
200877d68377Salnsn 	if (!(compiler_common.flags & REGEX_MATCH_END) || (compiler_common.flags & REGEX_MATCH_BEGIN)) {
200977d68377Salnsn 		if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {
201077d68377Salnsn 			/* We can bail out if no more active states remain and R_BEST_BEGIN != -1. */
201199e10043Salnsn 			EMIT_CMP(best_match_check_jump, SLJIT_NOT_EQUAL, R_BEST_BEGIN, 0, SLJIT_IMM, -1);
201277d68377Salnsn 		}
201377d68377Salnsn 		else {
201477d68377Salnsn 			/* We can bail out if no more active states remain (regardless of R_BEST_BEGIN). */
201599e10043Salnsn 			EMIT_CMP(best_match_check_jump, SLJIT_EQUAL, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
201677d68377Salnsn 		}
201777d68377Salnsn 	}
201877d68377Salnsn 
201977d68377Salnsn 	EMIT_LABEL(start_label);
202077d68377Salnsn 	sljit_set_label(jump, start_label);
202177d68377Salnsn 
202277d68377Salnsn 	if (!(compiler_common.flags & REGEX_MATCH_BEGIN) && suggest_fast_forward) {
202399e10043Salnsn 		EMIT_CMP(fast_forward_jump, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);
202477d68377Salnsn 	}
202577d68377Salnsn 
202677d68377Salnsn 	/* Loading the next character. */
2027*06eb4e7bSalnsn 	EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z, R_LENGTH, 0, R_LENGTH, 0, SLJIT_IMM, 1);
202899e10043Salnsn 	EMIT_JUMP(length_is_zero_jump, SLJIT_EQUAL);
202977d68377Salnsn 
203077d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_STRING, 0);
203177d68377Salnsn #ifdef REGEX_USE_8BIT_CHARS
203299e10043Salnsn 	EMIT_OP1(SLJIT_MOV_U8, R_CURR_CHAR, 0, SLJIT_MEM1(R_TEMP), 0);
203377d68377Salnsn 	EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, 1);
203477d68377Salnsn #else
203577d68377Salnsn 	EMIT_OP1(SLJIT_MOV_UH, R_CURR_CHAR, 0, SLJIT_MEM1(R_TEMP), 0);
203677d68377Salnsn 	EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, 2);
203777d68377Salnsn #endif
203877d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_STRING, 0, R_TEMP, 0);
203977d68377Salnsn 
204077d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
204177d68377Salnsn 	if (compiler_common.flags & REGEX_MATCH_VERBOSE) {
204277d68377Salnsn 		printf("(%3d): ", 0);
204377d68377Salnsn 		CHECK(trace_transitions(0, &compiler_common));
204477d68377Salnsn 		while (compiler_common.stack.count > 0) {
204577d68377Salnsn 			ind = stack_pop(&compiler_common.stack)->value;
204677d68377Salnsn 			if (compiler_common.search_states[ind].type >= 0)
204777d68377Salnsn 				printf("-> (%3d:%3d) ", compiler_common.search_states[ind].type, compiler_common.search_states[ind].value);
204877d68377Salnsn 			compiler_common.search_states[ind].value = -1;
204977d68377Salnsn 		}
205077d68377Salnsn 		printf("\n");
205177d68377Salnsn 	}
205277d68377Salnsn #endif
205377d68377Salnsn 
205477d68377Salnsn 	EMIT_LABEL(fast_forward_return_label);
205577d68377Salnsn 	if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {
205677d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 1);
205777d68377Salnsn 		if (!(compiler_common.flags & REGEX_MATCH_END)) {
205899e10043Salnsn 			EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_BEST_BEGIN, 0, SLJIT_IMM, -1);
205977d68377Salnsn 		}
206077d68377Salnsn 
206177d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_INDEX, 0);
206277d68377Salnsn 		CHECK(compile_uncond_tran(&compiler_common, R_NEXT_STATE));
206377d68377Salnsn 		/* And branching to the first state. */
206477d68377Salnsn 		CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
206577d68377Salnsn 
206677d68377Salnsn 		if (!(compiler_common.flags & REGEX_MATCH_END)) {
206777d68377Salnsn 			EMIT_LABEL(label);
206877d68377Salnsn 			sljit_set_label(jump, label);
206977d68377Salnsn 		}
207077d68377Salnsn 	}
207177d68377Salnsn 	/* This is the case where we only have to reset the R_NEXT_HEAD. */
207277d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);
207377d68377Salnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
207477d68377Salnsn 	CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
207577d68377Salnsn 
207677d68377Salnsn 	/* Fast-forward loop. */
207777d68377Salnsn 	if (fast_forward_jump) {
207877d68377Salnsn 		/* Quit from fast-forward loop. */
207977d68377Salnsn 		EMIT_LABEL(fast_forward_label);
208077d68377Salnsn 		EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_NEXT_HEAD, 0, SLJIT_IMM, 1);
208177d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_LENGTH, 0, R_NEXT_STATE, 0);
208277d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_STRING, 0, R_CURR_STATE, 0);
208377d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_CURR_INDEX, 0, R_NEXT_HEAD, 0);
208477d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next));
208577d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current));
208677d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head));
208777d68377Salnsn 
208877d68377Salnsn 		/* Update the start field of the locations. */
208977d68377Salnsn 		CHECK(trace_transitions(0, &compiler_common));
209077d68377Salnsn 		while (compiler_common.stack.count > 0) {
209177d68377Salnsn 			ind = stack_pop(&compiler_common.stack)->value;
209277d68377Salnsn 			if (compiler_common.search_states[ind].type >= 0) {
209377d68377Salnsn 				EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 2), R_TEMP, 0);
209477d68377Salnsn 			}
209577d68377Salnsn 			compiler_common.search_states[ind].value = -1;
209677d68377Salnsn 		}
209777d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);
209877d68377Salnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
209977d68377Salnsn 		sljit_set_label(jump, fast_forward_return_label);
210077d68377Salnsn 
210177d68377Salnsn 		/* Start fast-forward. */
210277d68377Salnsn 		EMIT_LABEL(label);
210377d68377Salnsn 		sljit_set_label(fast_forward_jump, label);
210477d68377Salnsn 
210577d68377Salnsn 		/* Moving everything to registers. */
210677d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next), R_NEXT_STATE, 0);
210777d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current), R_CURR_STATE, 0);
210877d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head), R_NEXT_HEAD, 0);
210977d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, R_LENGTH, 0);
211077d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, R_STRING, 0);
211177d68377Salnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, R_CURR_INDEX, 0);
211277d68377Salnsn 
211377d68377Salnsn 		/* Fast forward mainloop. */
211477d68377Salnsn 		EMIT_LABEL(label);
2115*06eb4e7bSalnsn 		EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z, R_NEXT_STATE, 0, R_NEXT_STATE, 0, SLJIT_IMM, 1);
211699e10043Salnsn 		EMIT_JUMP(fast_forward_jump, SLJIT_EQUAL);
211777d68377Salnsn 
211877d68377Salnsn #ifdef REGEX_USE_8BIT_CHARS
211999e10043Salnsn 		EMIT_OP1(SLJIT_MOV_U8, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), 0);
212077d68377Salnsn 		EMIT_OP2(SLJIT_ADD, R_CURR_STATE, 0, R_CURR_STATE, 0, SLJIT_IMM, 1);
212177d68377Salnsn #else
212277d68377Salnsn 		EMIT_OP1(SLJIT_MOV_UH, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), 0);
212377d68377Salnsn 		EMIT_OP2(SLJIT_ADD, R_CURR_STATE, 0, R_CURR_STATE, 0, SLJIT_IMM, 2);
212477d68377Salnsn #endif
212577d68377Salnsn 
212677d68377Salnsn 		CHECK(trace_transitions(0, &compiler_common));
212777d68377Salnsn 		CHECK(compile_leave_fast_forward(&compiler_common, fast_forward_label));
212877d68377Salnsn 
212977d68377Salnsn 		EMIT_OP2(SLJIT_ADD, R_NEXT_HEAD, 0, R_NEXT_HEAD, 0, SLJIT_IMM, 1);
213077d68377Salnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
213177d68377Salnsn 		sljit_set_label(jump, label);
213277d68377Salnsn 
213377d68377Salnsn 		/* String is finished. */
213477d68377Salnsn 		EMIT_LABEL(label);
213577d68377Salnsn 		sljit_set_label(fast_forward_jump, label);
213677d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index), R_NEXT_HEAD, 0);
213777d68377Salnsn 		EMIT_JUMP(fast_forward_jump, SLJIT_JUMP);
213877d68377Salnsn 	}
213977d68377Salnsn 
214077d68377Salnsn 	/* End check. */
214177d68377Salnsn 	if (end_check_jump) {
214277d68377Salnsn 		EMIT_LABEL(label);
214377d68377Salnsn 		sljit_set_label(end_check_jump, label);
214477d68377Salnsn 
214577d68377Salnsn 		if (!(compiler_common.flags & REGEX_MATCH_NON_GREEDY) || !(compiler_common.flags & REGEX_MATCH_BEGIN)) {
214677d68377Salnsn 			CHECK(compile_end_check(&compiler_common, end_check_label));
214777d68377Salnsn 		}
214877d68377Salnsn 		else {
214977d68377Salnsn 			/* Since we leave, we do not need to update the R_BEST_BEGIN. */
215077d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);
215177d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);
215277d68377Salnsn 			if (compiler_common.flags & REGEX_ID_CHECK) {
215377d68377Salnsn 				EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2));
215477d68377Salnsn 			}
215577d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 1);
215677d68377Salnsn 			EMIT_JUMP(non_greedy_end_jump, SLJIT_JUMP);
215777d68377Salnsn 		}
215877d68377Salnsn 	}
215977d68377Salnsn 
216077d68377Salnsn 	/* Finish check. */
216177d68377Salnsn 	if (best_match_check_jump) {
216277d68377Salnsn 		EMIT_LABEL(label);
216377d68377Salnsn 		sljit_set_label(best_match_check_jump, label);
216477d68377Salnsn 
216577d68377Salnsn 		if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {
216699e10043Salnsn 			EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
216777d68377Salnsn 			sljit_set_label(jump, start_label);
216877d68377Salnsn 		}
216977d68377Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 1);
217077d68377Salnsn 	}
217177d68377Salnsn 
217277d68377Salnsn 	/* Leaving matching and storing the necessary values. */
217377d68377Salnsn 	EMIT_LABEL(label);
217477d68377Salnsn 	sljit_set_label(length_is_zero_jump, label);
217577d68377Salnsn 	if (non_greedy_end_jump)
217677d68377Salnsn 		sljit_set_label(non_greedy_end_jump, label);
217777d68377Salnsn 
217877d68377Salnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index), R_CURR_INDEX, 0);
217977d68377Salnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head), R_NEXT_HEAD, 0);
218077d68377Salnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next), R_NEXT_STATE, 0);
218177d68377Salnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current), R_CURR_STATE, 0);
218277d68377Salnsn 
218377d68377Salnsn 	/* Exit from JIT. */
218477d68377Salnsn 	EMIT_LABEL(label);
218577d68377Salnsn 	sljit_set_label(best_match_found_jump, label);
218677d68377Salnsn 	if (fast_forward_jump)
218777d68377Salnsn 		sljit_set_label(fast_forward_jump, label);
218877d68377Salnsn 	CHECK(sljit_emit_return(compiler_common.compiler, SLJIT_UNUSED, 0, 0));
218977d68377Salnsn 
219099e10043Salnsn 	for (ind = 1; ind < compiler_common.dfa_size - 1; ind++) {
219177d68377Salnsn 		if (compiler_common.search_states[ind].type >= 0) {
219277d68377Salnsn 			SLJIT_ASSERT(compiler_common.search_states[ind].type < compiler_common.terms_size);
219377d68377Salnsn 			EMIT_LABEL(label);
219477d68377Salnsn 			compiler_common.machine->entry_addrs[compiler_common.search_states[ind].type] = (sljit_uw)label;
219577d68377Salnsn 
219677d68377Salnsn 			if (compiler_common.dfa_transitions[ind].type == type_char) {
219799e10043Salnsn 				EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, compiler_common.dfa_transitions[ind].value);
219877d68377Salnsn 			}
219977d68377Salnsn 			else if (compiler_common.dfa_transitions[ind].type == type_rng_start) {
220077d68377Salnsn 				ind = compile_range_check(&compiler_common, ind);
220177d68377Salnsn 				CHECK(!ind);
220277d68377Salnsn 			}
220377d68377Salnsn 			else {
220477d68377Salnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_newline);
220577d68377Salnsn 				CHECK(compile_newline_check(&compiler_common, ind));
220677d68377Salnsn 			}
220777d68377Salnsn 
220877d68377Salnsn 			CHECK(trace_transitions(ind, &compiler_common));
220977d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
221077d68377Salnsn 			if (compiler_common.flags & REGEX_MATCH_VERBOSE)
221177d68377Salnsn 				printf("(%3d): ", compiler_common.search_states[ind].type);
221277d68377Salnsn #endif
221377d68377Salnsn 			CHECK(compile_cond_tran(&compiler_common, compiler_common.search_states[ind].type));
221477d68377Salnsn 
221577d68377Salnsn 			if (compiler_common.dfa_transitions[ind].type == type_char) {
221677d68377Salnsn 				EMIT_LABEL(label);
221777d68377Salnsn 				sljit_set_label(jump, label);
221877d68377Salnsn 			}
221977d68377Salnsn 			else if (compiler_common.dfa_transitions[ind].type == type_rng_end) {
222077d68377Salnsn 				EMIT_LABEL(label);
222177d68377Salnsn 				range_set_label(compiler_common.range_jump_list, label);
222277d68377Salnsn 			}
222377d68377Salnsn 			else {
222477d68377Salnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_newline);
222577d68377Salnsn 			}
222677d68377Salnsn 
222777d68377Salnsn 			/* Branch to the next item in the list. */
222877d68377Salnsn 			EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 1));
222977d68377Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 1), SLJIT_IMM, -1);
223077d68377Salnsn 			CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
223177d68377Salnsn 		}
223277d68377Salnsn 	}
223377d68377Salnsn 
223477d68377Salnsn 	if (ind == compiler_common.dfa_size - 1) {
223577d68377Salnsn 		/* Generate an init stub function. */
223677d68377Salnsn 		EMIT_LABEL(label);
223799e10043Salnsn 		CHECK(sljit_emit_enter(compiler_common.compiler, 0, 2, 3, 3, 0, 0, 0));
223877d68377Salnsn 
223977d68377Salnsn 		if (empty_match_id == -1) {
224099e10043Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, -1);
224199e10043Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_IMM, 0);
224277d68377Salnsn 		}
224377d68377Salnsn 		else {
224499e10043Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);
224599e10043Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_IMM, empty_match_id);
224677d68377Salnsn 		}
224777d68377Salnsn 
224899e10043Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, index), SLJIT_IMM, !(compiler_common.flags & REGEX_FAKE_MATCH_BEGIN) ? 1 : 2);
224977d68377Salnsn 
225077d68377Salnsn 		if (!(compiler_common.flags & REGEX_MATCH_NON_GREEDY) || empty_match_id == -1) {
225177d68377Salnsn 			/* The else is a really rare event, so we still generate an empty function instead of a runtime pointer check. */
225299e10043Salnsn 			SLJIT_ASSERT(R_CURR_STATE == SLJIT_S0);
225377d68377Salnsn 			if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {
225477d68377Salnsn 				/* R_CURR_INDEX (put to R_TEMP) is zero. */
225577d68377Salnsn 				EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, 0);
225677d68377Salnsn 			}
225777d68377Salnsn 			CHECK(compile_uncond_tran(&compiler_common, R_CURR_STATE));
225877d68377Salnsn 		}
225977d68377Salnsn 		else {
226077d68377Salnsn 			EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
226177d68377Salnsn 		}
226277d68377Salnsn 		CHECK(sljit_emit_return(compiler_common.compiler, SLJIT_MOV, R_NEXT_HEAD, 0));
226377d68377Salnsn 
226477d68377Salnsn 		compiler_common.machine->continue_match = sljit_generate_code(compiler_common.compiler);
226577d68377Salnsn #ifndef SLJIT_INDIRECT_CALL
2266e5292e6bSalnsn 		compiler_common.machine->u.init_match = (void*)(sljit_sw)sljit_get_label_addr(label);
226777d68377Salnsn #else
226877d68377Salnsn 		sljit_set_function_context(&compiler_common.machine->u.init_match, &compiler_common.machine->context, sljit_get_label_addr(label), regex_compile);
226977d68377Salnsn #endif
227077d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
227177d68377Salnsn 		if (compiler_common.flags & REGEX_MATCH_VERBOSE)
227277d68377Salnsn 			printf("Continue match: %p Init match: %p\n\n", compiler_common.machine->continue_match, compiler_common.machine->u.init_match);
227377d68377Salnsn #endif
227477d68377Salnsn 		if (compiler_common.machine->continue_match) {
227577d68377Salnsn 			for (ind = 0; ind < compiler_common.terms_size; ++ind)
227677d68377Salnsn 				compiler_common.machine->entry_addrs[ind] = sljit_get_label_addr((struct sljit_label*)compiler_common.machine->entry_addrs[ind]);
227777d68377Salnsn 			done = 1;
227877d68377Salnsn 		}
227977d68377Salnsn 	}
228077d68377Salnsn 	END_GUARD
228177d68377Salnsn 
228277d68377Salnsn 	stack_destroy(&compiler_common.stack);
228377d68377Salnsn 	stack_destroy(&compiler_common.depth);
228499e10043Salnsn 	SLJIT_FREE(compiler_common.dfa_transitions, NULL);
228599e10043Salnsn 	SLJIT_FREE(compiler_common.search_states, NULL);
228677d68377Salnsn 	if (compiler_common.range_jump_list)
228799e10043Salnsn 		SLJIT_FREE(compiler_common.range_jump_list, NULL);
228877d68377Salnsn 	if (compiler_common.compiler)
228977d68377Salnsn 		sljit_free_compiler(compiler_common.compiler);
229077d68377Salnsn 	if (done)
229177d68377Salnsn 		return compiler_common.machine;
229277d68377Salnsn 
229377d68377Salnsn 	if (compiler_common.machine) {
229499e10043Salnsn 		SLJIT_FREE(compiler_common.machine, NULL);
229577d68377Salnsn 	}
229677d68377Salnsn 	if (error)
229777d68377Salnsn 		*error = REGEX_MEMORY_ERROR;
229877d68377Salnsn 	return NULL;
229977d68377Salnsn }
230077d68377Salnsn 
230177d68377Salnsn #undef TERM_OFFSET_OF
230277d68377Salnsn #undef EMIT_OP1
230377d68377Salnsn #undef EMIT_OP2
230477d68377Salnsn #undef EMIT_LABEL
230577d68377Salnsn #undef EMIT_JUMP
230677d68377Salnsn #undef EMIT_CMP
230777d68377Salnsn #undef BEGIN_GUARD
230877d68377Salnsn #undef END_GUARD
230977d68377Salnsn #undef CHECK
231077d68377Salnsn 
regex_free_machine(struct regex_machine * machine)231177d68377Salnsn void regex_free_machine(struct regex_machine *machine)
231277d68377Salnsn {
231377d68377Salnsn 	sljit_free_code(machine->continue_match);
231499e10043Salnsn 	SLJIT_FREE(machine, NULL);
231577d68377Salnsn }
231677d68377Salnsn 
regex_get_platform_name(void)231777d68377Salnsn const char* regex_get_platform_name(void)
231877d68377Salnsn {
231977d68377Salnsn 	return sljit_get_platform_name();
232077d68377Salnsn }
232177d68377Salnsn 
232277d68377Salnsn /* --------------------------------------------------------------------- */
232377d68377Salnsn /*  Mathching utilities                                                  */
232477d68377Salnsn /* --------------------------------------------------------------------- */
232577d68377Salnsn 
regex_begin_match(struct regex_machine * machine)232677d68377Salnsn struct regex_match* regex_begin_match(struct regex_machine *machine)
232777d68377Salnsn {
2328e5292e6bSalnsn 	sljit_sw *ptr1;
2329e5292e6bSalnsn 	sljit_sw *ptr2;
2330e5292e6bSalnsn 	sljit_sw *end;
2331e5292e6bSalnsn 	sljit_sw *entry_addrs;
233277d68377Salnsn 
233399e10043Salnsn 	struct regex_match *match = (struct regex_match*)SLJIT_MALLOC(sizeof(struct regex_match) + (machine->size * 2 - 1) * sizeof(sljit_sw), NULL);
233477d68377Salnsn 	if (!match)
233577d68377Salnsn 		return NULL;
233677d68377Salnsn 
233777d68377Salnsn 	ptr1 = match->states;
233877d68377Salnsn 	ptr2 = match->states + machine->size;
233977d68377Salnsn 	end = ptr2;
2340e5292e6bSalnsn 	entry_addrs = (sljit_sw*)machine->entry_addrs;
234177d68377Salnsn 
234277d68377Salnsn 	match->current = ptr1;
234377d68377Salnsn 	match->next = ptr2;
234477d68377Salnsn 	match->head = 0;
234577d68377Salnsn 	match->machine = machine;
234677d68377Salnsn 
234777d68377Salnsn 	/* Init machine states. */
234877d68377Salnsn 	switch (machine->no_states) {
234977d68377Salnsn 	case 2:
235077d68377Salnsn 		while (ptr1 < end) {
235177d68377Salnsn 			*ptr1++ = *entry_addrs;
235277d68377Salnsn 			*ptr2++ = *entry_addrs++;
235377d68377Salnsn 			*ptr1++ = -1;
235477d68377Salnsn 			*ptr2++ = -1;
235577d68377Salnsn 		}
235677d68377Salnsn 		break;
235777d68377Salnsn 
235877d68377Salnsn 	case 3:
235977d68377Salnsn 		while (ptr1 < end) {
236077d68377Salnsn 			*ptr1++ = *entry_addrs;
236177d68377Salnsn 			*ptr2++ = *entry_addrs++;
236277d68377Salnsn 			*ptr1++ = -1;
236377d68377Salnsn 			*ptr2++ = -1;
236477d68377Salnsn 			*ptr1++ = 0;
236577d68377Salnsn 			*ptr2++ = 0;
236677d68377Salnsn 		}
236777d68377Salnsn 		break;
236877d68377Salnsn 
236977d68377Salnsn 	case 4:
237077d68377Salnsn 		while (ptr1 < end) {
237177d68377Salnsn 			*ptr1++ = *entry_addrs;
237277d68377Salnsn 			*ptr2++ = *entry_addrs++;
237377d68377Salnsn 			*ptr1++ = -1;
237477d68377Salnsn 			*ptr2++ = -1;
237577d68377Salnsn 			*ptr1++ = 0;
237677d68377Salnsn 			*ptr2++ = 0;
237777d68377Salnsn 			*ptr1++ = 0;
237877d68377Salnsn 			*ptr2++ = 0;
237977d68377Salnsn 		}
238077d68377Salnsn 		break;
238177d68377Salnsn 
238277d68377Salnsn 	default:
2383*06eb4e7bSalnsn 		SLJIT_UNREACHABLE();
238477d68377Salnsn 		break;
238577d68377Salnsn 	}
238677d68377Salnsn 
238777d68377Salnsn 	SLJIT_ASSERT(ptr1 == end);
238877d68377Salnsn 
238977d68377Salnsn 	match->u.continue_match = machine->continue_match;
239077d68377Salnsn 
239177d68377Salnsn 	regex_reset_match(match);
239277d68377Salnsn 	return match;
239377d68377Salnsn }
239477d68377Salnsn 
regex_reset_match(struct regex_match * match)239577d68377Salnsn void regex_reset_match(struct regex_match *match)
239677d68377Salnsn {
239777d68377Salnsn 	struct regex_machine *machine = match->machine;
2398e5292e6bSalnsn 	sljit_sw current, ind;
2399e5292e6bSalnsn 	sljit_sw *current_ptr;
240077d68377Salnsn 
240177d68377Salnsn 	match->best_end = 0;
240277d68377Salnsn 	match->fast_quit = 0;
240377d68377Salnsn 	match->fast_forward = 0;
240477d68377Salnsn 
240577d68377Salnsn 	if (match->head != 0) {
240677d68377Salnsn 		/* Clear the current state. */
240777d68377Salnsn 		current = match->head;
240877d68377Salnsn 		current_ptr = match->current;
240977d68377Salnsn 		do {
2410e5292e6bSalnsn 			ind = (current / sizeof(sljit_sw)) + 1;
241177d68377Salnsn 			current = current_ptr[ind];
241277d68377Salnsn 			current_ptr[ind] = -1;
241377d68377Salnsn 		} while (current != 0);
241477d68377Salnsn 	}
241577d68377Salnsn 	match->head = machine->u.call_init(match->current, match);
241677d68377Salnsn }
241777d68377Salnsn 
regex_free_match(struct regex_match * match)241877d68377Salnsn void regex_free_match(struct regex_match *match)
241977d68377Salnsn {
242099e10043Salnsn 	SLJIT_FREE(match, NULL);
242177d68377Salnsn }
242277d68377Salnsn 
regex_continue_match(struct regex_match * match,const regex_char_t * input_string,int length)242377d68377Salnsn void regex_continue_match(struct regex_match *match, const regex_char_t *input_string, int length)
242477d68377Salnsn {
242577d68377Salnsn 	match->u.call_continue(match, input_string, length);
242677d68377Salnsn }
242777d68377Salnsn 
regex_get_result(struct regex_match * match,int * end,int * id)242877d68377Salnsn int regex_get_result(struct regex_match *match, int *end, int *id)
242977d68377Salnsn {
243077d68377Salnsn 	int flags = match->machine->flags;
2431e5292e6bSalnsn 	sljit_sw no_states;
243277d68377Salnsn 
243377d68377Salnsn 	*end = match->best_end;
243477d68377Salnsn 	*id = match->best_id;
243577d68377Salnsn 	if (!(flags & (REGEX_MATCH_END | REGEX_FAKE_MATCH_END)))
243677d68377Salnsn 		return match->best_begin;
243777d68377Salnsn 
243877d68377Salnsn 	if (flags & REGEX_FAKE_MATCH_END) {
243977d68377Salnsn 		SLJIT_ASSERT(!(flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END)));
244077d68377Salnsn 		if (match->best_begin != -1)
244177d68377Salnsn 			return match->best_begin;
244277d68377Salnsn 
244377d68377Salnsn 		no_states = match->machine->no_states;
244477d68377Salnsn 		if (match->current[no_states + 1] == -1)
244577d68377Salnsn 			return -1;
244677d68377Salnsn 		if (flags & REGEX_ID_CHECK)
244777d68377Salnsn 			*id = match->current[no_states + 3];
244877d68377Salnsn 		if (!(flags & REGEX_FAKE_MATCH_BEGIN))
244977d68377Salnsn 			*end = match->index - 1;
245077d68377Salnsn 		else
245177d68377Salnsn 			*end = match->index - 2;
245277d68377Salnsn 		return match->current[no_states + 2];
245377d68377Salnsn 	}
245477d68377Salnsn 	else {
245577d68377Salnsn 		/* Check the status of the last code. */
245677d68377Salnsn 		if (!(flags & REGEX_MATCH_BEGIN)) {
245777d68377Salnsn 			/* No shortcut in this case. */
245877d68377Salnsn 			if (!(flags & REGEX_ID_CHECK)) {
245977d68377Salnsn 				if (match->current[1] == -1)
246077d68377Salnsn 					return -1;
246177d68377Salnsn 				*end = match->index - 1;
246277d68377Salnsn 				return match->current[2];
246377d68377Salnsn 			}
246477d68377Salnsn 
246577d68377Salnsn 			if (match->current[1] == -1)
246677d68377Salnsn 				return -1;
246777d68377Salnsn 			*end = match->index - 1;
246877d68377Salnsn 			*id = match->current[3];
246977d68377Salnsn 			return match->current[2];
247077d68377Salnsn 		}
247177d68377Salnsn 
247277d68377Salnsn 		/* Shortcut is possible in this case. */
247377d68377Salnsn 		if (!(flags & REGEX_ID_CHECK)) {
247477d68377Salnsn 			if (match->current[1] == -1 || match->head == -1)
247577d68377Salnsn 				return -1;
247677d68377Salnsn 			*end = match->index - 1;
247777d68377Salnsn 			return 0;
247877d68377Salnsn 		}
247977d68377Salnsn 
248077d68377Salnsn 		if (match->current[1] == -1 || match->head == -1)
248177d68377Salnsn 			return -1;
248277d68377Salnsn 		*end = match->index - 1;
248377d68377Salnsn 		*id = match->current[2];
248477d68377Salnsn 		return 0;
248577d68377Salnsn 	}
248677d68377Salnsn }
248777d68377Salnsn 
regex_is_match_finished(struct regex_match * match)248877d68377Salnsn int regex_is_match_finished(struct regex_match *match)
248977d68377Salnsn {
249077d68377Salnsn 	return match->fast_quit;
249177d68377Salnsn }
249277d68377Salnsn 
249377d68377Salnsn #ifdef REGEX_MATCH_VERBOSE
regex_continue_match_debug(struct regex_match * match,const regex_char_t * input_string,int length)249477d68377Salnsn void regex_continue_match_debug(struct regex_match *match, const regex_char_t *input_string, int length)
249577d68377Salnsn {
2496e5292e6bSalnsn 	sljit_sw *ptr;
2497e5292e6bSalnsn 	sljit_sw *end;
2498e5292e6bSalnsn 	sljit_sw count;
249977d68377Salnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
2500e5292e6bSalnsn 	sljit_sw current;
250177d68377Salnsn #endif
2502e5292e6bSalnsn 	sljit_sw no_states = match->machine->no_states;
2503e5292e6bSalnsn 	sljit_sw len = match->machine->size;
250477d68377Salnsn 
250577d68377Salnsn 	while (length > 0) {
250677d68377Salnsn 		match->u.call_continue(match, input_string, 1);
250777d68377Salnsn 
250877d68377Salnsn 		if (match->fast_forward) {
250977d68377Salnsn 			if (match->machine->flags & REGEX_MATCH_VERBOSE)
251077d68377Salnsn 				printf("fast forward\n");
251177d68377Salnsn 		}
251277d68377Salnsn 
251377d68377Salnsn 		/* Verbose (first). */
251477d68377Salnsn 		if (match->machine->flags & REGEX_MATCH_VERBOSE) {
251577d68377Salnsn 			ptr = match->current;
251677d68377Salnsn 			end = ptr + len;
251777d68377Salnsn 			count = 0;
251877d68377Salnsn 			printf("'%c' (%3ld->%3ld [%3ld]) ", *input_string, (long)match->best_begin, (long)match->best_end, (long)match->best_id);
251977d68377Salnsn 			while (ptr < end) {
252077d68377Salnsn 				printf("[%3ld:", (long)count++);
252177d68377Salnsn 				switch (no_states) {
252277d68377Salnsn 				case 2:
252377d68377Salnsn 					if (ptr[1] != -1)
252477d68377Salnsn 						printf("+] ");
252577d68377Salnsn 					else
252677d68377Salnsn 						printf(" ] ");
252777d68377Salnsn 					break;
252877d68377Salnsn 
252977d68377Salnsn 				case 3:
253077d68377Salnsn 					if (ptr[1] != -1)
253177d68377Salnsn 						printf("+,%3ld] ", (long)ptr[2]);
253277d68377Salnsn 					else
253377d68377Salnsn 						printf(" ,XXX] ");
253477d68377Salnsn 					break;
253577d68377Salnsn 
253677d68377Salnsn 				case 4:
253777d68377Salnsn 					if (ptr[1] != -1)
253877d68377Salnsn 						printf("+,%3ld,%3ld] ", (long)ptr[2], (long)ptr[3]);
253977d68377Salnsn 					else
254077d68377Salnsn 						printf(" ,XXX,XXX] ");
254177d68377Salnsn 					break;
254277d68377Salnsn 				}
254377d68377Salnsn 				ptr += no_states;
254477d68377Salnsn 			}
254577d68377Salnsn 			printf("\n");
254677d68377Salnsn 		}
254777d68377Salnsn 
254877d68377Salnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
254977d68377Salnsn 		/* Sanity check (later). */
255077d68377Salnsn 		ptr = match->next;
255177d68377Salnsn 		end = ptr + len;
255277d68377Salnsn 		while (ptr < end) {
255377d68377Salnsn 			SLJIT_ASSERT(ptr[1] == -1);
255477d68377Salnsn 			ptr += no_states;
255577d68377Salnsn 		}
255677d68377Salnsn 
255777d68377Salnsn 		/* Check number of active elements. */
255877d68377Salnsn 		ptr = match->current + no_states;
255977d68377Salnsn 		end = ptr + len - no_states;
256077d68377Salnsn 		count = 0;
256177d68377Salnsn 		while (ptr < end) {
256277d68377Salnsn 			if (ptr[1] != -1)
256377d68377Salnsn 				count++;
256477d68377Salnsn 			ptr += no_states;
256577d68377Salnsn 		}
256677d68377Salnsn 
256777d68377Salnsn 		/* Check chain list. */
256877d68377Salnsn 		current = match->head;
256977d68377Salnsn 		ptr = match->current;
257077d68377Salnsn 		while (current != 0) {
2571e5292e6bSalnsn 			SLJIT_ASSERT(current >= 0 && current < len * sizeof(sljit_sw));
2572e5292e6bSalnsn 			SLJIT_ASSERT((current % (no_states * sizeof(sljit_sw))) == 0);
257377d68377Salnsn 			SLJIT_ASSERT(count > 0);
2574e5292e6bSalnsn 			current = ptr[(current / sizeof(sljit_sw)) + 1];
257577d68377Salnsn 			count--;
257677d68377Salnsn 		}
257777d68377Salnsn 		SLJIT_ASSERT(count == 0);
257877d68377Salnsn #endif
257977d68377Salnsn 
258077d68377Salnsn 		if (match->fast_quit) {
258177d68377Salnsn 			/* the machine has stopped working. */
258277d68377Salnsn 			if (match->machine->flags & REGEX_MATCH_VERBOSE)
258377d68377Salnsn 				printf("Best match has found\n");
258477d68377Salnsn 			break;
258577d68377Salnsn 		}
258677d68377Salnsn 
258777d68377Salnsn 		input_string++;
258877d68377Salnsn 		length--;
258977d68377Salnsn 	}
259077d68377Salnsn }
259177d68377Salnsn #endif
2592