📄 regexec.c
字号:
/********************************************************************** regexec.c - Oniguruma (regular expression library)**********************************************************************//*- * Copyright (c) 2002-2005 K.Kosako <sndgk393 AT ybb DOT ne DOT jp> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "regint.h"#ifdef USE_CAPTURE_HISTORYstatic void history_tree_free(OnigCaptureTreeNode* node);static voidhistory_tree_clear(OnigCaptureTreeNode* node){ int i; if (IS_NOT_NULL(node)) { for (i = 0; i < node->num_childs; i++) { if (IS_NOT_NULL(node->childs[i])) { history_tree_free(node->childs[i]); } } for (i = 0; i < node->allocated; i++) { node->childs[i] = (OnigCaptureTreeNode* )0; } node->num_childs = 0; node->beg = ONIG_REGION_NOTPOS; node->end = ONIG_REGION_NOTPOS; node->group = -1; }}static voidhistory_tree_free(OnigCaptureTreeNode* node){ history_tree_clear(node); xfree(node);}static voidhistory_root_free(OnigRegion* r){ if (IS_NOT_NULL(r->history_root)) { history_tree_free(r->history_root); r->history_root = (OnigCaptureTreeNode* )0; }}static OnigCaptureTreeNode*history_node_new(){ OnigCaptureTreeNode* node; node = (OnigCaptureTreeNode* )xmalloc(sizeof(OnigCaptureTreeNode)); CHECK_NULL_RETURN(node); node->childs = (OnigCaptureTreeNode** )0; node->allocated = 0; node->num_childs = 0; node->group = -1; node->beg = ONIG_REGION_NOTPOS; node->end = ONIG_REGION_NOTPOS; return node;}static inthistory_tree_add_child(OnigCaptureTreeNode* parent, OnigCaptureTreeNode* child){#define HISTORY_TREE_INIT_ALLOC_SIZE 8 if (parent->num_childs >= parent->allocated) { int n, i; if (IS_NULL(parent->childs)) { n = HISTORY_TREE_INIT_ALLOC_SIZE; parent->childs = (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n); } else { n = parent->allocated * 2; parent->childs = (OnigCaptureTreeNode** )xrealloc(parent->childs, sizeof(OnigCaptureTreeNode*) * n); } CHECK_NULL_RETURN_VAL(parent->childs, ONIGERR_MEMORY); for (i = parent->allocated; i < n; i++) { parent->childs[i] = (OnigCaptureTreeNode* )0; } parent->allocated = n; } parent->childs[parent->num_childs] = child; parent->num_childs++; return 0;}static OnigCaptureTreeNode*history_tree_clone(OnigCaptureTreeNode* node){ int i; OnigCaptureTreeNode *clone, *child; clone = history_node_new(); CHECK_NULL_RETURN(clone); clone->beg = node->beg; clone->end = node->end; for (i = 0; i < node->num_childs; i++) { child = history_tree_clone(node->childs[i]); if (IS_NULL(child)) { history_tree_free(clone); return (OnigCaptureTreeNode* )0; } history_tree_add_child(clone, child); } return clone;}extern OnigCaptureTreeNode*onig_get_capture_tree(OnigRegion* region){ return region->history_root;}#endif /* USE_CAPTURE_HISTORY */extern voidonig_region_clear(OnigRegion* region){ int i; for (i = 0; i < region->num_regs; i++) { region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS; }#ifdef USE_CAPTURE_HISTORY history_root_free(region);#endif}extern intonig_region_resize(OnigRegion* region, int n){ region->num_regs = n; if (n < ONIG_NREGION) n = ONIG_NREGION; if (region->allocated == 0) { region->beg = (int* )xmalloc(n * sizeof(int)); region->end = (int* )xmalloc(n * sizeof(int)); if (region->beg == 0 || region->end == 0) return ONIGERR_MEMORY; region->allocated = n; } else if (region->allocated < n) { region->beg = (int* )xrealloc(region->beg, n * sizeof(int)); region->end = (int* )xrealloc(region->end, n * sizeof(int)); if (region->beg == 0 || region->end == 0) return ONIGERR_MEMORY; region->allocated = n; } return 0;}extern intonig_region_resize_clear(OnigRegion* region, int n){ int r; r = onig_region_resize(region, n); if (r != 0) return r; onig_region_clear(region); return 0;} extern intonig_region_set(OnigRegion* region, int at, int beg, int end){ if (at < 0) return ONIGERR_INVALID_ARGUMENT; if (at >= region->allocated) { int r = onig_region_resize(region, at + 1); if (r < 0) return r; } region->beg[at] = beg; region->end[at] = end; return 0;}extern voidonig_region_init(OnigRegion* region){ region->num_regs = 0; region->allocated = 0; region->beg = (int* )0; region->end = (int* )0; region->history_root = (OnigCaptureTreeNode* )0;}extern OnigRegion*onig_region_new(){ OnigRegion* r; r = (OnigRegion* )xmalloc(sizeof(OnigRegion)); onig_region_init(r); return r;}extern voidonig_region_free(OnigRegion* r, int free_self){ if (r) { if (r->allocated > 0) { if (r->beg) xfree(r->beg); if (r->end) xfree(r->end); r->allocated = 0; }#ifdef USE_CAPTURE_HISTORY history_root_free(r);#endif if (free_self) xfree(r); }}extern voidonig_region_copy(OnigRegion* to, OnigRegion* from){#define RREGC_SIZE (sizeof(int) * from->num_regs) int i; if (to == from) return; if (to->allocated == 0) { if (from->num_regs > 0) { to->beg = (int* )xmalloc(RREGC_SIZE); to->end = (int* )xmalloc(RREGC_SIZE); to->allocated = from->num_regs; } } else if (to->allocated < from->num_regs) { to->beg = (int* )xrealloc(to->beg, RREGC_SIZE); to->end = (int* )xrealloc(to->end, RREGC_SIZE); to->allocated = from->num_regs; } for (i = 0; i < from->num_regs; i++) { to->beg[i] = from->beg[i]; to->end[i] = from->end[i]; } to->num_regs = from->num_regs;#ifdef USE_CAPTURE_HISTORY history_root_free(to); if (IS_NOT_NULL(from->history_root)) { to->history_root = history_tree_clone(from->history_root); }#endif}/** stack **/#define INVALID_STACK_INDEX -1typedef long StackIndex;typedef struct _StackType { unsigned int type; union { struct { UChar *pcode; /* byte code position */ UChar *pstr; /* string position */ UChar *pstr_prev; /* previous char position of pstr */ } state; struct { int count; /* for OP_REPEAT_INC, OP_REPEAT_INC_NG */ UChar *pcode; /* byte code position (head of repeated target) */ int num; /* repeat id */ } repeat; struct { StackIndex si; /* index of stack */ } repeat_inc; struct { int num; /* memory num */ UChar *pstr; /* start/end position */ /* Following information is setted, if this stack type is MEM-START */ StackIndex start; /* prev. info (for backtrack "(...)*" ) */ StackIndex end; /* prev. info (for backtrack "(...)*" ) */ } mem; struct { int num; /* null check id */ UChar *pstr; /* start position */ } null_check;#ifdef USE_SUBEXP_CALL struct { UChar *ret_addr; /* byte code position */ int num; /* null check id */ UChar *pstr; /* string position */ } call_frame;#endif } u;} StackType;/* stack type *//* used by normal-POP */#define STK_ALT 0x0001#define STK_LOOK_BEHIND_NOT 0x0003#define STK_POS_NOT 0x0005/* avoided by normal-POP, but value should be small */#define STK_NULL_CHECK_START 0x0100/* handled by normal-POP */#define STK_MEM_START 0x0200#define STK_MEM_END 0x0300#define STK_REPEAT_INC 0x0400/* avoided by normal-POP */#define STK_POS 0x0500 /* used when POP-POS */#define STK_STOP_BT 0x0600 /* mark for "(?>...)" */#define STK_REPEAT 0x0700#define STK_CALL_FRAME 0x0800#define STK_RETURN 0x0900#define STK_MEM_END_MARK 0x0a00#define STK_VOID 0x0b00 /* for fill a blank */#define STK_NULL_CHECK_END 0x0c00 /* for recursive call *//* stack type check mask */#define STK_MASK_POP_USED 0x00ff#define IS_TO_VOID_TARGET(stk) \ (((stk)->type & STK_MASK_POP_USED) || (stk)->type == STK_NULL_CHECK_START)typedef struct { void* stack_p; int stack_n; OnigOptionType options; OnigRegion* region; const UChar* start; /* search start position (for \G: BEGIN_POSITION) */} MatchArg;#define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start) do {\ (msa).stack_p = (void* )0;\ (msa).options = (arg_option);\ (msa).region = (arg_region);\ (msa).start = (arg_start);\} while (0)#define MATCH_ARG_FREE(msa) if ((msa).stack_p) xfree((msa).stack_p)#define STACK_INIT(alloc_addr, ptr_num, stack_num) do {\ if (msa->stack_p) {\ alloc_addr = (char* )xalloca(sizeof(char*) * (ptr_num));\ stk_alloc = (StackType* )(msa->stack_p);\ stk_base = stk_alloc;\ stk = stk_base;\ stk_end = stk_base + msa->stack_n;\ }\ else {\ alloc_addr = (char* )xalloca(sizeof(char*) * (ptr_num)\ + sizeof(StackType) * (stack_num));\ stk_alloc = (StackType* )(alloc_addr + sizeof(char*) * (ptr_num));\ stk_base = stk_alloc;\ stk = stk_base;\ stk_end = stk_base + (stack_num);\ }\} while(0)#define STACK_SAVE do{\ if (stk_base != stk_alloc) {\ msa->stack_p = stk_base;\ msa->stack_n = stk_end - stk_base;\ };\} while(0)static unsigned int MatchStackLimitSize = DEFAULT_MATCH_STACK_LIMIT_SIZE;extern unsigned intonig_get_match_stack_limit_size(void){ return MatchStackLimitSize;}extern intonig_set_match_stack_limit_size(unsigned int size){ MatchStackLimitSize = size; return 0;}static intstack_double(StackType** arg_stk_base, StackType** arg_stk_end, StackType** arg_stk, StackType* stk_alloc, MatchArg* msa){ unsigned int n; StackType *x, *stk_base, *stk_end, *stk; stk_base = *arg_stk_base; stk_end = *arg_stk_end; stk = *arg_stk; n = stk_end - stk_base; if (stk_base == stk_alloc && IS_NULL(msa->stack_p)) { x = (StackType* )xmalloc(sizeof(StackType) * n * 2); if (IS_NULL(x)) { STACK_SAVE; return ONIGERR_MEMORY; } xmemcpy(x, stk_base, n * sizeof(StackType)); n *= 2; } else { n *= 2; if (MatchStackLimitSize != 0 && n > MatchStackLimitSize) { if ((unsigned int )(stk_end - stk_base) == MatchStackLimitSize) return ONIGERR_MATCH_STACK_LIMIT_OVER; else n = MatchStackLimitSize; } x = (StackType* )xrealloc(stk_base, sizeof(StackType) * n); if (IS_NULL(x)) { STACK_SAVE; return ONIGERR_MEMORY; } } *arg_stk = x + (stk - stk_base); *arg_stk_base = x; *arg_stk_end = x + n; return 0;}#define STACK_ENSURE(n) do {\ if (stk_end - stk < (n)) {\ int r = stack_double(&stk_base, &stk_end, &stk, stk_alloc, msa);\ if (r != 0) { STACK_SAVE; return r; } \ }\} while(0)#define STACK_AT(index) (stk_base + (index))#define GET_STACK_INDEX(stk) ((stk) - stk_base)#define STACK_PUSH(stack_type,pat,s,sprev) do {\ STACK_ENSURE(1);\ stk->type = (stack_type);\ stk->u.state.pcode = (pat);\ stk->u.state.pstr = (s);\ stk->u.state.pstr_prev = (sprev);\ STACK_INC;\} while(0)#define STACK_PUSH_ENSURED(stack_type,pat) do {\ stk->type = (stack_type);\ stk->u.state.pcode = (pat);\ STACK_INC;\} while(0)#define STACK_PUSH_TYPE(stack_type) do {\ STACK_ENSURE(1);\ stk->type = (stack_type);\ STACK_INC;\} while(0)#define STACK_PUSH_ALT(pat,s,sprev) STACK_PUSH(STK_ALT,pat,s,sprev)#define STACK_PUSH_POS(s,sprev) STACK_PUSH(STK_POS,NULL_UCHARP,s,sprev)#define STACK_PUSH_POS_NOT(pat,s,sprev) STACK_PUSH(STK_POS_NOT,pat,s,sprev)#define STACK_PUSH_STOP_BT STACK_PUSH_TYPE(STK_STOP_BT)#define STACK_PUSH_LOOK_BEHIND_NOT(pat,s,sprev) \ STACK_PUSH(STK_LOOK_BEHIND_NOT,pat,s,sprev)#define STACK_PUSH_REPEAT(id, pat) do {\ STACK_ENSURE(1);\ stk->type = STK_REPEAT;\ stk->u.repeat.num = (id);\ stk->u.repeat.pcode = (pat);\ stk->u.repeat.count = 0;\ STACK_INC;\} while(0)#define STACK_PUSH_REPEAT_INC(sindex) do {\ STACK_ENSURE(1);\ stk->type = STK_REPEAT_INC;\ stk->u.repeat_inc.si = (sindex);\ STACK_INC;\} while(0)#define STACK_PUSH_MEM_START(mnum, s) do {\ STACK_ENSURE(1);\ stk->type = STK_MEM_START;\ stk->u.mem.num = (mnum);\ stk->u.mem.pstr = (s);\ stk->u.mem.start = mem_start_stk[mnum];\ stk->u.mem.end = mem_end_stk[mnum];\ mem_start_stk[mnum] = GET_STACK_INDEX(stk);\ mem_end_stk[mnum] = INVALID_STACK_INDEX;\ STACK_INC;\} while(0)#define STACK_PUSH_MEM_END(mnum, s) do {\ STACK_ENSURE(1);\ stk->type = STK_MEM_END;\ stk->u.mem.num = (mnum);\ stk->u.mem.pstr = (s);\ stk->u.mem.start = mem_start_stk[mnum];\ stk->u.mem.end = mem_end_stk[mnum];\ mem_end_stk[mnum] = GET_STACK_INDEX(stk);\ STACK_INC;\} while(0)#define STACK_PUSH_MEM_END_MARK(mnum) do {\ STACK_ENSURE(1);\ stk->type = STK_MEM_END_MARK;\ stk->u.mem.num = (mnum);\ STACK_INC;\} while(0)#define STACK_GET_MEM_START(mnum, k) do {\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -