-int re_set_syntax(int syntax);
-/* This sets the syntax to use and returns the previous syntax. The
- syntax is specified by a bit mask of the above defined bits. */
-
-SilcResult re_compile_pattern(char *regex, int regex_size, SilcRegex compiled);
-/* This compiles the regexp (given in regex and length in regex_size).
- This returns NULL if the regexp compiled successfully, and an error
- message if an error was encountered. The buffer field must be
- initialized to a memory area allocated by malloc (or to NULL) before
- use, and the allocated field must be set to its length (or 0 if buffer is
- NULL). Also, the translate field must be set to point to a valid
- translation table, or NULL if it is not used. */
-
-int re_match(SilcRegex compiled, char *string, int size, int pos,
- regexp_registers_t regs, unsigned int flags);
-/* This tries to match the regexp against the string. This returns the
- length of the matched portion, or -1 if the pattern could not be
- matched and -2 if an error (such as failure stack overflow) is
- encountered. */
-
-int re_match_2(SilcRegex compiled, char *string1, int size1,
- char *string2, int size2, int pos, regexp_registers_t regs,
- int mstop, unsigned int flags);
-/* This tries to match the regexp to the concatenation of string1 and
- string2. This returns the length of the matched portion, or -1 if the
- pattern could not be matched and -2 if an error (such as failure stack
- overflow) is encountered. */
-
-int re_search(SilcRegex compiled, char *string, int size, int startpos,
- int range, regexp_registers_t regs, unsigned int flags);
-/* This rearches for a substring matching the regexp. This returns the first
- index at which a match is found. range specifies at how many positions to
- try matching; positive values indicate searching forwards, and negative
- values indicate searching backwards. mstop specifies the offset beyond
- which a match must not go. This returns -1 if no match is found, and
- -2 if an error (such as failure stack overflow) is encountered. */
-
-int re_search_2(SilcRegex compiled, char *string1, int size1,
- char *string2, int size2, int startpos, int range,
- regexp_registers_t regs, int mstop, unsigned int flags);
-/* This is like re_search, but search from the concatenation of string1 and
- string2. */
-
-void re_compile_fastmap(SilcRegex compiled);
-/* This computes the fastmap for the regexp. For this to have any effect,
- the calling program must have initialized the fastmap field to point
- to an array of 256 characters. */
-
-#define MACRO_BEGIN do {
-#define MACRO_END } while (0)
+/* The original code blithely assumed that sizeof(short) == 2. Not
+ * always true. Original instances of "(short)x" were replaced by
+ * SHORT(x), where SHORT is #defined below. */
+
+#define SHORT(x) ((x) & 0x8000 ? (x) - 0x10000 : (x))
+
+/* The stack implementation is taken from an idea by Andrew Kuchling.
+ * It's a doubly linked list of arrays. The advantages of this over a
+ * simple linked list are that the number of mallocs required are
+ * reduced. It also makes it possible to statically allocate enough
+ * space so that small patterns don't ever need to call malloc.
+ *
+ * The advantages over a single array is that is periodically
+ * realloced when more space is needed is that we avoid ever copying
+ * the stack. */
+
+/* item_t is the basic stack element. Defined as a union of
+ * structures so that both registers, failure points, and counters can
+ * be pushed/popped from the stack. There's nothing built into the
+ * item to keep track of whether a certain stack item is a register, a
+ * failure point, or a counter. */
+
+typedef union item_t
+{
+ struct
+ {
+ int num;
+ int level;
+ unsigned char *start;
+ unsigned char *end;
+ } reg;
+ struct
+ {
+ int count;
+ int level;
+ int phantom;
+ unsigned char *code;
+ unsigned char *text;
+ } fail;
+ struct
+ {
+ int num;
+ int level;
+ int count;
+ } cntr;
+} item_t;
+
+#define STACK_PAGE_SIZE 256
+#define NUM_REGISTERS 256
+
+/* A 'page' of stack items. */
+
+typedef struct item_page_t
+{
+ item_t items[STACK_PAGE_SIZE];
+ struct item_page_t *prev;
+ struct item_page_t *next;
+} item_page_t;
+
+typedef struct match_state
+{
+ /* The number of registers that have been pushed onto the stack
+ * since the last failure point. */
+
+ int count;
+
+ /* Used to control when registers need to be pushed onto the
+ * stack. */
+
+ int level;
+
+ /* The number of failure points on the stack. */
+
+ int point;
+
+ /* Storage for the registers. Each register consists of two
+ * pointers to characters. So register N is represented as
+ * start[N] and end[N]. The pointers must be converted to
+ * offsets from the beginning of the string before returning the
+ * registers to the calling program. */
+
+ unsigned char *start[NUM_REGISTERS];
+ unsigned char *end[NUM_REGISTERS];
+
+ /* Keeps track of whether a register has changed recently. */
+
+ int changed[NUM_REGISTERS];
+
+ /* Structure to encapsulate the stack. */
+ struct
+ {
+ /* index into the current page. If index == 0 and you need
+ * to pop an item, move to the previous page and set index
+ * = STACK_PAGE_SIZE - 1. Otherwise decrement index to
+ * push a page. If index == STACK_PAGE_SIZE and you need
+ * to push a page move to the next page and set index =
+ * 0. If there is no new next page, allocate a new page
+ * and link it in. Otherwise, increment index to push a
+ * page. */
+
+ int index;
+ item_page_t *current; /* Pointer to the current page. */
+ item_page_t first; /* First page is statically allocated. */
+ } stack;
+} match_state;
+
+/* Initialize a state object */
+
+/* #define NEW_STATE(state) \ */
+/* memset(&state, 0, (void *)(&state.stack) - (void *)(&state)); \ */
+/* state.stack.current = &state.stack.first; \ */
+/* state.stack.first.prev = NULL; \ */
+/* state.stack.first.next = NULL; \ */
+/* state.stack.index = 0; \ */
+/* state.level = 1 */
+
+#define NEW_STATE(state, nregs) \
+ { \
+ int i; \
+ for (i = 0; i < nregs; i++) \
+ { \
+ state.start[i] = NULL; \
+ state.end[i] = NULL; \
+ state.changed[i] = 0; \
+ } \
+ state.stack.current = &state.stack.first; \
+ state.stack.first.prev = NULL; \
+ state.stack.first.next = NULL; \
+ state.stack.index = 0; \
+ state.level = 1; \
+ state.count = 0; \
+ state.level = 0; \
+ state.point = 0; \
+ }
+
+/* Free any memory that might have been malloc'd */
+
+#define FREE_STATE(state) \
+ while(state.stack.first.next != NULL) \
+ { \
+ state.stack.current = state.stack.first.next; \
+ state.stack.first.next = state.stack.current->next; \
+ silc_sfree(bufp->rstack, state.stack.current); \
+ }
+
+/* Discard the top 'count' stack items. */
+
+#define STACK_DISCARD(stack, count, on_error) \
+ stack.index -= count; \
+ while (stack.index < 0) \
+ { \
+ if (stack.current->prev == NULL) \
+ on_error; \
+ stack.current = stack.current->prev; \
+ stack.index += STACK_PAGE_SIZE; \
+ }
+
+/* Store a pointer to the previous item on the stack. Used to pop an
+ * item off of the stack. */
+
+#define STACK_PREV(stack, top, on_error) \
+ if (stack.index == 0) \
+ { \
+ if (stack.current->prev == NULL) \
+ on_error; \
+ stack.current = stack.current->prev; \
+ stack.index = STACK_PAGE_SIZE - 1; \
+ } \
+ else \
+ { \
+ stack.index--; \
+ } \
+ top = &(stack.current->items[stack.index])
+
+/* Store a pointer to the next item on the stack. Used to push an item
+ * on to the stack. */
+
+#define STACK_NEXT(stack, top, on_error) \
+ if (stack.index == STACK_PAGE_SIZE) \
+ { \
+ if (stack.current->next == NULL) \
+ { \
+ stack.current->next = \
+ (item_page_t *)silc_smalloc(bufp->rstack, sizeof(item_page_t)); \
+ if (stack.current->next == NULL) \
+ on_error; \
+ stack.current->next->prev = stack.current; \
+ stack.current->next->next = NULL; \
+ } \
+ stack.current = stack.current->next; \
+ stack.index = 0; \
+ } \
+ top = &(stack.current->items[stack.index++])
+
+/* Store a pointer to the item that is 'count' items back in the
+ * stack. STACK_BACK(stack, top, 1, on_error) is equivalent to
+ * STACK_TOP(stack, top, on_error). */
+
+#define STACK_BACK(stack, top, count, on_error) \
+ { \
+ int index; \
+ item_page_t *current; \
+ current = stack.current; \
+ index = stack.index - (count); \
+ while (index < 0) \
+ { \
+ if (current->prev == NULL) \
+ on_error; \
+ current = current->prev; \
+ index += STACK_PAGE_SIZE; \
+ } \
+ top = &(current->items[index]); \
+ }
+
+/* Store a pointer to the top item on the stack. Execute the
+ * 'on_error' code if there are no items on the stack. */
+
+#define STACK_TOP(stack, top, on_error) \
+ if (stack.index == 0) \
+ { \
+ if (stack.current->prev == NULL) \
+ on_error; \
+ top = &(stack.current->prev->items[STACK_PAGE_SIZE - 1]); \
+ } \
+ else \
+ { \
+ top = &(stack.current->items[stack.index - 1]); \
+ }
+
+/* Test to see if the stack is empty */
+
+#define STACK_EMPTY(stack) ((stack.index == 0) && \
+ (stack.current->prev == NULL))
+
+/* Return the start of register 'reg' */
+
+#define GET_REG_START(state, reg) (state.start[reg])
+
+/* Return the end of register 'reg' */
+
+#define GET_REG_END(state, reg) (state.end[reg])
+
+/* Set the start of register 'reg'. If the state of the register needs
+ * saving, push it on the stack. */
+
+#define SET_REG_START(state, reg, text, on_error) \
+ if(state.changed[reg] < state.level) \
+ { \
+ item_t *item; \
+ STACK_NEXT(state.stack, item, on_error); \
+ item->reg.num = reg; \
+ item->reg.start = state.start[reg]; \
+ item->reg.end = state.end[reg]; \
+ item->reg.level = state.changed[reg]; \
+ state.changed[reg] = state.level; \
+ state.count++; \
+ } \
+ state.start[reg] = text
+
+/* Set the end of register 'reg'. If the state of the register needs
+ * saving, push it on the stack. */
+
+#define SET_REG_END(state, reg, text, on_error) \
+ if(state.changed[reg] < state.level) \
+ { \
+ item_t *item; \
+ STACK_NEXT(state.stack, item, on_error); \
+ item->reg.num = reg; \
+ item->reg.start = state.start[reg]; \
+ item->reg.end = state.end[reg]; \
+ item->reg.level = state.changed[reg]; \
+ state.changed[reg] = state.level; \
+ state.count++; \
+ } \
+ state.end[reg] = text
+
+#define PUSH_FAILURE(state, xcode, xtext, on_error) \
+ { \
+ item_t *item; \
+ STACK_NEXT(state.stack, item, on_error); \
+ item->fail.code = xcode; \
+ item->fail.text = xtext; \
+ item->fail.count = state.count; \
+ item->fail.level = state.level; \
+ item->fail.phantom = 0; \
+ state.count = 0; \
+ state.level++; \
+ state.point++; \
+ }
+
+/* Update the last failure point with a new position in the text. */
+
+#define UPDATE_FAILURE(state, xtext, on_error) \
+ { \
+ item_t *item; \
+ STACK_BACK(state.stack, item, state.count + 1, on_error); \
+ if (!item->fail.phantom) \
+ { \
+ item_t *item2; \
+ STACK_NEXT(state.stack, item2, on_error); \
+ item2->fail.code = item->fail.code; \
+ item2->fail.text = xtext; \
+ item2->fail.count = state.count; \
+ item2->fail.level = state.level; \
+ item2->fail.phantom = 1; \
+ state.count = 0; \
+ state.level++; \
+ state.point++; \
+ } \
+ else \
+ { \
+ STACK_DISCARD(state.stack, state.count, on_error); \
+ STACK_TOP(state.stack, item, on_error); \
+ item->fail.text = xtext; \
+ state.count = 0; \
+ state.level++; \
+ } \
+ }
+
+#define POP_FAILURE(state, xcode, xtext, on_empty, on_error) \
+ { \
+ item_t *item; \
+ do \
+ { \
+ while(state.count > 0) \
+ { \
+ STACK_PREV(state.stack, item, on_error); \
+ state.start[item->reg.num] = item->reg.start; \
+ state.end[item->reg.num] = item->reg.end; \
+ state.changed[item->reg.num] = item->reg.level; \
+ state.count--; \
+ } \
+ STACK_PREV(state.stack, item, on_empty); \
+ xcode = item->fail.code; \
+ xtext = item->fail.text; \
+ state.count = item->fail.count; \
+ state.level = item->fail.level; \
+ state.point--; \
+ } \
+ while (item->fail.text == NULL); \
+ }