3 * Author: Tatu Ylonen <ylo@ngs.fi>
5 * Copyright (c) 1991 Tatu Ylonen, Espoo, Finland
7 * Permission to use, copy, modify, distribute, and sell this software
8 * and its documentation for any purpose is hereby granted without
9 * fee, provided that the above copyright notice appear in all copies.
10 * This software is provided "as is" without express or implied
13 * Created: Thu Sep 26 17:14:05 1991 ylo
14 * Last modified: Mon Nov 4 17:06:48 1991 ylo
15 * Ported to Think C: 19 Jan 1992 guido@cwi.nl
17 * This code draws many ideas from the regular expression packages by
18 * Henry Spencer of the University of Toronto and Richard Stallman of
19 * the Free Software Foundation.
21 * Bugs fixed and lots of reorganization by Jeffrey C. Ollie, April
22 * 1997 Thanks for bug reports and ideas from Andrew Kuchling, Tim
23 * Peters, Guido van Rossum, Ka-Ping Yee, Sjoerd Mullender, and
24 * probably one or two others that I'm forgetting.
29 The SILC Regex API and modifications by Pekka Riikonen, under the same
30 license as the original code. We've added the following features:
32 - RE_SYNTAX_POSIX POSIX extended regular expression syntax
33 - RE_REPEAT bounded repeat a{n,m} (RE_SYNTAX_POSIX)
34 - RE_NOTBOL bol fails to match (conforming POSIX regex API)
35 - RE_NOTEOL eol fails to match (conforming POSIX regex API)
36 - SilcStack support compile/match without real memory allocations
41 #define RE_NREGS 128 /* number of registers available */
43 /* bit definitions for syntax */
44 #define RE_NO_BK_PARENS 1 /* no quoting for parentheses */
45 #define RE_NO_BK_VBAR 2 /* no quoting for vertical bar */
46 #define RE_BK_PLUS_QM 4 /* quoting needed for + and ? */
47 #define RE_TIGHT_VBAR 8 /* | binds tighter than ^ and $ */
48 #define RE_NEWLINE_OR 16 /* treat newline as or */
49 #define RE_CONTEXT_INDEP_OPS 32 /* ^$?*+ are special in all contexts */
50 #define RE_ANSI_HEX 64 /* ansi sequences (\n etc) and \xhh */
51 #define RE_NO_GNU_EXTENSIONS 128 /* no gnu extensions */
52 #define RE_NOTBOL 256 /* bol fails to match */
53 #define RE_NOTEOL 512 /* eol fails to match */
54 #define RE_REPEAT 1024 /* bounded repeat expression */
56 /* definitions for some common regexp styles */
57 #define RE_SYNTAX_AWK (RE_NO_BK_PARENS|RE_NO_BK_VBAR|RE_CONTEXT_INDEP_OPS)
58 #define RE_SYNTAX_EGREP (RE_SYNTAX_AWK|RE_NEWLINE_OR)
59 #define RE_SYNTAX_GREP (RE_BK_PLUS_QM|RE_NEWLINE_OR)
60 #define RE_SYNTAX_POSIX (RE_SYNTAX_AWK|RE_REPEAT)
61 #define RE_SYNTAX_EMACS 0
70 typedef struct re_registers {
71 int start[RE_NREGS]; /* start offset of region */
72 int end[RE_NREGS]; /* end offset of region */
73 } *regexp_registers_t;
75 /* The original code blithely assumed that sizeof(short) == 2. Not
76 * always true. Original instances of "(short)x" were replaced by
77 * SHORT(x), where SHORT is #defined below. */
79 #define SHORT(x) ((x) & 0x8000 ? (x) - 0x10000 : (x))
81 /* The stack implementation is taken from an idea by Andrew Kuchling.
82 * It's a doubly linked list of arrays. The advantages of this over a
83 * simple linked list are that the number of mallocs required are
84 * reduced. It also makes it possible to statically allocate enough
85 * space so that small patterns don't ever need to call malloc.
87 * The advantages over a single array is that is periodically
88 * realloced when more space is needed is that we avoid ever copying
91 /* item_t is the basic stack element. Defined as a union of
92 * structures so that both registers, failure points, and counters can
93 * be pushed/popped from the stack. There's nothing built into the
94 * item to keep track of whether a certain stack item is a register, a
95 * failure point, or a counter. */
103 unsigned char *start;
122 #define STACK_PAGE_SIZE 256
123 #define NUM_REGISTERS 256
125 /* A 'page' of stack items. */
127 typedef struct item_page_t
129 item_t items[STACK_PAGE_SIZE];
130 struct item_page_t *prev;
131 struct item_page_t *next;
134 typedef struct match_state
136 /* The number of registers that have been pushed onto the stack
137 * since the last failure point. */
141 /* Used to control when registers need to be pushed onto the
146 /* The number of failure points on the stack. */
150 /* Storage for the registers. Each register consists of two
151 * pointers to characters. So register N is represented as
152 * start[N] and end[N]. The pointers must be converted to
153 * offsets from the beginning of the string before returning the
154 * registers to the calling program. */
156 unsigned char *start[NUM_REGISTERS];
157 unsigned char *end[NUM_REGISTERS];
159 /* Keeps track of whether a register has changed recently. */
161 int changed[NUM_REGISTERS];
163 /* Structure to encapsulate the stack. */
166 /* index into the current page. If index == 0 and you need
167 * to pop an item, move to the previous page and set index
168 * = STACK_PAGE_SIZE - 1. Otherwise decrement index to
169 * push a page. If index == STACK_PAGE_SIZE and you need
170 * to push a page move to the next page and set index =
171 * 0. If there is no new next page, allocate a new page
172 * and link it in. Otherwise, increment index to push a
176 item_page_t *current; /* Pointer to the current page. */
177 item_page_t first; /* First page is statically allocated. */
181 /* Initialize a state object */
183 /* #define NEW_STATE(state) \ */
184 /* memset(&state, 0, (void *)(&state.stack) - (void *)(&state)); \ */
185 /* state.stack.current = &state.stack.first; \ */
186 /* state.stack.first.prev = NULL; \ */
187 /* state.stack.first.next = NULL; \ */
188 /* state.stack.index = 0; \ */
189 /* state.level = 1 */
191 #define NEW_STATE(state, nregs) \
194 for (i = 0; i < nregs; i++) \
196 state.start[i] = NULL; \
197 state.end[i] = NULL; \
198 state.changed[i] = 0; \
200 state.stack.current = &state.stack.first; \
201 state.stack.first.prev = NULL; \
202 state.stack.first.next = NULL; \
203 state.stack.index = 0; \
210 /* Free any memory that might have been malloc'd */
212 #define FREE_STATE(state) \
213 while(state.stack.first.next != NULL) \
215 state.stack.current = state.stack.first.next; \
216 state.stack.first.next = state.stack.current->next; \
217 silc_sfree(bufp->rstack, state.stack.current); \
220 /* Discard the top 'count' stack items. */
222 #define STACK_DISCARD(stack, count, on_error) \
223 stack.index -= count; \
224 while (stack.index < 0) \
226 if (stack.current->prev == NULL) \
228 stack.current = stack.current->prev; \
229 stack.index += STACK_PAGE_SIZE; \
232 /* Store a pointer to the previous item on the stack. Used to pop an
233 * item off of the stack. */
235 #define STACK_PREV(stack, top, on_error) \
236 if (stack.index == 0) \
238 if (stack.current->prev == NULL) \
240 stack.current = stack.current->prev; \
241 stack.index = STACK_PAGE_SIZE - 1; \
247 top = &(stack.current->items[stack.index])
249 /* Store a pointer to the next item on the stack. Used to push an item
250 * on to the stack. */
252 #define STACK_NEXT(stack, top, on_error) \
253 if (stack.index == STACK_PAGE_SIZE) \
255 if (stack.current->next == NULL) \
257 stack.current->next = \
258 (item_page_t *)silc_smalloc(bufp->rstack, sizeof(item_page_t)); \
259 if (stack.current->next == NULL) \
261 stack.current->next->prev = stack.current; \
262 stack.current->next->next = NULL; \
264 stack.current = stack.current->next; \
267 top = &(stack.current->items[stack.index++])
269 /* Store a pointer to the item that is 'count' items back in the
270 * stack. STACK_BACK(stack, top, 1, on_error) is equivalent to
271 * STACK_TOP(stack, top, on_error). */
273 #define STACK_BACK(stack, top, count, on_error) \
276 item_page_t *current; \
277 current = stack.current; \
278 index = stack.index - (count); \
281 if (current->prev == NULL) \
283 current = current->prev; \
284 index += STACK_PAGE_SIZE; \
286 top = &(current->items[index]); \
289 /* Store a pointer to the top item on the stack. Execute the
290 * 'on_error' code if there are no items on the stack. */
292 #define STACK_TOP(stack, top, on_error) \
293 if (stack.index == 0) \
295 if (stack.current->prev == NULL) \
297 top = &(stack.current->prev->items[STACK_PAGE_SIZE - 1]); \
301 top = &(stack.current->items[stack.index - 1]); \
304 /* Test to see if the stack is empty */
306 #define STACK_EMPTY(stack) ((stack.index == 0) && \
307 (stack.current->prev == NULL))
309 /* Return the start of register 'reg' */
311 #define GET_REG_START(state, reg) (state.start[reg])
313 /* Return the end of register 'reg' */
315 #define GET_REG_END(state, reg) (state.end[reg])
317 /* Set the start of register 'reg'. If the state of the register needs
318 * saving, push it on the stack. */
320 #define SET_REG_START(state, reg, text, on_error) \
321 if(state.changed[reg] < state.level) \
324 STACK_NEXT(state.stack, item, on_error); \
325 item->reg.num = reg; \
326 item->reg.start = state.start[reg]; \
327 item->reg.end = state.end[reg]; \
328 item->reg.level = state.changed[reg]; \
329 state.changed[reg] = state.level; \
332 state.start[reg] = text
334 /* Set the end of register 'reg'. If the state of the register needs
335 * saving, push it on the stack. */
337 #define SET_REG_END(state, reg, text, on_error) \
338 if(state.changed[reg] < state.level) \
341 STACK_NEXT(state.stack, item, on_error); \
342 item->reg.num = reg; \
343 item->reg.start = state.start[reg]; \
344 item->reg.end = state.end[reg]; \
345 item->reg.level = state.changed[reg]; \
346 state.changed[reg] = state.level; \
349 state.end[reg] = text
351 #define PUSH_FAILURE(state, xcode, xtext, on_error) \
354 STACK_NEXT(state.stack, item, on_error); \
355 item->fail.code = xcode; \
356 item->fail.text = xtext; \
357 item->fail.count = state.count; \
358 item->fail.level = state.level; \
359 item->fail.phantom = 0; \
365 /* Update the last failure point with a new position in the text. */
367 #define UPDATE_FAILURE(state, xtext, on_error) \
370 STACK_BACK(state.stack, item, state.count + 1, on_error); \
371 if (!item->fail.phantom) \
374 STACK_NEXT(state.stack, item2, on_error); \
375 item2->fail.code = item->fail.code; \
376 item2->fail.text = xtext; \
377 item2->fail.count = state.count; \
378 item2->fail.level = state.level; \
379 item2->fail.phantom = 1; \
386 STACK_DISCARD(state.stack, state.count, on_error); \
387 STACK_TOP(state.stack, item, on_error); \
388 item->fail.text = xtext; \
394 #define POP_FAILURE(state, xcode, xtext, on_empty, on_error) \
399 while(state.count > 0) \
401 STACK_PREV(state.stack, item, on_error); \
402 state.start[item->reg.num] = item->reg.start; \
403 state.end[item->reg.num] = item->reg.end; \
404 state.changed[item->reg.num] = item->reg.level; \
407 STACK_PREV(state.stack, item, on_empty); \
408 xcode = item->fail.code; \
409 xtext = item->fail.text; \
410 state.count = item->fail.count; \
411 state.level = item->fail.level; \
414 while (item->fail.text == NULL); \
417 enum regexp_compiled_ops /* opcodes for compiled regexp */
419 Cend, /* end of pattern reached */
420 Cbol, /* beginning of line */
421 Ceol, /* end of line */
422 Cset, /* character set. Followed by 32 bytes of set. */
423 Cexact, /* followed by a byte to match */
424 Canychar, /* matches any character except newline */
425 Cstart_memory, /* set register start addr (followed by reg number) */
426 Cend_memory, /* set register end addr (followed by reg number) */
427 Cmatch_memory, /* match a duplicate of reg contents (regnum follows)*/
428 Cjump, /* followed by two bytes (lsb,msb) of displacement. */
429 Cstar_jump, /* will change to jump/update_failure_jump at runtime */
430 Cfailure_jump, /* jump to addr on failure */
431 Cupdate_failure_jump, /* update topmost failure point and jump */
432 Cdummy_failure_jump, /* push a dummy failure point and jump */
433 Cbegbuf, /* match at beginning of buffer */
434 Cendbuf, /* match at end of buffer */
435 Cwordbeg, /* match at beginning of word */
436 Cwordend, /* match at end of word */
437 Cwordbound, /* match if at word boundary */
438 Cnotwordbound, /* match if not at word boundary */
439 Csyntaxspec, /* matches syntax code (1 byte follows) */
440 Cnotsyntaxspec, /* matches if syntax code does not match (1 byte foll)*/
444 enum regexp_syntax_op /* syntax codes for plain and quoted characters */
446 Rend, /* special code for end of regexp */
447 Rnormal, /* normal character */
448 Ranychar, /* any character except newline */
449 Rquote, /* the quote character */
450 Rbol, /* match beginning of line */
451 Reol, /* match end of line */
452 Roptional, /* match preceding expression optionally */
453 Rstar, /* match preceding expr zero or more times */
454 Rplus, /* match preceding expr one or more times */
455 Ror, /* match either of alternatives */
456 Ropenpar, /* opening parenthesis */
457 Rclosepar, /* closing parenthesis */
458 Rmemory, /* match memory register */
459 Rextended_memory, /* \vnn to match registers 10-99 */
460 Ropenset, /* open set. Internal syntax hard-coded below. */
461 /* the following are gnu extensions to "normal" regexp syntax */
462 Rbegbuf, /* beginning of buffer */
463 Rendbuf, /* end of buffer */
464 Rwordchar, /* word character */
465 Rnotwordchar, /* not word character */
466 Rwordbeg, /* beginning of word */
467 Rwordend, /* end of word */
468 Rwordbound, /* word bound */
469 Rnotwordbound, /* not word bound */
471 Ropenrep, /* opening bounded repeat */
474 static int re_compile_initialized = 0;
475 static int regexp_syntax = 0;
476 static unsigned char regexp_plain_ops[256];
477 static unsigned char regexp_quoted_ops[256];
478 static unsigned char regexp_precedences[Rnum_ops];
479 static int regexp_context_indep_ops;
480 static int regexp_ansi_sequences;
482 #define NUM_LEVELS 5 /* number of precedence levels in use */
483 #define MAX_NESTING 100 /* max nesting level of operators */
485 #define SYNTAX(ch) re_syntax_table[(unsigned char)(ch)]
487 static unsigned char re_syntax_table[256];
489 void silc_re_compile_initialize(void)
493 static int syntax_table_inited = 0;
495 if (!syntax_table_inited)
497 syntax_table_inited = 1;
498 memset(re_syntax_table, 0, 256);
499 for (a = 'a'; a <= 'z'; a++)
500 re_syntax_table[a] = Sword;
501 for (a = 'A'; a <= 'Z'; a++)
502 re_syntax_table[a] = Sword;
503 for (a = '0'; a <= '9'; a++)
504 re_syntax_table[a] = Sword | Sdigit | Shexdigit;
505 for (a = '0'; a <= '7'; a++)
506 re_syntax_table[a] |= Soctaldigit;
507 for (a = 'A'; a <= 'F'; a++)
508 re_syntax_table[a] |= Shexdigit;
509 for (a = 'a'; a <= 'f'; a++)
510 re_syntax_table[a] |= Shexdigit;
511 re_syntax_table['_'] = Sword;
512 for (a = 9; a <= 13; a++)
513 re_syntax_table[a] = Swhitespace;
514 re_syntax_table[' '] = Swhitespace;
516 re_compile_initialized = 1;
517 for (a = 0; a < 256; a++)
519 regexp_plain_ops[a] = Rnormal;
520 regexp_quoted_ops[a] = Rnormal;
522 for (a = '0'; a <= '9'; a++)
523 regexp_quoted_ops[a] = Rmemory;
524 regexp_plain_ops['\134'] = Rquote;
525 if (regexp_syntax & RE_NO_BK_PARENS)
527 regexp_plain_ops['('] = Ropenpar;
528 regexp_plain_ops[')'] = Rclosepar;
532 regexp_quoted_ops['('] = Ropenpar;
533 regexp_quoted_ops[')'] = Rclosepar;
535 if (regexp_syntax & RE_NO_BK_VBAR)
536 regexp_plain_ops['\174'] = Ror;
538 regexp_quoted_ops['\174'] = Ror;
539 regexp_plain_ops['*'] = Rstar;
540 if (regexp_syntax & RE_BK_PLUS_QM)
542 regexp_quoted_ops['+'] = Rplus;
543 regexp_quoted_ops['?'] = Roptional;
547 regexp_plain_ops['+'] = Rplus;
548 regexp_plain_ops['?'] = Roptional;
550 if (regexp_syntax & RE_NEWLINE_OR)
551 regexp_plain_ops['\n'] = Ror;
552 regexp_plain_ops['\133'] = Ropenset;
553 regexp_plain_ops['\136'] = Rbol;
554 regexp_plain_ops['$'] = Reol;
555 regexp_plain_ops['.'] = Ranychar;
556 if (!(regexp_syntax & RE_NO_GNU_EXTENSIONS))
558 regexp_quoted_ops['w'] = Rwordchar;
559 regexp_quoted_ops['W'] = Rnotwordchar;
560 regexp_quoted_ops['<'] = Rwordbeg;
561 regexp_quoted_ops['>'] = Rwordend;
562 regexp_quoted_ops['b'] = Rwordbound;
563 regexp_quoted_ops['B'] = Rnotwordbound;
564 regexp_quoted_ops['`'] = Rbegbuf;
565 regexp_quoted_ops['\''] = Rendbuf;
567 if (regexp_syntax & RE_ANSI_HEX)
568 regexp_quoted_ops['v'] = Rextended_memory;
569 for (a = 0; a < Rnum_ops; a++)
570 regexp_precedences[a] = 4;
571 if (regexp_syntax & RE_TIGHT_VBAR)
573 regexp_precedences[Ror] = 3;
574 regexp_precedences[Rbol] = 2;
575 regexp_precedences[Reol] = 2;
579 regexp_precedences[Ror] = 2;
580 regexp_precedences[Rbol] = 3;
581 regexp_precedences[Reol] = 3;
583 if (regexp_syntax & RE_REPEAT)
585 if (regexp_syntax & RE_NO_BK_PARENS)
587 regexp_plain_ops['{'] = Ropenrep;
591 regexp_quoted_ops['{'] = Ropenrep;
594 regexp_precedences[Rclosepar] = 1;
595 regexp_precedences[Rend] = 0;
596 regexp_context_indep_ops = (regexp_syntax & RE_CONTEXT_INDEP_OPS) != 0;
597 regexp_ansi_sequences = (regexp_syntax & RE_ANSI_HEX) != 0;
600 int silc_re_set_syntax(int syntax)
605 regexp_syntax = syntax;
606 silc_re_compile_initialize();
610 static int silc_hex_char_to_decimal(int ch)
612 if (ch >= '0' && ch <= '9')
614 if (ch >= 'a' && ch <= 'f')
615 return ch - 'a' + 10;
616 if (ch >= 'A' && ch <= 'F')
617 return ch - 'A' + 10;
621 static int silc_re_compile_fastmap_aux(unsigned char *code, int pos,
622 unsigned char *visited,
623 unsigned char *can_be_null,
624 unsigned char *fastmap)
631 return 0; /* we have already been here */
634 switch (code[pos++]) {
648 for (a = 0; a < 256; a++)
654 syntaxcode = code[pos++];
655 for (a = 0; a < 256; a++)
656 if (SYNTAX(a) & syntaxcode)
662 syntaxcode = code[pos++];
663 for (a = 0; a < 256; a++)
664 if (!(SYNTAX(a) & syntaxcode) )
671 if (*can_be_null == 0)
672 *can_be_null = 2; /* can match null, but only at end of buffer*/
677 for (a = 0; a < 256/8; a++)
678 if (code[pos + a] != 0)
679 for (b = 0; b < 8; b++)
680 if (code[pos + a] & (1 << b))
681 fastmap[(a << 3) + b] = 1;
687 fastmap[(unsigned char)code[pos]] = 1;
692 for (a = 0; a < 256; a++)
705 for (a = 0; a < 256; a++)
711 case Cdummy_failure_jump:
712 case Cupdate_failure_jump:
715 a = (unsigned char)code[pos++];
716 a |= (unsigned char)code[pos++] << 8;
717 pos += (int)SHORT(a);
720 /* argh... the regexp contains empty loops. This is not
721 good, as this may cause a failure stack overflow when
722 matching. Oh well. */
723 /* this path leads nowhere; pursue other paths. */
731 a = (unsigned char)code[pos++];
732 a |= (unsigned char)code[pos++] << 8;
733 a = pos + (int)SHORT(a);
734 return silc_re_compile_fastmap_aux(code, a, visited,
735 can_be_null, fastmap);
744 silc_set_errno(SILC_ERR_REGEX_OPCODE);
751 static int silc_re_do_compile_fastmap(unsigned char *buffer, int used, int pos,
752 unsigned char *can_be_null,
753 unsigned char *fastmap, SilcRegex bufp)
755 unsigned char small_visited[512], *visited;
758 if (used <= sizeof(small_visited))
759 visited = small_visited;
762 silc_stack_push(bufp->rstack, NULL);
763 visited = silc_smalloc(bufp->rstack, used);
765 silc_stack_pop(bufp->rstack);
770 memset(fastmap, 0, 256);
771 memset(visited, 0, used);
772 ret = silc_re_compile_fastmap_aux(buffer, pos, visited,
773 can_be_null, fastmap);
774 if (visited != small_visited) {
775 silc_sfree(bufp->rstack, visited);
776 silc_stack_pop(bufp->rstack);
781 int silc_re_compile_fastmap(SilcRegex bufp)
783 if (!bufp->fastmap || bufp->fastmap_accurate)
785 SILC_ASSERT(bufp->used > 0);
786 if (!silc_re_do_compile_fastmap(bufp->buffer,
790 bufp->fastmap, bufp))
792 if (bufp->buffer[0] == Cbol)
793 bufp->anchor = 1; /* begline */
795 if (bufp->buffer[0] == Cbegbuf)
796 bufp->anchor = 2; /* begbuf */
798 bufp->anchor = 0; /* none */
800 bufp->fastmap_accurate = 1;
807 * ... code for operand of star
809 * 2: ... code after star
811 * We change the star_jump to update_failure_jump if we can determine
812 * that it is safe to do so; otherwise we change it to an ordinary
819 * 2: ... code for operand of plus
821 * 3: ... code after plus
823 * For star_jump considerations this is processed identically to star.
827 static int silc_re_optimize_star_jump(SilcRegex bufp, unsigned char *code)
829 unsigned char map[256];
830 unsigned char can_be_null;
836 int num_instructions = 0;
838 a = (unsigned char)*code++;
839 a |= (unsigned char)*code++ << 8;
842 p1 = code + a + 3; /* skip the failure_jump */
843 /* Check that the jump is within the pattern */
844 if (p1<bufp->buffer || bufp->buffer+bufp->used<p1)
846 silc_set_errno(SILC_ERR_OVERFLOW);
850 SILC_ASSERT(p1[-3] == Cfailure_jump);
852 /* p1 points inside loop, p2 points to after loop */
853 if (!silc_re_do_compile_fastmap(bufp->buffer, bufp->used,
854 (int)(p2 - bufp->buffer),
855 &can_be_null, map, bufp))
856 goto make_normal_jump;
858 /* If we might introduce a new update point inside the
859 * loop, we can't optimize because then update_jump would
860 * update a wrong failure point. Thus we have to be
861 * quite careful here.
864 /* loop until we find something that consumes a character */
888 ch = (unsigned char)*p1++;
890 goto make_normal_jump;
895 for (b = 0; b < 256; b++)
896 if (b != '\n' && map[b])
897 goto make_normal_jump;
902 for (b = 0; b < 256; b++)
903 if ((p1[b >> 3] & (1 << (b & 7))) && map[b])
904 goto make_normal_jump;
910 goto make_normal_jump;
913 /* now we know that we can't backtrack. */
953 case Cupdate_failure_jump:
954 case Cdummy_failure_jump:
956 goto make_normal_jump;
965 /* make_update_jump: */
967 a += 3; /* jump to after the Cfailure_jump */
968 code[0] = Cupdate_failure_jump;
971 if (num_instructions > 1)
973 SILC_ASSERT(num_instructions == 1);
974 /* if the only instruction matches a single character, we can do
976 p1 = code + 3 + a; /* start of sole instruction */
977 if (*p1 == Cset || *p1 == Cexact || *p1 == Canychar ||
978 *p1 == Csyntaxspec || *p1 == Cnotsyntaxspec)
988 static int silc_re_optimize(SilcRegex bufp)
1024 case Cnotsyntaxspec:
1031 if (!silc_re_optimize_star_jump(bufp, code))
1037 case Cupdate_failure_jump:
1039 case Cdummy_failure_jump:
1054 #define NEXTCHAR(var) \
1057 goto ends_prematurely; \
1058 (var) = regex[pos]; \
1062 #define ALLOC(amount) \
1064 if (pattern_offset+(amount) > alloc) \
1066 pattern = silc_srealloc(bufp->rstack, alloc, pattern, \
1067 alloc + 256 + (amount)); \
1068 alloc += 256 + (amount); \
1070 goto out_of_memory; \
1074 #define STORE(ch) pattern[pattern_offset++] = (ch)
1076 #define CURRENT_LEVEL_START (starts[starts_base + current_level])
1078 #define SET_LEVEL_START starts[starts_base + current_level] = pattern_offset
1080 #define PUSH_LEVEL_STARTS \
1081 if (starts_base < (MAX_NESTING-1)*NUM_LEVELS) \
1082 starts_base += NUM_LEVELS; \
1086 #define POP_LEVEL_STARTS starts_base -= NUM_LEVELS
1088 #define PUT_ADDR(offset,addr) \
1090 int disp = (addr) - (offset) - 2; \
1091 pattern[(offset)] = disp & 0xff; \
1092 pattern[(offset)+1] = (disp>>8) & 0xff; \
1095 #define INSERT_JUMP(pos,type,addr) \
1097 int a, p = (pos), t = (type), ad = (addr); \
1098 for (a = pattern_offset - 1; a >= p; a--) \
1099 pattern[a + 3] = pattern[a]; \
1102 pattern_offset += 3; \
1105 #define SETBIT(buf,offset,bit) (buf)[(offset)+(bit)/8] |= (1<<((bit) & 7))
1107 #define SET_FIELDS \
1109 bufp->allocated = alloc; \
1110 bufp->buffer = pattern; \
1111 bufp->used = pattern_offset; \
1114 #define GETHEX(var) \
1116 unsigned char gethex_ch, gethex_value; \
1117 NEXTCHAR(gethex_ch); \
1118 gethex_value = silc_hex_char_to_decimal(gethex_ch); \
1119 if (gethex_value == 16) \
1121 NEXTCHAR(gethex_ch); \
1122 gethex_ch = silc_hex_char_to_decimal(gethex_ch); \
1123 if (gethex_ch == 16) \
1125 (var) = gethex_value * 16 + gethex_ch; \
1128 #define ANSI_TRANSLATE(ch) \
1135 ch = 7; /* audible bell */ \
1141 ch = 8; /* backspace */ \
1147 ch = 12; /* form feed */ \
1153 ch = 10; /* line feed */ \
1159 ch = 13; /* carriage return */ \
1171 ch = 11; /* vertical tab */ \
1174 case 'x': /* hex code */ \
1182 /* other characters passed through */ \
1184 ch = translate[(unsigned char)ch]; \
1190 SilcResult silc_re_compile_pattern(unsigned char *regex, int size,
1199 int pattern_offset = 0, alloc;
1200 int starts[NUM_LEVELS * MAX_NESTING];
1202 int future_jumps[MAX_NESTING];
1204 unsigned char ch = '\0';
1205 unsigned char *pattern;
1206 unsigned char *translate;
1209 int num_open_registers;
1210 int open_registers[RE_NREGS];
1211 int beginning_context;
1213 if (!re_compile_initialized)
1214 silc_re_compile_initialize();
1216 bufp->fastmap_accurate = 0;
1217 bufp->uses_registers = 1;
1218 bufp->num_registers = 1;
1219 translate = bufp->translate;
1220 pattern = bufp->buffer;
1221 alloc = bufp->allocated;
1222 if (alloc == 0 || pattern == NULL)
1225 pattern = silc_smalloc(bufp->rstack, alloc);
1234 num_open_registers = 0;
1237 beginning_context = 1;
1239 /* we use Rend dummy to ensure that pending jumps are updated
1240 (due to low priority of Rend) before exiting the loop. */
1250 ch = translate[(unsigned char)ch];
1251 op = regexp_plain_ops[(unsigned char)ch];
1255 op = regexp_quoted_ops[(unsigned char)ch];
1256 if (op == Rnormal && regexp_ansi_sequences)
1260 level = regexp_precedences[op];
1261 /* printf("ch='%c' op=%d level=%d current_level=%d
1262 curlevstart=%d\n", ch, op, level, current_level,
1263 CURRENT_LEVEL_START); */
1264 if (level > current_level)
1266 for (current_level++; current_level < level; current_level++)
1271 if (level < current_level)
1273 current_level = level;
1274 for (;num_jumps > 0 &&
1275 future_jumps[num_jumps-1] >= CURRENT_LEVEL_START;
1277 PUT_ADDR(future_jumps[num_jumps-1], pattern_offset);
1289 store_opcode_and_arg: /* opcode & ch must be set */
1307 SILC_VERIFY(op != Rquote);
1312 if (!beginning_context) {
1313 if (regexp_context_indep_ops)
1323 if (!((pos >= size) ||
1324 ((regexp_syntax & RE_NO_BK_VBAR) ?
1325 (regex[pos] == '\174') :
1326 (pos+1 < size && regex[pos] == '\134' &&
1327 regex[pos+1] == '\174')) ||
1328 ((regexp_syntax & RE_NO_BK_PARENS)?
1329 (regex[pos] == ')'):
1330 (pos+1 < size && regex[pos] == '\134' &&
1331 regex[pos+1] == ')')))) {
1332 if (regexp_context_indep_ops)
1344 if (beginning_context) {
1345 if (regexp_context_indep_ops)
1350 if (CURRENT_LEVEL_START == pattern_offset)
1351 break; /* ignore empty patterns for ? */
1353 INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
1354 pattern_offset + 3);
1360 if (beginning_context) {
1361 if (regexp_context_indep_ops)
1366 if (CURRENT_LEVEL_START == pattern_offset)
1367 break; /* ignore empty patterns for + and * */
1370 INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
1371 pattern_offset + 6);
1372 INSERT_JUMP(pattern_offset, Cstar_jump, CURRENT_LEVEL_START);
1373 if (op == Rplus) /* jump over initial failure_jump */
1374 INSERT_JUMP(CURRENT_LEVEL_START, Cdummy_failure_jump,
1375 CURRENT_LEVEL_START + 6);
1381 INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
1382 pattern_offset + 6);
1383 if (num_jumps >= MAX_NESTING)
1386 future_jumps[num_jumps++] = pattern_offset;
1395 if (next_register < RE_NREGS)
1397 bufp->uses_registers = 1;
1399 STORE(Cstart_memory);
1400 STORE(next_register);
1401 open_registers[num_open_registers++] = next_register;
1402 bufp->num_registers++;
1413 if (paren_depth <= 0)
1414 goto parenthesis_error;
1416 current_level = regexp_precedences[Ropenpar];
1418 if (paren_depth < num_open_registers)
1420 bufp->uses_registers = 1;
1423 num_open_registers--;
1424 STORE(open_registers[num_open_registers]);
1431 goto bad_match_register;
1432 SILC_ASSERT(ch >= '0' && ch <= '9');
1433 bufp->uses_registers = 1;
1434 opcode = Cmatch_memory;
1436 goto store_opcode_and_arg;
1438 case Rextended_memory:
1441 if (ch < '0' || ch > '9')
1442 goto bad_match_register;
1444 if (a < '0' || a > '9')
1445 goto bad_match_register;
1446 ch = 10 * (a - '0') + ch - '0';
1447 if (ch == 0 || ch >= RE_NREGS)
1448 goto bad_match_register;
1449 bufp->uses_registers = 1;
1450 opcode = Cmatch_memory;
1451 goto store_opcode_and_arg;
1464 offset = pattern_offset;
1465 for (a = 0; a < 256/8; a++)
1469 ch = translate[(unsigned char)ch];
1475 ch = translate[(unsigned char)ch];
1482 while (ch != '\135' || firstchar)
1485 if (regexp_ansi_sequences && ch == '\134')
1492 for (a = prev; a <= (int)ch; a++)
1493 SETBIT(pattern, offset, a);
1498 if (prev != -1 && ch == '-')
1502 SETBIT(pattern, offset, ch);
1507 ch = translate[(unsigned char)ch];
1510 SETBIT(pattern, offset, '-');
1513 for (a = 0; a < 256/8; a++)
1514 pattern[offset+a] ^= 0xff;
1520 /* The bounded repeat syntax: a{n}, a{n,} and a{n,m}. The first
1521 is compiled as n-1 Rnormals. The second is compiled as n-1
1522 Rnormals and one Rplus. The third is compiled as n-1 Rnormals
1523 and m-n Rnormals with Roptionals. 0 values have special
1528 goto normal_char; /* Consider literal */
1530 /* Get the preceding atom */
1532 goto normal_char; /* Consider literal */
1540 goto normal_char; /* Consider literal */
1543 while (isdigit(ch)) {
1550 goto repeat_value_error;
1556 /* Will not do any matching with a{0} */
1557 pattern_offset -= 2;
1561 /* Store min - 1 many Cexacts. */
1562 for (i = 0; i < min - 1; i++) {
1566 STORE((unsigned char)a);
1575 /* The a{n,} case */
1578 /* Store Rstar with a{0,} */
1583 /* Store min - 1 many Cexacts. */
1584 for (i = 0; i < min - 1; i++) {
1588 STORE((unsigned char)a);
1596 /* The a{n,m} case */
1600 goto repeat_value_error;
1603 while (isdigit(ch)) {
1610 goto repeat_value_error;
1612 goto repeat_value_error;
1615 /* Will not do any matching with a{0,0} */
1616 pattern_offset -= 2;
1624 /* Only optional matching with a{0,m}. */
1625 pattern_offset -= 2;
1627 /* Store min - 1 many Cexacts. */
1628 for (i = 0; min && i < min - 1; i++) {
1632 STORE((unsigned char)a);
1635 /* Store max - min Cexacts and Roptionals. */
1636 for (i = 0; i < max - min; i++) {
1640 STORE((unsigned char)a);
1642 INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
1643 pattern_offset + 3);
1662 opcode = Csyntaxspec;
1664 goto store_opcode_and_arg;
1668 opcode = Cnotsyntaxspec;
1670 goto store_opcode_and_arg;
1684 opcode = Cwordbound;
1689 opcode = Cnotwordbound;
1697 beginning_context = (op == Ropenpar || op == Ror);
1699 if (starts_base != 0)
1700 goto parenthesis_error;
1701 SILC_ASSERT(num_jumps == 0);
1705 if (!silc_re_optimize(bufp))
1711 return SILC_ERR_REGEX_SPECIAL;
1715 return SILC_ERR_REGEX_REG;
1719 return SILC_ERR_REGEX_HEX;
1723 return SILC_ERR_REGEX_PAREN;
1727 return SILC_ERR_OUT_OF_MEMORY;
1731 return SILC_ERR_OVERFLOW;
1735 return SILC_ERR_REGEX_TOO_COMPLEX;
1739 return SILC_ERR_REGEX_REPEAT;
1747 #undef CURRENT_LEVEL_START
1748 #undef SET_LEVEL_START
1749 #undef PUSH_LEVEL_STARTS
1750 #undef POP_LEVEL_STARTS
1756 #define PREFETCH if (text == textend) goto fail
1758 #define NEXTCHAR(var) \
1760 var = (unsigned char)*text++; \
1762 var = translate[var]
1764 int silc_re_match(SilcRegex bufp, unsigned char *string, int size, int pos,
1765 regexp_registers_t old_regs, unsigned int flags)
1767 unsigned char *code;
1768 unsigned char *translate;
1769 unsigned char *text;
1770 unsigned char *textstart;
1771 unsigned char *textend;
1777 unsigned char *regstart;
1778 unsigned char *regend;
1782 SILC_ASSERT(pos >= 0 && size >= 0);
1783 SILC_ASSERT(pos <= size);
1785 text = string + pos;
1787 textend = string + size;
1789 code = bufp->buffer;
1791 translate = bufp->translate;
1793 NEW_STATE(state, bufp->num_registers);
1800 match_end = text - textstart;
1803 old_regs->start[0] = pos;
1804 old_regs->end[0] = match_end;
1805 if (!bufp->uses_registers)
1807 for (a = 1; a < RE_NREGS; a++)
1809 old_regs->start[a] = -1;
1810 old_regs->end[a] = -1;
1815 for (a = 1; a < bufp->num_registers; a++)
1817 if ((GET_REG_START(state, a) == NULL) ||
1818 (GET_REG_END(state, a) == NULL))
1820 old_regs->start[a] = -1;
1821 old_regs->end[a] = -1;
1824 old_regs->start[a] = GET_REG_START(state, a) - textstart;
1825 old_regs->end[a] = GET_REG_END(state, a) - textstart;
1827 for (; a < RE_NREGS; a++)
1829 old_regs->start[a] = -1;
1830 old_regs->end[a] = -1;
1835 return match_end - pos;
1839 if (text == textstart || text[-1] == '\n') {
1840 if (flags & RE_NOTBOL)
1842 goto continue_matching;
1848 if (text == textend || *text == '\n') {
1849 if (flags & RE_NOTEOL)
1851 goto continue_matching;
1858 if (code[ch/8] & (1<<(ch & 7)))
1861 goto continue_matching;
1868 if (ch != (unsigned char)*code++)
1870 goto continue_matching;
1877 goto continue_matching;
1882 SET_REG_START(state, reg, text, goto error);
1883 goto continue_matching;
1888 SET_REG_END(state, reg, text, goto error);
1889 goto continue_matching;
1894 regstart = GET_REG_START(state, reg);
1895 regend = GET_REG_END(state, reg);
1896 if ((regstart == NULL) || (regend == NULL))
1897 goto fail; /* or should we just match nothing? */
1898 regsize = regend - regstart;
1900 if (regsize > (textend - text))
1904 for (; regstart < regend; regstart++, text++)
1905 if (translate[*regstart] != translate[*text])
1909 for (; regstart < regend; regstart++, text++)
1910 if (*regstart != *text)
1912 goto continue_matching;
1914 case Cupdate_failure_jump:
1916 UPDATE_FAILURE(state, text, goto error);
1917 /* fall to next case */
1919 /* treat Cstar_jump just like Cjump if it hasn't been optimized */
1923 a = (unsigned char)*code++;
1924 a |= (unsigned char)*code++ << 8;
1925 code += (int)SHORT(a);
1926 if (code<bufp->buffer || bufp->buffer+bufp->used<code) {
1927 silc_set_errno(SILC_ERR_OVERFLOW);
1931 goto continue_matching;
1933 case Cdummy_failure_jump:
1935 unsigned char *failuredest;
1937 a = (unsigned char)*code++;
1938 a |= (unsigned char)*code++ << 8;
1940 SILC_ASSERT(*code == Cfailure_jump);
1941 b = (unsigned char)code[1];
1942 b |= (unsigned char)code[2] << 8;
1943 failuredest = code + (int)SHORT(b) + 3;
1944 if (failuredest<bufp->buffer || bufp->buffer+bufp->used < failuredest) {
1945 silc_set_errno(SILC_ERR_OVERFLOW);
1949 PUSH_FAILURE(state, failuredest, NULL, goto error);
1951 if (code<bufp->buffer || bufp->buffer+bufp->used < code) {
1952 silc_set_errno(SILC_ERR_OVERFLOW);
1956 goto continue_matching;
1960 a = (unsigned char)*code++;
1961 a |= (unsigned char)*code++ << 8;
1963 if (code+a<bufp->buffer || bufp->buffer+bufp->used < code+a) {
1964 silc_set_errno(SILC_ERR_OVERFLOW);
1968 PUSH_FAILURE(state, code + a, text, goto error);
1969 goto continue_matching;
1973 unsigned char *pinst;
1974 a = (unsigned char)*code++;
1975 a |= (unsigned char)*code++ << 8;
1978 if (pinst<bufp->buffer || bufp->buffer+bufp->used<pinst) {
1979 silc_set_errno(SILC_ERR_OVERFLOW);
1983 /* pinst is sole instruction in loop, and it matches a
1984 * single character. Since Crepeat1 was originally a
1985 * Cupdate_failure_jump, we also know that backtracking
1986 * is useless: so long as the single-character
1987 * expression matches, it must be used. Also, in the
1988 * case of +, we've already matched one character, so +
1989 * can't fail: nothing here can cause a failure. */
1996 while (text < textend)
1998 ch = translate[(unsigned char)*text];
1999 if (pinst[ch/8] & (1<<(ch & 7)))
2007 while (text < textend)
2009 ch = (unsigned char)*text;
2010 if (pinst[ch/8] & (1<<(ch & 7)))
2020 ch = (unsigned char)*pinst;
2023 while (text < textend &&
2024 translate[(unsigned char)*text] == ch)
2029 while (text < textend && (unsigned char)*text == ch)
2036 while (text < textend && (unsigned char)*text != '\n')
2042 a = (unsigned char)*pinst;
2045 while (text < textend &&
2046 (SYNTAX(translate[*text]) & a) )
2051 while (text < textend && (SYNTAX(*text) & a) )
2056 case Cnotsyntaxspec:
2058 a = (unsigned char)*pinst;
2061 while (text < textend &&
2062 !(SYNTAX(translate[*text]) & a) )
2067 while (text < textend && !(SYNTAX(*text) & a) )
2075 silc_set_errno(SILC_ERR_REGEX_OPCODE);
2080 /* due to the funky way + and * are compiled, the top
2081 * failure- stack entry at this point is actually a
2082 * success entry -- update it & pop it */
2083 UPDATE_FAILURE(state, text, goto error);
2084 goto fail; /* i.e., succeed <wink/sigh> */
2088 if (text == textstart)
2089 goto continue_matching;
2094 if (text == textend)
2095 goto continue_matching;
2100 if (text == textend)
2102 if (!(SYNTAX(*text) & Sword))
2104 if (text == textstart)
2105 goto continue_matching;
2106 if (!(SYNTAX(text[-1]) & Sword))
2107 goto continue_matching;
2112 if (text == textstart)
2114 if (!(SYNTAX(text[-1]) & Sword))
2116 if (text == textend)
2117 goto continue_matching;
2118 if (!(SYNTAX(*text) & Sword))
2119 goto continue_matching;
2124 /* Note: as in gnu regexp, this also matches at the
2125 * beginning and end of buffer. */
2127 if (text == textstart || text == textend)
2128 goto continue_matching;
2129 if ((SYNTAX(text[-1]) & Sword) ^ (SYNTAX(*text) & Sword))
2130 goto continue_matching;
2135 /* Note: as in gnu regexp, this never matches at the
2136 * beginning and end of buffer. */
2137 if (text == textstart || text == textend)
2139 if (!((SYNTAX(text[-1]) & Sword) ^ (SYNTAX(*text) & Sword)))
2140 goto continue_matching;
2146 if (!(SYNTAX(ch) & (unsigned char)*code++))
2148 goto continue_matching;
2150 case Cnotsyntaxspec:
2153 if (SYNTAX(ch) & (unsigned char)*code++)
2155 goto continue_matching;
2160 silc_set_errno(SILC_ERR_REGEX_OPCODE);
2166 /* Using "break;" in the above switch statement is equivalent to
2169 POP_FAILURE(state, code, text, goto done_matching, goto error);
2170 goto continue_matching;
2173 /* if(translated != NULL) */
2174 /* free(translated); */
2179 /* if (translated != NULL) */
2180 /* free(translated); */
2188 int silc_re_search(SilcRegex bufp, unsigned char *string, int size, int pos,
2189 int range, regexp_registers_t regs, unsigned int flags)
2191 unsigned char *fastmap;
2192 unsigned char *translate;
2193 unsigned char *text;
2194 unsigned char *partstart;
2195 unsigned char *partend;
2198 unsigned char anchor;
2200 SILC_ASSERT(size >= 0 && pos >= 0);
2201 SILC_ASSERT(pos + range >= 0 && pos + range <= size); /* Bugfix by ylo */
2203 fastmap = bufp->fastmap;
2204 translate = bufp->translate;
2205 if (fastmap && !bufp->fastmap_accurate) {
2206 if (silc_re_compile_fastmap(bufp))
2210 anchor = bufp->anchor;
2211 if (bufp->can_be_null == 1) /* can_be_null == 2: can match null at eob */
2229 for (; range >= 0; range--, pos += dir)
2234 { /* searching forwards */
2236 text = string + pos;
2237 partend = string + size;
2240 while (text != partend &&
2241 !fastmap[(unsigned char) translate[(unsigned char)*text]])
2244 while (text != partend && !fastmap[(unsigned char)*text])
2246 pos += text - partstart;
2247 range -= text - partstart;
2248 if (pos == size && bufp->can_be_null == 0)
2252 { /* searching backwards */
2253 text = string + pos;
2254 partstart = string + pos - range;
2257 while (text != partstart &&
2258 !fastmap[(unsigned char)
2259 translate[(unsigned char)*text]])
2262 while (text != partstart &&
2263 !fastmap[(unsigned char)*text])
2265 pos -= partend - text;
2266 range -= partend - text;
2270 { /* anchored to begline */
2271 if (pos > 0 && (string[pos - 1] != '\n'))
2274 SILC_ASSERT(pos >= 0 && pos <= size);
2275 ret = silc_re_match(bufp, string, size, pos, regs, flags);
2284 /****************************** SILC Regex API ******************************/
2286 /* Compile regular expression */
2288 SilcBool silc_regex_compile(SilcRegex regexp, const char *regex,
2289 SilcRegexFlags flags)
2294 if (!regexp || !regex) {
2295 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
2299 memset(regexp, 0, sizeof(*regexp));
2301 /* Get global stack, if set, and create child stack. */
2302 regexp->rstack = silc_stack_get_global();
2304 regexp->rstack = silc_stack_alloc(512, regexp->rstack);
2307 syntax |= RE_SYNTAX_POSIX;
2308 silc_re_set_syntax(syntax);
2311 ret = silc_re_compile_pattern((char *)regex, strlen(regex), regexp);
2313 silc_set_errno(ret);
2315 if (ret != SILC_OK) {
2316 silc_regex_free(regexp);
2317 regexp->rstack = NULL;
2318 regexp->buffer = NULL;
2321 return ret == SILC_OK;
2324 /* Match compiled regular expression */
2326 SilcBool silc_regex_match(SilcRegex regexp, const char *string,
2327 SilcUInt32 string_len, SilcUInt32 num_match,
2328 SilcRegexMatch match, SilcRegexFlags flags)
2330 struct re_registers regs;
2334 if (!regexp || !string) {
2335 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
2339 if (num_match && !match) {
2340 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
2344 /* Internal limit for maximum number of registers */
2345 if (num_match > RE_NREGS)
2346 num_match = RE_NREGS;
2349 if (flags & SILC_REGEX_NOTBOL)
2351 if (flags & SILC_REGEX_NOTEOL)
2355 ret = silc_re_search(regexp, (char *)string, string_len, 0, string_len,
2356 num_match ? ®s : NULL, f);
2359 silc_set_errno(SILC_ERR_NOT_FOUND);
2363 /* Return matches */
2364 for (i = 0; i < num_match; i++) {
2365 match[i].start = regs.start[i];
2366 match[i].end = regs.end[i];
2375 void silc_regex_free(SilcRegex regexp)
2377 silc_sfree(regexp->rstack, regexp->buffer);
2378 silc_stack_free(regexp->rstack);
2383 SilcBool silc_regex_va(const char *string, SilcUInt32 string_len,
2384 const char *regex, SilcBuffer match, va_list va)
2386 SilcRegexStruct reg;
2387 SilcRegexMatch m = NULL;
2388 SilcBuffer buf, *rets = NULL;
2393 if (!silc_regex_compile(®, regex, 0))
2397 silc_stack_push(stack, NULL);
2399 /* Get match pointers */
2401 rets = silc_smalloc(stack, sizeof(*rets));
2403 silc_stack_pop(stack);
2404 silc_regex_free(®);
2409 while ((buf = va_arg(va, SilcBuffer))) {
2410 rets = silc_srealloc(stack, c * sizeof(*rets),
2411 rets, (c + 1) * sizeof(*rets));
2413 silc_stack_pop(stack);
2414 silc_regex_free(®);
2420 m = silc_smalloc(stack, c * sizeof(*m));
2422 silc_sfree(stack, rets);
2423 silc_stack_pop(stack);
2424 silc_regex_free(®);
2430 if (!silc_regex_match(®, string, string_len, c, m, 0)) {
2431 silc_sfree(stack, m);
2432 silc_sfree(stack, rets);
2433 silc_stack_pop(stack);
2434 silc_regex_free(®);
2438 /* Return matches */
2439 for (i = 0; i < c; i++) {
2440 if (m[i].start == -1)
2442 silc_buffer_set(rets[i], (unsigned char *)string + m[i].start,
2443 m[i].end - m[i].start);
2446 silc_sfree(stack, m);
2447 silc_sfree(stack, rets);
2448 silc_stack_pop(stack);
2449 silc_regex_free(®);
2456 SilcBool silc_regex(const char *string, const char *regex,
2457 SilcBuffer match, ...)
2462 if (!string || !regex) {
2463 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
2468 va_start(va, match);
2470 ret = silc_regex_va(string, strlen(string), regex, match, va);
2480 SilcBool silc_regex_buffer(SilcBuffer buffer, const char *regex,
2481 SilcBuffer match, ...)
2486 if (!buffer || !regex) {
2487 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
2492 va_start(va, match);
2494 ret = silc_regex_va((const char *)silc_buffer_data(buffer),
2495 silc_buffer_len(buffer), regex, match, va);