10675068dSalnsn /*
20675068dSalnsn  *    Stack-less Just-In-Time compiler
30675068dSalnsn  *
4*e52d5ebbSalnsn  *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
50675068dSalnsn  *
60675068dSalnsn  * Redistribution and use in source and binary forms, with or without modification, are
70675068dSalnsn  * permitted provided that the following conditions are met:
80675068dSalnsn  *
90675068dSalnsn  *   1. Redistributions of source code must retain the above copyright notice, this list of
100675068dSalnsn  *      conditions and the following disclaimer.
110675068dSalnsn  *
120675068dSalnsn  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
130675068dSalnsn  *      of conditions and the following disclaimer in the documentation and/or other materials
140675068dSalnsn  *      provided with the distribution.
150675068dSalnsn  *
160675068dSalnsn  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
170675068dSalnsn  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
180675068dSalnsn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
190675068dSalnsn  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
200675068dSalnsn  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
210675068dSalnsn  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
220675068dSalnsn  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
230675068dSalnsn  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
240675068dSalnsn  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
250675068dSalnsn  */
260675068dSalnsn 
270675068dSalnsn #include "sljitLir.h"
280675068dSalnsn #include "regexJIT.h"
290675068dSalnsn 
30*e52d5ebbSalnsn #include <stdlib.h>
31*e52d5ebbSalnsn 
320675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
330675068dSalnsn #include <stdio.h>
340675068dSalnsn #endif
350675068dSalnsn 
360675068dSalnsn /* Extra, hidden flags:
370675068dSalnsn    {id!} where id > 0 found in the code. */
380675068dSalnsn #define REGEX_ID_CHECK		0x100
390675068dSalnsn /* When REGEX_NEWLINE && REGEX_MATCH_BEGIN defined, the pattern turn to a normal search,
400675068dSalnsn    which starts with [\r\n] character range. */
410675068dSalnsn #define REGEX_FAKE_MATCH_BEGIN	0x200
420675068dSalnsn /* When REGEX_NEWLINE && REGEX_MATCH_END defined, the pattern turn to a normal search,
430675068dSalnsn    which ends with [\r\n] character range. */
440675068dSalnsn #define REGEX_FAKE_MATCH_END	0x400
450675068dSalnsn 
460675068dSalnsn /* Check match completition after every (FINISH_TEST + 1) steps. */
470675068dSalnsn #define FINISH_TEST	0x7
480675068dSalnsn 
490675068dSalnsn /* --------------------------------------------------------------------- */
500675068dSalnsn /*  Structures for JIT-ed pattern matching                               */
510675068dSalnsn /* --------------------------------------------------------------------- */
520675068dSalnsn 
530675068dSalnsn struct regex_machine
540675068dSalnsn {
550675068dSalnsn 	/* flags. */
560675068dSalnsn 	int flags;
570675068dSalnsn 	/* Number of state descriptors for one term. */
5808987447Salnsn 	sljit_sw no_states;
590675068dSalnsn 	/* Total size. */
6008987447Salnsn 	sljit_sw size;
610675068dSalnsn 
620675068dSalnsn 	union {
630675068dSalnsn 		void *init_match;
6408987447Salnsn 		sljit_sw (SLJIT_CALL *call_init)(void *next, void* match);
650675068dSalnsn 	} u;
660675068dSalnsn #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
670675068dSalnsn 	struct sljit_function_context context;
680675068dSalnsn #endif
690675068dSalnsn 
700675068dSalnsn 	void *continue_match;
710675068dSalnsn 
720675068dSalnsn 	/* Variable sized array to contain the handler addresses. */
730675068dSalnsn 	sljit_uw entry_addrs[1];
740675068dSalnsn };
750675068dSalnsn 
760675068dSalnsn struct regex_match
770675068dSalnsn {
780675068dSalnsn 	/* Current and next state array. */
7908987447Salnsn 	sljit_sw *current;
8008987447Salnsn 	sljit_sw *next;
810675068dSalnsn 	/* Starting. */
8208987447Salnsn 	sljit_sw head;
830675068dSalnsn 	/* String character index (ever increasing). */
8408987447Salnsn 	sljit_sw index;
850675068dSalnsn 	/* Best match found so far (members in priority order). */
8608987447Salnsn 	sljit_sw best_begin;
8708987447Salnsn 	sljit_sw best_end;
8808987447Salnsn 	sljit_sw best_id;
890675068dSalnsn 	/* Bool flags (encoded as word). */
9008987447Salnsn 	sljit_sw fast_quit;
9108987447Salnsn 	sljit_sw fast_forward;
920675068dSalnsn 	/* Machine. */
930675068dSalnsn 	struct regex_machine *machine;
940675068dSalnsn 
950675068dSalnsn 	union {
960675068dSalnsn 		void *continue_match;
970675068dSalnsn 		void (SLJIT_CALL *call_continue)(struct regex_match *match, const regex_char_t *input_string, int length);
980675068dSalnsn 	} u;
990675068dSalnsn 
1000675068dSalnsn 	/* Variable sized array to contain the state arrays. */
10108987447Salnsn 	sljit_sw states[1];
1020675068dSalnsn };
1030675068dSalnsn 
1040675068dSalnsn /* State vector
1050675068dSalnsn     ITEM[0] - pointer to the address inside the machine code
1060675068dSalnsn     ITEM[1] - next pointer
1070675068dSalnsn     ITEM[2] - string started from (optional)
1080675068dSalnsn     ITEM[3] - max ID (optional) */
1090675068dSalnsn 
1100675068dSalnsn /* Register allocation. */
1110675068dSalnsn /* Current state array (loaded & stored: regex_match->current). */
11248dfc815Salnsn #define R_CURR_STATE	SLJIT_S0
1130675068dSalnsn /* Next state array (loaded & stored: regex_match->next). */
11448dfc815Salnsn #define R_NEXT_STATE	SLJIT_S1
1150675068dSalnsn /* Head (loaded & stored: regex_match->head). */
11648dfc815Salnsn #define R_NEXT_HEAD	SLJIT_S2
1170675068dSalnsn /* String fragment pointer. */
11848dfc815Salnsn #define R_STRING	SLJIT_S3
1190675068dSalnsn /* String fragment length. */
12048dfc815Salnsn #define R_LENGTH	SLJIT_S4
1210675068dSalnsn /* 'struct regex_match*' */
12248dfc815Salnsn #define R_REGEX_MATCH	SLJIT_R0
1230675068dSalnsn /* Current character. */
12448dfc815Salnsn #define R_CURR_CHAR	SLJIT_R1
1250675068dSalnsn /* Temporary register. */
12648dfc815Salnsn #define R_TEMP		SLJIT_R2
1270675068dSalnsn /* Caches the regex_match->best_begin. */
12848dfc815Salnsn #define R_BEST_BEGIN	SLJIT_R3
1290675068dSalnsn /* Current character index. */
13048dfc815Salnsn #define R_CURR_INDEX	SLJIT_R4
1310675068dSalnsn 
1320675068dSalnsn /* --------------------------------------------------------------------- */
1330675068dSalnsn /*  Stack management                                                     */
1340675068dSalnsn /* --------------------------------------------------------------------- */
1350675068dSalnsn 
1360675068dSalnsn /* Try to allocate 2^n blocks. */
1370675068dSalnsn #define STACK_FRAGMENT_SIZE (((64 * sizeof(struct stack_item)) - (sizeof(struct stack_fragment_data))) / (sizeof(struct stack_item)))
1380675068dSalnsn 
1390675068dSalnsn struct stack_item {
1400675068dSalnsn 	int type;
1410675068dSalnsn 	int value;
1420675068dSalnsn };
1430675068dSalnsn 
1440675068dSalnsn struct stack_fragment_data {
1450675068dSalnsn 	struct stack_fragment *next;
1460675068dSalnsn 	struct stack_fragment *prev;
1470675068dSalnsn };
1480675068dSalnsn 
1490675068dSalnsn struct stack_fragment {
1500675068dSalnsn 	struct stack_fragment_data data;
1510675068dSalnsn 	struct stack_item items[STACK_FRAGMENT_SIZE];
1520675068dSalnsn };
1530675068dSalnsn 
1540675068dSalnsn struct stack {
1550675068dSalnsn 	struct stack_fragment *first;
1560675068dSalnsn 	struct stack_fragment *last;
1570675068dSalnsn 	int index;
1580675068dSalnsn 	int count;
1590675068dSalnsn };
1600675068dSalnsn 
1610675068dSalnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
1620675068dSalnsn 
stack_check(struct stack * stack)1630675068dSalnsn static void stack_check(struct stack *stack)
1640675068dSalnsn {
1650675068dSalnsn 	struct stack_fragment *curr;
1660675068dSalnsn 	int found;
1670675068dSalnsn 
1680675068dSalnsn 	if (!stack)
1690675068dSalnsn 		return;
1700675068dSalnsn 
1710675068dSalnsn 	SLJIT_ASSERT(stack->index >= 0 && stack->index < STACK_FRAGMENT_SIZE);
1720675068dSalnsn 
1730675068dSalnsn 	if (stack->first == NULL) {
1740675068dSalnsn 		SLJIT_ASSERT(stack->first == NULL && stack->last == NULL);
1750675068dSalnsn 		SLJIT_ASSERT(stack->index == STACK_FRAGMENT_SIZE - 1 && stack->count == 0);
1760675068dSalnsn 		return;
1770675068dSalnsn 	}
1780675068dSalnsn 
1790675068dSalnsn 	found = 0;
1800675068dSalnsn 	if (stack->last == NULL) {
1810675068dSalnsn 		SLJIT_ASSERT(stack->index == STACK_FRAGMENT_SIZE - 1 && stack->count == 0);
1820675068dSalnsn 		found = 1;
1830675068dSalnsn 	}
1840675068dSalnsn 	else
1850675068dSalnsn 		SLJIT_ASSERT(stack->index >= 0 && stack->count >= 0);
1860675068dSalnsn 
1870675068dSalnsn 	SLJIT_ASSERT(stack->first->data.prev == NULL);
1880675068dSalnsn 	curr = stack->first;
1890675068dSalnsn 	while (curr) {
1900675068dSalnsn 		if (curr == stack->last)
1910675068dSalnsn 			found = 1;
1920675068dSalnsn 		if (curr->data.next)
1930675068dSalnsn 			SLJIT_ASSERT(curr->data.next->data.prev == curr);
1940675068dSalnsn 		curr = curr->data.next;
1950675068dSalnsn 	}
1960675068dSalnsn 	SLJIT_ASSERT(found);
1970675068dSalnsn }
1980675068dSalnsn 
1990675068dSalnsn #endif
2000675068dSalnsn 
stack_init(struct stack * stack)2010675068dSalnsn static void stack_init(struct stack *stack)
2020675068dSalnsn {
2030675068dSalnsn 	stack->first = NULL;
2040675068dSalnsn 	stack->last = NULL;
2050675068dSalnsn 	stack->index = STACK_FRAGMENT_SIZE - 1;
2060675068dSalnsn 	stack->count = 0;
2070675068dSalnsn }
2080675068dSalnsn 
stack_destroy(struct stack * stack)2090675068dSalnsn static void stack_destroy(struct stack *stack)
2100675068dSalnsn {
2110675068dSalnsn 	struct stack_fragment *curr = stack->first;
2120675068dSalnsn 	struct stack_fragment *prev;
2130675068dSalnsn 
2140675068dSalnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
2150675068dSalnsn 	stack_check(stack);
2160675068dSalnsn #endif
2170675068dSalnsn 
2180675068dSalnsn 	while (curr) {
2190675068dSalnsn 		prev = curr;
2200675068dSalnsn 		curr = curr->data.next;
22148dfc815Salnsn 		SLJIT_FREE(prev, NULL);
2220675068dSalnsn 	}
2230675068dSalnsn }
2240675068dSalnsn 
stack_top(struct stack * stack)2250675068dSalnsn static SLJIT_INLINE struct stack_item* stack_top(struct stack *stack)
2260675068dSalnsn {
2270675068dSalnsn 	SLJIT_ASSERT(stack->last);
2280675068dSalnsn 	return stack->last->items + stack->index;
2290675068dSalnsn }
2300675068dSalnsn 
stack_push(struct stack * stack,int type,int value)2310675068dSalnsn static int stack_push(struct stack *stack, int type, int value)
2320675068dSalnsn {
2330675068dSalnsn 	if (stack->last) {
2340675068dSalnsn 		stack->index++;
2350675068dSalnsn 		if (stack->index >= STACK_FRAGMENT_SIZE) {
2360675068dSalnsn 			stack->index = 0;
2370675068dSalnsn 			if (!stack->last->data.next) {
23848dfc815Salnsn 				stack->last->data.next = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);
2390675068dSalnsn 				if (!stack->last->data.next)
2400675068dSalnsn 					return 1;
2410675068dSalnsn 				stack->last->data.next->data.next = NULL;
2420675068dSalnsn 				stack->last->data.next->data.prev = stack->last;
2430675068dSalnsn 			}
2440675068dSalnsn 			stack->last = stack->last->data.next;
2450675068dSalnsn 		}
2460675068dSalnsn 	}
2470675068dSalnsn 	else if (!stack->first) {
24848dfc815Salnsn 		stack->last = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);
2490675068dSalnsn 		if (!stack->last)
2500675068dSalnsn 			return 1;
2510675068dSalnsn 		stack->last->data.prev = NULL;
2520675068dSalnsn 		stack->last->data.next = NULL;
2530675068dSalnsn 		stack->first = stack->last;
2540675068dSalnsn 		stack->index = 0;
2550675068dSalnsn 	}
2560675068dSalnsn 	else {
2570675068dSalnsn 		stack->last = stack->first;
2580675068dSalnsn 		stack->index = 0;
2590675068dSalnsn 	}
2600675068dSalnsn 	stack->last->items[stack->index].type = type;
2610675068dSalnsn 	stack->last->items[stack->index].value = value;
2620675068dSalnsn 	stack->count++;
2630675068dSalnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
2640675068dSalnsn 	stack_check(stack);
2650675068dSalnsn #endif
2660675068dSalnsn 	return 0;
2670675068dSalnsn }
2680675068dSalnsn 
stack_pop(struct stack * stack)2690675068dSalnsn static struct stack_item* stack_pop(struct stack *stack)
2700675068dSalnsn {
2710675068dSalnsn 	struct stack_item *ret = stack_top(stack);
2720675068dSalnsn 
2730675068dSalnsn 	if (stack->index > 0)
2740675068dSalnsn 		stack->index--;
2750675068dSalnsn 	else {
2760675068dSalnsn 		stack->last = stack->last->data.prev;
2770675068dSalnsn 		stack->index = STACK_FRAGMENT_SIZE - 1;
2780675068dSalnsn 	}
2790675068dSalnsn 
2800675068dSalnsn 	stack->count--;
2810675068dSalnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
2820675068dSalnsn 	stack_check(stack);
2830675068dSalnsn #endif
2840675068dSalnsn 	return ret;
2850675068dSalnsn }
2860675068dSalnsn 
stack_clone(struct stack * src,struct stack * dst)2870675068dSalnsn static SLJIT_INLINE void stack_clone(struct stack *src, struct stack *dst)
2880675068dSalnsn {
2890675068dSalnsn 	*dst = *src;
2900675068dSalnsn }
2910675068dSalnsn 
stack_push_copy(struct stack * stack,int items,int length)2920675068dSalnsn static int stack_push_copy(struct stack *stack, int items, int length)
2930675068dSalnsn {
2940675068dSalnsn 	struct stack_fragment *frag1;
2950675068dSalnsn 	int ind1;
2960675068dSalnsn 	struct stack_fragment *frag2;
2970675068dSalnsn 	int ind2;
2980675068dSalnsn 	int counter;
2990675068dSalnsn 
3000675068dSalnsn 	SLJIT_ASSERT(stack->count >= length && items <= length && items > 0);
3010675068dSalnsn 
3020675068dSalnsn 	/* Allocate the necessary elements. */
3030675068dSalnsn 	counter = items;
3040675068dSalnsn 	frag1 = stack->last;
3050675068dSalnsn 	ind1 = stack->index;
3060675068dSalnsn 	while (counter > 0) {
3070675068dSalnsn 		if (stack->index + counter >= STACK_FRAGMENT_SIZE) {
3080675068dSalnsn 			counter -= STACK_FRAGMENT_SIZE - stack->index - 1 + 1;
3090675068dSalnsn 			stack->index = 0;
3100675068dSalnsn 			if (!stack->last->data.next) {
31148dfc815Salnsn 				stack->last->data.next = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);
3120675068dSalnsn 				if (!stack->last->data.next)
3130675068dSalnsn 					return 1;
3140675068dSalnsn 				stack->last->data.next->data.next = NULL;
3150675068dSalnsn 				stack->last->data.next->data.prev = stack->last;
3160675068dSalnsn 			}
3170675068dSalnsn 			stack->last = stack->last->data.next;
3180675068dSalnsn 		}
3190675068dSalnsn 		else {
3200675068dSalnsn 			stack->index += counter;
3210675068dSalnsn 			counter = 0;
3220675068dSalnsn 		}
3230675068dSalnsn 	}
3240675068dSalnsn 
3250675068dSalnsn 	frag2 = stack->last;
3260675068dSalnsn 	ind2 = stack->index;
3270675068dSalnsn 	while (length > 0) {
3280675068dSalnsn 		frag2->items[ind2--] = frag1->items[ind1--];
3290675068dSalnsn 		if (ind1 < 0) {
3300675068dSalnsn 			ind1 = STACK_FRAGMENT_SIZE - 1;
3310675068dSalnsn 			frag1 = frag1->data.prev;
3320675068dSalnsn 		}
3330675068dSalnsn 		if (ind2 < 0) {
3340675068dSalnsn 			ind2 = STACK_FRAGMENT_SIZE - 1;
3350675068dSalnsn 			frag2 = frag2->data.prev;
3360675068dSalnsn 		}
3370675068dSalnsn 		length--;
3380675068dSalnsn 	}
3390675068dSalnsn 
3400675068dSalnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
3410675068dSalnsn 	stack_check(stack);
3420675068dSalnsn #endif
3430675068dSalnsn 	stack->count += items;
3440675068dSalnsn 	return 0;
3450675068dSalnsn }
3460675068dSalnsn 
3470675068dSalnsn /* --------------------------------------------------------------------- */
3480675068dSalnsn /*  Parser                                                               */
3490675068dSalnsn /* --------------------------------------------------------------------- */
3500675068dSalnsn 
3510675068dSalnsn enum {
3520675068dSalnsn 	/* Common. */
3530675068dSalnsn 	type_begin,
3540675068dSalnsn 	type_end,
3550675068dSalnsn 	type_char,
3560675068dSalnsn 	type_newline,
3570675068dSalnsn 	type_id,
3580675068dSalnsn 	type_rng_start,
3590675068dSalnsn 	type_rng_end,
3600675068dSalnsn 	type_rng_char,
3610675068dSalnsn 	type_rng_left,
3620675068dSalnsn 	type_rng_right,
3630675068dSalnsn 
3640675068dSalnsn 	/* generator only. */
3650675068dSalnsn 	type_branch,
3660675068dSalnsn 	type_jump,
3670675068dSalnsn 
3680675068dSalnsn 	/* Parser only. */
3690675068dSalnsn 	type_open_br,
3700675068dSalnsn 	type_close_br,
3710675068dSalnsn 	type_select,
3720675068dSalnsn 	type_asterisk,
3730675068dSalnsn 	type_plus_sign,
3740675068dSalnsn 	type_qestion_mark
3750675068dSalnsn };
3760675068dSalnsn 
3770675068dSalnsn struct compiler_common {
3780675068dSalnsn 	/* Temporary stacks. */
3790675068dSalnsn 	struct stack stack;
3800675068dSalnsn 	struct stack depth;
3810675068dSalnsn 	/* REGEX_ flags. */
3820675068dSalnsn 	int flags;
3830675068dSalnsn 	/* Encoded size of the dfa representation. */
38408987447Salnsn 	sljit_sw dfa_size;
3850675068dSalnsn 	/* Number of terms. */
38608987447Salnsn 	sljit_sw terms_size;
3870675068dSalnsn 	/* Number of state descriptors for one term (same as machine->no_states). */
38808987447Salnsn 	sljit_sw no_states;
3890675068dSalnsn 	/* Number of type_rng_(char|left)-s in the longest character range. */
39008987447Salnsn 	sljit_sw longest_range_size;
3910675068dSalnsn 
3920675068dSalnsn 	/* DFA linear representation (size: dfa_size). */
3930675068dSalnsn 	struct stack_item *dfa_transitions;
3940675068dSalnsn 	/* Term id and search state pairs (size: dfa_size). */
3950675068dSalnsn 	struct stack_item *search_states;
3960675068dSalnsn 
3970675068dSalnsn 	/* sljit compiler */
3980675068dSalnsn 	struct sljit_compiler *compiler;
3990675068dSalnsn 	/* Machine data, which must be kept for later use. */
4000675068dSalnsn 	struct regex_machine *machine;
4010675068dSalnsn 	/* Temporary space for jumps (size: longest_range_size). */
4020675068dSalnsn 	struct sljit_jump **range_jump_list;
4030675068dSalnsn };
4040675068dSalnsn 
decode_number(const regex_char_t * regex_string,int length,int * result)4050675068dSalnsn static const regex_char_t* decode_number(const regex_char_t *regex_string, int length, int *result)
4060675068dSalnsn {
4070675068dSalnsn 	int value = 0;
4080675068dSalnsn 
4090675068dSalnsn 	SLJIT_ASSERT(length > 0);
4100675068dSalnsn 	if (*regex_string < '0' || *regex_string > '9') {
4110675068dSalnsn 		*result = -1;
4120675068dSalnsn 		return regex_string;
4130675068dSalnsn 	}
4140675068dSalnsn 
4150675068dSalnsn 	while (length > 0 && *regex_string >= '0' && *regex_string <= '9') {
4160675068dSalnsn 		value = value * 10 + (*regex_string - '0');
4170675068dSalnsn 		length--;
4180675068dSalnsn 		regex_string++;
4190675068dSalnsn 	}
4200675068dSalnsn 
4210675068dSalnsn 	*result = value;
4220675068dSalnsn 	return regex_string;
4230675068dSalnsn }
4240675068dSalnsn 
iterate(struct stack * stack,int min,int max)4250675068dSalnsn static int iterate(struct stack *stack, int min, int max)
4260675068dSalnsn {
4270675068dSalnsn 	struct stack it;
4280675068dSalnsn 	struct stack_item *item;
4290675068dSalnsn 	int count = -1;
4300675068dSalnsn 	int len = 0;
4310675068dSalnsn 	int depth = 0;
4320675068dSalnsn 
4330675068dSalnsn 	stack_clone(stack, &it);
4340675068dSalnsn 
4350675068dSalnsn 	/* Calculate size. */
4360675068dSalnsn 	while (count < 0) {
4370675068dSalnsn 		item = stack_pop(&it);
4380675068dSalnsn 		switch (item->type) {
4390675068dSalnsn 		case type_id:
4400675068dSalnsn 		case type_rng_end:
4410675068dSalnsn 		case type_rng_char:
4420675068dSalnsn 		case type_rng_left:
4430675068dSalnsn 		case type_rng_right:
4440675068dSalnsn 		case type_plus_sign:
4450675068dSalnsn 		case type_qestion_mark:
4460675068dSalnsn 			len++;
4470675068dSalnsn 			break;
4480675068dSalnsn 
4490675068dSalnsn 		case type_asterisk:
4500675068dSalnsn 			len += 2;
4510675068dSalnsn 			break;
4520675068dSalnsn 
4530675068dSalnsn 		case type_close_br:
4540675068dSalnsn 			depth++;
4550675068dSalnsn 			break;
4560675068dSalnsn 
4570675068dSalnsn 		case type_open_br:
4580675068dSalnsn 			SLJIT_ASSERT(depth > 0);
4590675068dSalnsn 			depth--;
4600675068dSalnsn 			if (depth == 0)
4610675068dSalnsn 				count = it.count;
4620675068dSalnsn 			break;
4630675068dSalnsn 
4640675068dSalnsn 		case type_select:
4650675068dSalnsn 			SLJIT_ASSERT(depth > 0);
4660675068dSalnsn 			len += 2;
4670675068dSalnsn 			break;
4680675068dSalnsn 
4690675068dSalnsn 		default:
4700675068dSalnsn 			SLJIT_ASSERT(item->type != type_begin && item->type != type_end);
4710675068dSalnsn 			if (depth == 0)
4720675068dSalnsn 				count = it.count;
4730675068dSalnsn 			len++;
4740675068dSalnsn 			break;
4750675068dSalnsn 		}
4760675068dSalnsn 	}
4770675068dSalnsn 
4780675068dSalnsn 	if (min == 0 && max == 0) {
4790675068dSalnsn 		/* {0,0} case, not {0,} case: delete subtree. */
4800675068dSalnsn 		stack_clone(&it, stack);
4810675068dSalnsn 		/* and put an empty bracket expression instead of it. */
4820675068dSalnsn 		if (stack_push(stack, type_open_br, 0))
4830675068dSalnsn 			return REGEX_MEMORY_ERROR;
4840675068dSalnsn 		if (stack_push(stack, type_close_br, 0))
4850675068dSalnsn 			return REGEX_MEMORY_ERROR;
4860675068dSalnsn 		return len;
4870675068dSalnsn 	}
4880675068dSalnsn 
4890675068dSalnsn 	count = stack->count - count;
4900675068dSalnsn 
4910675068dSalnsn 	/* Put an open bracket before the sequence. */
4920675068dSalnsn 	if (stack_push_copy(stack, 1, count))
4930675068dSalnsn 		return -1;
4940675068dSalnsn 
4950675068dSalnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
4960675068dSalnsn 	SLJIT_ASSERT(stack_push(&it, type_open_br, 0) == 0);
4970675068dSalnsn #else
4980675068dSalnsn 	stack_push(&it, type_open_br, 0);
4990675068dSalnsn #endif
5000675068dSalnsn 
5010675068dSalnsn 	/* Copy the data. */
5020675068dSalnsn 	if (max > 0) {
5030675068dSalnsn 		len = len * (max - 1);
5040675068dSalnsn 		max -= min;
5050675068dSalnsn 		/* Insert ? operators. */
5060675068dSalnsn 		len += max;
5070675068dSalnsn 
5080675068dSalnsn 		if (min > 0) {
5090675068dSalnsn 			min--;
5100675068dSalnsn 			while (min > 0) {
5110675068dSalnsn 				if (stack_push_copy(stack, count, count))
5120675068dSalnsn 					return -1;
5130675068dSalnsn 				min--;
5140675068dSalnsn 			}
5150675068dSalnsn 			if (max > 0) {
5160675068dSalnsn 				if (stack_push_copy(stack, count, count))
5170675068dSalnsn 					return -1;
5180675068dSalnsn 				if (stack_push(stack, type_qestion_mark, 0))
5190675068dSalnsn 					return REGEX_MEMORY_ERROR;
5200675068dSalnsn 				count++;
5210675068dSalnsn 				max--;
5220675068dSalnsn 			}
5230675068dSalnsn 		}
5240675068dSalnsn 		else {
5250675068dSalnsn 			SLJIT_ASSERT(max > 0);
5260675068dSalnsn 			max--;
5270675068dSalnsn 			count++;
5280675068dSalnsn 			if (stack_push(stack, type_qestion_mark, 0))
5290675068dSalnsn 				return REGEX_MEMORY_ERROR;
5300675068dSalnsn 		}
5310675068dSalnsn 
5320675068dSalnsn 		while (max > 0) {
5330675068dSalnsn 			if (stack_push_copy(stack, count, count))
5340675068dSalnsn 				return -1;
5350675068dSalnsn 			max--;
5360675068dSalnsn 		}
5370675068dSalnsn 	}
5380675068dSalnsn 	else {
5390675068dSalnsn 		SLJIT_ASSERT(min > 0);
5400675068dSalnsn 		min--;
5410675068dSalnsn 		/* Insert + operator. */
5420675068dSalnsn 		len = len * min + 1;
5430675068dSalnsn 		while (min > 0) {
5440675068dSalnsn 			if (stack_push_copy(stack, count, count))
5450675068dSalnsn 				return -1;
5460675068dSalnsn 			min--;
5470675068dSalnsn 		}
5480675068dSalnsn 
5490675068dSalnsn 		if (stack_push(stack, type_plus_sign, 0))
5500675068dSalnsn 			return REGEX_MEMORY_ERROR;
5510675068dSalnsn 	}
5520675068dSalnsn 
5530675068dSalnsn 	/* Close the opened bracket. */
5540675068dSalnsn 	if (stack_push(stack, type_close_br, 0))
5550675068dSalnsn 		return REGEX_MEMORY_ERROR;
5560675068dSalnsn 
5570675068dSalnsn 	return len;
5580675068dSalnsn }
5590675068dSalnsn 
parse_iterator(const regex_char_t * regex_string,int length,struct stack * stack,sljit_sw * dfa_size,int begin)56008987447Salnsn static int parse_iterator(const regex_char_t *regex_string, int length, struct stack *stack, sljit_sw *dfa_size, int begin)
5610675068dSalnsn {
5620675068dSalnsn 	/* We only know that *regex_string == { . */
5630675068dSalnsn 	int val1, val2;
5640675068dSalnsn 	const regex_char_t *base_from = regex_string;
5650675068dSalnsn 	const regex_char_t *from;
5660675068dSalnsn 
5670675068dSalnsn 	length--;
5680675068dSalnsn 	regex_string++;
5690675068dSalnsn 
5700675068dSalnsn 	/* Decode left value. */
5710675068dSalnsn 	val2 = -1;
5720675068dSalnsn 	if (length == 0)
5730675068dSalnsn 		return -2;
5740675068dSalnsn 	if (*regex_string == ',') {
5750675068dSalnsn 		val1 = 0;
5760675068dSalnsn 		length--;
5770675068dSalnsn 		regex_string++;
5780675068dSalnsn 	}
5790675068dSalnsn 	else {
5800675068dSalnsn 		from = regex_string;
5810675068dSalnsn 		regex_string = decode_number(regex_string, length, &val1);
5820675068dSalnsn 		if (val1 < 0)
5830675068dSalnsn 			return -2;
5840675068dSalnsn 		length -= regex_string - from;
5850675068dSalnsn 
5860675068dSalnsn 		if (length == 0)
5870675068dSalnsn 			return -2;
5880675068dSalnsn 		if (*regex_string == '}') {
5890675068dSalnsn 			val2 = val1;
5900675068dSalnsn 			if (val1 == 0)
5910675068dSalnsn 				val1 = -1;
5920675068dSalnsn 		}
5930675068dSalnsn 		else if (length >= 2 && *regex_string == '!' && regex_string[1] == '}') {
5940675068dSalnsn 			/* Non posix extension. */
5950675068dSalnsn 			if (stack_push(stack, type_id, val1))
5960675068dSalnsn 				return -1;
5970675068dSalnsn 			(*dfa_size)++;
5980675068dSalnsn 			return (regex_string - base_from) + 1;
5990675068dSalnsn 		}
6000675068dSalnsn 		else {
6010675068dSalnsn 			if (*regex_string != ',')
6020675068dSalnsn 				return -2;
6030675068dSalnsn 			length--;
6040675068dSalnsn 			regex_string++;
6050675068dSalnsn 		}
6060675068dSalnsn 	}
6070675068dSalnsn 
6080675068dSalnsn 	if (begin)
6090675068dSalnsn 		return -2;
6100675068dSalnsn 
6110675068dSalnsn 	/* Decode right value. */
6120675068dSalnsn 	if (val2 == -1) {
6130675068dSalnsn 		if (length == 0)
6140675068dSalnsn 			return -2;
6150675068dSalnsn 		if (*regex_string == '}')
6160675068dSalnsn 			val2 = 0;
6170675068dSalnsn 		else {
6180675068dSalnsn 			from = regex_string;
6190675068dSalnsn 			regex_string = decode_number(regex_string, length, &val2);
6200675068dSalnsn 			length -= regex_string - from;
6210675068dSalnsn 			if (val2 < 0 || length == 0 || *regex_string != '}' || val2 < val1)
6220675068dSalnsn 				return -2;
6230675068dSalnsn 			if (val2 == 0) {
6240675068dSalnsn 				SLJIT_ASSERT(val1 == 0);
6250675068dSalnsn 				val1 = -1;
6260675068dSalnsn 			}
6270675068dSalnsn 		}
6280675068dSalnsn 	}
6290675068dSalnsn 
6300675068dSalnsn 	/* Fast cases. */
6310675068dSalnsn 	if (val1 > 1 || val2 > 1) {
6320675068dSalnsn 		val1 = iterate(stack, val1, val2);
6330675068dSalnsn 		if (val1 < 0)
6340675068dSalnsn 			return -1;
6350675068dSalnsn 		*dfa_size += val1;
6360675068dSalnsn 	}
6370675068dSalnsn 	else if (val1 == 0 && val2 == 0) {
6380675068dSalnsn 		if (stack_push(stack, type_asterisk, 0))
6390675068dSalnsn 			return -1;
6400675068dSalnsn 		*dfa_size += 2;
6410675068dSalnsn 	}
6420675068dSalnsn 	else if (val1 == 1 && val2 == 0) {
6430675068dSalnsn 		if (stack_push(stack, type_plus_sign, 0))
6440675068dSalnsn 			return -1;
6450675068dSalnsn 		(*dfa_size)++;
6460675068dSalnsn 	}
6470675068dSalnsn 	else if (val1 == 0 && val2 == 1) {
6480675068dSalnsn 		if (stack_push(stack, type_qestion_mark, 0))
6490675068dSalnsn 			return -1;
6500675068dSalnsn 		(*dfa_size)++;
6510675068dSalnsn 	}
6520675068dSalnsn 	else if (val1 == -1) {
6530675068dSalnsn 		val1 = iterate(stack, 0, 0);
6540675068dSalnsn 		if (val1 < 0)
6550675068dSalnsn 			return -1;
6560675068dSalnsn 		*dfa_size -= val1;
6570675068dSalnsn 		SLJIT_ASSERT(*dfa_size >= 2);
6580675068dSalnsn 	}
6590675068dSalnsn 	else {
6600675068dSalnsn 		/* Ignore. */
6610675068dSalnsn 		SLJIT_ASSERT(val1 == 1 && val2 == 1);
6620675068dSalnsn 	}
6630675068dSalnsn 	return regex_string - base_from;
6640675068dSalnsn }
6650675068dSalnsn 
parse_char_range(const regex_char_t * regex_string,int length,struct compiler_common * compiler_common)6660675068dSalnsn static int parse_char_range(const regex_char_t *regex_string, int length, struct compiler_common *compiler_common)
6670675068dSalnsn {
6680675068dSalnsn 	struct stack* stack = &compiler_common->stack;
6690675068dSalnsn 	const regex_char_t *base_from = regex_string;
6700675068dSalnsn 	regex_char_t left_char, right_char, tmp_char;
6710675068dSalnsn 
6720675068dSalnsn 	length--;
6730675068dSalnsn 	regex_string++;
6740675068dSalnsn 
6750675068dSalnsn 	if (length == 0)
6760675068dSalnsn 		return -2;
6770675068dSalnsn 
6780675068dSalnsn 	if (*regex_string != '^') {
6790675068dSalnsn 		if (stack_push(stack, type_rng_start, 0))
6800675068dSalnsn 			return -1;
6810675068dSalnsn 	}
6820675068dSalnsn 	else {
6830675068dSalnsn 		length--;
6840675068dSalnsn 		regex_string++;
6850675068dSalnsn 
6860675068dSalnsn 		if (length == 0)
6870675068dSalnsn 			return -2;
6880675068dSalnsn 
6890675068dSalnsn 		if (stack_push(stack, type_rng_start, 1))
6900675068dSalnsn 			return -1;
6910675068dSalnsn 	}
6920675068dSalnsn 	/* For both the type_rng_start & type_rng_end. */
6930675068dSalnsn 	compiler_common->dfa_size += 2;
6940675068dSalnsn 
6950675068dSalnsn 	/* Range must be at least 1 character. */
6960675068dSalnsn 	if (*regex_string == ']') {
6970675068dSalnsn 		length--;
6980675068dSalnsn 		regex_string++;
6990675068dSalnsn 		if (stack_push(stack, type_rng_char, ']'))
7000675068dSalnsn 			return -1;
7010675068dSalnsn 		compiler_common->dfa_size++;
7020675068dSalnsn 	}
7030675068dSalnsn 
7040675068dSalnsn 	while (1) {
7050675068dSalnsn 		if (length == 0)
7060675068dSalnsn 			return -2;
7070675068dSalnsn 
7080675068dSalnsn 		if (*regex_string == ']')
7090675068dSalnsn 			break;
7100675068dSalnsn 
7110675068dSalnsn 		if (*regex_string != '\\')
7120675068dSalnsn 			left_char = *regex_string;
7130675068dSalnsn 		else {
7140675068dSalnsn 			regex_string++;
7150675068dSalnsn 			length--;
7160675068dSalnsn 			if (length == 0)
7170675068dSalnsn 				return -2;
7180675068dSalnsn 			left_char = *regex_string;
7190675068dSalnsn 		}
7200675068dSalnsn 		regex_string++;
7210675068dSalnsn 		length--;
7220675068dSalnsn 
7230675068dSalnsn 		/* Is a range here? */
7240675068dSalnsn 		if (length >= 3 && *regex_string == '-' && *(regex_string + 1) != ']') {
7250675068dSalnsn 			regex_string++;
7260675068dSalnsn 			length--;
7270675068dSalnsn 
7280675068dSalnsn 			if (*regex_string != '\\')
7290675068dSalnsn 				right_char = *regex_string;
7300675068dSalnsn 			else {
7310675068dSalnsn 				regex_string++;
7320675068dSalnsn 				length--;
7330675068dSalnsn 				if (length == 0)
7340675068dSalnsn 					return -2;
7350675068dSalnsn 				right_char = *regex_string;
7360675068dSalnsn 			}
7370675068dSalnsn 			regex_string++;
7380675068dSalnsn 			length--;
7390675068dSalnsn 
7400675068dSalnsn 			if (left_char > right_char) {
7410675068dSalnsn 				/* Swap if necessary. */
7420675068dSalnsn 				tmp_char = left_char;
7430675068dSalnsn 				left_char = right_char;
7440675068dSalnsn 				right_char = tmp_char;
7450675068dSalnsn 			}
7460675068dSalnsn 
7470675068dSalnsn 			if (stack_push(stack, type_rng_left, left_char))
7480675068dSalnsn 				return -1;
7490675068dSalnsn 			if (stack_push(stack, type_rng_right, right_char))
7500675068dSalnsn 				return -1;
7510675068dSalnsn 			compiler_common->dfa_size += 2;
7520675068dSalnsn 		}
7530675068dSalnsn 		else {
7540675068dSalnsn 			if (stack_push(stack, type_rng_char, left_char))
7550675068dSalnsn 				return -1;
7560675068dSalnsn 			compiler_common->dfa_size++;
7570675068dSalnsn 		}
7580675068dSalnsn 	}
7590675068dSalnsn 
7600675068dSalnsn 	if (stack_push(stack, type_rng_end, 0))
7610675068dSalnsn 		return -1;
7620675068dSalnsn 	return regex_string - base_from;
7630675068dSalnsn }
7640675068dSalnsn 
parse(const regex_char_t * regex_string,int length,struct compiler_common * compiler_common)7650675068dSalnsn static int parse(const regex_char_t *regex_string, int length, struct compiler_common *compiler_common)
7660675068dSalnsn {
7670675068dSalnsn 	/* Depth of bracketed expressions. */
7680675068dSalnsn 	int depth = 0;
7690675068dSalnsn 	/* Have we already found a term? '1' if not yet. */
7700675068dSalnsn 	int begin = 1;
7710675068dSalnsn 	/* Cache stack pointer. */
7720675068dSalnsn 	struct stack* stack = &compiler_common->stack;
7730675068dSalnsn 	int tmp;
7740675068dSalnsn 
7750675068dSalnsn 	/* Type_begin and type_end. */
7760675068dSalnsn 	compiler_common->dfa_size = 2;
7770675068dSalnsn 	stack_init(stack);
7780675068dSalnsn 	if (stack_push(stack, type_begin, 0))
7790675068dSalnsn 		return REGEX_MEMORY_ERROR;
7800675068dSalnsn 
7810675068dSalnsn 	if (length > 0 && *regex_string == '^') {
7820675068dSalnsn 		compiler_common->flags |= REGEX_MATCH_BEGIN;
7830675068dSalnsn 		length--;
7840675068dSalnsn 		regex_string++;
7850675068dSalnsn 	}
7860675068dSalnsn 
7870675068dSalnsn 	if ((compiler_common->flags & (REGEX_MATCH_BEGIN | REGEX_NEWLINE)) == (REGEX_MATCH_BEGIN | REGEX_NEWLINE)) {
7880675068dSalnsn 		/* Replace REGEX_MATCH_BEGIN flag to REGEX_FAKE_MATCH_BEGIN */
7890675068dSalnsn 		compiler_common->flags &= ~REGEX_MATCH_BEGIN;
7900675068dSalnsn 		compiler_common->flags |= REGEX_FAKE_MATCH_BEGIN;
7910675068dSalnsn 		/* and append a new-line search. */
7920675068dSalnsn 		if (stack_push(stack, type_newline, 0))
7930675068dSalnsn 			return REGEX_MEMORY_ERROR;
7940675068dSalnsn 		compiler_common->dfa_size++;
7950675068dSalnsn 		/* Begin intentionally kept as 1. */
7960675068dSalnsn 	}
7970675068dSalnsn 
7980675068dSalnsn 	while (length > 0) {
7990675068dSalnsn 		switch (*regex_string) {
8000675068dSalnsn 		case '\\' :
8010675068dSalnsn 			length--;
8020675068dSalnsn 			regex_string++;
8030675068dSalnsn 			if (length == 0)
8040675068dSalnsn 				return REGEX_INVALID_REGEX;
8050675068dSalnsn 			if (stack_push(stack, type_char, *regex_string))
8060675068dSalnsn 				return REGEX_MEMORY_ERROR;
8070675068dSalnsn 			begin = 0;
8080675068dSalnsn 			compiler_common->dfa_size++;
8090675068dSalnsn 			break;
8100675068dSalnsn 
8110675068dSalnsn 		case '.' :
8120675068dSalnsn 			if (stack_push(stack, type_rng_start, 1))
8130675068dSalnsn 				return REGEX_MEMORY_ERROR;
8140675068dSalnsn 			if (compiler_common->flags & REGEX_NEWLINE) {
8150675068dSalnsn 				if (stack_push(stack, type_rng_char, '\n'))
8160675068dSalnsn 					return REGEX_MEMORY_ERROR;
8170675068dSalnsn 				if (stack_push(stack, type_rng_char, '\r'))
8180675068dSalnsn 					return REGEX_MEMORY_ERROR;
8190675068dSalnsn 				compiler_common->dfa_size += 2;
8200675068dSalnsn 			}
8210675068dSalnsn 			if (stack_push(stack, type_rng_end, 1))
8220675068dSalnsn 				return REGEX_MEMORY_ERROR;
8230675068dSalnsn 			begin = 0;
8240675068dSalnsn 			compiler_common->dfa_size += 2;
8250675068dSalnsn 			break;
8260675068dSalnsn 
8270675068dSalnsn 		case '(' :
8280675068dSalnsn 			depth++;
8290675068dSalnsn 			if (stack_push(stack, type_open_br, 0))
8300675068dSalnsn 				return REGEX_MEMORY_ERROR;
8310675068dSalnsn 			begin = 1;
8320675068dSalnsn 			break;
8330675068dSalnsn 
8340675068dSalnsn 		case ')' :
8350675068dSalnsn 			if (depth == 0)
8360675068dSalnsn 				return REGEX_INVALID_REGEX;
8370675068dSalnsn 			depth--;
8380675068dSalnsn 			if (stack_push(stack, type_close_br, 0))
8390675068dSalnsn 				return REGEX_MEMORY_ERROR;
8400675068dSalnsn 			begin = 0;
8410675068dSalnsn 			break;
8420675068dSalnsn 
8430675068dSalnsn 		case '|' :
8440675068dSalnsn 			if (stack_push(stack, type_select, 0))
8450675068dSalnsn 				return REGEX_MEMORY_ERROR;
8460675068dSalnsn 			begin = 1;
8470675068dSalnsn 			compiler_common->dfa_size += 2;
8480675068dSalnsn 			break;
8490675068dSalnsn 
8500675068dSalnsn 		case '*' :
8510675068dSalnsn 			if (begin)
8520675068dSalnsn 				return REGEX_INVALID_REGEX;
8530675068dSalnsn 			if (stack_push(stack, type_asterisk, 0))
8540675068dSalnsn 				return REGEX_MEMORY_ERROR;
8550675068dSalnsn 			compiler_common->dfa_size += 2;
8560675068dSalnsn 			break;
8570675068dSalnsn 
8580675068dSalnsn 		case '?' :
8590675068dSalnsn 		case '+' :
8600675068dSalnsn 			if (begin)
8610675068dSalnsn 				return REGEX_INVALID_REGEX;
8620675068dSalnsn 			if (stack_push(stack, (*regex_string == '+') ? type_plus_sign : type_qestion_mark, 0))
8630675068dSalnsn 				return REGEX_MEMORY_ERROR;
8640675068dSalnsn 			compiler_common->dfa_size++;
8650675068dSalnsn 			break;
8660675068dSalnsn 
8670675068dSalnsn 		case '{' :
8680675068dSalnsn 			tmp = parse_iterator(regex_string, length, stack, &compiler_common->dfa_size, begin);
8690675068dSalnsn 
8700675068dSalnsn 			if (tmp >= 0) {
8710675068dSalnsn 				length -= tmp;
8720675068dSalnsn 				regex_string += tmp;
8730675068dSalnsn 			}
8740675068dSalnsn 			else if (tmp == -1)
8750675068dSalnsn 				return REGEX_MEMORY_ERROR;
8760675068dSalnsn 			else {
8770675068dSalnsn 				/* Not a valid range expression. */
8780675068dSalnsn 				SLJIT_ASSERT(tmp == -2);
8790675068dSalnsn 				if (stack_push(stack, type_char, '{'))
8800675068dSalnsn 					return REGEX_MEMORY_ERROR;
8810675068dSalnsn 				compiler_common->dfa_size++;
8820675068dSalnsn 			}
8830675068dSalnsn 			break;
8840675068dSalnsn 
8850675068dSalnsn 		case '[' :
8860675068dSalnsn 			tmp = parse_char_range(regex_string, length, compiler_common);
8870675068dSalnsn 			if (tmp >= 0) {
8880675068dSalnsn 				length -= tmp;
8890675068dSalnsn 				regex_string += tmp;
8900675068dSalnsn 			}
8910675068dSalnsn 			else if (tmp == -1)
8920675068dSalnsn 				return REGEX_MEMORY_ERROR;
8930675068dSalnsn 			else {
8940675068dSalnsn 				SLJIT_ASSERT(tmp == -2);
8950675068dSalnsn 				return REGEX_INVALID_REGEX;
8960675068dSalnsn 			}
8970675068dSalnsn 			begin = 0;
8980675068dSalnsn 			break;
8990675068dSalnsn 
9000675068dSalnsn 		default:
9010675068dSalnsn 			if (length == 1 && *regex_string == '$') {
9020675068dSalnsn 				compiler_common->flags |= REGEX_MATCH_END;
9030675068dSalnsn 				break;
9040675068dSalnsn 			}
9050675068dSalnsn 			if (stack_push(stack, type_char, *regex_string))
9060675068dSalnsn 				return REGEX_MEMORY_ERROR;
9070675068dSalnsn 			begin = 0;
9080675068dSalnsn 			compiler_common->dfa_size++;
9090675068dSalnsn 			break;
9100675068dSalnsn 		}
9110675068dSalnsn 		length--;
9120675068dSalnsn 		regex_string++;
9130675068dSalnsn 	}
9140675068dSalnsn 
9150675068dSalnsn 	if (depth != 0)
9160675068dSalnsn 		return REGEX_INVALID_REGEX;
9170675068dSalnsn 
9180675068dSalnsn 	if ((compiler_common->flags & (REGEX_MATCH_END | REGEX_NEWLINE)) == (REGEX_MATCH_END | REGEX_NEWLINE)) {
9190675068dSalnsn 		/* Replace REGEX_MATCH_END flag to REGEX_FAKE_MATCH_END */
9200675068dSalnsn 		compiler_common->flags &= ~REGEX_MATCH_END;
9210675068dSalnsn 		compiler_common->flags |= REGEX_FAKE_MATCH_END;
9220675068dSalnsn 		/* and append a new-line search. */
9230675068dSalnsn 		if (stack_push(stack, type_newline, 1))
9240675068dSalnsn 			return REGEX_MEMORY_ERROR;
9250675068dSalnsn 		compiler_common->dfa_size++;
9260675068dSalnsn 		/* Begin intentionally kept as 1. */
9270675068dSalnsn 	}
9280675068dSalnsn 
9290675068dSalnsn 	if (stack_push(stack, type_end, 0))
9300675068dSalnsn 		return REGEX_MEMORY_ERROR;
9310675068dSalnsn 
9320675068dSalnsn 	return REGEX_NO_ERROR;
9330675068dSalnsn }
9340675068dSalnsn 
9350675068dSalnsn /* --------------------------------------------------------------------- */
9360675068dSalnsn /*  Generating machine state transitions                                 */
9370675068dSalnsn /* --------------------------------------------------------------------- */
9380675068dSalnsn 
9390675068dSalnsn #define PUT_TRANSITION(typ, val) \
9400675068dSalnsn 	do { \
9410675068dSalnsn 		--transitions_ptr; \
9420675068dSalnsn 		transitions_ptr->type = typ; \
9430675068dSalnsn 		transitions_ptr->value = val; \
9440675068dSalnsn 	} while (0)
9450675068dSalnsn 
handle_iteratives(struct stack_item * transitions_ptr,struct stack_item * transitions,struct stack * depth)9460675068dSalnsn static struct stack_item* handle_iteratives(struct stack_item *transitions_ptr, struct stack_item *transitions, struct stack *depth)
9470675068dSalnsn {
9480675068dSalnsn 	struct stack_item *item;
9490675068dSalnsn 
9500675068dSalnsn 	while (1) {
9510675068dSalnsn 		item = stack_top(depth);
9520675068dSalnsn 
9530675068dSalnsn 		switch (item->type) {
9540675068dSalnsn 		case type_asterisk:
9550675068dSalnsn 			SLJIT_ASSERT(transitions[item->value].type == type_branch);
9560675068dSalnsn 			transitions[item->value].value = transitions_ptr - transitions;
9570675068dSalnsn 			PUT_TRANSITION(type_branch, item->value + 1);
9580675068dSalnsn 			break;
9590675068dSalnsn 
9600675068dSalnsn 		case type_plus_sign:
9610675068dSalnsn 			SLJIT_ASSERT(transitions[item->value].type == type_branch);
9620675068dSalnsn 			transitions[item->value].value = transitions_ptr - transitions;
9630675068dSalnsn 			break;
9640675068dSalnsn 
9650675068dSalnsn 		case type_qestion_mark:
9660675068dSalnsn 			PUT_TRANSITION(type_branch, item->value);
9670675068dSalnsn 			break;
9680675068dSalnsn 
9690675068dSalnsn 		default:
9700675068dSalnsn 			return transitions_ptr;
9710675068dSalnsn 		}
9720675068dSalnsn 		stack_pop(depth);
9730675068dSalnsn 	}
9740675068dSalnsn }
9750675068dSalnsn 
generate_transitions(struct compiler_common * compiler_common)9760675068dSalnsn static int generate_transitions(struct compiler_common *compiler_common)
9770675068dSalnsn {
9780675068dSalnsn 	struct stack *stack = &compiler_common->stack;
9790675068dSalnsn 	struct stack *depth = &compiler_common->depth;
9800675068dSalnsn 	struct stack_item *transitions_ptr;
9810675068dSalnsn 	struct stack_item *item;
9820675068dSalnsn 
9830675068dSalnsn 	stack_init(depth);
98448dfc815Salnsn 	compiler_common->dfa_transitions = SLJIT_MALLOC(sizeof(struct stack_item) * compiler_common->dfa_size, NULL);
9850675068dSalnsn 	if (!compiler_common->dfa_transitions)
9860675068dSalnsn 		return REGEX_MEMORY_ERROR;
9870675068dSalnsn 
9880675068dSalnsn 	/* Go through the items of the stack and generate the necessary branches and jumps (edges of DFA). */
9890675068dSalnsn 	transitions_ptr = compiler_common->dfa_transitions + compiler_common->dfa_size;
9900675068dSalnsn 	while (stack->count > 0) {
9910675068dSalnsn 		item = stack_pop(stack);
9920675068dSalnsn 		switch (item->type) {
9930675068dSalnsn 		case type_begin:
9940675068dSalnsn 		case type_open_br:
9950675068dSalnsn 			item = stack_pop(depth);
9960675068dSalnsn 			if (item->type == type_select)
9970675068dSalnsn 				PUT_TRANSITION(type_branch, item->value + 1);
9980675068dSalnsn 			else
9990675068dSalnsn 				SLJIT_ASSERT(item->type == type_close_br);
10000675068dSalnsn 			if (stack->count == 0)
10010675068dSalnsn 				PUT_TRANSITION(type_begin, 0);
10020675068dSalnsn 			else
10030675068dSalnsn 				transitions_ptr = handle_iteratives(transitions_ptr, compiler_common->dfa_transitions, depth);
10040675068dSalnsn 			break;
10050675068dSalnsn 
10060675068dSalnsn 		case type_end:
10070675068dSalnsn 		case type_close_br:
10080675068dSalnsn 			if (item->type == type_end)
10090675068dSalnsn 				*--transitions_ptr = *item;
10100675068dSalnsn 			if (stack_push(depth, type_close_br, transitions_ptr - compiler_common->dfa_transitions))
10110675068dSalnsn 				return REGEX_MEMORY_ERROR;
10120675068dSalnsn 			break;
10130675068dSalnsn 
10140675068dSalnsn 		case type_select:
10150675068dSalnsn 			item = stack_top(depth);
10160675068dSalnsn 			if (item->type == type_select) {
10170675068dSalnsn 				SLJIT_ASSERT(compiler_common->dfa_transitions[item->value].type == type_jump);
10180675068dSalnsn 				PUT_TRANSITION(type_branch, item->value + 1);
10190675068dSalnsn 				PUT_TRANSITION(type_jump, item->value);
10200675068dSalnsn 				item->value = transitions_ptr - compiler_common->dfa_transitions;
10210675068dSalnsn 			}
10220675068dSalnsn 			else {
10230675068dSalnsn 				SLJIT_ASSERT(item->type == type_close_br);
10240675068dSalnsn 				item->type = type_select;
10250675068dSalnsn 				PUT_TRANSITION(type_jump, item->value);
10260675068dSalnsn 				item->value = transitions_ptr - compiler_common->dfa_transitions;
10270675068dSalnsn 			}
10280675068dSalnsn 			break;
10290675068dSalnsn 
10300675068dSalnsn 		case type_asterisk:
10310675068dSalnsn 		case type_plus_sign:
10320675068dSalnsn 		case type_qestion_mark:
10330675068dSalnsn 			if (item->type != type_qestion_mark)
10340675068dSalnsn 				PUT_TRANSITION(type_branch, 0);
10350675068dSalnsn 			if (stack_push(depth, item->type, transitions_ptr - compiler_common->dfa_transitions))
10360675068dSalnsn 				return REGEX_MEMORY_ERROR;
10370675068dSalnsn 			break;
10380675068dSalnsn 
10390675068dSalnsn 		case type_char:
10400675068dSalnsn 		case type_newline:
10410675068dSalnsn 		case type_rng_start:
10420675068dSalnsn 			/* Requires handle_iteratives. */
10430675068dSalnsn 			*--transitions_ptr = *item;
10440675068dSalnsn 			transitions_ptr = handle_iteratives(transitions_ptr, compiler_common->dfa_transitions, depth);
10450675068dSalnsn 			break;
10460675068dSalnsn 
10470675068dSalnsn 		default:
10480675068dSalnsn 			*--transitions_ptr = *item;
10490675068dSalnsn 			break;
10500675068dSalnsn 		}
10510675068dSalnsn 	}
10520675068dSalnsn 
10530675068dSalnsn 	SLJIT_ASSERT(compiler_common->dfa_transitions == transitions_ptr);
10540675068dSalnsn 	SLJIT_ASSERT(depth->count == 0);
10550675068dSalnsn 	return REGEX_NO_ERROR;
10560675068dSalnsn }
10570675068dSalnsn 
10580675068dSalnsn #undef PUT_TRANSITION
10590675068dSalnsn 
10600675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
10610675068dSalnsn 
verbose_transitions(struct compiler_common * compiler_common)10620675068dSalnsn static void verbose_transitions(struct compiler_common *compiler_common)
10630675068dSalnsn {
10640675068dSalnsn 	struct stack_item *transitions_ptr = compiler_common->dfa_transitions;
10650675068dSalnsn 	struct stack_item *transitions_end = transitions_ptr + compiler_common->dfa_size;
10660675068dSalnsn 	struct stack_item *search_states_ptr = compiler_common->search_states;
10670675068dSalnsn 	int pos;
10680675068dSalnsn 
10690675068dSalnsn 	printf("-----------------\nTransitions\n-----------------\n");
10700675068dSalnsn 	pos = 0;
10710675068dSalnsn 	while (transitions_ptr < transitions_end) {
10720675068dSalnsn 		printf("[%3d] ", pos++);
10730675068dSalnsn 		if (search_states_ptr->type >= 0)
10740675068dSalnsn 			printf("(%3d) ", search_states_ptr->type);
10750675068dSalnsn 		switch (transitions_ptr->type) {
10760675068dSalnsn 		case type_begin:
10770675068dSalnsn 			printf("type_begin\n");
10780675068dSalnsn 			break;
10790675068dSalnsn 
10800675068dSalnsn 		case type_end:
10810675068dSalnsn 			printf("type_end\n");
10820675068dSalnsn 			break;
10830675068dSalnsn 
10840675068dSalnsn 		case type_char:
10850675068dSalnsn 			if (transitions_ptr->value >= ' ')
10860675068dSalnsn 				printf("type_char '%c'\n", transitions_ptr->value);
10870675068dSalnsn 			else
10880675068dSalnsn 				printf("type_char 0x%x\n", transitions_ptr->value);
10890675068dSalnsn 			break;
10900675068dSalnsn 
10910675068dSalnsn 		case type_newline:
10920675068dSalnsn 			printf("type_newline %s\n", transitions_ptr->value ? "(end)" : "(begin)");
10930675068dSalnsn 			break;
10940675068dSalnsn 
10950675068dSalnsn 		case type_id:
10960675068dSalnsn 			printf("type_id %d\n", transitions_ptr->value);
10970675068dSalnsn 			break;
10980675068dSalnsn 
10990675068dSalnsn 		case type_rng_start:
11000675068dSalnsn 			printf("type_rng_start %s\n", transitions_ptr->value ? "(invert)" : "(normal)");
11010675068dSalnsn 			break;
11020675068dSalnsn 
11030675068dSalnsn 		case type_rng_end:
11040675068dSalnsn 			printf("type_rng_end\n");
11050675068dSalnsn 			break;
11060675068dSalnsn 
11070675068dSalnsn 		case type_rng_char:
11080675068dSalnsn 			if (transitions_ptr->value >= ' ')
11090675068dSalnsn 				printf("type_rng_char '%c'\n", transitions_ptr->value);
11100675068dSalnsn 			else
11110675068dSalnsn 				printf("type_rng_char 0x%x\n", transitions_ptr->value);
11120675068dSalnsn 			break;
11130675068dSalnsn 
11140675068dSalnsn 		case type_rng_left:
11150675068dSalnsn 			if (transitions_ptr->value >= ' ')
11160675068dSalnsn 				printf("type_rng_left '%c'\n", transitions_ptr->value);
11170675068dSalnsn 			else
11180675068dSalnsn 				printf("type_rng_left 0x%x\n", transitions_ptr->value);
11190675068dSalnsn 			break;
11200675068dSalnsn 
11210675068dSalnsn 		case type_rng_right:
11220675068dSalnsn 			if (transitions_ptr->value >= ' ')
11230675068dSalnsn 				printf("type_rng_right '%c'\n", transitions_ptr->value);
11240675068dSalnsn 			else
11250675068dSalnsn 				printf("type_rng_right 0x%x\n", transitions_ptr->value);
11260675068dSalnsn 			break;
11270675068dSalnsn 
11280675068dSalnsn 		case type_branch:
11290675068dSalnsn 			printf("type_branch -> %d\n", transitions_ptr->value);
11300675068dSalnsn 			break;
11310675068dSalnsn 
11320675068dSalnsn 		case type_jump:
11330675068dSalnsn 			printf("type_jump -> %d\n", transitions_ptr->value);
11340675068dSalnsn 			break;
11350675068dSalnsn 
11360675068dSalnsn 		default:
11370675068dSalnsn 			printf("UNEXPECTED TYPE\n");
11380675068dSalnsn 			break;
11390675068dSalnsn 		}
11400675068dSalnsn 		transitions_ptr++;
11410675068dSalnsn 		search_states_ptr++;
11420675068dSalnsn 	}
11430675068dSalnsn 	printf("flags: ");
11440675068dSalnsn 	if (!(compiler_common->flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_NEWLINE | REGEX_ID_CHECK | REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)))
11450675068dSalnsn 		printf("none ");
11460675068dSalnsn 	if (compiler_common->flags & REGEX_MATCH_BEGIN)
11470675068dSalnsn 		printf("REGEX_MATCH_BEGIN ");
11480675068dSalnsn 	if (compiler_common->flags & REGEX_MATCH_END)
11490675068dSalnsn 		printf("REGEX_MATCH_END ");
11500675068dSalnsn 	if (compiler_common->flags & REGEX_NEWLINE)
11510675068dSalnsn 		printf("REGEX_NEWLINE ");
11520675068dSalnsn 	if (compiler_common->flags & REGEX_ID_CHECK)
11530675068dSalnsn 		printf("REGEX_ID_CHECK ");
11540675068dSalnsn 	if (compiler_common->flags & REGEX_FAKE_MATCH_BEGIN)
11550675068dSalnsn 		printf("REGEX_FAKE_MATCH_BEGIN ");
11560675068dSalnsn 	if (compiler_common->flags & REGEX_FAKE_MATCH_END)
11570675068dSalnsn 		printf("REGEX_FAKE_MATCH_END ");
11580675068dSalnsn 	if (compiler_common->longest_range_size > 0)
11590675068dSalnsn 		printf("(longest range: %ld) ", (long)compiler_common->longest_range_size);
11600675068dSalnsn 	printf("\n");
11610675068dSalnsn }
11620675068dSalnsn 
11630675068dSalnsn #endif
11640675068dSalnsn 
11650675068dSalnsn /* --------------------------------------------------------------------- */
11660675068dSalnsn /*  Utilities                                                            */
11670675068dSalnsn /* --------------------------------------------------------------------- */
11680675068dSalnsn 
generate_search_states(struct compiler_common * compiler_common)11690675068dSalnsn static int generate_search_states(struct compiler_common *compiler_common)
11700675068dSalnsn {
11710675068dSalnsn 	struct stack_item *transitions_ptr = compiler_common->dfa_transitions;
11720675068dSalnsn 	struct stack_item *transitions_end = transitions_ptr + compiler_common->dfa_size;
11730675068dSalnsn 	struct stack_item *search_states_ptr;
11740675068dSalnsn 	struct stack_item *rng_start = NULL;
11750675068dSalnsn 
11760675068dSalnsn 	compiler_common->terms_size = !(compiler_common->flags & REGEX_FAKE_MATCH_END) ? 1 : 2;
11770675068dSalnsn 	compiler_common->longest_range_size = 0;
117848dfc815Salnsn 	compiler_common->search_states = SLJIT_MALLOC(sizeof(struct stack_item) * compiler_common->dfa_size, NULL);
11790675068dSalnsn 	if (!compiler_common->search_states)
11800675068dSalnsn 		return REGEX_MEMORY_ERROR;
11810675068dSalnsn 
11820675068dSalnsn 	search_states_ptr = compiler_common->search_states;
11830675068dSalnsn 	while (transitions_ptr < transitions_end) {
11840675068dSalnsn 		switch (transitions_ptr->type) {
11850675068dSalnsn 		case type_begin:
11860675068dSalnsn 		case type_end:
11870675068dSalnsn 			search_states_ptr->type = 0;
11880675068dSalnsn 			break;
11890675068dSalnsn 
11900675068dSalnsn 		case type_char:
11910675068dSalnsn 			search_states_ptr->type = compiler_common->terms_size++;
11920675068dSalnsn 			break;
11930675068dSalnsn 
11940675068dSalnsn 		case type_newline:
11950675068dSalnsn 			if (transitions_ptr->value)
11960675068dSalnsn 				search_states_ptr->type = 1;
11970675068dSalnsn 			else
11980675068dSalnsn 				search_states_ptr->type = compiler_common->terms_size++;
11990675068dSalnsn 			SLJIT_ASSERT(search_states_ptr->type == 1 || search_states_ptr->type == 2);
12000675068dSalnsn 			break;
12010675068dSalnsn 
12020675068dSalnsn 		case type_id:
12030675068dSalnsn 			if (transitions_ptr->value > 0)
12040675068dSalnsn 				compiler_common->flags |= REGEX_ID_CHECK;
12050675068dSalnsn 			search_states_ptr->type = -1;
12060675068dSalnsn 			break;
12070675068dSalnsn 
12080675068dSalnsn 		case type_rng_start:
12090675068dSalnsn 			search_states_ptr->type = compiler_common->terms_size;
12100675068dSalnsn 			rng_start = search_states_ptr;
12110675068dSalnsn 			break;
12120675068dSalnsn 
12130675068dSalnsn 		case type_rng_end:
12140675068dSalnsn 			search_states_ptr->type = compiler_common->terms_size++;
12150675068dSalnsn 			/* Ok, this is a blunt over estimation :) */
12160675068dSalnsn 			if (compiler_common->longest_range_size < search_states_ptr - rng_start)
12170675068dSalnsn 				compiler_common->longest_range_size = search_states_ptr - rng_start;
12180675068dSalnsn 			break;
12190675068dSalnsn 
12200675068dSalnsn 		default:
12210675068dSalnsn 			search_states_ptr->type = -1;
12220675068dSalnsn 			break;
12230675068dSalnsn 		}
12240675068dSalnsn 		search_states_ptr->value = -1;
12250675068dSalnsn 		search_states_ptr++;
12260675068dSalnsn 		transitions_ptr++;
12270675068dSalnsn 	}
12280675068dSalnsn 	return REGEX_NO_ERROR;
12290675068dSalnsn }
12300675068dSalnsn 
trace_transitions(int from,struct compiler_common * compiler_common)12310675068dSalnsn static int trace_transitions(int from, struct compiler_common *compiler_common)
12320675068dSalnsn {
12330675068dSalnsn 	int id = 0;
12340675068dSalnsn 	struct stack *stack = &compiler_common->stack;
12350675068dSalnsn 	struct stack *depth = &compiler_common->depth;
12360675068dSalnsn 	struct stack_item *dfa_transitions = compiler_common->dfa_transitions;
12370675068dSalnsn 	struct stack_item *search_states = compiler_common->search_states;
12380675068dSalnsn 
12390675068dSalnsn 	SLJIT_ASSERT(search_states[from].type >= 0);
12400675068dSalnsn 
12410675068dSalnsn 	from++;
12420675068dSalnsn 
12430675068dSalnsn 	/* Be prepared for any paths (loops, etc). */
12440675068dSalnsn 	while (1) {
12450675068dSalnsn 		if (dfa_transitions[from].type == type_id)
12460675068dSalnsn 			if (id < dfa_transitions[from].value)
12470675068dSalnsn 				id = dfa_transitions[from].value;
12480675068dSalnsn 
12490675068dSalnsn 		if (search_states[from].value < id) {
12500675068dSalnsn 			/* Forward step. */
12510675068dSalnsn 			if (search_states[from].value == -1)
12520675068dSalnsn 				if (stack_push(stack, 0, from))
12530675068dSalnsn 					return REGEX_MEMORY_ERROR;
12540675068dSalnsn 			search_states[from].value = id;
12550675068dSalnsn 
12560675068dSalnsn 			if (dfa_transitions[from].type == type_branch) {
12570675068dSalnsn 				if (stack_push(depth, id, from))
12580675068dSalnsn 					return REGEX_MEMORY_ERROR;
12590675068dSalnsn 				from++;
12600675068dSalnsn 				continue;
12610675068dSalnsn 			}
12620675068dSalnsn 			else if (dfa_transitions[from].type == type_jump) {
12630675068dSalnsn 				from = dfa_transitions[from].value;
12640675068dSalnsn 				continue;
12650675068dSalnsn 			}
12660675068dSalnsn 			else if (search_states[from].type < 0) {
12670675068dSalnsn 				from++;
12680675068dSalnsn 				continue;
12690675068dSalnsn 			}
12700675068dSalnsn 		}
12710675068dSalnsn 
12720675068dSalnsn 		/* Back tracking. */
12730675068dSalnsn 		if (depth->count > 0) {
12740675068dSalnsn 			id = stack_top(depth)->type;
12750675068dSalnsn 			from = dfa_transitions[stack_pop(depth)->value].value;
12760675068dSalnsn 			continue;
12770675068dSalnsn 		}
12780675068dSalnsn 		return 0;
12790675068dSalnsn 	}
12800675068dSalnsn }
12810675068dSalnsn 
12820675068dSalnsn /* --------------------------------------------------------------------- */
12830675068dSalnsn /*  Code generator                                                       */
12840675068dSalnsn /* --------------------------------------------------------------------- */
12850675068dSalnsn 
128608987447Salnsn #define TERM_OFFSET_OF(index, offs)	(((index) * no_states + (offs)) * sizeof(sljit_sw))
128708987447Salnsn #define TERM_REL_OFFSET_OF(base, offs)	((base) + ((offs) * sizeof(sljit_sw)))
12880675068dSalnsn 
12890675068dSalnsn #define EMIT_OP1(type, arg1, arg2, arg3, arg4) \
12900675068dSalnsn 	CHECK(sljit_emit_op1(compiler, type, arg1, arg2, arg3, arg4))
12910675068dSalnsn 
12920675068dSalnsn #define EMIT_OP2(type, arg1, arg2, arg3, arg4, arg5, arg6) \
12930675068dSalnsn 	CHECK(sljit_emit_op2(compiler, type, arg1, arg2, arg3, arg4, arg5, arg6))
12940675068dSalnsn 
12950675068dSalnsn #define EMIT_LABEL(label) \
12960675068dSalnsn 	label = sljit_emit_label(compiler); \
12970675068dSalnsn 	CHECK(!label)
12980675068dSalnsn 
12990675068dSalnsn #define EMIT_JUMP(jump, type) \
13000675068dSalnsn 	jump = sljit_emit_jump(compiler, type); \
13010675068dSalnsn 	CHECK(!jump)
13020675068dSalnsn 
13030675068dSalnsn #define EMIT_CMP(jump, type, arg1, arg2, arg3, arg4) \
13040675068dSalnsn 	jump = sljit_emit_cmp(compiler, type, arg1, arg2, arg3, arg4); \
13050675068dSalnsn 	CHECK(!jump)
13060675068dSalnsn 
13070675068dSalnsn /* CHECK depends on the use case. */
13080675068dSalnsn 
13090675068dSalnsn #define CHECK(exp) \
13100675068dSalnsn 	if (SLJIT_UNLIKELY(exp)) \
13110675068dSalnsn 		return REGEX_MEMORY_ERROR
13120675068dSalnsn 
compile_uncond_tran(struct compiler_common * compiler_common,int reg)13130675068dSalnsn static int compile_uncond_tran(struct compiler_common *compiler_common, int reg)
13140675068dSalnsn {
13150675068dSalnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
13160675068dSalnsn 	struct stack *stack = &compiler_common->stack;
13170675068dSalnsn 	struct stack_item *search_states = compiler_common->search_states;
13180675068dSalnsn 	int flags = compiler_common->flags;
131908987447Salnsn 	sljit_sw no_states = compiler_common->no_states;
13200675068dSalnsn 	sljit_uw head = 0;
132108987447Salnsn 	sljit_sw offset, value;
13220675068dSalnsn 
13230675068dSalnsn 	if (reg != R_CURR_STATE || !(compiler_common->flags & REGEX_FAKE_MATCH_BEGIN)) {
13240675068dSalnsn 		CHECK(trace_transitions(0, compiler_common));
13250675068dSalnsn 	}
13260675068dSalnsn 	else {
13270675068dSalnsn 		CHECK(trace_transitions(1, compiler_common));
13280675068dSalnsn 	}
13290675068dSalnsn 
13300675068dSalnsn 	while (stack->count > 0) {
13310675068dSalnsn 		value = stack_pop(stack)->value;
13320675068dSalnsn 		if (search_states[value].type >= 0) {
13330675068dSalnsn 			offset = TERM_OFFSET_OF(search_states[value].type, 0);
13340675068dSalnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 1), SLJIT_IMM, head);
13350675068dSalnsn 			if (offset > 0)
13360675068dSalnsn 				head = offset;
13370675068dSalnsn 
13380675068dSalnsn 			if (!(flags & REGEX_MATCH_BEGIN)) {
13390675068dSalnsn 				EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), R_TEMP, 0);
13400675068dSalnsn 				if (flags & REGEX_ID_CHECK) {
13410675068dSalnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 3), SLJIT_IMM, search_states[value].value);
13420675068dSalnsn 				}
13430675068dSalnsn 			}
13440675068dSalnsn 			else if (flags & REGEX_ID_CHECK) {
13450675068dSalnsn 				EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), SLJIT_IMM, search_states[value].value);
13460675068dSalnsn 			}
13470675068dSalnsn 		}
13480675068dSalnsn 		search_states[value].value = -1;
13490675068dSalnsn 	}
13500675068dSalnsn 	if (reg == R_NEXT_STATE) {
13510675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);
13520675068dSalnsn 	}
13530675068dSalnsn 	else if (flags & REGEX_FAKE_MATCH_BEGIN) {
13540675068dSalnsn 		SLJIT_ASSERT(compiler_common->dfa_transitions[1].type == type_newline && !compiler_common->dfa_transitions[1].value);
13550675068dSalnsn 		offset = TERM_OFFSET_OF(search_states[1].type, 0);
13560675068dSalnsn 
13570675068dSalnsn 		SLJIT_ASSERT(!(flags & REGEX_MATCH_BEGIN));
13580675068dSalnsn 
13590675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 1), SLJIT_IMM, head);
13600675068dSalnsn 		head = offset;
13610675068dSalnsn 
13620675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), SLJIT_IMM, 1);
13630675068dSalnsn 		if (flags & REGEX_ID_CHECK) {
13640675068dSalnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 3), SLJIT_IMM, 0);
13650675068dSalnsn 		}
13660675068dSalnsn 	}
13670675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, head);
13680675068dSalnsn 	return REGEX_NO_ERROR;
13690675068dSalnsn }
13700675068dSalnsn 
compile_cond_tran(struct compiler_common * compiler_common,sljit_sw curr_index)137108987447Salnsn static int compile_cond_tran(struct compiler_common *compiler_common, sljit_sw curr_index)
13720675068dSalnsn {
13730675068dSalnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
13740675068dSalnsn 	struct stack *stack = &compiler_common->stack;
13750675068dSalnsn 	struct stack_item *search_states = compiler_common->search_states;
137608987447Salnsn 	sljit_sw offset;
13770675068dSalnsn 	int flags;
137808987447Salnsn 	sljit_sw no_states;
137908987447Salnsn 	sljit_sw value;
13800675068dSalnsn 	struct sljit_jump *jump1;
13810675068dSalnsn 	struct sljit_jump *jump2;
13820675068dSalnsn 	struct sljit_jump *jump3;
13830675068dSalnsn 	struct sljit_jump *jump4;
13840675068dSalnsn 	struct sljit_jump *jump5;
13850675068dSalnsn 	struct sljit_label *label1;
13860675068dSalnsn 
13870675068dSalnsn 	flags = compiler_common->flags;
13880675068dSalnsn 	no_states = compiler_common->no_states;
13890675068dSalnsn 
13900675068dSalnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);
13910675068dSalnsn 	if (!(flags & (REGEX_ID_CHECK | REGEX_MATCH_BEGIN))) {
13920675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));
13930675068dSalnsn 	}
13940675068dSalnsn 
13950675068dSalnsn 	while (stack->count > 0) {
13960675068dSalnsn 		value = stack_pop(stack)->value;
13970675068dSalnsn 		if (search_states[value].type >= 0) {
13980675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
13990675068dSalnsn 			if (flags & REGEX_MATCH_VERBOSE)
14000675068dSalnsn 				printf("-> (%3d:%3d) ", search_states[value].type, search_states[value].value);
14010675068dSalnsn #endif
14020675068dSalnsn 			offset = TERM_OFFSET_OF(search_states[value].type, 0);
14030675068dSalnsn 
14040675068dSalnsn 			if (!(flags & REGEX_ID_CHECK)) {
14050675068dSalnsn 				if (!(flags & REGEX_MATCH_BEGIN)) {
14060675068dSalnsn 					/* Check whether item is inserted. */
140748dfc815Salnsn 					EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), SLJIT_IMM, -1);
140808987447Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), R_NEXT_HEAD, 0);
14090675068dSalnsn 					if (offset > 0) {
14100675068dSalnsn 						EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);
14110675068dSalnsn 					}
14120675068dSalnsn 					EMIT_JUMP(jump2, SLJIT_JUMP);
14130675068dSalnsn 
14140675068dSalnsn 					/* Check whether old index <= index. */
14150675068dSalnsn 					EMIT_LABEL(label1);
14160675068dSalnsn 					sljit_set_label(jump1, label1);
14170675068dSalnsn 
141848dfc815Salnsn 					EMIT_CMP(jump1, SLJIT_LESS_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
14190675068dSalnsn 
14200675068dSalnsn 					EMIT_LABEL(label1);
14210675068dSalnsn 					sljit_set_label(jump2, label1);
142208987447Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
14230675068dSalnsn 
14240675068dSalnsn 					EMIT_LABEL(label1);
14250675068dSalnsn 					sljit_set_label(jump1, label1);
14260675068dSalnsn 				}
14270675068dSalnsn 				else {
14280675068dSalnsn 					/* Check whether item is inserted. */
142948dfc815Salnsn 					EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), SLJIT_IMM, -1);
143008987447Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), R_NEXT_HEAD, 0);
14310675068dSalnsn 					if (offset > 0) {
14320675068dSalnsn 						EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);
14330675068dSalnsn 					}
14340675068dSalnsn 					EMIT_LABEL(label1);
14350675068dSalnsn 					sljit_set_label(jump1, label1);
14360675068dSalnsn 				}
14370675068dSalnsn 			}
14380675068dSalnsn 			else {
14390675068dSalnsn 				if (!(flags & REGEX_MATCH_BEGIN)) {
14400675068dSalnsn 					EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));
14410675068dSalnsn 
14420675068dSalnsn 					/* Check whether item is inserted. */
144348dfc815Salnsn 					EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), SLJIT_IMM, -1);
144408987447Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), R_NEXT_HEAD, 0);
14450675068dSalnsn 					if (offset > 0) {
14460675068dSalnsn 						EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);
14470675068dSalnsn 					}
14480675068dSalnsn 					EMIT_JUMP(jump2, SLJIT_JUMP);
14490675068dSalnsn 
14500675068dSalnsn 					/* Check whether old index != index. */
14510675068dSalnsn 					EMIT_LABEL(label1);
14520675068dSalnsn 					sljit_set_label(jump1, label1);
14530675068dSalnsn 
1454*e52d5ebbSalnsn 					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);
145548dfc815Salnsn 					EMIT_JUMP(jump1, SLJIT_LESS);
1456*e52d5ebbSalnsn 					EMIT_JUMP(jump3, SLJIT_NOT_EQUAL); /* Greater. */
14570675068dSalnsn 
14580675068dSalnsn 					/* Old index == index. */
14590675068dSalnsn 					EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 3));
14600675068dSalnsn 					if (search_states[value].value > 0) {
146148dfc815Salnsn 						EMIT_CMP(jump4, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
14620675068dSalnsn 
14630675068dSalnsn 						EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
14640675068dSalnsn 						EMIT_LABEL(label1);
14650675068dSalnsn 						sljit_set_label(jump4, label1);
14660675068dSalnsn 					}
14670675068dSalnsn 
1468*e52d5ebbSalnsn 					EMIT_OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, SLJIT_MEM1(R_NEXT_STATE), offset + 3 * sizeof(sljit_sw), R_TEMP, 0);
146948dfc815Salnsn 					EMIT_JUMP(jump4, SLJIT_GREATER_EQUAL);
14700675068dSalnsn 					EMIT_JUMP(jump5, SLJIT_JUMP);
14710675068dSalnsn 
14720675068dSalnsn 					/* Overwrite index & id. */
14730675068dSalnsn 					EMIT_LABEL(label1);
14740675068dSalnsn 					sljit_set_label(jump3, label1);
14750675068dSalnsn 					sljit_set_label(jump2, label1);
147608987447Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
14770675068dSalnsn 
14780675068dSalnsn 					EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 3));
14790675068dSalnsn 					if (search_states[value].value > 0) {
148048dfc815Salnsn 						EMIT_CMP(jump3, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
14810675068dSalnsn 
14820675068dSalnsn 						EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
14830675068dSalnsn 						EMIT_LABEL(label1);
14840675068dSalnsn 						sljit_set_label(jump3, label1);
14850675068dSalnsn 					}
14860675068dSalnsn 
14870675068dSalnsn 					EMIT_LABEL(label1);
14880675068dSalnsn 					sljit_set_label(jump5, label1);
148908987447Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 3 * sizeof(sljit_sw), R_TEMP, 0);
14900675068dSalnsn 
14910675068dSalnsn 					/* Exit. */
14920675068dSalnsn 					EMIT_LABEL(label1);
14930675068dSalnsn 					sljit_set_label(jump1, label1);
14940675068dSalnsn 					sljit_set_label(jump4, label1);
14950675068dSalnsn 				}
14960675068dSalnsn 				else {
14970675068dSalnsn 					EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));
14980675068dSalnsn 
14990675068dSalnsn 					if (search_states[value].value > 0) {
150048dfc815Salnsn 						EMIT_CMP(jump1, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
15010675068dSalnsn 
15020675068dSalnsn 						EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);
15030675068dSalnsn 						EMIT_LABEL(label1);
15040675068dSalnsn 						sljit_set_label(jump1, label1);
15050675068dSalnsn 					}
15060675068dSalnsn 
15070675068dSalnsn 					/* Check whether item is inserted. */
150848dfc815Salnsn 					EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), SLJIT_IMM, -1);
150908987447Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + sizeof(sljit_sw), R_NEXT_HEAD, 0);
15100675068dSalnsn 					if (offset > 0) {
15110675068dSalnsn 						EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);
15120675068dSalnsn 					}
15130675068dSalnsn 					EMIT_JUMP(jump2, SLJIT_JUMP);
15140675068dSalnsn 
15150675068dSalnsn 					/* Check whether old id >= id. */
15160675068dSalnsn 					EMIT_LABEL(label1);
15170675068dSalnsn 					sljit_set_label(jump1, label1);
15180675068dSalnsn 
151948dfc815Salnsn 					EMIT_CMP(jump1, SLJIT_GREATER_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
15200675068dSalnsn 
15210675068dSalnsn 					EMIT_LABEL(label1);
15220675068dSalnsn 					sljit_set_label(jump2, label1);
152308987447Salnsn 					EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * sizeof(sljit_sw), R_TEMP, 0);
15240675068dSalnsn 
15250675068dSalnsn 					EMIT_LABEL(label1);
15260675068dSalnsn 					sljit_set_label(jump1, label1);
15270675068dSalnsn 				}
15280675068dSalnsn 			}
15290675068dSalnsn 		}
15300675068dSalnsn 		search_states[value].value = -1;
15310675068dSalnsn 	}
15320675068dSalnsn 
15330675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
15340675068dSalnsn 	if (flags & REGEX_MATCH_VERBOSE)
15350675068dSalnsn 		printf("\n");
15360675068dSalnsn #endif
15370675068dSalnsn 	return REGEX_NO_ERROR;
15380675068dSalnsn }
15390675068dSalnsn 
compile_end_check(struct compiler_common * compiler_common,struct sljit_label * end_check_label)15400675068dSalnsn static int compile_end_check(struct compiler_common *compiler_common, struct sljit_label *end_check_label)
15410675068dSalnsn {
15420675068dSalnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
15430675068dSalnsn 	struct sljit_jump *jump;
15440675068dSalnsn 	struct sljit_jump *clear_states_jump;
15450675068dSalnsn 	struct sljit_label *label;
15460675068dSalnsn 	struct sljit_label *leave_label;
15470675068dSalnsn 	struct sljit_label *begin_loop_label;
15480675068dSalnsn 
15490675068dSalnsn 	/* Priority order: best_begin > best_end > best_id.
15500675068dSalnsn 	   In other words:
15510675068dSalnsn 	       if (new best_begin > old test_begin) do nothing
15520675068dSalnsn 	       otherwise we know that new_end > old_end, since R_CURR_INDEX ever increasing
15530675068dSalnsn 	       therefore we must overwrite all best_* variables (new_id also contains the highest id for this turn). */
15540675068dSalnsn 
15550675068dSalnsn 	/* Both R_CURR_CHAR and R_BEST_BEGIN used as temporary registers. */
15560675068dSalnsn 
15570675068dSalnsn 	if (!(compiler_common->flags & REGEX_MATCH_BEGIN)) {
15580675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2));
155948dfc815Salnsn 		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);
15600675068dSalnsn 		sljit_set_label(jump, end_check_label);
15610675068dSalnsn 
15620675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), R_CURR_CHAR, 0);
15630675068dSalnsn 		if (!(compiler_common->flags & (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END))) {
15640675068dSalnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);
15650675068dSalnsn 		}
15660675068dSalnsn 		else {
15670675068dSalnsn 			if ((compiler_common->flags & (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)) == (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)) {
15680675068dSalnsn 				EMIT_OP2(SLJIT_SUB, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0, SLJIT_IMM, 2);
15690675068dSalnsn 			}
15700675068dSalnsn 			else {
15710675068dSalnsn 				EMIT_OP2(SLJIT_SUB, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0, SLJIT_IMM, 1);
15720675068dSalnsn 			}
15730675068dSalnsn 		}
15740675068dSalnsn 		if (compiler_common->flags & REGEX_ID_CHECK) {
15750675068dSalnsn 			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));
15760675068dSalnsn 		}
15770675068dSalnsn 
157848dfc815Salnsn 		EMIT_CMP(clear_states_jump, SLJIT_LESS, R_CURR_CHAR, 0, R_BEST_BEGIN, 0);
15790675068dSalnsn 
15800675068dSalnsn 		EMIT_LABEL(leave_label);
15810675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, R_CURR_CHAR, 0);
15820675068dSalnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
15830675068dSalnsn 		sljit_set_label(jump, end_check_label);
15840675068dSalnsn 
15850675068dSalnsn 		/* A loop to clear all states, which are > (or >=) than R_CURR_CHAR. */
15860675068dSalnsn 		EMIT_LABEL(label);
15870675068dSalnsn 		sljit_set_label(clear_states_jump, label);
15880675068dSalnsn 
15890675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);
15900675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
15910675068dSalnsn 
15920675068dSalnsn 		/* Begin of the loop. */
15930675068dSalnsn 		EMIT_LABEL(begin_loop_label);
159448dfc815Salnsn 		EMIT_CMP(jump, SLJIT_EQUAL, R_TEMP, 0, SLJIT_IMM, 0);
15950675068dSalnsn 		sljit_set_label(jump, leave_label);
15960675068dSalnsn 
15970675068dSalnsn 		EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, R_CURR_STATE, 0);
159808987447Salnsn 		EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw));
159948dfc815Salnsn 		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);
16000675068dSalnsn 
16010675068dSalnsn 		/* Case 1: keep this case. */
160208987447Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw), R_NEXT_HEAD, 0);
16030675068dSalnsn 		EMIT_OP2(SLJIT_SUB, R_NEXT_HEAD, 0, R_TEMP, 0, R_CURR_STATE, 0);
16040675068dSalnsn 
16050675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_BEST_BEGIN, 0);
16060675068dSalnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
16070675068dSalnsn 		sljit_set_label(jump, begin_loop_label);
16080675068dSalnsn 
16090675068dSalnsn 		/* Case 2: remove this case. */
16100675068dSalnsn 		EMIT_LABEL(label);
16110675068dSalnsn 		sljit_set_label(clear_states_jump, label);
16120675068dSalnsn 
161308987447Salnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw), SLJIT_IMM, -1);
16140675068dSalnsn 
16150675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_BEST_BEGIN, 0);
16160675068dSalnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
16170675068dSalnsn 		sljit_set_label(jump, begin_loop_label);
16180675068dSalnsn 	}
16190675068dSalnsn 	else {
16200675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_IMM, 0);
16210675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);
16220675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);
16230675068dSalnsn 		if (compiler_common->flags & REGEX_ID_CHECK) {
16240675068dSalnsn 			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));
16250675068dSalnsn 		}
16260675068dSalnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
16270675068dSalnsn 		sljit_set_label(jump, end_check_label);
16280675068dSalnsn 	}
16290675068dSalnsn 	return REGEX_NO_ERROR;
16300675068dSalnsn }
16310675068dSalnsn 
compile_leave_fast_forward(struct compiler_common * compiler_common,struct sljit_label * fast_forward_label)16320675068dSalnsn static int compile_leave_fast_forward(struct compiler_common *compiler_common, struct sljit_label *fast_forward_label)
16330675068dSalnsn {
16340675068dSalnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
16350675068dSalnsn 	struct stack *stack = &compiler_common->stack;
16360675068dSalnsn 	struct stack_item *dfa_transitions = compiler_common->dfa_transitions;
16370675068dSalnsn 	struct stack_item *search_states = compiler_common->search_states;
16380675068dSalnsn 	int ind;
16390675068dSalnsn 	struct sljit_jump *jump;
16400675068dSalnsn 	int init_range = 1, prev_value = 0;
16410675068dSalnsn 
16420675068dSalnsn 	while (stack->count > 0) {
16430675068dSalnsn 		ind = stack_pop(stack)->value;
16440675068dSalnsn 		search_states[ind].value = -1;
16450675068dSalnsn 		if (search_states[ind].type >= 0) {
16460675068dSalnsn 			if (dfa_transitions[ind].type == type_char) {
164748dfc815Salnsn 				EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);
16480675068dSalnsn 				sljit_set_label(jump, fast_forward_label);
16490675068dSalnsn 			}
16500675068dSalnsn 			else if (dfa_transitions[ind].type == type_rng_start) {
16510675068dSalnsn 				SLJIT_ASSERT(!dfa_transitions[ind].value);
16520675068dSalnsn 				ind++;
16530675068dSalnsn 				while (dfa_transitions[ind].type != type_rng_end) {
16540675068dSalnsn 					if (dfa_transitions[ind].type == type_rng_char) {
165548dfc815Salnsn 						EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);
16560675068dSalnsn 						sljit_set_label(jump, fast_forward_label);
16570675068dSalnsn 					}
16580675068dSalnsn 					else {
16590675068dSalnsn 						SLJIT_ASSERT(dfa_transitions[ind].type == type_rng_left);
16600675068dSalnsn 						if (init_range) {
16610675068dSalnsn 							EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_CHAR, 0);
16620675068dSalnsn 							init_range = 0;
16630675068dSalnsn 						}
16640675068dSalnsn 						if (dfa_transitions[ind].value != prev_value) {
16650675068dSalnsn 							/* Best compatibility to all archs. */
16660675068dSalnsn 							prev_value -= dfa_transitions[ind].value;
16670675068dSalnsn 							if (prev_value < 0) {
16680675068dSalnsn 								EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, -prev_value);
16690675068dSalnsn 							}
16700675068dSalnsn 							else {
16710675068dSalnsn 								EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, prev_value);
16720675068dSalnsn 							}
16730675068dSalnsn 							prev_value = dfa_transitions[ind].value;
16740675068dSalnsn 						}
167548dfc815Salnsn 						EMIT_CMP(jump, SLJIT_LESS_EQUAL, R_TEMP, 0, SLJIT_IMM, dfa_transitions[ind + 1].value - dfa_transitions[ind].value);
16760675068dSalnsn 						sljit_set_label(jump, fast_forward_label);
16770675068dSalnsn 						ind++;
16780675068dSalnsn 					}
16790675068dSalnsn 					ind++;
16800675068dSalnsn 				}
16810675068dSalnsn 			}
16820675068dSalnsn 			else {
16830675068dSalnsn 				SLJIT_ASSERT(dfa_transitions[ind].type == type_newline);
168448dfc815Salnsn 				EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\n');
16850675068dSalnsn 				sljit_set_label(jump, fast_forward_label);
168648dfc815Salnsn 				EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\r');
16870675068dSalnsn 				sljit_set_label(jump, fast_forward_label);
16880675068dSalnsn 			}
16890675068dSalnsn 		}
16900675068dSalnsn 	}
16910675068dSalnsn 	return REGEX_NO_ERROR;
16920675068dSalnsn }
16930675068dSalnsn 
compile_newline_check(struct compiler_common * compiler_common,sljit_sw ind)169408987447Salnsn static int compile_newline_check(struct compiler_common *compiler_common, sljit_sw ind)
16950675068dSalnsn {
16960675068dSalnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
16970675068dSalnsn 	struct sljit_jump *jump1;
16980675068dSalnsn 	struct sljit_jump *jump2;
16990675068dSalnsn 	struct sljit_label *label;
170008987447Salnsn 	sljit_sw no_states;
170108987447Salnsn 	sljit_sw offset;
17020675068dSalnsn 
17030675068dSalnsn 	/* Check whether a new-line character is found. */
170448dfc815Salnsn 	EMIT_CMP(jump1, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\n');
170548dfc815Salnsn 	EMIT_CMP(jump2, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\r');
17060675068dSalnsn 
17070675068dSalnsn 	no_states = compiler_common->no_states;
17080675068dSalnsn 	offset = TERM_OFFSET_OF(compiler_common->search_states[ind].type, 1);
17090675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), offset);
17100675068dSalnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), offset, SLJIT_IMM, -1);
17110675068dSalnsn 	CHECK(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
17120675068dSalnsn 
17130675068dSalnsn 	EMIT_LABEL(label);
17140675068dSalnsn 	sljit_set_label(jump1, label);
17150675068dSalnsn 	sljit_set_label(jump2, label);
17160675068dSalnsn 	return REGEX_NO_ERROR;
17170675068dSalnsn }
17180675068dSalnsn 
17190675068dSalnsn #undef CHECK
17200675068dSalnsn 
17210675068dSalnsn #define CHECK(exp) \
17220675068dSalnsn 	if (SLJIT_UNLIKELY(exp)) \
17230675068dSalnsn 		return 0
17240675068dSalnsn 
range_set_label(struct sljit_jump ** range_jump_list,struct sljit_label * label)17250675068dSalnsn static SLJIT_INLINE void range_set_label(struct sljit_jump **range_jump_list, struct sljit_label *label)
17260675068dSalnsn {
17270675068dSalnsn 	while (*range_jump_list) {
17280675068dSalnsn 		sljit_set_label(*range_jump_list, label);
17290675068dSalnsn 		range_jump_list++;
17300675068dSalnsn 	}
17310675068dSalnsn }
17320675068dSalnsn 
compile_range_check(struct compiler_common * compiler_common,sljit_sw ind)173308987447Salnsn static sljit_sw compile_range_check(struct compiler_common *compiler_common, sljit_sw ind)
17340675068dSalnsn {
17350675068dSalnsn 	struct sljit_compiler *compiler = compiler_common->compiler;
17360675068dSalnsn 	struct stack_item *dfa_transitions = compiler_common->dfa_transitions;
17370675068dSalnsn 	struct sljit_jump **range_jump_list = compiler_common->range_jump_list;
17380675068dSalnsn 	int invert = dfa_transitions[ind].value;
17390675068dSalnsn 	struct sljit_label *label;
174008987447Salnsn 	sljit_sw no_states;
174108987447Salnsn 	sljit_sw offset;
17420675068dSalnsn 	int init_range = 1, prev_value = 0;
17430675068dSalnsn 
17440675068dSalnsn 	ind++;
17450675068dSalnsn 
17460675068dSalnsn 	while (dfa_transitions[ind].type != type_rng_end) {
17470675068dSalnsn 		if (dfa_transitions[ind].type == type_rng_char) {
174848dfc815Salnsn 			EMIT_CMP(*range_jump_list, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);
17490675068dSalnsn 			range_jump_list++;
17500675068dSalnsn 		}
17510675068dSalnsn 		else {
17520675068dSalnsn 			SLJIT_ASSERT(dfa_transitions[ind].type == type_rng_left);
17530675068dSalnsn 			if (init_range) {
17540675068dSalnsn 				EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_CHAR, 0);
17550675068dSalnsn 				init_range = 0;
17560675068dSalnsn 			}
17570675068dSalnsn 			if (dfa_transitions[ind].value != prev_value) {
17580675068dSalnsn 				/* Best compatibility to all archs. */
17590675068dSalnsn 				prev_value -= dfa_transitions[ind].value;
17600675068dSalnsn 				if (prev_value < 0) {
17610675068dSalnsn 					EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, -prev_value);
17620675068dSalnsn 				}
17630675068dSalnsn 				else {
17640675068dSalnsn 					EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, prev_value);
17650675068dSalnsn 				}
17660675068dSalnsn 				prev_value = dfa_transitions[ind].value;
17670675068dSalnsn 			}
176848dfc815Salnsn 			EMIT_CMP(*range_jump_list, SLJIT_LESS_EQUAL, R_TEMP, 0, SLJIT_IMM, dfa_transitions[ind + 1].value - dfa_transitions[ind].value);
17690675068dSalnsn 			range_jump_list++;
17700675068dSalnsn 			ind++;
17710675068dSalnsn 		}
17720675068dSalnsn 		ind++;
17730675068dSalnsn 	}
17740675068dSalnsn 
17750675068dSalnsn 	*range_jump_list = NULL;
17760675068dSalnsn 
17770675068dSalnsn 	if (!invert) {
17780675068dSalnsn 		no_states = compiler_common->no_states;
17790675068dSalnsn 		offset = TERM_OFFSET_OF(compiler_common->search_states[ind].type, 1);
17800675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), offset);
17810675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), offset, SLJIT_IMM, -1);
17820675068dSalnsn 		CHECK(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
17830675068dSalnsn 
17840675068dSalnsn 		EMIT_LABEL(label);
17850675068dSalnsn 		range_set_label(compiler_common->range_jump_list, label);
17860675068dSalnsn 		/* Clears the jump list. */
17870675068dSalnsn 		*compiler_common->range_jump_list = NULL;
17880675068dSalnsn 	}
17890675068dSalnsn 	return ind;
17900675068dSalnsn }
17910675068dSalnsn 
17920675068dSalnsn #undef TERM_OFFSET_OF
17930675068dSalnsn #undef EMIT_OP1
17940675068dSalnsn #undef EMIT_OP2
17950675068dSalnsn #undef EMIT_LABEL
17960675068dSalnsn #undef EMIT_JUMP
17970675068dSalnsn #undef EMIT_CMP
17980675068dSalnsn #undef CHECK
17990675068dSalnsn 
18000675068dSalnsn /* --------------------------------------------------------------------- */
18010675068dSalnsn /*  Main compiler                                                        */
18020675068dSalnsn /* --------------------------------------------------------------------- */
18030675068dSalnsn 
180408987447Salnsn #define TERM_OFFSET_OF(ind, offs) (((ind) * compiler_common.no_states + (offs)) * sizeof(sljit_sw))
18050675068dSalnsn 
18060675068dSalnsn #define EMIT_OP1(type, arg1, arg2, arg3, arg4) \
18070675068dSalnsn 	CHECK(sljit_emit_op1(compiler_common.compiler, type, arg1, arg2, arg3, arg4))
18080675068dSalnsn 
18090675068dSalnsn #define EMIT_OP2(type, arg1, arg2, arg3, arg4, arg5, arg6) \
18100675068dSalnsn 	CHECK(sljit_emit_op2(compiler_common.compiler, type, arg1, arg2, arg3, arg4, arg5, arg6))
18110675068dSalnsn 
18120675068dSalnsn #define EMIT_LABEL(label) \
18130675068dSalnsn 	label = sljit_emit_label(compiler_common.compiler); \
18140675068dSalnsn 	CHECK(!label)
18150675068dSalnsn 
18160675068dSalnsn #define EMIT_JUMP(jump, type) \
18170675068dSalnsn 	jump = sljit_emit_jump(compiler_common.compiler, type); \
18180675068dSalnsn 	CHECK(!jump)
18190675068dSalnsn 
18200675068dSalnsn #define EMIT_CMP(jump, type, arg1, arg2, arg3, arg4) \
18210675068dSalnsn 	jump = sljit_emit_cmp(compiler_common.compiler, type, arg1, arg2, arg3, arg4); \
18220675068dSalnsn 	CHECK(!jump)
18230675068dSalnsn 
18240675068dSalnsn /* A do {} while(0) expression helps to avoid goto statements. */
18250675068dSalnsn #define BEGIN_GUARD \
18260675068dSalnsn 	do {
18270675068dSalnsn 
18280675068dSalnsn #define END_GUARD \
18290675068dSalnsn 	} while(0);
18300675068dSalnsn 
18310675068dSalnsn #define CHECK(exp) \
18320675068dSalnsn 	if (SLJIT_UNLIKELY(exp)) \
18330675068dSalnsn 		break;
18340675068dSalnsn 
regex_compile(const regex_char_t * regex_string,int length,int re_flags,int * error)18350675068dSalnsn struct regex_machine* regex_compile(const regex_char_t *regex_string, int length, int re_flags, int *error)
18360675068dSalnsn {
18370675068dSalnsn 	struct compiler_common compiler_common;
183808987447Salnsn 	sljit_sw ind;
18390675068dSalnsn 	int error_code, done, suggest_fast_forward;
18400675068dSalnsn 	/* ID of an empty match (-1 if not reachable). */
18410675068dSalnsn 	int empty_match_id;
18420675068dSalnsn 
18430675068dSalnsn 	struct sljit_jump *jump;
18440675068dSalnsn 	struct sljit_jump *best_match_found_jump;
18450675068dSalnsn 	struct sljit_jump *fast_forward_jump = NULL;
18460675068dSalnsn 	struct sljit_jump *length_is_zero_jump;
18470675068dSalnsn 	struct sljit_jump *end_check_jump = NULL;
18480675068dSalnsn 	struct sljit_jump *best_match_check_jump = NULL;
18490675068dSalnsn 	struct sljit_jump *non_greedy_end_jump = NULL;
18500675068dSalnsn 	struct sljit_label *label;
18510675068dSalnsn 	struct sljit_label *end_check_label = NULL;
18520675068dSalnsn 	struct sljit_label *start_label;
18530675068dSalnsn 	struct sljit_label *fast_forward_label;
18540675068dSalnsn 	struct sljit_label *fast_forward_return_label;
18550675068dSalnsn 
18560675068dSalnsn 	if (error)
18570675068dSalnsn 		*error = REGEX_NO_ERROR;
18580675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
18590675068dSalnsn 	compiler_common.flags = re_flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_MATCH_NON_GREEDY | REGEX_NEWLINE | REGEX_MATCH_VERBOSE);
18600675068dSalnsn #else
18610675068dSalnsn 	compiler_common.flags = re_flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_MATCH_NON_GREEDY | REGEX_NEWLINE);
18620675068dSalnsn #endif
18630675068dSalnsn 
18640675068dSalnsn 	/* Step 1: parsing (Left->Right).
18650675068dSalnsn 	   Syntax check and AST generator. */
18660675068dSalnsn 	error_code = parse(regex_string, length, &compiler_common);
18670675068dSalnsn 	if (error_code) {
18680675068dSalnsn 		stack_destroy(&compiler_common.stack);
18690675068dSalnsn 		if (error)
18700675068dSalnsn 			*error = error_code;
18710675068dSalnsn 		return NULL;
18720675068dSalnsn 	}
18730675068dSalnsn 
18740675068dSalnsn 	/* Step 2: generating branches (Right->Left). */
18750675068dSalnsn 	error_code = generate_transitions(&compiler_common);
18760675068dSalnsn 	stack_destroy(&compiler_common.stack);
18770675068dSalnsn 	stack_destroy(&compiler_common.depth);
18780675068dSalnsn 	if (error_code) {
18790675068dSalnsn 		if (compiler_common.dfa_transitions)
188048dfc815Salnsn 			SLJIT_FREE(compiler_common.dfa_transitions, NULL);
18810675068dSalnsn 		if (error)
18820675068dSalnsn 			*error = error_code;
18830675068dSalnsn 		return NULL;
18840675068dSalnsn 	}
18850675068dSalnsn 
18860675068dSalnsn 	/* Step 3: Generate necessary data for depth-first search (Left->Right). */
18870675068dSalnsn 	error_code = generate_search_states(&compiler_common);
18880675068dSalnsn 	if (error_code) {
188948dfc815Salnsn 		SLJIT_FREE(compiler_common.dfa_transitions, NULL);
18900675068dSalnsn 		if (error)
18910675068dSalnsn 			*error = error_code;
18920675068dSalnsn 		return NULL;
18930675068dSalnsn 	}
18940675068dSalnsn 
18950675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
18960675068dSalnsn 	if (compiler_common.flags & REGEX_MATCH_VERBOSE)
18970675068dSalnsn 		verbose_transitions(&compiler_common);
18980675068dSalnsn #endif
18990675068dSalnsn 
19000675068dSalnsn 	/* Step 4: Left->Right generate code. */
19010675068dSalnsn 	stack_init(&compiler_common.stack);
19020675068dSalnsn 	stack_init(&compiler_common.depth);
19030675068dSalnsn 	done = 0;
19040675068dSalnsn 	compiler_common.machine = NULL;
19050675068dSalnsn 	compiler_common.compiler = NULL;
19060675068dSalnsn 	compiler_common.range_jump_list = NULL;
19070675068dSalnsn 
19080675068dSalnsn 	BEGIN_GUARD
19090675068dSalnsn 
191048dfc815Salnsn 	compiler_common.machine = (struct regex_machine*)SLJIT_MALLOC(sizeof(struct regex_machine) + (compiler_common.terms_size - 1) * sizeof(sljit_uw), NULL);
19110675068dSalnsn 	CHECK(!compiler_common.machine);
19120675068dSalnsn 
191348dfc815Salnsn 	compiler_common.compiler = sljit_create_compiler(NULL);
19140675068dSalnsn 	CHECK(!compiler_common.compiler);
19150675068dSalnsn 
19160675068dSalnsn 	if (compiler_common.longest_range_size > 0) {
191748dfc815Salnsn 		compiler_common.range_jump_list = (struct sljit_jump**)SLJIT_MALLOC(sizeof(struct sljit_jump*) * compiler_common.longest_range_size, NULL);
19180675068dSalnsn 		CHECK(!compiler_common.range_jump_list);
19190675068dSalnsn 	}
19200675068dSalnsn 
19210675068dSalnsn 	if ((compiler_common.flags & REGEX_ID_CHECK) && !(compiler_common.flags & REGEX_MATCH_BEGIN))
19220675068dSalnsn 		compiler_common.no_states = 4;
19230675068dSalnsn 	else if (!(compiler_common.flags & REGEX_ID_CHECK) && (compiler_common.flags & REGEX_MATCH_BEGIN))
19240675068dSalnsn 		compiler_common.no_states = 2;
19250675068dSalnsn 	else
19260675068dSalnsn 		compiler_common.no_states = 3;
19270675068dSalnsn 
19280675068dSalnsn 	compiler_common.machine->flags = compiler_common.flags;
19290675068dSalnsn 	compiler_common.machine->no_states = compiler_common.no_states;
19300675068dSalnsn 	compiler_common.machine->size = compiler_common.machine->no_states * compiler_common.terms_size;
19310675068dSalnsn 
19320675068dSalnsn 	/* Study the regular expression. */
19330675068dSalnsn 	empty_match_id = -1;
19340675068dSalnsn 	suggest_fast_forward = 1;
19350675068dSalnsn 	if (!(compiler_common.flags & REGEX_FAKE_MATCH_BEGIN)) {
19360675068dSalnsn 		CHECK(trace_transitions(0, &compiler_common));
19370675068dSalnsn 		while (compiler_common.stack.count > 0) {
19380675068dSalnsn 			ind = stack_pop(&compiler_common.stack)->value;
19390675068dSalnsn 			if (compiler_common.search_states[ind].type == 0) {
19400675068dSalnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_end);
19410675068dSalnsn 				suggest_fast_forward = 0;
19420675068dSalnsn 				empty_match_id = compiler_common.search_states[ind].value;
19430675068dSalnsn 			}
19440675068dSalnsn 			else if (compiler_common.search_states[ind].type > 0) {
19450675068dSalnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type != type_end);
19460675068dSalnsn 				if (compiler_common.dfa_transitions[ind].type == type_rng_start && compiler_common.dfa_transitions[ind].value)
19470675068dSalnsn 					suggest_fast_forward = 0;
19480675068dSalnsn 			}
19490675068dSalnsn 			compiler_common.search_states[ind].value = -1;
19500675068dSalnsn 		}
19510675068dSalnsn 	}
19520675068dSalnsn 	else {
19530675068dSalnsn 		SLJIT_ASSERT(compiler_common.dfa_transitions[1].type == type_newline);
19540675068dSalnsn 		CHECK(trace_transitions(1, &compiler_common));
19550675068dSalnsn 		while (compiler_common.stack.count > 0) {
19560675068dSalnsn 			ind = stack_pop(&compiler_common.stack)->value;
19570675068dSalnsn 			if (compiler_common.search_states[ind].type == 0) {
19580675068dSalnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_end);
19590675068dSalnsn 				suggest_fast_forward = 0;
19600675068dSalnsn 				empty_match_id = compiler_common.search_states[ind].value;
19610675068dSalnsn 			}
19620675068dSalnsn 			compiler_common.search_states[ind].value = -1;
19630675068dSalnsn 		}
19640675068dSalnsn 	}
19650675068dSalnsn 
19660675068dSalnsn 	/* Step 4.1: Generate entry. */
196748dfc815Salnsn 	CHECK(sljit_emit_enter(compiler_common.compiler, 0, 3, 5, 5, 0, 0, 0));
19680675068dSalnsn 
19690675068dSalnsn 	/* Copy arguments to their place. */
197048dfc815Salnsn 	EMIT_OP1(SLJIT_MOV, R_REGEX_MATCH, 0, SLJIT_S0, 0);
197148dfc815Salnsn 	EMIT_OP1(SLJIT_MOV, R_STRING, 0, SLJIT_S1, 0);
197248dfc815Salnsn 	EMIT_OP2(SLJIT_ADD, R_LENGTH, 0, SLJIT_S2, 0, SLJIT_IMM, 1);
19730675068dSalnsn 
19740675068dSalnsn 	/* Init global registers. */
19750675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current));
19760675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next));
19770675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head));
19780675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin));
19790675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_CURR_INDEX, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index));
19800675068dSalnsn 
19810675068dSalnsn 	/* Check whether the best match has already found in a previous frame. */
198248dfc815Salnsn 	EMIT_CMP(jump, SLJIT_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 0);
19830675068dSalnsn 	EMIT_JUMP(best_match_found_jump, SLJIT_JUMP);
19840675068dSalnsn 
19850675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
19860675068dSalnsn 	if (compiler_common.flags & REGEX_MATCH_VERBOSE)
19870675068dSalnsn 		printf("\n-----------------\nTrace\n-----------------\n");
19880675068dSalnsn #endif
19890675068dSalnsn 
19900675068dSalnsn 	/* Step 4.2: Generate code for state 0. */
19910675068dSalnsn 	EMIT_LABEL(label);
19920675068dSalnsn 	compiler_common.machine->entry_addrs[0] = (sljit_uw)label;
19930675068dSalnsn 
19940675068dSalnsn 	/* Swapping current and next. */
19950675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_STATE, 0);
19960675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, R_NEXT_STATE, 0);
19970675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, R_TEMP, 0);
19980675068dSalnsn 
19990675068dSalnsn 	/* Checking whether the best case needs to be updated. */
20000675068dSalnsn 	if (!(compiler_common.flags & REGEX_MATCH_END)) {
200148dfc815Salnsn 		EMIT_CMP(end_check_jump, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 1), SLJIT_IMM, -1);
20020675068dSalnsn 		EMIT_LABEL(end_check_label);
20030675068dSalnsn 	}
20040675068dSalnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), TERM_REL_OFFSET_OF(0, 1), SLJIT_IMM, -1);
20050675068dSalnsn 	EMIT_OP2(SLJIT_ADD, R_CURR_INDEX, 0, R_CURR_INDEX, 0, SLJIT_IMM, 1);
20060675068dSalnsn 
20070675068dSalnsn 	/* Checking whether best case has already found. */
20080675068dSalnsn 	if (!(compiler_common.flags & REGEX_MATCH_END) || (compiler_common.flags & REGEX_MATCH_BEGIN)) {
20090675068dSalnsn 		if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {
20100675068dSalnsn 			/* We can bail out if no more active states remain and R_BEST_BEGIN != -1. */
201148dfc815Salnsn 			EMIT_CMP(best_match_check_jump, SLJIT_NOT_EQUAL, R_BEST_BEGIN, 0, SLJIT_IMM, -1);
20120675068dSalnsn 		}
20130675068dSalnsn 		else {
20140675068dSalnsn 			/* We can bail out if no more active states remain (regardless of R_BEST_BEGIN). */
201548dfc815Salnsn 			EMIT_CMP(best_match_check_jump, SLJIT_EQUAL, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
20160675068dSalnsn 		}
20170675068dSalnsn 	}
20180675068dSalnsn 
20190675068dSalnsn 	EMIT_LABEL(start_label);
20200675068dSalnsn 	sljit_set_label(jump, start_label);
20210675068dSalnsn 
20220675068dSalnsn 	if (!(compiler_common.flags & REGEX_MATCH_BEGIN) && suggest_fast_forward) {
202348dfc815Salnsn 		EMIT_CMP(fast_forward_jump, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);
20240675068dSalnsn 	}
20250675068dSalnsn 
20260675068dSalnsn 	/* Loading the next character. */
2027*e52d5ebbSalnsn 	EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z, R_LENGTH, 0, R_LENGTH, 0, SLJIT_IMM, 1);
202848dfc815Salnsn 	EMIT_JUMP(length_is_zero_jump, SLJIT_EQUAL);
20290675068dSalnsn 
20300675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_STRING, 0);
20310675068dSalnsn #ifdef REGEX_USE_8BIT_CHARS
203248dfc815Salnsn 	EMIT_OP1(SLJIT_MOV_U8, R_CURR_CHAR, 0, SLJIT_MEM1(R_TEMP), 0);
20330675068dSalnsn 	EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, 1);
20340675068dSalnsn #else
20350675068dSalnsn 	EMIT_OP1(SLJIT_MOV_UH, R_CURR_CHAR, 0, SLJIT_MEM1(R_TEMP), 0);
20360675068dSalnsn 	EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, 2);
20370675068dSalnsn #endif
20380675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_STRING, 0, R_TEMP, 0);
20390675068dSalnsn 
20400675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
20410675068dSalnsn 	if (compiler_common.flags & REGEX_MATCH_VERBOSE) {
20420675068dSalnsn 		printf("(%3d): ", 0);
20430675068dSalnsn 		CHECK(trace_transitions(0, &compiler_common));
20440675068dSalnsn 		while (compiler_common.stack.count > 0) {
20450675068dSalnsn 			ind = stack_pop(&compiler_common.stack)->value;
20460675068dSalnsn 			if (compiler_common.search_states[ind].type >= 0)
20470675068dSalnsn 				printf("-> (%3d:%3d) ", compiler_common.search_states[ind].type, compiler_common.search_states[ind].value);
20480675068dSalnsn 			compiler_common.search_states[ind].value = -1;
20490675068dSalnsn 		}
20500675068dSalnsn 		printf("\n");
20510675068dSalnsn 	}
20520675068dSalnsn #endif
20530675068dSalnsn 
20540675068dSalnsn 	EMIT_LABEL(fast_forward_return_label);
20550675068dSalnsn 	if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {
20560675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 1);
20570675068dSalnsn 		if (!(compiler_common.flags & REGEX_MATCH_END)) {
205848dfc815Salnsn 			EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_BEST_BEGIN, 0, SLJIT_IMM, -1);
20590675068dSalnsn 		}
20600675068dSalnsn 
20610675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_INDEX, 0);
20620675068dSalnsn 		CHECK(compile_uncond_tran(&compiler_common, R_NEXT_STATE));
20630675068dSalnsn 		/* And branching to the first state. */
20640675068dSalnsn 		CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
20650675068dSalnsn 
20660675068dSalnsn 		if (!(compiler_common.flags & REGEX_MATCH_END)) {
20670675068dSalnsn 			EMIT_LABEL(label);
20680675068dSalnsn 			sljit_set_label(jump, label);
20690675068dSalnsn 		}
20700675068dSalnsn 	}
20710675068dSalnsn 	/* This is the case where we only have to reset the R_NEXT_HEAD. */
20720675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);
20730675068dSalnsn 	EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
20740675068dSalnsn 	CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
20750675068dSalnsn 
20760675068dSalnsn 	/* Fast-forward loop. */
20770675068dSalnsn 	if (fast_forward_jump) {
20780675068dSalnsn 		/* Quit from fast-forward loop. */
20790675068dSalnsn 		EMIT_LABEL(fast_forward_label);
20800675068dSalnsn 		EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_NEXT_HEAD, 0, SLJIT_IMM, 1);
20810675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_LENGTH, 0, R_NEXT_STATE, 0);
20820675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_STRING, 0, R_CURR_STATE, 0);
20830675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_CURR_INDEX, 0, R_NEXT_HEAD, 0);
20840675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next));
20850675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current));
20860675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head));
20870675068dSalnsn 
20880675068dSalnsn 		/* Update the start field of the locations. */
20890675068dSalnsn 		CHECK(trace_transitions(0, &compiler_common));
20900675068dSalnsn 		while (compiler_common.stack.count > 0) {
20910675068dSalnsn 			ind = stack_pop(&compiler_common.stack)->value;
20920675068dSalnsn 			if (compiler_common.search_states[ind].type >= 0) {
20930675068dSalnsn 				EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 2), R_TEMP, 0);
20940675068dSalnsn 			}
20950675068dSalnsn 			compiler_common.search_states[ind].value = -1;
20960675068dSalnsn 		}
20970675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);
20980675068dSalnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
20990675068dSalnsn 		sljit_set_label(jump, fast_forward_return_label);
21000675068dSalnsn 
21010675068dSalnsn 		/* Start fast-forward. */
21020675068dSalnsn 		EMIT_LABEL(label);
21030675068dSalnsn 		sljit_set_label(fast_forward_jump, label);
21040675068dSalnsn 
21050675068dSalnsn 		/* Moving everything to registers. */
21060675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next), R_NEXT_STATE, 0);
21070675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current), R_CURR_STATE, 0);
21080675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head), R_NEXT_HEAD, 0);
21090675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, R_LENGTH, 0);
21100675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, R_STRING, 0);
21110675068dSalnsn 		EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, R_CURR_INDEX, 0);
21120675068dSalnsn 
21130675068dSalnsn 		/* Fast forward mainloop. */
21140675068dSalnsn 		EMIT_LABEL(label);
2115*e52d5ebbSalnsn 		EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z, R_NEXT_STATE, 0, R_NEXT_STATE, 0, SLJIT_IMM, 1);
211648dfc815Salnsn 		EMIT_JUMP(fast_forward_jump, SLJIT_EQUAL);
21170675068dSalnsn 
21180675068dSalnsn #ifdef REGEX_USE_8BIT_CHARS
211948dfc815Salnsn 		EMIT_OP1(SLJIT_MOV_U8, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), 0);
21200675068dSalnsn 		EMIT_OP2(SLJIT_ADD, R_CURR_STATE, 0, R_CURR_STATE, 0, SLJIT_IMM, 1);
21210675068dSalnsn #else
21220675068dSalnsn 		EMIT_OP1(SLJIT_MOV_UH, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), 0);
21230675068dSalnsn 		EMIT_OP2(SLJIT_ADD, R_CURR_STATE, 0, R_CURR_STATE, 0, SLJIT_IMM, 2);
21240675068dSalnsn #endif
21250675068dSalnsn 
21260675068dSalnsn 		CHECK(trace_transitions(0, &compiler_common));
21270675068dSalnsn 		CHECK(compile_leave_fast_forward(&compiler_common, fast_forward_label));
21280675068dSalnsn 
21290675068dSalnsn 		EMIT_OP2(SLJIT_ADD, R_NEXT_HEAD, 0, R_NEXT_HEAD, 0, SLJIT_IMM, 1);
21300675068dSalnsn 		EMIT_JUMP(jump, SLJIT_JUMP);
21310675068dSalnsn 		sljit_set_label(jump, label);
21320675068dSalnsn 
21330675068dSalnsn 		/* String is finished. */
21340675068dSalnsn 		EMIT_LABEL(label);
21350675068dSalnsn 		sljit_set_label(fast_forward_jump, label);
21360675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index), R_NEXT_HEAD, 0);
21370675068dSalnsn 		EMIT_JUMP(fast_forward_jump, SLJIT_JUMP);
21380675068dSalnsn 	}
21390675068dSalnsn 
21400675068dSalnsn 	/* End check. */
21410675068dSalnsn 	if (end_check_jump) {
21420675068dSalnsn 		EMIT_LABEL(label);
21430675068dSalnsn 		sljit_set_label(end_check_jump, label);
21440675068dSalnsn 
21450675068dSalnsn 		if (!(compiler_common.flags & REGEX_MATCH_NON_GREEDY) || !(compiler_common.flags & REGEX_MATCH_BEGIN)) {
21460675068dSalnsn 			CHECK(compile_end_check(&compiler_common, end_check_label));
21470675068dSalnsn 		}
21480675068dSalnsn 		else {
21490675068dSalnsn 			/* Since we leave, we do not need to update the R_BEST_BEGIN. */
21500675068dSalnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);
21510675068dSalnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);
21520675068dSalnsn 			if (compiler_common.flags & REGEX_ID_CHECK) {
21530675068dSalnsn 				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));
21540675068dSalnsn 			}
21550675068dSalnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 1);
21560675068dSalnsn 			EMIT_JUMP(non_greedy_end_jump, SLJIT_JUMP);
21570675068dSalnsn 		}
21580675068dSalnsn 	}
21590675068dSalnsn 
21600675068dSalnsn 	/* Finish check. */
21610675068dSalnsn 	if (best_match_check_jump) {
21620675068dSalnsn 		EMIT_LABEL(label);
21630675068dSalnsn 		sljit_set_label(best_match_check_jump, label);
21640675068dSalnsn 
21650675068dSalnsn 		if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {
216648dfc815Salnsn 			EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
21670675068dSalnsn 			sljit_set_label(jump, start_label);
21680675068dSalnsn 		}
21690675068dSalnsn 		EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 1);
21700675068dSalnsn 	}
21710675068dSalnsn 
21720675068dSalnsn 	/* Leaving matching and storing the necessary values. */
21730675068dSalnsn 	EMIT_LABEL(label);
21740675068dSalnsn 	sljit_set_label(length_is_zero_jump, label);
21750675068dSalnsn 	if (non_greedy_end_jump)
21760675068dSalnsn 		sljit_set_label(non_greedy_end_jump, label);
21770675068dSalnsn 
21780675068dSalnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index), R_CURR_INDEX, 0);
21790675068dSalnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head), R_NEXT_HEAD, 0);
21800675068dSalnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next), R_NEXT_STATE, 0);
21810675068dSalnsn 	EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current), R_CURR_STATE, 0);
21820675068dSalnsn 
21830675068dSalnsn 	/* Exit from JIT. */
21840675068dSalnsn 	EMIT_LABEL(label);
21850675068dSalnsn 	sljit_set_label(best_match_found_jump, label);
21860675068dSalnsn 	if (fast_forward_jump)
21870675068dSalnsn 		sljit_set_label(fast_forward_jump, label);
21880675068dSalnsn 	CHECK(sljit_emit_return(compiler_common.compiler, SLJIT_UNUSED, 0, 0));
21890675068dSalnsn 
219048dfc815Salnsn 	for (ind = 1; ind < compiler_common.dfa_size - 1; ind++) {
21910675068dSalnsn 		if (compiler_common.search_states[ind].type >= 0) {
21920675068dSalnsn 			SLJIT_ASSERT(compiler_common.search_states[ind].type < compiler_common.terms_size);
21930675068dSalnsn 			EMIT_LABEL(label);
21940675068dSalnsn 			compiler_common.machine->entry_addrs[compiler_common.search_states[ind].type] = (sljit_uw)label;
21950675068dSalnsn 
21960675068dSalnsn 			if (compiler_common.dfa_transitions[ind].type == type_char) {
219748dfc815Salnsn 				EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, compiler_common.dfa_transitions[ind].value);
21980675068dSalnsn 			}
21990675068dSalnsn 			else if (compiler_common.dfa_transitions[ind].type == type_rng_start) {
22000675068dSalnsn 				ind = compile_range_check(&compiler_common, ind);
22010675068dSalnsn 				CHECK(!ind);
22020675068dSalnsn 			}
22030675068dSalnsn 			else {
22040675068dSalnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_newline);
22050675068dSalnsn 				CHECK(compile_newline_check(&compiler_common, ind));
22060675068dSalnsn 			}
22070675068dSalnsn 
22080675068dSalnsn 			CHECK(trace_transitions(ind, &compiler_common));
22090675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
22100675068dSalnsn 			if (compiler_common.flags & REGEX_MATCH_VERBOSE)
22110675068dSalnsn 				printf("(%3d): ", compiler_common.search_states[ind].type);
22120675068dSalnsn #endif
22130675068dSalnsn 			CHECK(compile_cond_tran(&compiler_common, compiler_common.search_states[ind].type));
22140675068dSalnsn 
22150675068dSalnsn 			if (compiler_common.dfa_transitions[ind].type == type_char) {
22160675068dSalnsn 				EMIT_LABEL(label);
22170675068dSalnsn 				sljit_set_label(jump, label);
22180675068dSalnsn 			}
22190675068dSalnsn 			else if (compiler_common.dfa_transitions[ind].type == type_rng_end) {
22200675068dSalnsn 				EMIT_LABEL(label);
22210675068dSalnsn 				range_set_label(compiler_common.range_jump_list, label);
22220675068dSalnsn 			}
22230675068dSalnsn 			else {
22240675068dSalnsn 				SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_newline);
22250675068dSalnsn 			}
22260675068dSalnsn 
22270675068dSalnsn 			/* Branch to the next item in the list. */
22280675068dSalnsn 			EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 1));
22290675068dSalnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 1), SLJIT_IMM, -1);
22300675068dSalnsn 			CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));
22310675068dSalnsn 		}
22320675068dSalnsn 	}
22330675068dSalnsn 
22340675068dSalnsn 	if (ind == compiler_common.dfa_size - 1) {
22350675068dSalnsn 		/* Generate an init stub function. */
22360675068dSalnsn 		EMIT_LABEL(label);
223748dfc815Salnsn 		CHECK(sljit_emit_enter(compiler_common.compiler, 0, 2, 3, 3, 0, 0, 0));
22380675068dSalnsn 
22390675068dSalnsn 		if (empty_match_id == -1) {
224048dfc815Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, -1);
224148dfc815Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_IMM, 0);
22420675068dSalnsn 		}
22430675068dSalnsn 		else {
224448dfc815Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);
224548dfc815Salnsn 			EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_IMM, empty_match_id);
22460675068dSalnsn 		}
22470675068dSalnsn 
224848dfc815Salnsn 		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);
22490675068dSalnsn 
22500675068dSalnsn 		if (!(compiler_common.flags & REGEX_MATCH_NON_GREEDY) || empty_match_id == -1) {
22510675068dSalnsn 			/* The else is a really rare event, so we still generate an empty function instead of a runtime pointer check. */
225248dfc815Salnsn 			SLJIT_ASSERT(R_CURR_STATE == SLJIT_S0);
22530675068dSalnsn 			if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {
22540675068dSalnsn 				/* R_CURR_INDEX (put to R_TEMP) is zero. */
22550675068dSalnsn 				EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, 0);
22560675068dSalnsn 			}
22570675068dSalnsn 			CHECK(compile_uncond_tran(&compiler_common, R_CURR_STATE));
22580675068dSalnsn 		}
22590675068dSalnsn 		else {
22600675068dSalnsn 			EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);
22610675068dSalnsn 		}
22620675068dSalnsn 		CHECK(sljit_emit_return(compiler_common.compiler, SLJIT_MOV, R_NEXT_HEAD, 0));
22630675068dSalnsn 
22640675068dSalnsn 		compiler_common.machine->continue_match = sljit_generate_code(compiler_common.compiler);
22650675068dSalnsn #ifndef SLJIT_INDIRECT_CALL
226608987447Salnsn 		compiler_common.machine->u.init_match = (void*)(sljit_sw)sljit_get_label_addr(label);
22670675068dSalnsn #else
22680675068dSalnsn 		sljit_set_function_context(&compiler_common.machine->u.init_match, &compiler_common.machine->context, sljit_get_label_addr(label), regex_compile);
22690675068dSalnsn #endif
22700675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
22710675068dSalnsn 		if (compiler_common.flags & REGEX_MATCH_VERBOSE)
22720675068dSalnsn 			printf("Continue match: %p Init match: %p\n\n", compiler_common.machine->continue_match, compiler_common.machine->u.init_match);
22730675068dSalnsn #endif
22740675068dSalnsn 		if (compiler_common.machine->continue_match) {
22750675068dSalnsn 			for (ind = 0; ind < compiler_common.terms_size; ++ind)
22760675068dSalnsn 				compiler_common.machine->entry_addrs[ind] = sljit_get_label_addr((struct sljit_label*)compiler_common.machine->entry_addrs[ind]);
22770675068dSalnsn 			done = 1;
22780675068dSalnsn 		}
22790675068dSalnsn 	}
22800675068dSalnsn 	END_GUARD
22810675068dSalnsn 
22820675068dSalnsn 	stack_destroy(&compiler_common.stack);
22830675068dSalnsn 	stack_destroy(&compiler_common.depth);
228448dfc815Salnsn 	SLJIT_FREE(compiler_common.dfa_transitions, NULL);
228548dfc815Salnsn 	SLJIT_FREE(compiler_common.search_states, NULL);
22860675068dSalnsn 	if (compiler_common.range_jump_list)
228748dfc815Salnsn 		SLJIT_FREE(compiler_common.range_jump_list, NULL);
22880675068dSalnsn 	if (compiler_common.compiler)
22890675068dSalnsn 		sljit_free_compiler(compiler_common.compiler);
22900675068dSalnsn 	if (done)
22910675068dSalnsn 		return compiler_common.machine;
22920675068dSalnsn 
22930675068dSalnsn 	if (compiler_common.machine) {
229448dfc815Salnsn 		SLJIT_FREE(compiler_common.machine, NULL);
22950675068dSalnsn 	}
22960675068dSalnsn 	if (error)
22970675068dSalnsn 		*error = REGEX_MEMORY_ERROR;
22980675068dSalnsn 	return NULL;
22990675068dSalnsn }
23000675068dSalnsn 
23010675068dSalnsn #undef TERM_OFFSET_OF
23020675068dSalnsn #undef EMIT_OP1
23030675068dSalnsn #undef EMIT_OP2
23040675068dSalnsn #undef EMIT_LABEL
23050675068dSalnsn #undef EMIT_JUMP
23060675068dSalnsn #undef EMIT_CMP
23070675068dSalnsn #undef BEGIN_GUARD
23080675068dSalnsn #undef END_GUARD
23090675068dSalnsn #undef CHECK
23100675068dSalnsn 
regex_free_machine(struct regex_machine * machine)23110675068dSalnsn void regex_free_machine(struct regex_machine *machine)
23120675068dSalnsn {
23130675068dSalnsn 	sljit_free_code(machine->continue_match);
231448dfc815Salnsn 	SLJIT_FREE(machine, NULL);
23150675068dSalnsn }
23160675068dSalnsn 
regex_get_platform_name(void)23170675068dSalnsn const char* regex_get_platform_name(void)
23180675068dSalnsn {
23190675068dSalnsn 	return sljit_get_platform_name();
23200675068dSalnsn }
23210675068dSalnsn 
23220675068dSalnsn /* --------------------------------------------------------------------- */
23230675068dSalnsn /*  Mathching utilities                                                  */
23240675068dSalnsn /* --------------------------------------------------------------------- */
23250675068dSalnsn 
regex_begin_match(struct regex_machine * machine)23260675068dSalnsn struct regex_match* regex_begin_match(struct regex_machine *machine)
23270675068dSalnsn {
232808987447Salnsn 	sljit_sw *ptr1;
232908987447Salnsn 	sljit_sw *ptr2;
233008987447Salnsn 	sljit_sw *end;
233108987447Salnsn 	sljit_sw *entry_addrs;
23320675068dSalnsn 
233348dfc815Salnsn 	struct regex_match *match = (struct regex_match*)SLJIT_MALLOC(sizeof(struct regex_match) + (machine->size * 2 - 1) * sizeof(sljit_sw), NULL);
23340675068dSalnsn 	if (!match)
23350675068dSalnsn 		return NULL;
23360675068dSalnsn 
23370675068dSalnsn 	ptr1 = match->states;
23380675068dSalnsn 	ptr2 = match->states + machine->size;
23390675068dSalnsn 	end = ptr2;
234008987447Salnsn 	entry_addrs = (sljit_sw*)machine->entry_addrs;
23410675068dSalnsn 
23420675068dSalnsn 	match->current = ptr1;
23430675068dSalnsn 	match->next = ptr2;
23440675068dSalnsn 	match->head = 0;
23450675068dSalnsn 	match->machine = machine;
23460675068dSalnsn 
23470675068dSalnsn 	/* Init machine states. */
23480675068dSalnsn 	switch (machine->no_states) {
23490675068dSalnsn 	case 2:
23500675068dSalnsn 		while (ptr1 < end) {
23510675068dSalnsn 			*ptr1++ = *entry_addrs;
23520675068dSalnsn 			*ptr2++ = *entry_addrs++;
23530675068dSalnsn 			*ptr1++ = -1;
23540675068dSalnsn 			*ptr2++ = -1;
23550675068dSalnsn 		}
23560675068dSalnsn 		break;
23570675068dSalnsn 
23580675068dSalnsn 	case 3:
23590675068dSalnsn 		while (ptr1 < end) {
23600675068dSalnsn 			*ptr1++ = *entry_addrs;
23610675068dSalnsn 			*ptr2++ = *entry_addrs++;
23620675068dSalnsn 			*ptr1++ = -1;
23630675068dSalnsn 			*ptr2++ = -1;
23640675068dSalnsn 			*ptr1++ = 0;
23650675068dSalnsn 			*ptr2++ = 0;
23660675068dSalnsn 		}
23670675068dSalnsn 		break;
23680675068dSalnsn 
23690675068dSalnsn 	case 4:
23700675068dSalnsn 		while (ptr1 < end) {
23710675068dSalnsn 			*ptr1++ = *entry_addrs;
23720675068dSalnsn 			*ptr2++ = *entry_addrs++;
23730675068dSalnsn 			*ptr1++ = -1;
23740675068dSalnsn 			*ptr2++ = -1;
23750675068dSalnsn 			*ptr1++ = 0;
23760675068dSalnsn 			*ptr2++ = 0;
23770675068dSalnsn 			*ptr1++ = 0;
23780675068dSalnsn 			*ptr2++ = 0;
23790675068dSalnsn 		}
23800675068dSalnsn 		break;
23810675068dSalnsn 
23820675068dSalnsn 	default:
2383*e52d5ebbSalnsn 		SLJIT_UNREACHABLE();
23840675068dSalnsn 		break;
23850675068dSalnsn 	}
23860675068dSalnsn 
23870675068dSalnsn 	SLJIT_ASSERT(ptr1 == end);
23880675068dSalnsn 
23890675068dSalnsn 	match->u.continue_match = machine->continue_match;
23900675068dSalnsn 
23910675068dSalnsn 	regex_reset_match(match);
23920675068dSalnsn 	return match;
23930675068dSalnsn }
23940675068dSalnsn 
regex_reset_match(struct regex_match * match)23950675068dSalnsn void regex_reset_match(struct regex_match *match)
23960675068dSalnsn {
23970675068dSalnsn 	struct regex_machine *machine = match->machine;
239808987447Salnsn 	sljit_sw current, ind;
239908987447Salnsn 	sljit_sw *current_ptr;
24000675068dSalnsn 
24010675068dSalnsn 	match->best_end = 0;
24020675068dSalnsn 	match->fast_quit = 0;
24030675068dSalnsn 	match->fast_forward = 0;
24040675068dSalnsn 
24050675068dSalnsn 	if (match->head != 0) {
24060675068dSalnsn 		/* Clear the current state. */
24070675068dSalnsn 		current = match->head;
24080675068dSalnsn 		current_ptr = match->current;
24090675068dSalnsn 		do {
241008987447Salnsn 			ind = (current / sizeof(sljit_sw)) + 1;
24110675068dSalnsn 			current = current_ptr[ind];
24120675068dSalnsn 			current_ptr[ind] = -1;
24130675068dSalnsn 		} while (current != 0);
24140675068dSalnsn 	}
24150675068dSalnsn 	match->head = machine->u.call_init(match->current, match);
24160675068dSalnsn }
24170675068dSalnsn 
regex_free_match(struct regex_match * match)24180675068dSalnsn void regex_free_match(struct regex_match *match)
24190675068dSalnsn {
242048dfc815Salnsn 	SLJIT_FREE(match, NULL);
24210675068dSalnsn }
24220675068dSalnsn 
regex_continue_match(struct regex_match * match,const regex_char_t * input_string,int length)24230675068dSalnsn void regex_continue_match(struct regex_match *match, const regex_char_t *input_string, int length)
24240675068dSalnsn {
24250675068dSalnsn 	match->u.call_continue(match, input_string, length);
24260675068dSalnsn }
24270675068dSalnsn 
regex_get_result(struct regex_match * match,int * end,int * id)24280675068dSalnsn int regex_get_result(struct regex_match *match, int *end, int *id)
24290675068dSalnsn {
24300675068dSalnsn 	int flags = match->machine->flags;
243108987447Salnsn 	sljit_sw no_states;
24320675068dSalnsn 
24330675068dSalnsn 	*end = match->best_end;
24340675068dSalnsn 	*id = match->best_id;
24350675068dSalnsn 	if (!(flags & (REGEX_MATCH_END | REGEX_FAKE_MATCH_END)))
24360675068dSalnsn 		return match->best_begin;
24370675068dSalnsn 
24380675068dSalnsn 	if (flags & REGEX_FAKE_MATCH_END) {
24390675068dSalnsn 		SLJIT_ASSERT(!(flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END)));
24400675068dSalnsn 		if (match->best_begin != -1)
24410675068dSalnsn 			return match->best_begin;
24420675068dSalnsn 
24430675068dSalnsn 		no_states = match->machine->no_states;
24440675068dSalnsn 		if (match->current[no_states + 1] == -1)
24450675068dSalnsn 			return -1;
24460675068dSalnsn 		if (flags & REGEX_ID_CHECK)
24470675068dSalnsn 			*id = match->current[no_states + 3];
24480675068dSalnsn 		if (!(flags & REGEX_FAKE_MATCH_BEGIN))
24490675068dSalnsn 			*end = match->index - 1;
24500675068dSalnsn 		else
24510675068dSalnsn 			*end = match->index - 2;
24520675068dSalnsn 		return match->current[no_states + 2];
24530675068dSalnsn 	}
24540675068dSalnsn 	else {
24550675068dSalnsn 		/* Check the status of the last code. */
24560675068dSalnsn 		if (!(flags & REGEX_MATCH_BEGIN)) {
24570675068dSalnsn 			/* No shortcut in this case. */
24580675068dSalnsn 			if (!(flags & REGEX_ID_CHECK)) {
24590675068dSalnsn 				if (match->current[1] == -1)
24600675068dSalnsn 					return -1;
24610675068dSalnsn 				*end = match->index - 1;
24620675068dSalnsn 				return match->current[2];
24630675068dSalnsn 			}
24640675068dSalnsn 
24650675068dSalnsn 			if (match->current[1] == -1)
24660675068dSalnsn 				return -1;
24670675068dSalnsn 			*end = match->index - 1;
24680675068dSalnsn 			*id = match->current[3];
24690675068dSalnsn 			return match->current[2];
24700675068dSalnsn 		}
24710675068dSalnsn 
24720675068dSalnsn 		/* Shortcut is possible in this case. */
24730675068dSalnsn 		if (!(flags & REGEX_ID_CHECK)) {
24740675068dSalnsn 			if (match->current[1] == -1 || match->head == -1)
24750675068dSalnsn 				return -1;
24760675068dSalnsn 			*end = match->index - 1;
24770675068dSalnsn 			return 0;
24780675068dSalnsn 		}
24790675068dSalnsn 
24800675068dSalnsn 		if (match->current[1] == -1 || match->head == -1)
24810675068dSalnsn 			return -1;
24820675068dSalnsn 		*end = match->index - 1;
24830675068dSalnsn 		*id = match->current[2];
24840675068dSalnsn 		return 0;
24850675068dSalnsn 	}
24860675068dSalnsn }
24870675068dSalnsn 
regex_is_match_finished(struct regex_match * match)24880675068dSalnsn int regex_is_match_finished(struct regex_match *match)
24890675068dSalnsn {
24900675068dSalnsn 	return match->fast_quit;
24910675068dSalnsn }
24920675068dSalnsn 
24930675068dSalnsn #ifdef REGEX_MATCH_VERBOSE
regex_continue_match_debug(struct regex_match * match,const regex_char_t * input_string,int length)24940675068dSalnsn void regex_continue_match_debug(struct regex_match *match, const regex_char_t *input_string, int length)
24950675068dSalnsn {
249608987447Salnsn 	sljit_sw *ptr;
249708987447Salnsn 	sljit_sw *end;
249808987447Salnsn 	sljit_sw count;
24990675068dSalnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
250008987447Salnsn 	sljit_sw current;
25010675068dSalnsn #endif
250208987447Salnsn 	sljit_sw no_states = match->machine->no_states;
250308987447Salnsn 	sljit_sw len = match->machine->size;
25040675068dSalnsn 
25050675068dSalnsn 	while (length > 0) {
25060675068dSalnsn 		match->u.call_continue(match, input_string, 1);
25070675068dSalnsn 
25080675068dSalnsn 		if (match->fast_forward) {
25090675068dSalnsn 			if (match->machine->flags & REGEX_MATCH_VERBOSE)
25100675068dSalnsn 				printf("fast forward\n");
25110675068dSalnsn 		}
25120675068dSalnsn 
25130675068dSalnsn 		/* Verbose (first). */
25140675068dSalnsn 		if (match->machine->flags & REGEX_MATCH_VERBOSE) {
25150675068dSalnsn 			ptr = match->current;
25160675068dSalnsn 			end = ptr + len;
25170675068dSalnsn 			count = 0;
25180675068dSalnsn 			printf("'%c' (%3ld->%3ld [%3ld]) ", *input_string, (long)match->best_begin, (long)match->best_end, (long)match->best_id);
25190675068dSalnsn 			while (ptr < end) {
25200675068dSalnsn 				printf("[%3ld:", (long)count++);
25210675068dSalnsn 				switch (no_states) {
25220675068dSalnsn 				case 2:
25230675068dSalnsn 					if (ptr[1] != -1)
25240675068dSalnsn 						printf("+] ");
25250675068dSalnsn 					else
25260675068dSalnsn 						printf(" ] ");
25270675068dSalnsn 					break;
25280675068dSalnsn 
25290675068dSalnsn 				case 3:
25300675068dSalnsn 					if (ptr[1] != -1)
25310675068dSalnsn 						printf("+,%3ld] ", (long)ptr[2]);
25320675068dSalnsn 					else
25330675068dSalnsn 						printf(" ,XXX] ");
25340675068dSalnsn 					break;
25350675068dSalnsn 
25360675068dSalnsn 				case 4:
25370675068dSalnsn 					if (ptr[1] != -1)
25380675068dSalnsn 						printf("+,%3ld,%3ld] ", (long)ptr[2], (long)ptr[3]);
25390675068dSalnsn 					else
25400675068dSalnsn 						printf(" ,XXX,XXX] ");
25410675068dSalnsn 					break;
25420675068dSalnsn 				}
25430675068dSalnsn 				ptr += no_states;
25440675068dSalnsn 			}
25450675068dSalnsn 			printf("\n");
25460675068dSalnsn 		}
25470675068dSalnsn 
25480675068dSalnsn #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
25490675068dSalnsn 		/* Sanity check (later). */
25500675068dSalnsn 		ptr = match->next;
25510675068dSalnsn 		end = ptr + len;
25520675068dSalnsn 		while (ptr < end) {
25530675068dSalnsn 			SLJIT_ASSERT(ptr[1] == -1);
25540675068dSalnsn 			ptr += no_states;
25550675068dSalnsn 		}
25560675068dSalnsn 
25570675068dSalnsn 		/* Check number of active elements. */
25580675068dSalnsn 		ptr = match->current + no_states;
25590675068dSalnsn 		end = ptr + len - no_states;
25600675068dSalnsn 		count = 0;
25610675068dSalnsn 		while (ptr < end) {
25620675068dSalnsn 			if (ptr[1] != -1)
25630675068dSalnsn 				count++;
25640675068dSalnsn 			ptr += no_states;
25650675068dSalnsn 		}
25660675068dSalnsn 
25670675068dSalnsn 		/* Check chain list. */
25680675068dSalnsn 		current = match->head;
25690675068dSalnsn 		ptr = match->current;
25700675068dSalnsn 		while (current != 0) {
257108987447Salnsn 			SLJIT_ASSERT(current >= 0 && current < len * sizeof(sljit_sw));
257208987447Salnsn 			SLJIT_ASSERT((current % (no_states * sizeof(sljit_sw))) == 0);
25730675068dSalnsn 			SLJIT_ASSERT(count > 0);
257408987447Salnsn 			current = ptr[(current / sizeof(sljit_sw)) + 1];
25750675068dSalnsn 			count--;
25760675068dSalnsn 		}
25770675068dSalnsn 		SLJIT_ASSERT(count == 0);
25780675068dSalnsn #endif
25790675068dSalnsn 
25800675068dSalnsn 		if (match->fast_quit) {
25810675068dSalnsn 			/* the machine has stopped working. */
25820675068dSalnsn 			if (match->machine->flags & REGEX_MATCH_VERBOSE)
25830675068dSalnsn 				printf("Best match has found\n");
25840675068dSalnsn 			break;
25850675068dSalnsn 		}
25860675068dSalnsn 
25870675068dSalnsn 		input_string++;
25880675068dSalnsn 		length--;
25890675068dSalnsn 	}
25900675068dSalnsn }
25910675068dSalnsn #endif
2592