|
Packit |
b89d10 |
/**********************************************************************
|
|
Packit |
b89d10 |
regcomp.c - Oniguruma (regular expression library)
|
|
Packit |
b89d10 |
**********************************************************************/
|
|
Packit |
b89d10 |
/*-
|
|
Packit |
b89d10 |
* Copyright (c) 2002-2018 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
|
|
Packit |
b89d10 |
* All rights reserved.
|
|
Packit |
b89d10 |
*
|
|
Packit |
b89d10 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
b89d10 |
* modification, are permitted provided that the following conditions
|
|
Packit |
b89d10 |
* are met:
|
|
Packit |
b89d10 |
* 1. Redistributions of source code must retain the above copyright
|
|
Packit |
b89d10 |
* notice, this list of conditions and the following disclaimer.
|
|
Packit |
b89d10 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
Packit |
b89d10 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit |
b89d10 |
* documentation and/or other materials provided with the distribution.
|
|
Packit |
b89d10 |
*
|
|
Packit |
b89d10 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
Packit |
b89d10 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
b89d10 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
b89d10 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
Packit |
b89d10 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit |
b89d10 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
Packit |
b89d10 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
Packit |
b89d10 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
Packit |
b89d10 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
Packit |
b89d10 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
Packit |
b89d10 |
* SUCH DAMAGE.
|
|
Packit |
b89d10 |
*/
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#include "regparse.h"
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
OnigCaseFoldType OnigDefaultCaseFoldFlag = ONIGENC_CASE_FOLD_MIN;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#if 0
|
|
Packit |
b89d10 |
typedef struct {
|
|
Packit |
b89d10 |
int n;
|
|
Packit |
b89d10 |
int alloc;
|
|
Packit |
b89d10 |
int* v;
|
|
Packit |
b89d10 |
} int_stack;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
make_int_stack(int_stack** rs, int init_size)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int_stack* s;
|
|
Packit |
b89d10 |
int* v;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
*rs = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
s = xmalloc(sizeof(*s));
|
|
Packit |
b89d10 |
if (IS_NULL(s)) return ONIGERR_MEMORY;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
v = (int* )xmalloc(sizeof(int) * init_size);
|
|
Packit |
b89d10 |
if (IS_NULL(v)) {
|
|
Packit |
b89d10 |
xfree(s);
|
|
Packit |
b89d10 |
return ONIGERR_MEMORY;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
s->n = 0;
|
|
Packit |
b89d10 |
s->alloc = init_size;
|
|
Packit |
b89d10 |
s->v = v;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
*rs = s;
|
|
Packit |
b89d10 |
return ONIG_NORMAL;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static void
|
|
Packit |
b89d10 |
free_int_stack(int_stack* s)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(s)) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(s->v))
|
|
Packit |
b89d10 |
xfree(s->v);
|
|
Packit |
b89d10 |
xfree(s);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
int_stack_push(int_stack* s, int v)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (s->n >= s->alloc) {
|
|
Packit |
b89d10 |
int new_size = s->alloc * 2;
|
|
Packit |
b89d10 |
int* nv = (int* )xrealloc(s->v, sizeof(int) * new_size);
|
|
Packit |
b89d10 |
if (IS_NULL(nv)) return ONIGERR_MEMORY;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
s->alloc = new_size;
|
|
Packit |
b89d10 |
s->v = nv;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
s->v[s->n] = v;
|
|
Packit |
b89d10 |
s->n++;
|
|
Packit |
b89d10 |
return ONIG_NORMAL;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
int_stack_pop(int_stack* s)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int v;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef ONIG_DEBUG
|
|
Packit |
b89d10 |
if (s->n <= 0) {
|
|
Packit |
b89d10 |
fprintf(stderr, "int_stack_pop: fail empty. %p\n", s);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
v = s->v[s->n];
|
|
Packit |
b89d10 |
s->n--;
|
|
Packit |
b89d10 |
return v;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
extern OnigCaseFoldType
|
|
Packit |
b89d10 |
onig_get_default_case_fold_flag(void)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
return OnigDefaultCaseFoldFlag;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
extern int
|
|
Packit |
b89d10 |
onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
OnigDefaultCaseFoldFlag = case_fold_flag;
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
int_multiply_cmp(int x, int y, int v)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (x == 0 || y == 0) return -1;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (x < INT_MAX / y) {
|
|
Packit |
b89d10 |
int xy = x * y;
|
|
Packit |
b89d10 |
if (xy > v) return 1;
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (xy == v) return 0;
|
|
Packit |
b89d10 |
else return -1;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifndef PLATFORM_UNALIGNED_WORD_ACCESS
|
|
Packit |
b89d10 |
static unsigned char PadBuf[WORD_ALIGNMENT_SIZE];
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static void
|
|
Packit |
b89d10 |
swap_node(Node* a, Node* b)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node c;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
c = *a; *a = *b; *b = c;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_TYPE(a) == NODE_STRING) {
|
|
Packit |
b89d10 |
StrNode* sn = STR_(a);
|
|
Packit |
b89d10 |
if (sn->capa == 0) {
|
|
Packit |
b89d10 |
int len = (int )(sn->end - sn->s);
|
|
Packit |
b89d10 |
sn->s = sn->buf;
|
|
Packit |
b89d10 |
sn->end = sn->s + len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_TYPE(b) == NODE_STRING) {
|
|
Packit |
b89d10 |
StrNode* sn = STR_(b);
|
|
Packit |
b89d10 |
if (sn->capa == 0) {
|
|
Packit |
b89d10 |
int len = (int )(sn->end - sn->s);
|
|
Packit |
b89d10 |
sn->s = sn->buf;
|
|
Packit |
b89d10 |
sn->end = sn->s + len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static OnigLen
|
|
Packit |
b89d10 |
distance_add(OnigLen d1, OnigLen d2)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (d1 == INFINITE_LEN || d2 == INFINITE_LEN)
|
|
Packit |
b89d10 |
return INFINITE_LEN;
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (d1 <= INFINITE_LEN - d2) return d1 + d2;
|
|
Packit |
b89d10 |
else return INFINITE_LEN;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static OnigLen
|
|
Packit |
b89d10 |
distance_multiply(OnigLen d, int m)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (m == 0) return 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (d < INFINITE_LEN / m)
|
|
Packit |
b89d10 |
return d * m;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return INFINITE_LEN;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
bitset_is_empty(BitSetRef bs)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int i;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (i = 0; i < (int )BITSET_SIZE; i++) {
|
|
Packit |
b89d10 |
if (bs[i] != 0) return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
extern int
|
|
Packit |
b89d10 |
onig_bbuf_init(BBuf* buf, int size)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (size <= 0) {
|
|
Packit |
b89d10 |
size = 0;
|
|
Packit |
b89d10 |
buf->p = NULL;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
buf->p = (UChar* )xmalloc(size);
|
|
Packit |
b89d10 |
if (IS_NULL(buf->p)) return(ONIGERR_MEMORY);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
buf->alloc = size;
|
|
Packit |
b89d10 |
buf->used = 0;
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
unset_addr_list_init(UnsetAddrList* list, int size)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
UnsetAddr* p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size);
|
|
Packit |
b89d10 |
CHECK_NULL_RETURN_MEMERR(p);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
list->num = 0;
|
|
Packit |
b89d10 |
list->alloc = size;
|
|
Packit |
b89d10 |
list->us = p;
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static void
|
|
Packit |
b89d10 |
unset_addr_list_end(UnsetAddrList* list)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(list->us))
|
|
Packit |
b89d10 |
xfree(list->us);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
unset_addr_list_add(UnsetAddrList* list, int offset, struct _Node* node)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
UnsetAddr* p;
|
|
Packit |
b89d10 |
int size;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (list->num >= list->alloc) {
|
|
Packit |
b89d10 |
size = list->alloc * 2;
|
|
Packit |
b89d10 |
p = (UnsetAddr* )xrealloc(list->us, sizeof(UnsetAddr) * size);
|
|
Packit |
b89d10 |
CHECK_NULL_RETURN_MEMERR(p);
|
|
Packit |
b89d10 |
list->alloc = size;
|
|
Packit |
b89d10 |
list->us = p;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
list->us[list->num].offset = offset;
|
|
Packit |
b89d10 |
list->us[list->num].target = node;
|
|
Packit |
b89d10 |
list->num++;
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#endif /* USE_CALL */
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_opcode(regex_t* reg, int opcode)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
BB_ADD1(reg, opcode);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_rel_addr(regex_t* reg, int addr)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
RelAddrType ra = (RelAddrType )addr;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
BB_ADD(reg, &ra, SIZE_RELADDR);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_abs_addr(regex_t* reg, int addr)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
AbsAddrType ra = (AbsAddrType )addr;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
BB_ADD(reg, &ra, SIZE_ABSADDR);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_length(regex_t* reg, int len)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
LengthType l = (LengthType )len;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
BB_ADD(reg, &l, SIZE_LENGTH);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_mem_num(regex_t* reg, int num)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
MemNumType n = (MemNumType )num;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
BB_ADD(reg, &n, SIZE_MEMNUM);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#if 0
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_pointer(regex_t* reg, void* addr)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
PointerType ptr = (PointerType )addr;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
BB_ADD(reg, &ptr, SIZE_POINTER);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_option(regex_t* reg, OnigOptionType option)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
BB_ADD(reg, &option, SIZE_OPTION);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_save_type(regex_t* reg, enum SaveType type)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
SaveType t = (SaveType )type;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
BB_ADD(reg, &t, SIZE_SAVE_TYPE);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_update_var_type(regex_t* reg, enum UpdateVarType type)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
UpdateVarType t = (UpdateVarType )type;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
BB_ADD(reg, &t, SIZE_UPDATE_VAR_TYPE);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_mode(regex_t* reg, ModeType mode)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
BB_ADD(reg, &mode, SIZE_MODE);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_opcode_rel_addr(regex_t* reg, int opcode, int addr)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_opcode(reg, opcode);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_rel_addr(reg, addr);
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_bytes(regex_t* reg, UChar* bytes, int len)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
BB_ADD(reg, bytes, len);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_bitset(regex_t* reg, BitSetRef bs)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
BB_ADD(reg, bs, SIZE_BITSET);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_opcode_option(regex_t* reg, int opcode, OnigOptionType option)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_opcode(reg, opcode);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_option(reg, option);
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int compile_length_tree(Node* node, regex_t* reg);
|
|
Packit |
b89d10 |
static int compile_tree(Node* node, regex_t* reg, ScanEnv* env);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#define IS_NEED_STR_LEN_OP_EXACT(op) \
|
|
Packit |
b89d10 |
((op) == OP_EXACTN || (op) == OP_EXACTMB2N ||\
|
|
Packit |
b89d10 |
(op) == OP_EXACTMB3N || (op) == OP_EXACTMBN || (op) == OP_EXACTN_IC)
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
select_str_opcode(int mb_len, int str_len, int ignore_case)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int op;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (ignore_case) {
|
|
Packit |
b89d10 |
switch (str_len) {
|
|
Packit |
b89d10 |
case 1: op = OP_EXACT1_IC; break;
|
|
Packit |
b89d10 |
default: op = OP_EXACTN_IC; break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
switch (mb_len) {
|
|
Packit |
b89d10 |
case 1:
|
|
Packit |
b89d10 |
switch (str_len) {
|
|
Packit |
b89d10 |
case 1: op = OP_EXACT1; break;
|
|
Packit |
b89d10 |
case 2: op = OP_EXACT2; break;
|
|
Packit |
b89d10 |
case 3: op = OP_EXACT3; break;
|
|
Packit |
b89d10 |
case 4: op = OP_EXACT4; break;
|
|
Packit |
b89d10 |
case 5: op = OP_EXACT5; break;
|
|
Packit |
b89d10 |
default: op = OP_EXACTN; break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case 2:
|
|
Packit |
b89d10 |
switch (str_len) {
|
|
Packit |
b89d10 |
case 1: op = OP_EXACTMB2N1; break;
|
|
Packit |
b89d10 |
case 2: op = OP_EXACTMB2N2; break;
|
|
Packit |
b89d10 |
case 3: op = OP_EXACTMB2N3; break;
|
|
Packit |
b89d10 |
default: op = OP_EXACTMB2N; break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case 3:
|
|
Packit |
b89d10 |
op = OP_EXACTMB3N;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
op = OP_EXACTMBN;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return op;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_tree_empty_check(Node* node, regex_t* reg, int empty_info, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
int saved_num_null_check = reg->num_null_check;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (empty_info != QUANT_BODY_IS_NOT_EMPTY) {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_EMPTY_CHECK_START);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
reg->num_null_check++;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = compile_tree(node, reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (empty_info != QUANT_BODY_IS_NOT_EMPTY) {
|
|
Packit |
b89d10 |
if (empty_info == QUANT_BODY_IS_EMPTY)
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_EMPTY_CHECK_END);
|
|
Packit |
b89d10 |
else if (empty_info == QUANT_BODY_IS_EMPTY_MEM)
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_EMPTY_CHECK_END_MEMST);
|
|
Packit |
b89d10 |
else if (empty_info == QUANT_BODY_IS_EMPTY_REC)
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_EMPTY_CHECK_END_MEMST_PUSH);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, saved_num_null_check); /* NULL CHECK ID */
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_call(CallNode* node, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_CALL);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = unset_addr_list_add(env->unset_addr_list, BB_GET_OFFSET_POS(reg),
|
|
Packit |
b89d10 |
NODE_CALL_BODY(node));
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_abs_addr(reg, 0 /*dummy addr.*/);
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_tree_n_times(Node* node, int n, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int i, r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (i = 0; i < n; i++) {
|
|
Packit |
b89d10 |
r = compile_tree(node, reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_compile_string_length(UChar* s ARG_UNUSED, int mb_len, int str_len,
|
|
Packit |
b89d10 |
regex_t* reg ARG_UNUSED, int ignore_case)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int len;
|
|
Packit |
b89d10 |
int op = select_str_opcode(mb_len, str_len, ignore_case);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = SIZE_OPCODE;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (op == OP_EXACTMBN) len += SIZE_LENGTH;
|
|
Packit |
b89d10 |
if (IS_NEED_STR_LEN_OP_EXACT(op))
|
|
Packit |
b89d10 |
len += SIZE_LENGTH;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len += mb_len * str_len;
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_compile_string(UChar* s, int mb_len, int str_len,
|
|
Packit |
b89d10 |
regex_t* reg, int ignore_case)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int op = select_str_opcode(mb_len, str_len, ignore_case);
|
|
Packit |
b89d10 |
add_opcode(reg, op);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (op == OP_EXACTMBN)
|
|
Packit |
b89d10 |
add_length(reg, mb_len);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NEED_STR_LEN_OP_EXACT(op)) {
|
|
Packit |
b89d10 |
if (op == OP_EXACTN_IC)
|
|
Packit |
b89d10 |
add_length(reg, mb_len * str_len);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
add_length(reg, str_len);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
add_bytes(reg, s, mb_len * str_len);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_string_node(Node* node, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int rlen, r, len, prev_len, slen, ambig;
|
|
Packit |
b89d10 |
UChar *p, *prev;
|
|
Packit |
b89d10 |
StrNode* sn;
|
|
Packit |
b89d10 |
OnigEncoding enc = reg->enc;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
sn = STR_(node);
|
|
Packit |
b89d10 |
if (sn->end <= sn->s)
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
ambig = NODE_STRING_IS_AMBIG(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
p = prev = sn->s;
|
|
Packit |
b89d10 |
prev_len = enclen(enc, p);
|
|
Packit |
b89d10 |
p += prev_len;
|
|
Packit |
b89d10 |
slen = 1;
|
|
Packit |
b89d10 |
rlen = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (; p < sn->end; ) {
|
|
Packit |
b89d10 |
len = enclen(enc, p);
|
|
Packit |
b89d10 |
if (len == prev_len) {
|
|
Packit |
b89d10 |
slen++;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
|
|
Packit |
b89d10 |
rlen += r;
|
|
Packit |
b89d10 |
prev = p;
|
|
Packit |
b89d10 |
slen = 1;
|
|
Packit |
b89d10 |
prev_len = len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
p += len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
|
|
Packit |
b89d10 |
rlen += r;
|
|
Packit |
b89d10 |
return rlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_string_raw_node(StrNode* sn, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (sn->end <= sn->s)
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return add_compile_string_length(sn->s, 1 /* sb */, (int )(sn->end - sn->s),
|
|
Packit |
b89d10 |
reg, 0);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_string_node(Node* node, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r, len, prev_len, slen, ambig;
|
|
Packit |
b89d10 |
UChar *p, *prev, *end;
|
|
Packit |
b89d10 |
StrNode* sn;
|
|
Packit |
b89d10 |
OnigEncoding enc = reg->enc;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
sn = STR_(node);
|
|
Packit |
b89d10 |
if (sn->end <= sn->s)
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
end = sn->end;
|
|
Packit |
b89d10 |
ambig = NODE_STRING_IS_AMBIG(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
p = prev = sn->s;
|
|
Packit |
b89d10 |
prev_len = enclen(enc, p);
|
|
Packit |
b89d10 |
p += prev_len;
|
|
Packit |
b89d10 |
slen = 1;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (; p < end; ) {
|
|
Packit |
b89d10 |
len = enclen(enc, p);
|
|
Packit |
b89d10 |
if (len == prev_len) {
|
|
Packit |
b89d10 |
slen++;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = add_compile_string(prev, prev_len, slen, reg, ambig);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
prev = p;
|
|
Packit |
b89d10 |
slen = 1;
|
|
Packit |
b89d10 |
prev_len = len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
p += len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return add_compile_string(prev, prev_len, slen, reg, ambig);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_string_raw_node(StrNode* sn, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (sn->end <= sn->s)
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return add_compile_string(sn->s, 1 /* sb */, (int )(sn->end - sn->s), reg, 0);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
add_multi_byte_cclass(BBuf* mbuf, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
|
|
Packit |
b89d10 |
add_length(reg, mbuf->used);
|
|
Packit |
b89d10 |
return add_bytes(reg, mbuf->p, mbuf->used);
|
|
Packit |
b89d10 |
#else
|
|
Packit |
b89d10 |
int r, pad_size;
|
|
Packit |
b89d10 |
UChar* p = BB_GET_ADD_ADDRESS(reg) + SIZE_LENGTH;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
GET_ALIGNMENT_PAD_SIZE(p, pad_size);
|
|
Packit |
b89d10 |
add_length(reg, mbuf->used + (WORD_ALIGNMENT_SIZE - 1));
|
|
Packit |
b89d10 |
if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_bytes(reg, mbuf->p, mbuf->used);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
/* padding for return value from compile_length_cclass_node() to be fix. */
|
|
Packit |
b89d10 |
pad_size = (WORD_ALIGNMENT_SIZE - 1) - pad_size;
|
|
Packit |
b89d10 |
if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_cclass_node(CClassNode* cc, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int len;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NULL(cc->mbuf)) {
|
|
Packit |
b89d10 |
len = SIZE_OPCODE + SIZE_BITSET;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
|
|
Packit |
b89d10 |
len = SIZE_OPCODE;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
len = SIZE_OPCODE + SIZE_BITSET;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
|
|
Packit |
b89d10 |
len += SIZE_LENGTH + cc->mbuf->used;
|
|
Packit |
b89d10 |
#else
|
|
Packit |
b89d10 |
len += SIZE_LENGTH + cc->mbuf->used + (WORD_ALIGNMENT_SIZE - 1);
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_cclass_node(CClassNode* cc, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NULL(cc->mbuf)) {
|
|
Packit |
b89d10 |
if (IS_NCCLASS_NOT(cc))
|
|
Packit |
b89d10 |
add_opcode(reg, OP_CCLASS_NOT);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
add_opcode(reg, OP_CCLASS);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_bitset(reg, cc->bs);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
|
|
Packit |
b89d10 |
if (IS_NCCLASS_NOT(cc))
|
|
Packit |
b89d10 |
add_opcode(reg, OP_CCLASS_MB_NOT);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
add_opcode(reg, OP_CCLASS_MB);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_multi_byte_cclass(cc->mbuf, reg);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (IS_NCCLASS_NOT(cc))
|
|
Packit |
b89d10 |
add_opcode(reg, OP_CCLASS_MIX_NOT);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
add_opcode(reg, OP_CCLASS_MIX);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_bitset(reg, cc->bs);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_multi_byte_cclass(cc->mbuf, reg);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
entry_repeat_range(regex_t* reg, int id, int lower, int upper)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
#define REPEAT_RANGE_ALLOC 4
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
OnigRepeatRange* p;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (reg->repeat_range_alloc == 0) {
|
|
Packit |
b89d10 |
p = (OnigRepeatRange* )xmalloc(sizeof(OnigRepeatRange) * REPEAT_RANGE_ALLOC);
|
|
Packit |
b89d10 |
CHECK_NULL_RETURN_MEMERR(p);
|
|
Packit |
b89d10 |
reg->repeat_range = p;
|
|
Packit |
b89d10 |
reg->repeat_range_alloc = REPEAT_RANGE_ALLOC;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (reg->repeat_range_alloc <= id) {
|
|
Packit |
b89d10 |
int n;
|
|
Packit |
b89d10 |
n = reg->repeat_range_alloc + REPEAT_RANGE_ALLOC;
|
|
Packit |
b89d10 |
p = (OnigRepeatRange* )xrealloc(reg->repeat_range,
|
|
Packit |
b89d10 |
sizeof(OnigRepeatRange) * n);
|
|
Packit |
b89d10 |
CHECK_NULL_RETURN_MEMERR(p);
|
|
Packit |
b89d10 |
reg->repeat_range = p;
|
|
Packit |
b89d10 |
reg->repeat_range_alloc = n;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
p = reg->repeat_range;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
p[id].lower = lower;
|
|
Packit |
b89d10 |
p[id].upper = (IS_REPEAT_INFINITE(upper) ? 0x7fffffff : upper);
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_range_repeat_node(QuantNode* qn, int target_len, int empty_info,
|
|
Packit |
b89d10 |
regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
int num_repeat = reg->num_repeat;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_opcode(reg, qn->greedy ? OP_REPEAT : OP_REPEAT_NG);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
|
|
Packit |
b89d10 |
reg->num_repeat++;
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_rel_addr(reg, target_len + SIZE_OP_REPEAT_INC);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = entry_repeat_range(reg, num_repeat, qn->lower, qn->upper);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
NODE_IS_IN_MULTI_ENTRY(qn) ||
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
NODE_IS_IN_REAL_REPEAT(qn)) {
|
|
Packit |
b89d10 |
r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
is_anychar_infinite_greedy(QuantNode* qn)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (qn->greedy && IS_REPEAT_INFINITE(qn->upper) &&
|
|
Packit |
b89d10 |
NODE_IS_ANYCHAR(NODE_QUANT_BODY(qn)))
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#define QUANTIFIER_EXPAND_LIMIT_SIZE 50
|
|
Packit |
b89d10 |
#define CKN_ON (ckn > 0)
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_quantifier_node(QuantNode* qn, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int len, mod_tlen;
|
|
Packit |
b89d10 |
int infinite = IS_REPEAT_INFINITE(qn->upper);
|
|
Packit |
b89d10 |
enum QuantBodyEmpty empty_info = qn->body_empty_info;
|
|
Packit |
b89d10 |
int tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (tlen < 0) return tlen;
|
|
Packit |
b89d10 |
if (tlen == 0) return 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
/* anychar repeat */
|
|
Packit |
b89d10 |
if (is_anychar_infinite_greedy(qn)) {
|
|
Packit |
b89d10 |
if (qn->lower <= 1 ||
|
|
Packit |
b89d10 |
int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(qn->next_head_exact))
|
|
Packit |
b89d10 |
return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (empty_info == QUANT_BODY_IS_NOT_EMPTY)
|
|
Packit |
b89d10 |
mod_tlen = tlen;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
mod_tlen = tlen + (SIZE_OP_EMPTY_CHECK_START + SIZE_OP_EMPTY_CHECK_END);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (infinite &&
|
|
Packit |
b89d10 |
(qn->lower <= 1 ||
|
|
Packit |
b89d10 |
int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
|
|
Packit |
b89d10 |
if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
|
|
Packit |
b89d10 |
len = SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
len = tlen * qn->lower;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (qn->greedy) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(qn->head_exact))
|
|
Packit |
b89d10 |
len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
else if (IS_NOT_NULL(qn->next_head_exact))
|
|
Packit |
b89d10 |
len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
|
|
Packit |
b89d10 |
len = SIZE_OP_JUMP + tlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (!infinite && qn->greedy &&
|
|
Packit |
b89d10 |
(qn->upper == 1 ||
|
|
Packit |
b89d10 |
int_multiply_cmp(tlen + SIZE_OP_PUSH, qn->upper,
|
|
Packit |
b89d10 |
QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
|
|
Packit |
b89d10 |
len = tlen * qn->lower;
|
|
Packit |
b89d10 |
len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
|
|
Packit |
b89d10 |
len = SIZE_OP_PUSH + SIZE_OP_JUMP + tlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
len = SIZE_OP_REPEAT_INC
|
|
Packit |
b89d10 |
+ mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_quantifier_node(QuantNode* qn, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int i, r, mod_tlen;
|
|
Packit |
b89d10 |
int infinite = IS_REPEAT_INFINITE(qn->upper);
|
|
Packit |
b89d10 |
enum QuantBodyEmpty empty_info = qn->body_empty_info;
|
|
Packit |
b89d10 |
int tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (tlen < 0) return tlen;
|
|
Packit |
b89d10 |
if (tlen == 0) return 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (is_anychar_infinite_greedy(qn) &&
|
|
Packit |
b89d10 |
(qn->lower <= 1 ||
|
|
Packit |
b89d10 |
int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
|
|
Packit |
b89d10 |
r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(qn->next_head_exact)) {
|
|
Packit |
b89d10 |
if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg)))
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
return add_bytes(reg, STR_(qn->next_head_exact)->s, 1);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg)))
|
|
Packit |
b89d10 |
return add_opcode(reg, OP_ANYCHAR_ML_STAR);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return add_opcode(reg, OP_ANYCHAR_STAR);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (empty_info == QUANT_BODY_IS_NOT_EMPTY)
|
|
Packit |
b89d10 |
mod_tlen = tlen;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
mod_tlen = tlen + (SIZE_OP_EMPTY_CHECK_START + SIZE_OP_EMPTY_CHECK_END);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (infinite &&
|
|
Packit |
b89d10 |
(qn->lower <= 1 ||
|
|
Packit |
b89d10 |
int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
|
|
Packit |
b89d10 |
if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
|
|
Packit |
b89d10 |
if (qn->greedy) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(qn->head_exact))
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);
|
|
Packit |
b89d10 |
else if (IS_NOT_NULL(qn->next_head_exact))
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (qn->greedy) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(qn->head_exact)) {
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,
|
|
Packit |
b89d10 |
mod_tlen + SIZE_OP_JUMP);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
add_bytes(reg, STR_(qn->head_exact)->s, 1);
|
|
Packit |
b89d10 |
r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP,
|
|
Packit |
b89d10 |
-(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (IS_NOT_NULL(qn->next_head_exact)) {
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,
|
|
Packit |
b89d10 |
mod_tlen + SIZE_OP_JUMP);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
add_bytes(reg, STR_(qn->next_head_exact)->s, 1);
|
|
Packit |
b89d10 |
r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP,
|
|
Packit |
b89d10 |
-(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP,
|
|
Packit |
b89d10 |
-(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_QUANT_BODY(qn), reg, env);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (! infinite && qn->greedy &&
|
|
Packit |
b89d10 |
(qn->upper == 1 ||
|
|
Packit |
b89d10 |
int_multiply_cmp(tlen + SIZE_OP_PUSH, qn->upper,
|
|
Packit |
b89d10 |
QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
|
|
Packit |
b89d10 |
int n = qn->upper - qn->lower;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (i = 0; i < n; i++) {
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PUSH,
|
|
Packit |
b89d10 |
(n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_QUANT_BODY(qn), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (! qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_QUANT_BODY(qn), reg, env);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg, env);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_option_node(EnclosureNode* node, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int tlen;
|
|
Packit |
b89d10 |
OnigOptionType prev = reg->options;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
reg->options = node->o.options;
|
|
Packit |
b89d10 |
tlen = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);
|
|
Packit |
b89d10 |
reg->options = prev;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (tlen < 0) return tlen;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
|
|
Packit |
b89d10 |
return SIZE_OP_SET_OPTION_PUSH + SIZE_OP_SET_OPTION + SIZE_OP_FAIL
|
|
Packit |
b89d10 |
+ tlen + SIZE_OP_SET_OPTION;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return tlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_option_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
OnigOptionType prev = reg->options;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_DYNAMIC_OPTION(prev ^ node->o.options)) {
|
|
Packit |
b89d10 |
r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->o.options);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode_option(reg, OP_SET_OPTION, prev);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_FAIL);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
reg->options = node->o.options;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);
|
|
Packit |
b89d10 |
reg->options = prev;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_DYNAMIC_OPTION(prev ^ node->o.options)) {
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode_option(reg, OP_SET_OPTION, prev);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_enclosure_node(EnclosureNode* node, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int len;
|
|
Packit |
b89d10 |
int tlen;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (node->type == ENCLOSURE_OPTION)
|
|
Packit |
b89d10 |
return compile_length_option_node(node, reg);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_ENCLOSURE_BODY(node)) {
|
|
Packit |
b89d10 |
tlen = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);
|
|
Packit |
b89d10 |
if (tlen < 0) return tlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
tlen = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (node->type) {
|
|
Packit |
b89d10 |
case ENCLOSURE_MEMORY:
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (node->m.regnum == 0 && NODE_IS_CALLED(node)) {
|
|
Packit |
b89d10 |
len = tlen + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_IS_CALLED(node)) {
|
|
Packit |
b89d10 |
len = SIZE_OP_MEMORY_START_PUSH + tlen
|
|
Packit |
b89d10 |
+ SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
|
|
Packit |
b89d10 |
if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))
|
|
Packit |
b89d10 |
len += (NODE_IS_RECURSION(node)
|
|
Packit |
b89d10 |
? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
len += (NODE_IS_RECURSION(node)
|
|
Packit |
b89d10 |
? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (NODE_IS_RECURSION(node)) {
|
|
Packit |
b89d10 |
len = SIZE_OP_MEMORY_START_PUSH;
|
|
Packit |
b89d10 |
len += tlen + (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum)
|
|
Packit |
b89d10 |
? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_REC);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (MEM_STATUS_AT0(reg->bt_mem_start, node->m.regnum))
|
|
Packit |
b89d10 |
len = SIZE_OP_MEMORY_START_PUSH;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
len = SIZE_OP_MEMORY_START;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len += tlen + (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum)
|
|
Packit |
b89d10 |
? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ENCLOSURE_STOP_BACKTRACK:
|
|
Packit |
b89d10 |
if (NODE_IS_STOP_BT_SIMPLE_REPEAT(node)) {
|
|
Packit |
b89d10 |
QuantNode* qn = QUANT_(NODE_ENCLOSURE_BODY(node));
|
|
Packit |
b89d10 |
tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);
|
|
Packit |
b89d10 |
if (tlen < 0) return tlen;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = tlen * qn->lower
|
|
Packit |
b89d10 |
+ SIZE_OP_PUSH + tlen + SIZE_OP_POP_OUT + SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
len = SIZE_OP_ATOMIC_START + tlen + SIZE_OP_ATOMIC_END;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ENCLOSURE_IF_ELSE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node* cond = NODE_ENCLOSURE_BODY(node);
|
|
Packit |
b89d10 |
Node* Then = node->te.Then;
|
|
Packit |
b89d10 |
Node* Else = node->te.Else;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = compile_length_tree(cond, reg);
|
|
Packit |
b89d10 |
if (len < 0) return len;
|
|
Packit |
b89d10 |
len += SIZE_OP_PUSH;
|
|
Packit |
b89d10 |
len += SIZE_OP_ATOMIC_START + SIZE_OP_ATOMIC_END;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(Then)) {
|
|
Packit |
b89d10 |
tlen = compile_length_tree(Then, reg);
|
|
Packit |
b89d10 |
if (tlen < 0) return tlen;
|
|
Packit |
b89d10 |
len += tlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(Else)) {
|
|
Packit |
b89d10 |
len += SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
tlen = compile_length_tree(Else, reg);
|
|
Packit |
b89d10 |
if (tlen < 0) return tlen;
|
|
Packit |
b89d10 |
len += tlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
return ONIGERR_TYPE_BUG;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int get_char_length_tree(Node* node, regex_t* reg, int* len);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_enclosure_memory_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
int len;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
if (node->m.regnum == 0 && NODE_IS_CALLED(node)) {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_CALL);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
node->m.called_addr = BB_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_ADDR_FIXED);
|
|
Packit |
b89d10 |
r = add_abs_addr(reg, (int )node->m.called_addr);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
len = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);
|
|
Packit |
b89d10 |
len += SIZE_OP_RETURN;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, len);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_RETURN);
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_IS_CALLED(node)) {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_CALL);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
node->m.called_addr = BB_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_ADDR_FIXED);
|
|
Packit |
b89d10 |
r = add_abs_addr(reg, (int )node->m.called_addr);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
len = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);
|
|
Packit |
b89d10 |
len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);
|
|
Packit |
b89d10 |
if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))
|
|
Packit |
b89d10 |
len += (NODE_IS_RECURSION(node)
|
|
Packit |
b89d10 |
? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
len += (NODE_IS_RECURSION(node)
|
|
Packit |
b89d10 |
? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, len);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (MEM_STATUS_AT0(reg->bt_mem_start, node->m.regnum))
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_MEMORY_START_PUSH);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_MEMORY_START);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, node->m.regnum);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))
|
|
Packit |
b89d10 |
r = add_opcode(reg, (NODE_IS_RECURSION(node)
|
|
Packit |
b89d10 |
? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = add_opcode(reg, (NODE_IS_RECURSION(node)
|
|
Packit |
b89d10 |
? OP_MEMORY_END_REC : OP_MEMORY_END));
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, node->m.regnum);
|
|
Packit |
b89d10 |
if (NODE_IS_CALLED(node)) {
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_RETURN);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#else
|
|
Packit |
b89d10 |
if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_MEMORY_END_PUSH);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_MEMORY_END);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, node->m.regnum);
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_enclosure_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r, len;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (node->type) {
|
|
Packit |
b89d10 |
case ENCLOSURE_MEMORY:
|
|
Packit |
b89d10 |
r = compile_enclosure_memory_node(node, reg, env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ENCLOSURE_OPTION:
|
|
Packit |
b89d10 |
r = compile_option_node(node, reg, env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ENCLOSURE_STOP_BACKTRACK:
|
|
Packit |
b89d10 |
if (NODE_IS_STOP_BT_SIMPLE_REPEAT(node)) {
|
|
Packit |
b89d10 |
QuantNode* qn = QUANT_(NODE_ENCLOSURE_BODY(node));
|
|
Packit |
b89d10 |
r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = compile_length_tree(NODE_QUANT_BODY(qn), reg);
|
|
Packit |
b89d10 |
if (len < 0) return len;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP_OUT + SIZE_OP_JUMP);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_QUANT_BODY(qn), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_POP_OUT);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP,
|
|
Packit |
b89d10 |
-((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP_OUT + (int )SIZE_OP_JUMP));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_ATOMIC_START);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_ATOMIC_END);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ENCLOSURE_IF_ELSE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int cond_len, then_len, jump_len;
|
|
Packit |
b89d10 |
Node* cond = NODE_ENCLOSURE_BODY(node);
|
|
Packit |
b89d10 |
Node* Then = node->te.Then;
|
|
Packit |
b89d10 |
Node* Else = node->te.Else;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_ATOMIC_START);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
cond_len = compile_length_tree(cond, reg);
|
|
Packit |
b89d10 |
if (cond_len < 0) return cond_len;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(Then)) {
|
|
Packit |
b89d10 |
then_len = compile_length_tree(Then, reg);
|
|
Packit |
b89d10 |
if (then_len < 0) return then_len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
then_len = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
jump_len = cond_len + then_len + SIZE_OP_ATOMIC_END;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(Else)) jump_len += SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PUSH, jump_len);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(cond, reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_ATOMIC_END);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(Then)) {
|
|
Packit |
b89d10 |
r = compile_tree(Then, reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(Else)) {
|
|
Packit |
b89d10 |
int else_len = compile_length_tree(Else, reg);
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, else_len);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(Else, reg, env);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
return ONIGERR_TYPE_BUG;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_anchor_node(AnchorNode* node, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int len;
|
|
Packit |
b89d10 |
int tlen = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(NODE_ANCHOR_BODY(node))) {
|
|
Packit |
b89d10 |
tlen = compile_length_tree(NODE_ANCHOR_BODY(node), reg);
|
|
Packit |
b89d10 |
if (tlen < 0) return tlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (node->type) {
|
|
Packit |
b89d10 |
case ANCHOR_PREC_READ:
|
|
Packit |
b89d10 |
len = SIZE_OP_PREC_READ_START + tlen + SIZE_OP_PREC_READ_END;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
case ANCHOR_PREC_READ_NOT:
|
|
Packit |
b89d10 |
len = SIZE_OP_PREC_READ_NOT_START + tlen + SIZE_OP_PREC_READ_NOT_END;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
case ANCHOR_LOOK_BEHIND:
|
|
Packit |
b89d10 |
len = SIZE_OP_LOOK_BEHIND + tlen;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
case ANCHOR_LOOK_BEHIND_NOT:
|
|
Packit |
b89d10 |
len = SIZE_OP_LOOK_BEHIND_NOT_START + tlen + SIZE_OP_LOOK_BEHIND_NOT_END;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_WORD_BOUNDARY:
|
|
Packit |
b89d10 |
case ANCHOR_NO_WORD_BOUNDARY:
|
|
Packit |
b89d10 |
#ifdef USE_WORD_BEGIN_END
|
|
Packit |
b89d10 |
case ANCHOR_WORD_BEGIN:
|
|
Packit |
b89d10 |
case ANCHOR_WORD_END:
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
len = SIZE_OP_WORD_BOUNDARY;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:
|
|
Packit |
b89d10 |
case ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:
|
|
Packit |
b89d10 |
len = SIZE_OPCODE;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
len = SIZE_OPCODE;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_anchor_node(AnchorNode* node, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r, len;
|
|
Packit |
b89d10 |
enum OpCode op;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (node->type) {
|
|
Packit |
b89d10 |
case ANCHOR_BEGIN_BUF: r = add_opcode(reg, OP_BEGIN_BUF); break;
|
|
Packit |
b89d10 |
case ANCHOR_END_BUF: r = add_opcode(reg, OP_END_BUF); break;
|
|
Packit |
b89d10 |
case ANCHOR_BEGIN_LINE: r = add_opcode(reg, OP_BEGIN_LINE); break;
|
|
Packit |
b89d10 |
case ANCHOR_END_LINE: r = add_opcode(reg, OP_END_LINE); break;
|
|
Packit |
b89d10 |
case ANCHOR_SEMI_END_BUF: r = add_opcode(reg, OP_SEMI_END_BUF); break;
|
|
Packit |
b89d10 |
case ANCHOR_BEGIN_POSITION: r = add_opcode(reg, OP_BEGIN_POSITION); break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_WORD_BOUNDARY:
|
|
Packit |
b89d10 |
op = OP_WORD_BOUNDARY;
|
|
Packit |
b89d10 |
word:
|
|
Packit |
b89d10 |
r = add_opcode(reg, op);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mode(reg, (ModeType )node->ascii_mode);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_NO_WORD_BOUNDARY:
|
|
Packit |
b89d10 |
op = OP_NO_WORD_BOUNDARY; goto word;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#ifdef USE_WORD_BEGIN_END
|
|
Packit |
b89d10 |
case ANCHOR_WORD_BEGIN:
|
|
Packit |
b89d10 |
op = OP_WORD_BEGIN; goto word;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
case ANCHOR_WORD_END:
|
|
Packit |
b89d10 |
op = OP_WORD_END; goto word;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_PREC_READ:
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_PREC_READ_START);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_PREC_READ_END);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_PREC_READ_NOT:
|
|
Packit |
b89d10 |
len = compile_length_tree(NODE_ANCHOR_BODY(node), reg);
|
|
Packit |
b89d10 |
if (len < 0) return len;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_PREC_READ_NOT_START, len + SIZE_OP_PREC_READ_NOT_END);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_PREC_READ_NOT_END);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_LOOK_BEHIND:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int n;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_LOOK_BEHIND);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
if (node->char_len < 0) {
|
|
Packit |
b89d10 |
r = get_char_length_tree(NODE_ANCHOR_BODY(node), reg, &n);
|
|
Packit |
b89d10 |
if (r != 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
n = node->char_len;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = add_length(reg, n);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ANCHOR_LOOK_BEHIND_NOT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int n;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = compile_length_tree(NODE_ANCHOR_BODY(node), reg);
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_LOOK_BEHIND_NOT_START,
|
|
Packit |
b89d10 |
len + SIZE_OP_LOOK_BEHIND_NOT_END);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
if (node->char_len < 0) {
|
|
Packit |
b89d10 |
r = get_char_length_tree(NODE_ANCHOR_BODY(node), reg, &n);
|
|
Packit |
b89d10 |
if (r != 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
n = node->char_len;
|
|
Packit |
b89d10 |
r = add_length(reg, n);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_LOOK_BEHIND_NOT_END);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
return ONIGERR_TYPE_BUG;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_gimmick_node(GimmickNode* node, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (node->type) {
|
|
Packit |
b89d10 |
case GIMMICK_FAIL:
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_FAIL);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case GIMMICK_KEEP:
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_PUSH_SAVE_VAL);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_save_type(reg, SAVE_KEEP);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, node->id);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case GIMMICK_SAVE:
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_PUSH_SAVE_VAL);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_save_type(reg, node->detail_type);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, node->id);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case GIMMICK_UPDATE_VAR:
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_UPDATE_VAR);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_update_var_type(reg, node->detail_type);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, node->id);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALLOUT
|
|
Packit |
b89d10 |
case GIMMICK_CALLOUT:
|
|
Packit |
b89d10 |
switch (node->detail_type) {
|
|
Packit |
b89d10 |
case ONIG_CALLOUT_OF_CONTENTS:
|
|
Packit |
b89d10 |
case ONIG_CALLOUT_OF_NAME:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
r = add_opcode(reg, (node->detail_type == ONIG_CALLOUT_OF_CONTENTS) ?
|
|
Packit |
b89d10 |
OP_CALLOUT_CONTENTS : OP_CALLOUT_NAME);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
if (node->detail_type == ONIG_CALLOUT_OF_NAME) {
|
|
Packit |
b89d10 |
r = add_mem_num(reg, node->id);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
r = add_mem_num(reg, node->num);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
r = ONIGERR_TYPE_BUG;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_gimmick_node(GimmickNode* node, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int len;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (node->type) {
|
|
Packit |
b89d10 |
case GIMMICK_FAIL:
|
|
Packit |
b89d10 |
len = SIZE_OP_FAIL;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case GIMMICK_KEEP:
|
|
Packit |
b89d10 |
case GIMMICK_SAVE:
|
|
Packit |
b89d10 |
len = SIZE_OP_PUSH_SAVE_VAL;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case GIMMICK_UPDATE_VAR:
|
|
Packit |
b89d10 |
len = SIZE_OP_UPDATE_VAR;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALLOUT
|
|
Packit |
b89d10 |
case GIMMICK_CALLOUT:
|
|
Packit |
b89d10 |
switch (node->detail_type) {
|
|
Packit |
b89d10 |
case ONIG_CALLOUT_OF_CONTENTS:
|
|
Packit |
b89d10 |
len = SIZE_OP_CALLOUT_CONTENTS;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
case ONIG_CALLOUT_OF_NAME:
|
|
Packit |
b89d10 |
len = SIZE_OP_CALLOUT_NAME;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
len = ONIGERR_TYPE_BUG;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_length_tree(Node* node, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int len, r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
len = 0;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = compile_length_tree(NODE_CAR(node), reg);
|
|
Packit |
b89d10 |
if (r < 0) return r;
|
|
Packit |
b89d10 |
len += r;
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
r = len;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int n;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
n = r = 0;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r += compile_length_tree(NODE_CAR(node), reg);
|
|
Packit |
b89d10 |
n++;
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
if (NODE_STRING_IS_RAW(node))
|
|
Packit |
b89d10 |
r = compile_length_string_raw_node(STR_(node), reg);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = compile_length_string_node(node, reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
r = compile_length_cclass_node(CCLASS_(node), reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
r = SIZE_OPCODE;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
BackRefNode* br = BACKREF_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_IS_CHECKER(node)) {
|
|
Packit |
b89d10 |
#ifdef USE_BACKREF_WITH_LEVEL
|
|
Packit |
b89d10 |
if (NODE_IS_NEST_LEVEL(node)) {
|
|
Packit |
b89d10 |
r = SIZE_OPCODE + SIZE_LENGTH + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
#ifdef USE_BACKREF_WITH_LEVEL
|
|
Packit |
b89d10 |
if (NODE_IS_NEST_LEVEL(node)) {
|
|
Packit |
b89d10 |
r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +
|
|
Packit |
b89d10 |
SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
if (br->back_num == 1) {
|
|
Packit |
b89d10 |
r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)
|
|
Packit |
b89d10 |
? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
case NODE_CALL:
|
|
Packit |
b89d10 |
r = SIZE_OP_CALL;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = compile_length_quantifier_node(QUANT_(node), reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
r = compile_length_enclosure_node(ENCLOSURE_(node), reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
r = compile_length_anchor_node(ANCHOR_(node), reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_GIMMICK:
|
|
Packit |
b89d10 |
r = compile_length_gimmick_node(GIMMICK_(node), reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
return ONIGERR_TYPE_BUG;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
compile_tree(Node* node, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int n, len, pos, r = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = compile_tree(NODE_CAR(node), reg, env);
|
|
Packit |
b89d10 |
} while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node* x = node;
|
|
Packit |
b89d10 |
len = 0;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
len += compile_length_tree(NODE_CAR(x), reg);
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(NODE_CDR(x))) {
|
|
Packit |
b89d10 |
len += SIZE_OP_PUSH + SIZE_OP_JUMP;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(x = NODE_CDR(x)));
|
|
Packit |
b89d10 |
pos = reg->used + len; /* goal position */
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
len = compile_length_tree(NODE_CAR(node), reg);
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(NODE_CDR(node))) {
|
|
Packit |
b89d10 |
enum OpCode push = NODE_IS_SUPER(node) ? OP_PUSH_SUPER : OP_PUSH;
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, push, len + SIZE_OP_JUMP);
|
|
Packit |
b89d10 |
if (r != 0) break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
r = compile_tree(NODE_CAR(node), reg, env);
|
|
Packit |
b89d10 |
if (r != 0) break;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(NODE_CDR(node))) {
|
|
Packit |
b89d10 |
len = pos - (reg->used + SIZE_OP_JUMP);
|
|
Packit |
b89d10 |
r = add_opcode_rel_addr(reg, OP_JUMP, len);
|
|
Packit |
b89d10 |
if (r != 0) break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
if (NODE_STRING_IS_RAW(node))
|
|
Packit |
b89d10 |
r = compile_string_raw_node(STR_(node), reg);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = compile_string_node(node, reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
r = compile_cclass_node(CCLASS_(node), reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int op;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (CTYPE_(node)->ctype) {
|
|
Packit |
b89d10 |
case CTYPE_ANYCHAR:
|
|
Packit |
b89d10 |
if (IS_MULTILINE(CTYPE_OPTION(node, reg)))
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_ANYCHAR_ML);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_ANYCHAR);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ONIGENC_CTYPE_WORD:
|
|
Packit |
b89d10 |
if (CTYPE_(node)->ascii_mode == 0) {
|
|
Packit |
b89d10 |
op = CTYPE_(node)->not != 0 ? OP_NO_WORD : OP_WORD;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
op = CTYPE_(node)->not != 0 ? OP_NO_WORD_ASCII : OP_WORD_ASCII;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
r = add_opcode(reg, op);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
return ONIGERR_TYPE_BUG;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
BackRefNode* br = BACKREF_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_IS_CHECKER(node)) {
|
|
Packit |
b89d10 |
#ifdef USE_BACKREF_WITH_LEVEL
|
|
Packit |
b89d10 |
if (NODE_IS_NEST_LEVEL(node)) {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_BACKREF_CHECK_WITH_LEVEL);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_length(reg, br->nest_level);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_BACKREF_CHECK);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
goto add_bacref_mems;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
#ifdef USE_BACKREF_WITH_LEVEL
|
|
Packit |
b89d10 |
if (NODE_IS_NEST_LEVEL(node)) {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_BACKREF_WITH_LEVEL);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_length(reg, br->nest_level);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
goto add_bacref_mems;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
if (br->back_num == 1) {
|
|
Packit |
b89d10 |
n = br->back_static[0];
|
|
Packit |
b89d10 |
if (IS_IGNORECASE(reg->options)) {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_BACKREF_N_IC);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, n);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
switch (n) {
|
|
Packit |
b89d10 |
case 1: r = add_opcode(reg, OP_BACKREF1); break;
|
|
Packit |
b89d10 |
case 2: r = add_opcode(reg, OP_BACKREF2); break;
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_BACKREF_N);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
r = add_mem_num(reg, n);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
int i;
|
|
Packit |
b89d10 |
int* p;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_IGNORECASE(reg->options)) {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_BACKREF_MULTI_IC);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = add_opcode(reg, OP_BACKREF_MULTI);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
add_bacref_mems:
|
|
Packit |
b89d10 |
r = add_length(reg, br->back_num);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
p = BACKREFS_P(br);
|
|
Packit |
b89d10 |
for (i = br->back_num - 1; i >= 0; i--) {
|
|
Packit |
b89d10 |
r = add_mem_num(reg, p[i]);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
case NODE_CALL:
|
|
Packit |
b89d10 |
r = compile_call(CALL_(node), reg, env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = compile_quantifier_node(QUANT_(node), reg, env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
r = compile_enclosure_node(ENCLOSURE_(node), reg, env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
r = compile_anchor_node(ANCHOR_(node), reg, env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_GIMMICK:
|
|
Packit |
b89d10 |
r = compile_gimmick_node(GIMMICK_(node), reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
#ifdef ONIG_DEBUG
|
|
Packit |
b89d10 |
fprintf(stderr, "compile_tree: undefined node type %d\n", NODE_TYPE(node));
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r = 0;
|
|
Packit |
b89d10 |
Node* node = *plink;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = noname_disable_map(&(NODE_CAR(node)), map, counter);
|
|
Packit |
b89d10 |
} while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node** ptarget = &(NODE_BODY(node));
|
|
Packit |
b89d10 |
Node* old = *ptarget;
|
|
Packit |
b89d10 |
r = noname_disable_map(ptarget, map, counter);
|
|
Packit |
b89d10 |
if (*ptarget != old && NODE_TYPE(*ptarget) == NODE_QUANT) {
|
|
Packit |
b89d10 |
onig_reduce_nested_quantifier(node, *ptarget);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_MEMORY) {
|
|
Packit |
b89d10 |
if (NODE_IS_NAMED_GROUP(node)) {
|
|
Packit |
b89d10 |
(*counter)++;
|
|
Packit |
b89d10 |
map[en->m.regnum].new_val = *counter;
|
|
Packit |
b89d10 |
en->m.regnum = *counter;
|
|
Packit |
b89d10 |
r = noname_disable_map(&(NODE_BODY(node)), map, counter);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
*plink = NODE_BODY(node);
|
|
Packit |
b89d10 |
NODE_BODY(node) = NULL_NODE;
|
|
Packit |
b89d10 |
onig_node_free(node);
|
|
Packit |
b89d10 |
r = noname_disable_map(plink, map, counter);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
r = noname_disable_map(&(NODE_ENCLOSURE_BODY(en)), map, counter);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
r = noname_disable_map(&(en->te.Then), map, counter);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
r = noname_disable_map(&(en->te.Else), map, counter);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = noname_disable_map(&(NODE_BODY(node)), map, counter);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(NODE_BODY(node)))
|
|
Packit |
b89d10 |
r = noname_disable_map(&(NODE_BODY(node)), map, counter);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
renumber_node_backref(Node* node, GroupNumRemap* map)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int i, pos, n, old_num;
|
|
Packit |
b89d10 |
int *backs;
|
|
Packit |
b89d10 |
BackRefNode* bn = BACKREF_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (! NODE_IS_BY_NAME(node))
|
|
Packit |
b89d10 |
return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
old_num = bn->back_num;
|
|
Packit |
b89d10 |
if (IS_NULL(bn->back_dynamic))
|
|
Packit |
b89d10 |
backs = bn->back_static;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
backs = bn->back_dynamic;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (i = 0, pos = 0; i < old_num; i++) {
|
|
Packit |
b89d10 |
n = map[backs[i]].new_val;
|
|
Packit |
b89d10 |
if (n > 0) {
|
|
Packit |
b89d10 |
backs[pos] = n;
|
|
Packit |
b89d10 |
pos++;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
bn->back_num = pos;
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
renumber_by_map(Node* node, GroupNumRemap* map)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = renumber_by_map(NODE_CAR(node), map);
|
|
Packit |
b89d10 |
} while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = renumber_by_map(NODE_BODY(node), map);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = renumber_by_map(NODE_BODY(node), map);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
r = renumber_by_map(en->te.Then, map);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
r = renumber_by_map(en->te.Else, map);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
r = renumber_node_backref(node, map);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(NODE_BODY(node)))
|
|
Packit |
b89d10 |
r = renumber_by_map(NODE_BODY(node), map);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
numbered_ref_check(Node* node)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = numbered_ref_check(NODE_CAR(node));
|
|
Packit |
b89d10 |
} while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
if (IS_NULL(NODE_BODY(node)))
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
/* fall */
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = numbered_ref_check(NODE_BODY(node));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = numbered_ref_check(NODE_BODY(node));
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
r = numbered_ref_check(en->te.Then);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
r = numbered_ref_check(en->te.Else);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
if (! NODE_IS_BY_NAME(node))
|
|
Packit |
b89d10 |
return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r, i, pos, counter;
|
|
Packit |
b89d10 |
MemStatusType loc;
|
|
Packit |
b89d10 |
GroupNumRemap* map;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
map = (GroupNumRemap* )xalloca(sizeof(GroupNumRemap) * (env->num_mem + 1));
|
|
Packit |
b89d10 |
CHECK_NULL_RETURN_MEMERR(map);
|
|
Packit |
b89d10 |
for (i = 1; i <= env->num_mem; i++) {
|
|
Packit |
b89d10 |
map[i].new_val = 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
counter = 0;
|
|
Packit |
b89d10 |
r = noname_disable_map(root, map, &counter);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = renumber_by_map(*root, map);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (i = 1, pos = 1; i <= env->num_mem; i++) {
|
|
Packit |
b89d10 |
if (map[i].new_val > 0) {
|
|
Packit |
b89d10 |
SCANENV_MEMENV(env)[pos] = SCANENV_MEMENV(env)[i];
|
|
Packit |
b89d10 |
pos++;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
loc = env->capture_history;
|
|
Packit |
b89d10 |
MEM_STATUS_CLEAR(env->capture_history);
|
|
Packit |
b89d10 |
for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
|
|
Packit |
b89d10 |
if (MEM_STATUS_AT(loc, i)) {
|
|
Packit |
b89d10 |
MEM_STATUS_ON_SIMPLE(env->capture_history, map[i].new_val);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
env->num_mem = env->num_named;
|
|
Packit |
b89d10 |
reg->num_mem = env->num_named;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return onig_renumber_name_table(reg, map);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
fix_unset_addr_list(UnsetAddrList* uslist, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int i, offset;
|
|
Packit |
b89d10 |
EnclosureNode* en;
|
|
Packit |
b89d10 |
AbsAddrType addr;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (i = 0; i < uslist->num; i++) {
|
|
Packit |
b89d10 |
if (! NODE_IS_ADDR_FIXED(uslist->us[i].target))
|
|
Packit |
b89d10 |
return ONIGERR_PARSER_BUG;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
en = ENCLOSURE_(uslist->us[i].target);
|
|
Packit |
b89d10 |
addr = en->m.called_addr;
|
|
Packit |
b89d10 |
offset = uslist->us[i].offset;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
BB_WRITE(reg, offset, &addr, SIZE_ABSADDR);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#define GET_CHAR_LEN_VARLEN -1
|
|
Packit |
b89d10 |
#define GET_CHAR_LEN_TOP_ALT_VARLEN -2
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
/* fixed size pattern node only */
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int tlen;
|
|
Packit |
b89d10 |
int r = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
level++;
|
|
Packit |
b89d10 |
*len = 0;
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = get_char_length_tree1(NODE_CAR(node), reg, &tlen, level);
|
|
Packit |
b89d10 |
if (r == 0)
|
|
Packit |
b89d10 |
*len = distance_add(*len, tlen);
|
|
Packit |
b89d10 |
} while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int tlen2;
|
|
Packit |
b89d10 |
int varlen = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = get_char_length_tree1(NODE_CAR(node), reg, &tlen, level);
|
|
Packit |
b89d10 |
while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node))) {
|
|
Packit |
b89d10 |
r = get_char_length_tree1(NODE_CAR(node), reg, &tlen2, level);
|
|
Packit |
b89d10 |
if (r == 0) {
|
|
Packit |
b89d10 |
if (tlen != tlen2)
|
|
Packit |
b89d10 |
varlen = 1;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (r == 0) {
|
|
Packit |
b89d10 |
if (varlen != 0) {
|
|
Packit |
b89d10 |
if (level == 1)
|
|
Packit |
b89d10 |
r = GET_CHAR_LEN_TOP_ALT_VARLEN;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = GET_CHAR_LEN_VARLEN;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
*len = tlen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
StrNode* sn = STR_(node);
|
|
Packit |
b89d10 |
UChar *s = sn->s;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
while (s < sn->end) {
|
|
Packit |
b89d10 |
s += enclen(reg->enc, s);
|
|
Packit |
b89d10 |
(*len)++;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
QuantNode* qn = QUANT_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (qn->lower == qn->upper) {
|
|
Packit |
b89d10 |
if (qn->upper == 0) {
|
|
Packit |
b89d10 |
*len = 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = get_char_length_tree1(NODE_BODY(node), reg, &tlen, level);
|
|
Packit |
b89d10 |
if (r == 0)
|
|
Packit |
b89d10 |
*len = distance_multiply(tlen, qn->lower);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = GET_CHAR_LEN_VARLEN;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
case NODE_CALL:
|
|
Packit |
b89d10 |
if (! NODE_IS_RECURSION(node))
|
|
Packit |
b89d10 |
r = get_char_length_tree1(NODE_BODY(node), reg, len, level);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
r = GET_CHAR_LEN_VARLEN;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
*len = 1;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (en->type) {
|
|
Packit |
b89d10 |
case ENCLOSURE_MEMORY:
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
if (NODE_IS_CLEN_FIXED(node))
|
|
Packit |
b89d10 |
*len = en->char_len;
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = get_char_length_tree1(NODE_BODY(node), reg, len, level);
|
|
Packit |
b89d10 |
if (r == 0) {
|
|
Packit |
b89d10 |
en->char_len = *len;
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_CLEN_FIXED);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
case ENCLOSURE_OPTION:
|
|
Packit |
b89d10 |
case ENCLOSURE_STOP_BACKTRACK:
|
|
Packit |
b89d10 |
r = get_char_length_tree1(NODE_BODY(node), reg, len, level);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
case ENCLOSURE_IF_ELSE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int clen, elen;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = get_char_length_tree1(NODE_BODY(node), reg, &clen, level);
|
|
Packit |
b89d10 |
if (r == 0) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
r = get_char_length_tree1(en->te.Then, reg, &tlen, level);
|
|
Packit |
b89d10 |
if (r != 0) break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else tlen = 0;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
r = get_char_length_tree1(en->te.Else, reg, &elen, level);
|
|
Packit |
b89d10 |
if (r != 0) break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else elen = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (clen + tlen != elen) {
|
|
Packit |
b89d10 |
r = GET_CHAR_LEN_VARLEN;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
*len = elen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
case NODE_GIMMICK:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
if (NODE_IS_CHECKER(node))
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
/* fall */
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
r = GET_CHAR_LEN_VARLEN;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
get_char_length_tree(Node* node, regex_t* reg, int* len)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
return get_char_length_tree1(node, reg, len, 0);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
/* x is not included y ==> 1 : 0 */
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
is_exclusive(Node* x, Node* y, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int i, len;
|
|
Packit |
b89d10 |
OnigCodePoint code;
|
|
Packit |
b89d10 |
UChar *p;
|
|
Packit |
b89d10 |
NodeType ytype;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
retry:
|
|
Packit |
b89d10 |
ytype = NODE_TYPE(y);
|
|
Packit |
b89d10 |
switch (NODE_TYPE(x)) {
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
if (CTYPE_(x)->ctype == CTYPE_ANYCHAR ||
|
|
Packit |
b89d10 |
CTYPE_(y)->ctype == CTYPE_ANYCHAR)
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (ytype) {
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
if (CTYPE_(y)->ctype == CTYPE_(x)->ctype &&
|
|
Packit |
b89d10 |
CTYPE_(y)->not != CTYPE_(x)->not &&
|
|
Packit |
b89d10 |
CTYPE_(y)->ascii_mode == CTYPE_(x)->ascii_mode)
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
swap:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node* tmp;
|
|
Packit |
b89d10 |
tmp = x; x = y; y = tmp;
|
|
Packit |
b89d10 |
goto retry;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
goto swap;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int range;
|
|
Packit |
b89d10 |
CClassNode* xc = CCLASS_(x);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (ytype) {
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
switch (CTYPE_(y)->ctype) {
|
|
Packit |
b89d10 |
case CTYPE_ANYCHAR:
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ONIGENC_CTYPE_WORD:
|
|
Packit |
b89d10 |
if (CTYPE_(y)->not == 0) {
|
|
Packit |
b89d10 |
if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) {
|
|
Packit |
b89d10 |
range = CTYPE_(y)->ascii_mode != 0 ? 128 : SINGLE_BYTE_SIZE;
|
|
Packit |
b89d10 |
for (i = 0; i < range; i++) {
|
|
Packit |
b89d10 |
if (BITSET_AT(xc->bs, i)) {
|
|
Packit |
b89d10 |
if (ONIGENC_IS_CODE_WORD(reg->enc, i)) return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(xc->mbuf)) return 0;
|
|
Packit |
b89d10 |
if (IS_NCCLASS_NOT(xc)) return 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
range = CTYPE_(y)->ascii_mode != 0 ? 128 : SINGLE_BYTE_SIZE;
|
|
Packit |
b89d10 |
for (i = 0; i < range; i++) {
|
|
Packit |
b89d10 |
if (! ONIGENC_IS_CODE_WORD(reg->enc, i)) {
|
|
Packit |
b89d10 |
if (BITSET_AT(xc->bs, i))
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
for (i = range; i < SINGLE_BYTE_SIZE; i++) {
|
|
Packit |
b89d10 |
if (BITSET_AT(xc->bs, i)) return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int v;
|
|
Packit |
b89d10 |
CClassNode* yc = CCLASS_(y);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
|
|
Packit |
b89d10 |
v = BITSET_AT(xc->bs, i);
|
|
Packit |
b89d10 |
if ((v != 0 && !IS_NCCLASS_NOT(xc)) || (v == 0 && IS_NCCLASS_NOT(xc))) {
|
|
Packit |
b89d10 |
v = BITSET_AT(yc->bs, i);
|
|
Packit |
b89d10 |
if ((v != 0 && !IS_NCCLASS_NOT(yc)) ||
|
|
Packit |
b89d10 |
(v == 0 && IS_NCCLASS_NOT(yc)))
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) ||
|
|
Packit |
b89d10 |
(IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc)))
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
goto swap;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
StrNode* xs = STR_(x);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_STRING_LEN(x) == 0)
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (ytype) {
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
switch (CTYPE_(y)->ctype) {
|
|
Packit |
b89d10 |
case CTYPE_ANYCHAR:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ONIGENC_CTYPE_WORD:
|
|
Packit |
b89d10 |
if (CTYPE_(y)->ascii_mode == 0) {
|
|
Packit |
b89d10 |
if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end))
|
|
Packit |
b89d10 |
return CTYPE_(y)->not;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return !(CTYPE_(y)->not);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (ONIGENC_IS_MBC_WORD_ASCII(reg->enc, xs->s, xs->end))
|
|
Packit |
b89d10 |
return CTYPE_(y)->not;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
return !(CTYPE_(y)->not);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
CClassNode* cc = CCLASS_(y);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,
|
|
Packit |
b89d10 |
xs->s + ONIGENC_MBC_MAXLEN(reg->enc));
|
|
Packit |
b89d10 |
return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
UChar *q;
|
|
Packit |
b89d10 |
StrNode* ys = STR_(y);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = NODE_STRING_LEN(x);
|
|
Packit |
b89d10 |
if (len > NODE_STRING_LEN(y)) len = NODE_STRING_LEN(y);
|
|
Packit |
b89d10 |
if (NODE_STRING_IS_AMBIG(x) || NODE_STRING_IS_AMBIG(y)) {
|
|
Packit |
b89d10 |
/* tiny version */
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
for (i = 0, p = ys->s, q = xs->s; i < len; i++, p++, q++) {
|
|
Packit |
b89d10 |
if (*p != *q) return 1;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static Node*
|
|
Packit |
b89d10 |
get_head_value_node(Node* node, int exact, regex_t* reg)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node* n = NULL_NODE;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
case NODE_CALL:
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
if (CTYPE_(node)->ctype == CTYPE_ANYCHAR)
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
/* fall */
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
if (exact == 0) {
|
|
Packit |
b89d10 |
n = node;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
n = get_head_value_node(NODE_CAR(node), exact, reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
StrNode* sn = STR_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (sn->end <= sn->s)
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (exact != 0 &&
|
|
Packit |
b89d10 |
!NODE_STRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) {
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
n = node;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
QuantNode* qn = QUANT_(node);
|
|
Packit |
b89d10 |
if (qn->lower > 0) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(qn->head_exact))
|
|
Packit |
b89d10 |
n = qn->head_exact;
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
n = get_head_value_node(NODE_BODY(node), exact, reg);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
switch (en->type) {
|
|
Packit |
b89d10 |
case ENCLOSURE_OPTION:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
OnigOptionType options = reg->options;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
reg->options = ENCLOSURE_(node)->o.options;
|
|
Packit |
b89d10 |
n = get_head_value_node(NODE_BODY(node), exact, reg);
|
|
Packit |
b89d10 |
reg->options = options;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ENCLOSURE_MEMORY:
|
|
Packit |
b89d10 |
case ENCLOSURE_STOP_BACKTRACK:
|
|
Packit |
b89d10 |
case ENCLOSURE_IF_ELSE:
|
|
Packit |
b89d10 |
n = get_head_value_node(NODE_BODY(node), exact, reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
if (ANCHOR_(node)->type == ANCHOR_PREC_READ)
|
|
Packit |
b89d10 |
n = get_head_value_node(NODE_BODY(node), exact, reg);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_GIMMICK:
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return n;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
check_type_tree(Node* node, int type_mask, int enclosure_mask, int anchor_mask)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
NodeType type;
|
|
Packit |
b89d10 |
int r = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
type = NODE_TYPE(node);
|
|
Packit |
b89d10 |
if ((NODE_TYPE2BIT(type) & type_mask) == 0)
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (type) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = check_type_tree(NODE_CAR(node), type_mask, enclosure_mask,
|
|
Packit |
b89d10 |
anchor_mask);
|
|
Packit |
b89d10 |
} while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
if (((1<<en->type) & enclosure_mask) == 0)
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);
|
|
Packit |
b89d10 |
if (r == 0 && en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
r = check_type_tree(en->te.Then, type_mask, enclosure_mask, anchor_mask);
|
|
Packit |
b89d10 |
if (r != 0) break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
r = check_type_tree(en->te.Else, type_mask, enclosure_mask, anchor_mask);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
type = ANCHOR_(node)->type;
|
|
Packit |
b89d10 |
if ((type & anchor_mask) == 0)
|
|
Packit |
b89d10 |
return 1;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(NODE_BODY(node)))
|
|
Packit |
b89d10 |
r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_GIMMICK:
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static OnigLen
|
|
Packit |
b89d10 |
tree_min_len(Node* node, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
OnigLen len;
|
|
Packit |
b89d10 |
OnigLen tmin;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = 0;
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
if (! NODE_IS_CHECKER(node)) {
|
|
Packit |
b89d10 |
int i;
|
|
Packit |
b89d10 |
int* backs;
|
|
Packit |
b89d10 |
MemEnv* mem_env = SCANENV_MEMENV(env);
|
|
Packit |
b89d10 |
BackRefNode* br = BACKREF_(node);
|
|
Packit |
b89d10 |
if (NODE_IS_RECURSION(node)) break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
backs = BACKREFS_P(br);
|
|
Packit |
b89d10 |
len = tree_min_len(mem_env[backs[0]].node, env);
|
|
Packit |
b89d10 |
for (i = 1; i < br->back_num; i++) {
|
|
Packit |
b89d10 |
tmin = tree_min_len(mem_env[backs[i]].node, env);
|
|
Packit |
b89d10 |
if (len > tmin) len = tmin;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
case NODE_CALL:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node* t = NODE_BODY(node);
|
|
Packit |
b89d10 |
if (NODE_IS_RECURSION(node)) {
|
|
Packit |
b89d10 |
if (NODE_IS_MIN_FIXED(t))
|
|
Packit |
b89d10 |
len = ENCLOSURE_(t)->min_len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
len = tree_min_len(t, env);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
tmin = tree_min_len(NODE_CAR(node), env);
|
|
Packit |
b89d10 |
len = distance_add(len, tmin);
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node *x, *y;
|
|
Packit |
b89d10 |
y = node;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
x = NODE_CAR(y);
|
|
Packit |
b89d10 |
tmin = tree_min_len(x, env);
|
|
Packit |
b89d10 |
if (y == node) len = tmin;
|
|
Packit |
b89d10 |
else if (len > tmin) len = tmin;
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(y = NODE_CDR(y)));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
StrNode* sn = STR_(node);
|
|
Packit |
b89d10 |
len = (int )(sn->end - sn->s);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
len = ONIGENC_MBC_MINLEN(env->enc);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
QuantNode* qn = QUANT_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (qn->lower > 0) {
|
|
Packit |
b89d10 |
len = tree_min_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
len = distance_multiply(len, qn->lower);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
switch (en->type) {
|
|
Packit |
b89d10 |
case ENCLOSURE_MEMORY:
|
|
Packit |
b89d10 |
if (NODE_IS_MIN_FIXED(node))
|
|
Packit |
b89d10 |
len = en->min_len;
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (NODE_IS_MARK1(node))
|
|
Packit |
b89d10 |
len = 0; /* recursive */
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_MARK1);
|
|
Packit |
b89d10 |
len = tree_min_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
NODE_STATUS_REMOVE(node, NST_MARK1);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
en->min_len = len;
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_MIN_FIXED);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ENCLOSURE_OPTION:
|
|
Packit |
b89d10 |
case ENCLOSURE_STOP_BACKTRACK:
|
|
Packit |
b89d10 |
len = tree_min_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
case ENCLOSURE_IF_ELSE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
OnigLen elen;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = tree_min_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then))
|
|
Packit |
b89d10 |
len += tree_min_len(en->te.Then, env);
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else))
|
|
Packit |
b89d10 |
elen = tree_min_len(en->te.Else, env);
|
|
Packit |
b89d10 |
else elen = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (elen < len) len = elen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_GIMMICK:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
GimmickNode* g = GIMMICK_(node);
|
|
Packit |
b89d10 |
if (g->type == GIMMICK_FAIL) {
|
|
Packit |
b89d10 |
len = INFINITE_LEN;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
/* fall */
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static OnigLen
|
|
Packit |
b89d10 |
tree_max_len(Node* node, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
OnigLen len;
|
|
Packit |
b89d10 |
OnigLen tmax;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = 0;
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
tmax = tree_max_len(NODE_CAR(node), env);
|
|
Packit |
b89d10 |
len = distance_add(len, tmax);
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
tmax = tree_max_len(NODE_CAR(node), env);
|
|
Packit |
b89d10 |
if (len < tmax) len = tmax;
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_STRING:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
StrNode* sn = STR_(node);
|
|
Packit |
b89d10 |
len = (OnigLen )(sn->end - sn->s);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CTYPE:
|
|
Packit |
b89d10 |
case NODE_CCLASS:
|
|
Packit |
b89d10 |
len = ONIGENC_MBC_MAXLEN_DIST(env->enc);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
if (! NODE_IS_CHECKER(node)) {
|
|
Packit |
b89d10 |
int i;
|
|
Packit |
b89d10 |
int* backs;
|
|
Packit |
b89d10 |
MemEnv* mem_env = SCANENV_MEMENV(env);
|
|
Packit |
b89d10 |
BackRefNode* br = BACKREF_(node);
|
|
Packit |
b89d10 |
if (NODE_IS_RECURSION(node)) {
|
|
Packit |
b89d10 |
len = INFINITE_LEN;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
backs = BACKREFS_P(br);
|
|
Packit |
b89d10 |
for (i = 0; i < br->back_num; i++) {
|
|
Packit |
b89d10 |
tmax = tree_max_len(mem_env[backs[i]].node, env);
|
|
Packit |
b89d10 |
if (len < tmax) len = tmax;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
case NODE_CALL:
|
|
Packit |
b89d10 |
if (! NODE_IS_RECURSION(node))
|
|
Packit |
b89d10 |
len = tree_max_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
len = INFINITE_LEN;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
QuantNode* qn = QUANT_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (qn->upper != 0) {
|
|
Packit |
b89d10 |
len = tree_max_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
if (len != 0) {
|
|
Packit |
b89d10 |
if (! IS_REPEAT_INFINITE(qn->upper))
|
|
Packit |
b89d10 |
len = distance_multiply(len, qn->upper);
|
|
Packit |
b89d10 |
else
|
|
Packit |
b89d10 |
len = INFINITE_LEN;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
switch (en->type) {
|
|
Packit |
b89d10 |
case ENCLOSURE_MEMORY:
|
|
Packit |
b89d10 |
if (NODE_IS_MAX_FIXED(node))
|
|
Packit |
b89d10 |
len = en->max_len;
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
if (NODE_IS_MARK1(node))
|
|
Packit |
b89d10 |
len = INFINITE_LEN;
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_MARK1);
|
|
Packit |
b89d10 |
len = tree_max_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
NODE_STATUS_REMOVE(node, NST_MARK1);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
en->max_len = len;
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_MAX_FIXED);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case ENCLOSURE_OPTION:
|
|
Packit |
b89d10 |
case ENCLOSURE_STOP_BACKTRACK:
|
|
Packit |
b89d10 |
len = tree_max_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
case ENCLOSURE_IF_ELSE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
OnigLen tlen, elen;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
len = tree_max_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
tlen = tree_max_len(en->te.Then, env);
|
|
Packit |
b89d10 |
len = distance_add(len, tlen);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else))
|
|
Packit |
b89d10 |
elen = tree_max_len(en->te.Else, env);
|
|
Packit |
b89d10 |
else elen = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (elen > len) len = elen;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
case NODE_GIMMICK:
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return len;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
check_backrefs(Node* node, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = check_backrefs(NODE_CAR(node), env);
|
|
Packit |
b89d10 |
} while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
/* fall */
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = check_backrefs(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
r = check_backrefs(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
r = check_backrefs(en->te.Then, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
r = check_backrefs(en->te.Else, env);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_BACKREF:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int i;
|
|
Packit |
b89d10 |
BackRefNode* br = BACKREF_(node);
|
|
Packit |
b89d10 |
int* backs = BACKREFS_P(br);
|
|
Packit |
b89d10 |
MemEnv* mem_env = SCANENV_MEMENV(env);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
for (i = 0; i < br->back_num; i++) {
|
|
Packit |
b89d10 |
if (backs[i] > env->num_mem)
|
|
Packit |
b89d10 |
return ONIGERR_INVALID_BACKREF;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(mem_env[backs[i]].node, NST_BACKREF);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#ifdef USE_CALL
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#define RECURSION_EXIST (1<<0)
|
|
Packit |
b89d10 |
#define RECURSION_MUST (1<<1)
|
|
Packit |
b89d10 |
#define RECURSION_INFINITE (1<<2)
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
infinite_recursive_call_check(Node* node, ScanEnv* env, int head)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int ret;
|
|
Packit |
b89d10 |
int r = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node *x;
|
|
Packit |
b89d10 |
OnigLen min;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
x = node;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
ret = infinite_recursive_call_check(NODE_CAR(x), env, head);
|
|
Packit |
b89d10 |
if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;
|
|
Packit |
b89d10 |
r |= ret;
|
|
Packit |
b89d10 |
if (head != 0) {
|
|
Packit |
b89d10 |
min = tree_min_len(NODE_CAR(x), env);
|
|
Packit |
b89d10 |
if (min != 0) head = 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(x = NODE_CDR(x)));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int must;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
must = RECURSION_MUST;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
ret = infinite_recursive_call_check(NODE_CAR(node), env, head);
|
|
Packit |
b89d10 |
if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r |= (ret & RECURSION_EXIST);
|
|
Packit |
b89d10 |
must &= ret;
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
r |= must;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check(NODE_BODY(node), env, head);
|
|
Packit |
b89d10 |
if (r < 0) return r;
|
|
Packit |
b89d10 |
if ((r & RECURSION_MUST) != 0) {
|
|
Packit |
b89d10 |
if (QUANT_(node)->lower == 0)
|
|
Packit |
b89d10 |
r &= ~RECURSION_MUST;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
if (! ANCHOR_HAS_BODY(ANCHOR_(node)))
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
/* fall */
|
|
Packit |
b89d10 |
case NODE_CALL:
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check(NODE_BODY(node), env, head);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_MEMORY) {
|
|
Packit |
b89d10 |
if (NODE_IS_MARK2(node))
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
else if (NODE_IS_MARK1(node))
|
|
Packit |
b89d10 |
return (head == 0 ? RECURSION_EXIST | RECURSION_MUST
|
|
Packit |
b89d10 |
: RECURSION_EXIST | RECURSION_MUST | RECURSION_INFINITE);
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_MARK2);
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check(NODE_BODY(node), env, head);
|
|
Packit |
b89d10 |
NODE_STATUS_REMOVE(node, NST_MARK2);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
int eret;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
ret = infinite_recursive_call_check(NODE_BODY(node), env, head);
|
|
Packit |
b89d10 |
if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;
|
|
Packit |
b89d10 |
r |= ret;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
OnigLen min;
|
|
Packit |
b89d10 |
if (head != 0) {
|
|
Packit |
b89d10 |
min = tree_min_len(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else min = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
ret = infinite_recursive_call_check(en->te.Then, env, min != 0 ? 0:head);
|
|
Packit |
b89d10 |
if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;
|
|
Packit |
b89d10 |
r |= ret;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
eret = infinite_recursive_call_check(en->te.Else, env, head);
|
|
Packit |
b89d10 |
if (eret < 0 || (eret & RECURSION_INFINITE) != 0) return eret;
|
|
Packit |
b89d10 |
r |= (eret & RECURSION_EXIST);
|
|
Packit |
b89d10 |
if ((eret & RECURSION_MUST) == 0)
|
|
Packit |
b89d10 |
r &= ~RECURSION_MUST;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check(NODE_BODY(node), env, head);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
infinite_recursive_call_check_trav(Node* node, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check_trav(NODE_CAR(node), env);
|
|
Packit |
b89d10 |
} while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
/* fall */
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check_trav(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_MEMORY) {
|
|
Packit |
b89d10 |
if (NODE_IS_RECURSION(node) && NODE_IS_CALLED(node)) {
|
|
Packit |
b89d10 |
int ret;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_MARK1);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
ret = infinite_recursive_call_check(NODE_BODY(node), env, 1);
|
|
Packit |
b89d10 |
if (ret < 0) return ret;
|
|
Packit |
b89d10 |
else if ((ret & (RECURSION_MUST | RECURSION_INFINITE)) != 0)
|
|
Packit |
b89d10 |
return ONIGERR_NEVER_ENDING_RECURSION;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
NODE_STATUS_REMOVE(node, NST_MARK1);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check_trav(en->te.Then, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check_trav(en->te.Else, env);
|
|
Packit |
b89d10 |
if (r != 0) return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
r = infinite_recursive_call_check_trav(NODE_BODY(node), env);
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
recursive_call_check(Node* node)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
r |= recursive_call_check(NODE_CAR(node));
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
/* fall */
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = recursive_call_check(NODE_BODY(node));
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_CALL:
|
|
Packit |
b89d10 |
r = recursive_call_check(NODE_BODY(node));
|
|
Packit |
b89d10 |
if (r != 0) {
|
|
Packit |
b89d10 |
if (NODE_IS_MARK1(NODE_BODY(node)))
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_RECURSION);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_MEMORY) {
|
|
Packit |
b89d10 |
if (NODE_IS_MARK2(node))
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
else if (NODE_IS_MARK1(node))
|
|
Packit |
b89d10 |
return 1; /* recursion */
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_MARK2);
|
|
Packit |
b89d10 |
r = recursive_call_check(NODE_BODY(node));
|
|
Packit |
b89d10 |
NODE_STATUS_REMOVE(node, NST_MARK2);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else if (en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
r |= recursive_call_check(en->te.Then);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
r |= recursive_call_check(en->te.Else);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
r |= recursive_call_check(NODE_BODY(node));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
else {
|
|
Packit |
b89d10 |
r = recursive_call_check(NODE_BODY(node));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
r = 0;
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#define IN_RECURSION (1<<0)
|
|
Packit |
b89d10 |
#define FOUND_CALLED_NODE 1
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
recursive_call_check_trav(Node* node, ScanEnv* env, int state)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r = 0;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
switch (NODE_TYPE(node)) {
|
|
Packit |
b89d10 |
case NODE_LIST:
|
|
Packit |
b89d10 |
case NODE_ALT:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int ret;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
ret = recursive_call_check_trav(NODE_CAR(node), env, state);
|
|
Packit |
b89d10 |
if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;
|
|
Packit |
b89d10 |
else if (ret < 0) return ret;
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(node = NODE_CDR(node)));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_QUANT:
|
|
Packit |
b89d10 |
r = recursive_call_check_trav(NODE_BODY(node), env, state);
|
|
Packit |
b89d10 |
if (QUANT_(node)->upper == 0) {
|
|
Packit |
b89d10 |
if (r == FOUND_CALLED_NODE)
|
|
Packit |
b89d10 |
QUANT_(node)->is_refered = 1;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ANCHOR:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
AnchorNode* an = ANCHOR_(node);
|
|
Packit |
b89d10 |
if (ANCHOR_HAS_BODY(an))
|
|
Packit |
b89d10 |
r = recursive_call_check_trav(NODE_ANCHOR_BODY(an), env, state);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
case NODE_ENCLOSURE:
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int ret;
|
|
Packit |
b89d10 |
int state1;
|
|
Packit |
b89d10 |
EnclosureNode* en = ENCLOSURE_(node);
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_MEMORY) {
|
|
Packit |
b89d10 |
if (NODE_IS_CALLED(node) || (state & IN_RECURSION) != 0) {
|
|
Packit |
b89d10 |
if (! NODE_IS_RECURSION(node)) {
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_MARK1);
|
|
Packit |
b89d10 |
r = recursive_call_check(NODE_BODY(node));
|
|
Packit |
b89d10 |
if (r != 0)
|
|
Packit |
b89d10 |
NODE_STATUS_ADD(node, NST_RECURSION);
|
|
Packit |
b89d10 |
NODE_STATUS_REMOVE(node, NST_MARK1);
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (NODE_IS_CALLED(node))
|
|
Packit |
b89d10 |
r = FOUND_CALLED_NODE;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
state1 = state;
|
|
Packit |
b89d10 |
if (NODE_IS_RECURSION(node))
|
|
Packit |
b89d10 |
state1 |= IN_RECURSION;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
ret = recursive_call_check_trav(NODE_BODY(node), env, state1);
|
|
Packit |
b89d10 |
if (ret == FOUND_CALLED_NODE)
|
|
Packit |
b89d10 |
r = FOUND_CALLED_NODE;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (en->type == ENCLOSURE_IF_ELSE) {
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Then)) {
|
|
Packit |
b89d10 |
ret = recursive_call_check_trav(en->te.Then, env, state1);
|
|
Packit |
b89d10 |
if (ret == FOUND_CALLED_NODE)
|
|
Packit |
b89d10 |
r = FOUND_CALLED_NODE;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
if (IS_NOT_NULL(en->te.Else)) {
|
|
Packit |
b89d10 |
ret = recursive_call_check_trav(en->te.Else, env, state1);
|
|
Packit |
b89d10 |
if (ret == FOUND_CALLED_NODE)
|
|
Packit |
b89d10 |
r = FOUND_CALLED_NODE;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
default:
|
|
Packit |
b89d10 |
break;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
return r;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
#endif
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
/* divide different length alternatives in look-behind.
|
|
Packit |
b89d10 |
(?<=A|B) ==> (?<=A)|(?<=B)
|
|
Packit |
b89d10 |
(? (?
|
|
Packit |
b89d10 |
*/
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
divide_look_behind_alternatives(Node* node)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
Node *head, *np, *insert_node;
|
|
Packit |
b89d10 |
AnchorNode* an = ANCHOR_(node);
|
|
Packit |
b89d10 |
int anc_type = an->type;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
head = NODE_ANCHOR_BODY(an);
|
|
Packit |
b89d10 |
np = NODE_CAR(head);
|
|
Packit |
b89d10 |
swap_node(node, head);
|
|
Packit |
b89d10 |
NODE_CAR(node) = head;
|
|
Packit |
b89d10 |
NODE_BODY(head) = np;
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
np = node;
|
|
Packit |
b89d10 |
while (IS_NOT_NULL(np = NODE_CDR(np))) {
|
|
Packit |
b89d10 |
insert_node = onig_node_new_anchor(anc_type, an->ascii_mode);
|
|
Packit |
b89d10 |
CHECK_NULL_RETURN_MEMERR(insert_node);
|
|
Packit |
b89d10 |
NODE_BODY(insert_node) = NODE_CAR(np);
|
|
Packit |
b89d10 |
NODE_CAR(np) = insert_node;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
if (anc_type == ANCHOR_LOOK_BEHIND_NOT) {
|
|
Packit |
b89d10 |
np = node;
|
|
Packit |
b89d10 |
do {
|
|
Packit |
b89d10 |
NODE_SET_TYPE(np, NODE_LIST); /* alt -> list */
|
|
Packit |
b89d10 |
} while (IS_NOT_NULL(np = NODE_CDR(np)));
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
return 0;
|
|
Packit |
b89d10 |
}
|
|
Packit |
b89d10 |
|
|
Packit |
b89d10 |
static int
|
|
Packit |
b89d10 |
setup_look_behind(Node* node, regex_t* reg, ScanEnv* env)
|
|
Packit |
b89d10 |
{
|
|
Packit |
b89d10 |
int r, len;
|
|
Packit |
b89d10 |
AnchorNode* an = ANCHOR_(node);
|
|