Blame src/regparse.c

Packit b89d10
/**********************************************************************
Packit b89d10
  regparse.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
#include "st.h"
Packit b89d10
Packit b89d10
#ifdef DEBUG_NODE_FREE
Packit b89d10
#include <stdio.h>
Packit b89d10
#endif
Packit b89d10
Packit b89d10
#define INIT_TAG_NAMES_ALLOC_NUM   5
Packit b89d10
Packit b89d10
#define WARN_BUFSIZE    256
Packit b89d10
Packit b89d10
#define CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS
Packit b89d10
Packit b89d10
#define IS_ALLOWED_CODE_IN_CALLOUT_NAME(c) \
Packit b89d10
  ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' /* || c == '!' */)
Packit b89d10
#define IS_ALLOWED_CODE_IN_CALLOUT_TAG_NAME(c) \
Packit b89d10
  ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_')
Packit b89d10
Packit b89d10
Packit b89d10
OnigSyntaxType OnigSyntaxOniguruma = {
Packit b89d10
  (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY |
Packit b89d10
     ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 |
Packit b89d10
     ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_O_BRACE_OCTAL |
Packit b89d10
     ONIG_SYN_OP_ESC_CONTROL_CHARS |
Packit b89d10
     ONIG_SYN_OP_ESC_C_CONTROL )
Packit b89d10
   & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END )
Packit b89d10
  , ( ONIG_SYN_OP2_QMARK_GROUP_EFFECT |
Packit b89d10
      ONIG_SYN_OP2_OPTION_RUBY |
Packit b89d10
      ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP | ONIG_SYN_OP2_ESC_K_NAMED_BACKREF |
Packit b89d10
      ONIG_SYN_OP2_QMARK_LPAREN_IF_ELSE |
Packit b89d10
      ONIG_SYN_OP2_QMARK_TILDE_ABSENT_GROUP |
Packit b89d10
      ONIG_SYN_OP2_QMARK_BRACE_CALLOUT_CONTENTS |
Packit b89d10
      ONIG_SYN_OP2_ASTERISK_CALLOUT_NAME    |
Packit b89d10
      ONIG_SYN_OP2_ESC_X_Y_GRAPHEME_CLUSTER |
Packit b89d10
      ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE |
Packit b89d10
      ONIG_SYN_OP2_ESC_CAPITAL_N_O_SUPER_DOT |
Packit b89d10
      ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP |
Packit b89d10
      ONIG_SYN_OP2_ESC_G_SUBEXP_CALL |
Packit b89d10
      ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY  |
Packit b89d10
      ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT |
Packit b89d10
      ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT |
Packit b89d10
      ONIG_SYN_OP2_CCLASS_SET_OP | ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL |
Packit b89d10
      ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META | ONIG_SYN_OP2_ESC_V_VTAB |
Packit b89d10
      ONIG_SYN_OP2_ESC_H_XDIGIT | ONIG_SYN_OP2_ESC_U_HEX4 )
Packit b89d10
  , ( SYN_GNU_REGEX_BV | 
Packit b89d10
      ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV |
Packit b89d10
      ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND |
Packit b89d10
      ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP |
Packit b89d10
      ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME |
Packit b89d10
      ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY |
Packit b89d10
      ONIG_SYN_WARN_CC_OP_NOT_ESCAPED |
Packit b89d10
      ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT )
Packit b89d10
  , ONIG_OPTION_NONE
Packit b89d10
  ,
Packit b89d10
  {
Packit b89d10
      (OnigCodePoint )'\\'                       /* esc */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.'  */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*'  */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */
Packit b89d10
  }
Packit b89d10
};
Packit b89d10
Packit b89d10
OnigSyntaxType OnigSyntaxRuby = {
Packit b89d10
  (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY |
Packit b89d10
     ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 |
Packit b89d10
     ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_O_BRACE_OCTAL |
Packit b89d10
     ONIG_SYN_OP_ESC_CONTROL_CHARS |
Packit b89d10
     ONIG_SYN_OP_ESC_C_CONTROL )
Packit b89d10
   & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END )
Packit b89d10
  , ( ONIG_SYN_OP2_QMARK_GROUP_EFFECT |
Packit b89d10
      ONIG_SYN_OP2_OPTION_RUBY |
Packit b89d10
      ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP | ONIG_SYN_OP2_ESC_K_NAMED_BACKREF |
Packit b89d10
      ONIG_SYN_OP2_QMARK_LPAREN_IF_ELSE |
Packit b89d10
      ONIG_SYN_OP2_QMARK_TILDE_ABSENT_GROUP |
Packit b89d10
      ONIG_SYN_OP2_ESC_X_Y_GRAPHEME_CLUSTER |
Packit b89d10
      ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE |
Packit b89d10
      ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP |
Packit b89d10
      ONIG_SYN_OP2_ESC_G_SUBEXP_CALL |
Packit b89d10
      ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY  |
Packit b89d10
      ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT |
Packit b89d10
      ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT |
Packit b89d10
      ONIG_SYN_OP2_CCLASS_SET_OP | ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL |
Packit b89d10
      ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META | ONIG_SYN_OP2_ESC_V_VTAB |
Packit b89d10
      ONIG_SYN_OP2_ESC_H_XDIGIT | ONIG_SYN_OP2_ESC_U_HEX4 )
Packit b89d10
  , ( SYN_GNU_REGEX_BV | 
Packit b89d10
      ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV |
Packit b89d10
      ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND |
Packit b89d10
      ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP |
Packit b89d10
      ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME |
Packit b89d10
      ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY |
Packit b89d10
      ONIG_SYN_WARN_CC_OP_NOT_ESCAPED |
Packit b89d10
      ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT )
Packit b89d10
  , ONIG_OPTION_NONE
Packit b89d10
  ,
Packit b89d10
  {
Packit b89d10
      (OnigCodePoint )'\\'                       /* esc */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.'  */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*'  */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */
Packit b89d10
    , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */
Packit b89d10
  }
Packit b89d10
};
Packit b89d10
Packit b89d10
OnigSyntaxType*  OnigDefaultSyntax = ONIG_SYNTAX_ONIGURUMA;
Packit b89d10
Packit b89d10
extern void onig_null_warn(const char* s ARG_UNUSED) { }
Packit b89d10
Packit b89d10
#ifdef DEFAULT_WARN_FUNCTION
Packit b89d10
static OnigWarnFunc onig_warn = (OnigWarnFunc )DEFAULT_WARN_FUNCTION;
Packit b89d10
#else
Packit b89d10
static OnigWarnFunc onig_warn = onig_null_warn;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
#ifdef DEFAULT_VERB_WARN_FUNCTION
Packit b89d10
static OnigWarnFunc onig_verb_warn = (OnigWarnFunc )DEFAULT_VERB_WARN_FUNCTION;
Packit b89d10
#else
Packit b89d10
static OnigWarnFunc onig_verb_warn = onig_null_warn;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
extern void onig_set_warn_func(OnigWarnFunc f)
Packit b89d10
{
Packit b89d10
  onig_warn = f;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern void onig_set_verb_warn_func(OnigWarnFunc f)
Packit b89d10
{
Packit b89d10
  onig_verb_warn = f;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern void
Packit b89d10
onig_warning(const char* s)
Packit b89d10
{
Packit b89d10
  if (onig_warn == onig_null_warn) return ;
Packit b89d10
Packit b89d10
  (*onig_warn)(s);
Packit b89d10
}
Packit b89d10
Packit b89d10
#define DEFAULT_MAX_CAPTURE_NUM   32767
Packit b89d10
Packit b89d10
static int MaxCaptureNum = DEFAULT_MAX_CAPTURE_NUM;
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_set_capture_num_limit(int num)
Packit b89d10
{
Packit b89d10
  if (num < 0) return -1;
Packit b89d10
Packit b89d10
  MaxCaptureNum = num;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static unsigned int ParseDepthLimit = DEFAULT_PARSE_DEPTH_LIMIT;
Packit b89d10
Packit b89d10
extern unsigned int
Packit b89d10
onig_get_parse_depth_limit(void)
Packit b89d10
{
Packit b89d10
  return ParseDepthLimit;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_set_parse_depth_limit(unsigned int depth)
Packit b89d10
{
Packit b89d10
  if (depth == 0)
Packit b89d10
    ParseDepthLimit = DEFAULT_PARSE_DEPTH_LIMIT;
Packit b89d10
  else
Packit b89d10
    ParseDepthLimit = depth;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
positive_int_multiply(int x, int y)
Packit b89d10
{
Packit b89d10
  if (x == 0 || y == 0) return 0;
Packit b89d10
Packit b89d10
  if (x < INT_MAX / y)
Packit b89d10
    return x * y;
Packit b89d10
  else
Packit b89d10
    return -1;
Packit b89d10
}
Packit b89d10
Packit b89d10
static void
Packit b89d10
bbuf_free(BBuf* bbuf)
Packit b89d10
{
Packit b89d10
  if (IS_NOT_NULL(bbuf)) {
Packit b89d10
    if (IS_NOT_NULL(bbuf->p)) xfree(bbuf->p);
Packit b89d10
    xfree(bbuf);
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
bbuf_clone(BBuf** rto, BBuf* from)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  BBuf *to;
Packit b89d10
Packit b89d10
  *rto = to = (BBuf* )xmalloc(sizeof(BBuf));
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(to);
Packit b89d10
  r = BB_INIT(to, from->alloc);
Packit b89d10
  if (r != 0) {
Packit b89d10
    xfree(to->p);
Packit b89d10
    *rto = 0;
Packit b89d10
    return r;
Packit b89d10
  }
Packit b89d10
  to->used = from->used;
Packit b89d10
  xmemcpy(to->p, from->p, from->used);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int backref_rel_to_abs(int rel_no, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  if (rel_no > 0) {
Packit b89d10
    return env->num_mem + rel_no;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    return env->num_mem + 1 + rel_no;
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
#define OPTION_ON(v,f)     ((v) |= (f))
Packit b89d10
#define OPTION_OFF(v,f)    ((v) &= ~(f))
Packit b89d10
Packit b89d10
#define OPTION_NEGATE(v,f,negative)    (negative) ? ((v) &= ~(f)) : ((v) |= (f))
Packit b89d10
Packit b89d10
#define MBCODE_START_POS(enc) \
Packit b89d10
  (OnigCodePoint )(ONIGENC_MBC_MINLEN(enc) > 1 ? 0 : 0x80)
Packit b89d10
Packit b89d10
#define SET_ALL_MULTI_BYTE_RANGE(enc, pbuf) \
Packit b89d10
  add_code_range_to_buf(pbuf, MBCODE_START_POS(enc), ~((OnigCodePoint )0))
Packit b89d10
Packit b89d10
#define ADD_ALL_MULTI_BYTE_RANGE(enc, mbuf) do {\
Packit b89d10
  if (! ONIGENC_IS_SINGLEBYTE(enc)) {\
Packit b89d10
    r = SET_ALL_MULTI_BYTE_RANGE(enc, &(mbuf));\
Packit b89d10
    if (r != 0) return r;\
Packit b89d10
  }\
Packit b89d10
} while (0)
Packit b89d10
Packit b89d10
Packit b89d10
#define BITSET_IS_EMPTY(bs,empty) do {\
Packit b89d10
  int i;\
Packit b89d10
  empty = 1;\
Packit b89d10
  for (i = 0; i < (int )BITSET_SIZE; i++) {\
Packit b89d10
    if ((bs)[i] != 0) {\
Packit b89d10
      empty = 0; break;\
Packit b89d10
    }\
Packit b89d10
  }\
Packit b89d10
} while (0)
Packit b89d10
Packit b89d10
static void
Packit b89d10
bitset_set_range(BitSetRef bs, int from, int to)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  for (i = from; i <= to && i < SINGLE_BYTE_SIZE; i++) {
Packit b89d10
    BITSET_SET_BIT(bs, i);
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
#if 0
Packit b89d10
static void
Packit b89d10
bitset_set_all(BitSetRef bs)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  for (i = 0; i < BITSET_SIZE; i++) { bs[i] = ~((Bits )0); }
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
static void
Packit b89d10
bitset_invert(BitSetRef bs)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  for (i = 0; i < (int )BITSET_SIZE; i++) { bs[i] = ~(bs[i]); }
Packit b89d10
}
Packit b89d10
Packit b89d10
static void
Packit b89d10
bitset_invert_to(BitSetRef from, BitSetRef to)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  for (i = 0; i < (int )BITSET_SIZE; i++) { to[i] = ~(from[i]); }
Packit b89d10
}
Packit b89d10
Packit b89d10
static void
Packit b89d10
bitset_and(BitSetRef dest, BitSetRef bs)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  for (i = 0; i < (int )BITSET_SIZE; i++) { dest[i] &= bs[i]; }
Packit b89d10
}
Packit b89d10
Packit b89d10
static void
Packit b89d10
bitset_or(BitSetRef dest, BitSetRef bs)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  for (i = 0; i < (int )BITSET_SIZE; i++) { dest[i] |= bs[i]; }
Packit b89d10
}
Packit b89d10
Packit b89d10
static void
Packit b89d10
bitset_copy(BitSetRef dest, BitSetRef bs)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  for (i = 0; i < (int )BITSET_SIZE; i++) { dest[i] = bs[i]; }
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_strncmp(const UChar* s1, const UChar* s2, int n)
Packit b89d10
{
Packit b89d10
  int x;
Packit b89d10
Packit b89d10
  while (n-- > 0) {
Packit b89d10
    x = *s2++ - *s1++;
Packit b89d10
    if (x) return x;
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern void
Packit b89d10
onig_strcpy(UChar* dest, const UChar* src, const UChar* end)
Packit b89d10
{
Packit b89d10
  int len = (int )(end - src);
Packit b89d10
  if (len > 0) {
Packit b89d10
    xmemcpy(dest, src, len);
Packit b89d10
    dest[len] = (UChar )0;
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
save_entry(ScanEnv* env, enum SaveType type, int* id)
Packit b89d10
{
Packit b89d10
  int nid = env->save_num;
Packit b89d10
Packit b89d10
#if 0
Packit b89d10
  if (IS_NULL(env->saves)) {
Packit b89d10
    int n = 10;
Packit b89d10
    env->saves = (SaveItem* )xmalloc(sizeof(SaveItem) * n);
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(env->saves);
Packit b89d10
    env->save_alloc_num = n;
Packit b89d10
  }
Packit b89d10
  else if (env->save_alloc_num <= nid) {
Packit b89d10
    int n = env->save_alloc_num * 2;
Packit b89d10
    SaveItem* p = (SaveItem* )xrealloc(env->saves, sizeof(SaveItem) * n);
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(p);
Packit b89d10
    env->saves = p;
Packit b89d10
    env->save_alloc_num = n;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  env->saves[nid].type = type;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  env->save_num++;
Packit b89d10
  *id = nid;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
/* scan pattern methods */
Packit b89d10
#define PEND_VALUE   0
Packit b89d10
Packit b89d10
#define PFETCH_READY  UChar* pfetch_prev
Packit b89d10
#define PEND         (p < end ?  0 : 1)
Packit b89d10
#define PUNFETCH     p = pfetch_prev
Packit b89d10
#define PINC       do { \
Packit b89d10
  pfetch_prev = p; \
Packit b89d10
  p += ONIGENC_MBC_ENC_LEN(enc, p); \
Packit b89d10
} while (0)
Packit b89d10
#define PFETCH(c)  do { \
Packit b89d10
  c = ONIGENC_MBC_TO_CODE(enc, p, end); \
Packit b89d10
  pfetch_prev = p; \
Packit b89d10
  p += ONIGENC_MBC_ENC_LEN(enc, p); \
Packit b89d10
} while (0)
Packit b89d10
Packit b89d10
#define PINC_S     do { \
Packit b89d10
  p += ONIGENC_MBC_ENC_LEN(enc, p); \
Packit b89d10
} while (0)
Packit b89d10
#define PFETCH_S(c) do { \
Packit b89d10
  c = ONIGENC_MBC_TO_CODE(enc, p, end); \
Packit b89d10
  p += ONIGENC_MBC_ENC_LEN(enc, p); \
Packit b89d10
} while (0)
Packit b89d10
Packit b89d10
#define PPEEK        (p < end ? ONIGENC_MBC_TO_CODE(enc, p, end) : PEND_VALUE)
Packit b89d10
#define PPEEK_IS(c)  (PPEEK == (OnigCodePoint )c)
Packit b89d10
Packit b89d10
static UChar*
Packit b89d10
strcat_capa(UChar* dest, UChar* dest_end, const UChar* src, const UChar* src_end,
Packit b89d10
            int capa)
Packit b89d10
{
Packit b89d10
  UChar* r;
Packit b89d10
Packit b89d10
  if (dest)
Packit b89d10
    r = (UChar* )xrealloc(dest, capa + 1);
Packit b89d10
  else
Packit b89d10
    r = (UChar* )xmalloc(capa + 1);
Packit b89d10
Packit b89d10
  CHECK_NULL_RETURN(r);
Packit b89d10
  onig_strcpy(r + (dest_end - dest), src, src_end);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
/* dest on static area */
Packit b89d10
static UChar*
Packit b89d10
strcat_capa_from_static(UChar* dest, UChar* dest_end,
Packit b89d10
                        const UChar* src, const UChar* src_end, int capa)
Packit b89d10
{
Packit b89d10
  UChar* r;
Packit b89d10
Packit b89d10
  r = (UChar* )xmalloc(capa + 1);
Packit b89d10
  CHECK_NULL_RETURN(r);
Packit b89d10
  onig_strcpy(r, dest, dest_end);
Packit b89d10
  onig_strcpy(r + (dest_end - dest), src, src_end);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
#ifdef USE_ST_LIBRARY
Packit b89d10
Packit b89d10
typedef struct {
Packit b89d10
  UChar* s;
Packit b89d10
  UChar* end;
Packit b89d10
} st_str_end_key;
Packit b89d10
Packit b89d10
static int
Packit b89d10
str_end_cmp(st_str_end_key* x, st_str_end_key* y)
Packit b89d10
{
Packit b89d10
  UChar *p, *q;
Packit b89d10
  int c;
Packit b89d10
Packit b89d10
  if ((x->end - x->s) != (y->end - y->s))
Packit b89d10
    return 1;
Packit b89d10
Packit b89d10
  p = x->s;
Packit b89d10
  q = y->s;
Packit b89d10
  while (p < x->end) {
Packit b89d10
    c = (int )*p - (int )*q;
Packit b89d10
    if (c != 0) return c;
Packit b89d10
Packit b89d10
    p++; q++;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
str_end_hash(st_str_end_key* x)
Packit b89d10
{
Packit b89d10
  UChar *p;
Packit b89d10
  int val = 0;
Packit b89d10
Packit b89d10
  p = x->s;
Packit b89d10
  while (p < x->end) {
Packit b89d10
    val = val * 997 + (int )*p++;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return val + (val >> 5);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern hash_table_type*
Packit b89d10
onig_st_init_strend_table_with_size(int size)
Packit b89d10
{
Packit b89d10
  static struct st_hash_type hashType = {
Packit b89d10
    str_end_cmp,
Packit b89d10
    str_end_hash,
Packit b89d10
  };
Packit b89d10
Packit b89d10
  return (hash_table_type* )
Packit b89d10
           onig_st_init_table_with_size(&hashType, size);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_st_lookup_strend(hash_table_type* table, const UChar* str_key,
Packit b89d10
                      const UChar* end_key, hash_data_type *value)
Packit b89d10
{
Packit b89d10
  st_str_end_key key;
Packit b89d10
Packit b89d10
  key.s   = (UChar* )str_key;
Packit b89d10
  key.end = (UChar* )end_key;
Packit b89d10
Packit b89d10
  return onig_st_lookup(table, (st_data_t )(&key), value);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_st_insert_strend(hash_table_type* table, const UChar* str_key,
Packit b89d10
                      const UChar* end_key, hash_data_type value)
Packit b89d10
{
Packit b89d10
  st_str_end_key* key;
Packit b89d10
  int result;
Packit b89d10
Packit b89d10
  key = (st_str_end_key* )xmalloc(sizeof(st_str_end_key));
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(key);
Packit b89d10
Packit b89d10
  key->s   = (UChar* )str_key;
Packit b89d10
  key->end = (UChar* )end_key;
Packit b89d10
  result = onig_st_insert(table, (st_data_t )key, value);
Packit b89d10
  if (result) {
Packit b89d10
    xfree(key);
Packit b89d10
  }
Packit b89d10
  return result;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
typedef struct {
Packit b89d10
  OnigEncoding enc;
Packit b89d10
  int    type; /* callout type: single or not */
Packit b89d10
  UChar* s;
Packit b89d10
  UChar* end;
Packit b89d10
} st_callout_name_key;
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_name_table_cmp(st_callout_name_key* x, st_callout_name_key* y)
Packit b89d10
{
Packit b89d10
  UChar *p, *q;
Packit b89d10
  int c;
Packit b89d10
Packit b89d10
  if (x->enc  != y->enc)  return 1;
Packit b89d10
  if (x->type != y->type) return 1;
Packit b89d10
  if ((x->end - x->s) != (y->end - y->s))
Packit b89d10
    return 1;
Packit b89d10
Packit b89d10
  p = x->s;
Packit b89d10
  q = y->s;
Packit b89d10
  while (p < x->end) {
Packit b89d10
    c = (int )*p - (int )*q;
Packit b89d10
    if (c != 0) return c;
Packit b89d10
Packit b89d10
    p++; q++;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_name_table_hash(st_callout_name_key* x)
Packit b89d10
{
Packit b89d10
  UChar *p;
Packit b89d10
  int val = 0;
Packit b89d10
Packit b89d10
  p = x->s;
Packit b89d10
  while (p < x->end) {
Packit b89d10
    val = val * 997 + (int )*p++;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  /* use intptr_t for escape warning in Windows */
Packit b89d10
  return val + (val >> 5) + ((intptr_t )x->enc & 0xffff) + x->type;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern hash_table_type*
Packit b89d10
onig_st_init_callout_name_table_with_size(int size)
Packit b89d10
{
Packit b89d10
  static struct st_hash_type hashType = {
Packit b89d10
    callout_name_table_cmp,
Packit b89d10
    callout_name_table_hash,
Packit b89d10
  };
Packit b89d10
Packit b89d10
  return (hash_table_type* )
Packit b89d10
           onig_st_init_table_with_size(&hashType, size);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_st_lookup_callout_name_table(hash_table_type* table,
Packit b89d10
                                  OnigEncoding enc,
Packit b89d10
                                  int type,
Packit b89d10
                                  const UChar* str_key,
Packit b89d10
                                  const UChar* end_key,
Packit b89d10
                                  hash_data_type *value)
Packit b89d10
{
Packit b89d10
  st_callout_name_key key;
Packit b89d10
Packit b89d10
  key.enc  = enc;
Packit b89d10
  key.type = type;
Packit b89d10
  key.s    = (UChar* )str_key;
Packit b89d10
  key.end  = (UChar* )end_key;
Packit b89d10
Packit b89d10
  return onig_st_lookup(table, (st_data_t )(&key), value);
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
st_insert_callout_name_table(hash_table_type* table,
Packit b89d10
                             OnigEncoding enc, int type,
Packit b89d10
                             UChar* str_key, UChar* end_key,
Packit b89d10
                             hash_data_type value)
Packit b89d10
{
Packit b89d10
  st_callout_name_key* key;
Packit b89d10
  int result;
Packit b89d10
Packit b89d10
  key = (st_callout_name_key* )xmalloc(sizeof(st_callout_name_key));
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(key);
Packit b89d10
Packit b89d10
  /* key->s: don't duplicate, because str_key is duped in callout_name_entry() */
Packit b89d10
  key->enc  = enc;
Packit b89d10
  key->type = type;
Packit b89d10
  key->s    = str_key;
Packit b89d10
  key->end  = end_key;
Packit b89d10
  result = onig_st_insert(table, (st_data_t )key, value);
Packit b89d10
  if (result) {
Packit b89d10
    xfree(key);
Packit b89d10
  }
Packit b89d10
  return result;
Packit b89d10
}
Packit b89d10
Packit b89d10
#endif /* USE_ST_LIBRARY */
Packit b89d10
Packit b89d10
Packit b89d10
#define INIT_NAME_BACKREFS_ALLOC_NUM   8
Packit b89d10
Packit b89d10
typedef struct {
Packit b89d10
  UChar* name;
Packit b89d10
  int    name_len;   /* byte length */
Packit b89d10
  int    back_num;   /* number of backrefs */
Packit b89d10
  int    back_alloc;
Packit b89d10
  int    back_ref1;
Packit b89d10
  int*   back_refs;
Packit b89d10
} NameEntry;
Packit b89d10
Packit b89d10
#ifdef USE_ST_LIBRARY
Packit b89d10
Packit b89d10
#define INIT_NAMES_ALLOC_NUM    5
Packit b89d10
Packit b89d10
typedef st_table  NameTable;
Packit b89d10
typedef st_data_t HashDataType;   /* 1.6 st.h doesn't define st_data_t type */
Packit b89d10
Packit b89d10
#define NAMEBUF_SIZE    24
Packit b89d10
#define NAMEBUF_SIZE_1  25
Packit b89d10
Packit b89d10
#ifdef ONIG_DEBUG
Packit b89d10
static int
Packit b89d10
i_print_name_entry(UChar* key, NameEntry* e, void* arg)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  FILE* fp = (FILE* )arg;
Packit b89d10
Packit b89d10
  fprintf(fp, "%s: ", e->name);
Packit b89d10
  if (e->back_num == 0)
Packit b89d10
    fputs("-", fp);
Packit b89d10
  else if (e->back_num == 1)
Packit b89d10
    fprintf(fp, "%d", e->back_ref1);
Packit b89d10
  else {
Packit b89d10
    for (i = 0; i < e->back_num; i++) {
Packit b89d10
      if (i > 0) fprintf(fp, ", ");
Packit b89d10
      fprintf(fp, "%d", e->back_refs[i]);
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  fputs("\n", fp);
Packit b89d10
  return ST_CONTINUE;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_print_names(FILE* fp, regex_t* reg)
Packit b89d10
{
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    fprintf(fp, "name table\n");
Packit b89d10
    onig_st_foreach(t, i_print_name_entry, (HashDataType )fp);
Packit b89d10
    fputs("\n", fp);
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
#endif /* ONIG_DEBUG */
Packit b89d10
Packit b89d10
static int
Packit b89d10
i_free_name_entry(UChar* key, NameEntry* e, void* arg ARG_UNUSED)
Packit b89d10
{
Packit b89d10
  xfree(e->name);
Packit b89d10
  if (IS_NOT_NULL(e->back_refs)) xfree(e->back_refs);
Packit b89d10
  xfree(key);
Packit b89d10
  xfree(e);
Packit b89d10
  return ST_DELETE;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
names_clear(regex_t* reg)
Packit b89d10
{
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    onig_st_foreach(t, i_free_name_entry, 0);
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_names_free(regex_t* reg)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  NameTable* t;
Packit b89d10
Packit b89d10
  r = names_clear(reg);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  t = (NameTable* )reg->name_table;
Packit b89d10
  if (IS_NOT_NULL(t)) onig_st_free_table(t);
Packit b89d10
  reg->name_table = (void* )NULL;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static NameEntry*
Packit b89d10
name_find(regex_t* reg, const UChar* name, const UChar* name_end)
Packit b89d10
{
Packit b89d10
  NameEntry* e;
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  e = (NameEntry* )NULL;
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    onig_st_lookup_strend(t, name, name_end, (HashDataType* )((void* )(&e)));
Packit b89d10
  }
Packit b89d10
  return e;
Packit b89d10
}
Packit b89d10
Packit b89d10
typedef struct {
Packit b89d10
  int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*);
Packit b89d10
  regex_t* reg;
Packit b89d10
  void* arg;
Packit b89d10
  int ret;
Packit b89d10
  OnigEncoding enc;
Packit b89d10
} INamesArg;
Packit b89d10
Packit b89d10
static int
Packit b89d10
i_names(UChar* key ARG_UNUSED, NameEntry* e, INamesArg* arg)
Packit b89d10
{
Packit b89d10
  int r = (*(arg->func))(e->name,
Packit b89d10
                         e->name + e->name_len,
Packit b89d10
                         e->back_num,
Packit b89d10
                         (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
Packit b89d10
                         arg->reg, arg->arg);
Packit b89d10
  if (r != 0) {
Packit b89d10
    arg->ret = r;
Packit b89d10
    return ST_STOP;
Packit b89d10
  }
Packit b89d10
  return ST_CONTINUE;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_foreach_name(regex_t* reg,
Packit b89d10
  int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), void* arg)
Packit b89d10
{
Packit b89d10
  INamesArg narg;
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  narg.ret = 0;
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    narg.func = func;
Packit b89d10
    narg.reg  = reg;
Packit b89d10
    narg.arg  = arg;
Packit b89d10
    narg.enc  = reg->enc; /* should be pattern encoding. */
Packit b89d10
    onig_st_foreach(t, i_names, (HashDataType )&narg);
Packit b89d10
  }
Packit b89d10
  return narg.ret;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
i_renumber_name(UChar* key ARG_UNUSED, NameEntry* e, GroupNumRemap* map)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
Packit b89d10
  if (e->back_num > 1) {
Packit b89d10
    for (i = 0; i < e->back_num; i++) {
Packit b89d10
      e->back_refs[i] = map[e->back_refs[i]].new_val;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  else if (e->back_num == 1) {
Packit b89d10
    e->back_ref1 = map[e->back_ref1].new_val;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return ST_CONTINUE;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_renumber_name_table(regex_t* reg, GroupNumRemap* map)
Packit b89d10
{
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    onig_st_foreach(t, i_renumber_name, (HashDataType )map);
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_number_of_names(regex_t* reg)
Packit b89d10
{
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t))
Packit b89d10
    return t->num_entries;
Packit b89d10
  else
Packit b89d10
    return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
#else  /* USE_ST_LIBRARY */
Packit b89d10
Packit b89d10
#define INIT_NAMES_ALLOC_NUM    8
Packit b89d10
Packit b89d10
typedef struct {
Packit b89d10
  NameEntry* e;
Packit b89d10
  int        num;
Packit b89d10
  int        alloc;
Packit b89d10
} NameTable;
Packit b89d10
Packit b89d10
#ifdef ONIG_DEBUG
Packit b89d10
extern int
Packit b89d10
onig_print_names(FILE* fp, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int i, j;
Packit b89d10
  NameEntry* e;
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t) && t->num > 0) {
Packit b89d10
    fprintf(fp, "name table\n");
Packit b89d10
    for (i = 0; i < t->num; i++) {
Packit b89d10
      e = &(t->e[i]);
Packit b89d10
      fprintf(fp, "%s: ", e->name);
Packit b89d10
      if (e->back_num == 0) {
Packit b89d10
        fputs("-", fp);
Packit b89d10
      }
Packit b89d10
      else if (e->back_num == 1) {
Packit b89d10
        fprintf(fp, "%d", e->back_ref1);
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        for (j = 0; j < e->back_num; j++) {
Packit b89d10
          if (j > 0) fprintf(fp, ", ");
Packit b89d10
          fprintf(fp, "%d", e->back_refs[j]);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      fputs("\n", fp);
Packit b89d10
    }
Packit b89d10
    fputs("\n", fp);
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
static int
Packit b89d10
names_clear(regex_t* reg)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  NameEntry* e;
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    for (i = 0; i < t->num; i++) {
Packit b89d10
      e = &(t->e[i]);
Packit b89d10
      if (IS_NOT_NULL(e->name)) {
Packit b89d10
        xfree(e->name);
Packit b89d10
        e->name       = NULL;
Packit b89d10
        e->name_len   = 0;
Packit b89d10
        e->back_num   = 0;
Packit b89d10
        e->back_alloc = 0;
Packit b89d10
        if (IS_NOT_NULL(e->back_refs)) xfree(e->back_refs);
Packit b89d10
        e->back_refs = (int* )NULL;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    if (IS_NOT_NULL(t->e)) {
Packit b89d10
      xfree(t->e);
Packit b89d10
      t->e = NULL;
Packit b89d10
    }
Packit b89d10
    t->num = 0;
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_names_free(regex_t* reg)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  NameTable* t;
Packit b89d10
Packit b89d10
  r = names_clear(reg);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  t = (NameTable* )reg->name_table;
Packit b89d10
  if (IS_NOT_NULL(t)) xfree(t);
Packit b89d10
  reg->name_table = NULL;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static NameEntry*
Packit b89d10
name_find(regex_t* reg, UChar* name, UChar* name_end)
Packit b89d10
{
Packit b89d10
  int i, len;
Packit b89d10
  NameEntry* e;
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    len = name_end - name;
Packit b89d10
    for (i = 0; i < t->num; i++) {
Packit b89d10
      e = &(t->e[i]);
Packit b89d10
      if (len == e->name_len && onig_strncmp(name, e->name, len) == 0)
Packit b89d10
        return e;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  return (NameEntry* )NULL;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_foreach_name(regex_t* reg,
Packit b89d10
  int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), void* arg)
Packit b89d10
{
Packit b89d10
  int i, r;
Packit b89d10
  NameEntry* e;
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    for (i = 0; i < t->num; i++) {
Packit b89d10
      e = &(t->e[i]);
Packit b89d10
      r = (*func)(e->name, e->name + e->name_len, e->back_num,
Packit b89d10
                  (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
Packit b89d10
                  reg, arg);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_number_of_names(regex_t* reg)
Packit b89d10
{
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t))
Packit b89d10
    return t->num;
Packit b89d10
  else
Packit b89d10
    return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
#endif /* else USE_ST_LIBRARY */
Packit b89d10
Packit b89d10
static int
Packit b89d10
name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int alloc;
Packit b89d10
  NameEntry* e;
Packit b89d10
  NameTable* t = (NameTable* )reg->name_table;
Packit b89d10
Packit b89d10
  if (name_end - name <= 0)
Packit b89d10
    return ONIGERR_EMPTY_GROUP_NAME;
Packit b89d10
Packit b89d10
  e = name_find(reg, name, name_end);
Packit b89d10
  if (IS_NULL(e)) {
Packit b89d10
#ifdef USE_ST_LIBRARY
Packit b89d10
    if (IS_NULL(t)) {
Packit b89d10
      t = onig_st_init_strend_table_with_size(INIT_NAMES_ALLOC_NUM);
Packit b89d10
      reg->name_table = (void* )t;
Packit b89d10
    }
Packit b89d10
    e = (NameEntry* )xmalloc(sizeof(NameEntry));
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(e);
Packit b89d10
Packit b89d10
    e->name = onigenc_strdup(reg->enc, name, name_end);
Packit b89d10
    if (IS_NULL(e->name)) {
Packit b89d10
      xfree(e);  return ONIGERR_MEMORY;
Packit b89d10
    }
Packit b89d10
    r = onig_st_insert_strend(t, e->name, (e->name + (name_end - name)),
Packit b89d10
                              (HashDataType )e);
Packit b89d10
    if (r < 0) return r;
Packit b89d10
Packit b89d10
    e->name_len   = (int )(name_end - name);
Packit b89d10
    e->back_num   = 0;
Packit b89d10
    e->back_alloc = 0;
Packit b89d10
    e->back_refs  = (int* )NULL;
Packit b89d10
Packit b89d10
#else
Packit b89d10
Packit b89d10
    if (IS_NULL(t)) {
Packit b89d10
      alloc = INIT_NAMES_ALLOC_NUM;
Packit b89d10
      t = (NameTable* )xmalloc(sizeof(NameTable));
Packit b89d10
      CHECK_NULL_RETURN_MEMERR(t);
Packit b89d10
      t->e     = NULL;
Packit b89d10
      t->alloc = 0;
Packit b89d10
      t->num   = 0;
Packit b89d10
Packit b89d10
      t->e = (NameEntry* )xmalloc(sizeof(NameEntry) * alloc);
Packit b89d10
      if (IS_NULL(t->e)) {
Packit b89d10
        xfree(t);
Packit b89d10
        return ONIGERR_MEMORY;
Packit b89d10
      }
Packit b89d10
      t->alloc = alloc;
Packit b89d10
      reg->name_table = t;
Packit b89d10
      goto clear;
Packit b89d10
    }
Packit b89d10
    else if (t->num == t->alloc) {
Packit b89d10
      int i;
Packit b89d10
Packit b89d10
      alloc = t->alloc * 2;
Packit b89d10
      t->e = (NameEntry* )xrealloc(t->e, sizeof(NameEntry) * alloc);
Packit b89d10
      CHECK_NULL_RETURN_MEMERR(t->e);
Packit b89d10
      t->alloc = alloc;
Packit b89d10
Packit b89d10
    clear:
Packit b89d10
      for (i = t->num; i < t->alloc; i++) {
Packit b89d10
        t->e[i].name       = NULL;
Packit b89d10
        t->e[i].name_len   = 0;
Packit b89d10
        t->e[i].back_num   = 0;
Packit b89d10
        t->e[i].back_alloc = 0;
Packit b89d10
        t->e[i].back_refs  = (int* )NULL;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    e = &(t->e[t->num]);
Packit b89d10
    t->num++;
Packit b89d10
    e->name = onigenc_strdup(reg->enc, name, name_end);
Packit b89d10
    if (IS_NULL(e->name)) return ONIGERR_MEMORY;
Packit b89d10
    e->name_len = name_end - name;
Packit b89d10
#endif
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (e->back_num >= 1 &&
Packit b89d10
      ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME)) {
Packit b89d10
    onig_scan_env_set_error_string(env, ONIGERR_MULTIPLEX_DEFINED_NAME,
Packit b89d10
                                   name, name_end);
Packit b89d10
    return ONIGERR_MULTIPLEX_DEFINED_NAME;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  e->back_num++;
Packit b89d10
  if (e->back_num == 1) {
Packit b89d10
    e->back_ref1 = backref;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    if (e->back_num == 2) {
Packit b89d10
      alloc = INIT_NAME_BACKREFS_ALLOC_NUM;
Packit b89d10
      e->back_refs = (int* )xmalloc(sizeof(int) * alloc);
Packit b89d10
      CHECK_NULL_RETURN_MEMERR(e->back_refs);
Packit b89d10
      e->back_alloc = alloc;
Packit b89d10
      e->back_refs[0] = e->back_ref1;
Packit b89d10
      e->back_refs[1] = backref;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      if (e->back_num > e->back_alloc) {
Packit b89d10
        alloc = e->back_alloc * 2;
Packit b89d10
        e->back_refs = (int* )xrealloc(e->back_refs, sizeof(int) * alloc);
Packit b89d10
        CHECK_NULL_RETURN_MEMERR(e->back_refs);
Packit b89d10
        e->back_alloc = alloc;
Packit b89d10
      }
Packit b89d10
      e->back_refs[e->back_num - 1] = backref;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_name_to_group_numbers(regex_t* reg, const UChar* name,
Packit b89d10
                           const UChar* name_end, int** nums)
Packit b89d10
{
Packit b89d10
  NameEntry* e = name_find(reg, name, name_end);
Packit b89d10
Packit b89d10
  if (IS_NULL(e)) return ONIGERR_UNDEFINED_NAME_REFERENCE;
Packit b89d10
Packit b89d10
  switch (e->back_num) {
Packit b89d10
  case 0:
Packit b89d10
    break;
Packit b89d10
  case 1:
Packit b89d10
    *nums = &(e->back_ref1);
Packit b89d10
    break;
Packit b89d10
  default:
Packit b89d10
    *nums = e->back_refs;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
  return e->back_num;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_name_to_backref_number(regex_t* reg, const UChar* name,
Packit b89d10
                            const UChar* name_end, OnigRegion *region)
Packit b89d10
{
Packit b89d10
  int i, n, *nums;
Packit b89d10
Packit b89d10
  n = onig_name_to_group_numbers(reg, name, name_end, &nums);
Packit b89d10
  if (n < 0)
Packit b89d10
    return n;
Packit b89d10
  else if (n == 0)
Packit b89d10
    return ONIGERR_PARSER_BUG;
Packit b89d10
  else if (n == 1)
Packit b89d10
    return nums[0];
Packit b89d10
  else {
Packit b89d10
    if (IS_NOT_NULL(region)) {
Packit b89d10
      for (i = n - 1; i >= 0; i--) {
Packit b89d10
        if (region->beg[nums[i]] != ONIG_REGION_NOTPOS)
Packit b89d10
          return nums[i];
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    return nums[n - 1];
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_noname_group_capture_is_active(regex_t* reg)
Packit b89d10
{
Packit b89d10
  if (ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_DONT_CAPTURE_GROUP))
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  if (onig_number_of_names(reg) > 0 &&
Packit b89d10
      IS_SYNTAX_BV(reg->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
Packit b89d10
      !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) {
Packit b89d10
    return 0;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 1;
Packit b89d10
}
Packit b89d10
Packit b89d10
#ifdef USE_CALLOUT
Packit b89d10
Packit b89d10
typedef struct {
Packit b89d10
  OnigCalloutType type;
Packit b89d10
  int             in;
Packit b89d10
  OnigCalloutFunc start_func;
Packit b89d10
  OnigCalloutFunc end_func;
Packit b89d10
  int             arg_num;
Packit b89d10
  int             opt_arg_num;
Packit b89d10
  unsigned int    arg_types[ONIG_CALLOUT_MAX_ARGS_NUM];
Packit b89d10
  OnigValue       opt_defaults[ONIG_CALLOUT_MAX_ARGS_NUM];
Packit b89d10
  UChar*          name; /* reference to GlobalCalloutNameTable entry: e->name */
Packit b89d10
} CalloutNameListEntry;
Packit b89d10
Packit b89d10
typedef struct {
Packit b89d10
  int  n;
Packit b89d10
  int  alloc;
Packit b89d10
  CalloutNameListEntry* v;
Packit b89d10
} CalloutNameListType;
Packit b89d10
Packit b89d10
static CalloutNameListType* GlobalCalloutNameList;
Packit b89d10
Packit b89d10
static int
Packit b89d10
make_callout_func_list(CalloutNameListType** rs, int init_size)
Packit b89d10
{
Packit b89d10
  CalloutNameListType* s;
Packit b89d10
  CalloutNameListEntry* 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 = (CalloutNameListEntry* )xmalloc(sizeof(CalloutNameListEntry) * 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_callout_func_list(CalloutNameListType* s)
Packit b89d10
{
Packit b89d10
  if (IS_NOT_NULL(s)) {
Packit b89d10
    if (IS_NOT_NULL(s->v)) {
Packit b89d10
      int i, j;
Packit b89d10
Packit b89d10
      for (i = 0; i < s->n; i++) {
Packit b89d10
        CalloutNameListEntry* e = s->v + i;
Packit b89d10
        for (j = e->arg_num - e->opt_arg_num; j < e->arg_num; j++) {
Packit b89d10
          if (e->arg_types[j] == ONIG_TYPE_STRING) {
Packit b89d10
            UChar* p = e->opt_defaults[j].s.start;
Packit b89d10
            if (IS_NOT_NULL(p)) xfree(p);
Packit b89d10
          }
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      xfree(s->v);
Packit b89d10
    }
Packit b89d10
    xfree(s);
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_func_list_add(CalloutNameListType* s, int* rid)
Packit b89d10
{
Packit b89d10
  if (s->n >= s->alloc) {
Packit b89d10
    int new_size = s->alloc * 2;
Packit b89d10
    CalloutNameListEntry* nv = (CalloutNameListEntry* )
Packit b89d10
      xrealloc(s->v, sizeof(CalloutNameListEntry) * 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
  *rid = s->n;
Packit b89d10
Packit b89d10
  xmemset(&(s->v[s->n]), 0, sizeof(*(s->v)));
Packit b89d10
  s->n++;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
typedef struct {
Packit b89d10
  UChar* name;
Packit b89d10
  int    name_len;   /* byte length */
Packit b89d10
  int    id;
Packit b89d10
} CalloutNameEntry;
Packit b89d10
Packit b89d10
#ifdef USE_ST_LIBRARY
Packit b89d10
typedef st_table  CalloutNameTable;
Packit b89d10
#else
Packit b89d10
typedef struct {
Packit b89d10
  CalloutNameEntry* e;
Packit b89d10
  int               num;
Packit b89d10
  int               alloc;
Packit b89d10
} CalloutNameTable;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
static CalloutNameTable* GlobalCalloutNameTable;
Packit b89d10
static int CalloutNameIDCounter;
Packit b89d10
Packit b89d10
#ifdef USE_ST_LIBRARY
Packit b89d10
Packit b89d10
static int
Packit b89d10
i_free_callout_name_entry(st_callout_name_key* key, CalloutNameEntry* e,
Packit b89d10
                          void* arg ARG_UNUSED)
Packit b89d10
{
Packit b89d10
  xfree(e->name);
Packit b89d10
  /*xfree(key->s); */ /* is same as e->name */
Packit b89d10
  xfree(key);
Packit b89d10
  xfree(e);
Packit b89d10
  return ST_DELETE;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_name_table_clear(CalloutNameTable* t)
Packit b89d10
{
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    onig_st_foreach(t, i_free_callout_name_entry, 0);
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
global_callout_name_table_free(void)
Packit b89d10
{
Packit b89d10
  if (IS_NOT_NULL(GlobalCalloutNameTable)) {
Packit b89d10
    int r = callout_name_table_clear(GlobalCalloutNameTable);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
Packit b89d10
    onig_st_free_table(GlobalCalloutNameTable);
Packit b89d10
    GlobalCalloutNameTable = 0;
Packit b89d10
    CalloutNameIDCounter = 0;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static CalloutNameEntry*
Packit b89d10
callout_name_find(OnigEncoding enc, int is_not_single,
Packit b89d10
                  const UChar* name, const UChar* name_end)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  CalloutNameEntry* e;
Packit b89d10
  CalloutNameTable* t = GlobalCalloutNameTable;
Packit b89d10
Packit b89d10
  e = (CalloutNameEntry* )NULL;
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    r = onig_st_lookup_callout_name_table(t, enc, is_not_single, name, name_end,
Packit b89d10
                                          (HashDataType* )((void* )(&e)));
Packit b89d10
    if (r == 0) { /* not found */
Packit b89d10
      if (enc != ONIG_ENCODING_ASCII &&
Packit b89d10
          ONIGENC_IS_ASCII_COMPATIBLE_ENCODING(enc)) {
Packit b89d10
        enc = ONIG_ENCODING_ASCII;
Packit b89d10
        onig_st_lookup_callout_name_table(t, enc, is_not_single, name, name_end,
Packit b89d10
                                          (HashDataType* )((void* )(&e)));
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  return e;
Packit b89d10
}
Packit b89d10
Packit b89d10
#else
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_name_table_clear(CalloutNameTable* t)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  CalloutNameEntry* e;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    for (i = 0; i < t->num; i++) {
Packit b89d10
      e = &(t->e[i]);
Packit b89d10
      if (IS_NOT_NULL(e->name)) {
Packit b89d10
        xfree(e->name);
Packit b89d10
        e->name     = NULL;
Packit b89d10
        e->name_len = 0;
Packit b89d10
        e->id       = 0;
Packit b89d10
        e->func     = 0;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    if (IS_NOT_NULL(t->e)) {
Packit b89d10
      xfree(t->e);
Packit b89d10
      t->e = NULL;
Packit b89d10
    }
Packit b89d10
    t->num = 0;
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
global_callout_name_table_free(void)
Packit b89d10
{
Packit b89d10
  if (IS_NOT_NULL(GlobalCalloutNameTable)) {
Packit b89d10
    int r = callout_name_table_clear(GlobalCalloutNameTable);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
Packit b89d10
    xfree(GlobalCalloutNameTable);
Packit b89d10
    GlobalCalloutNameTable = 0;
Packit b89d10
    CalloutNameIDCounter = 0;
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static CalloutNameEntry*
Packit b89d10
callout_name_find(UChar* name, UChar* name_end)
Packit b89d10
{
Packit b89d10
  int i, len;
Packit b89d10
  CalloutNameEntry* e;
Packit b89d10
  CalloutNameTable* t = Calloutnames;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    len = name_end - name;
Packit b89d10
    for (i = 0; i < t->num; i++) {
Packit b89d10
      e = &(t->e[i]);
Packit b89d10
      if (len == e->name_len && onig_strncmp(name, e->name, len) == 0)
Packit b89d10
        return e;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  return (CalloutNameEntry* )NULL;
Packit b89d10
}
Packit b89d10
Packit b89d10
#endif
Packit b89d10
Packit b89d10
/* name string must be single byte char string. */
Packit b89d10
static int
Packit b89d10
callout_name_entry(CalloutNameEntry** rentry, OnigEncoding enc,
Packit b89d10
                   int is_not_single, UChar* name, UChar* name_end)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  CalloutNameEntry* e;
Packit b89d10
  CalloutNameTable* t = GlobalCalloutNameTable;
Packit b89d10
Packit b89d10
  *rentry = 0;
Packit b89d10
  if (name_end - name <= 0)
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_NAME;
Packit b89d10
Packit b89d10
  e = callout_name_find(enc, is_not_single, name, name_end);
Packit b89d10
  if (IS_NULL(e)) {
Packit b89d10
#ifdef USE_ST_LIBRARY
Packit b89d10
    if (IS_NULL(t)) {
Packit b89d10
      t = onig_st_init_callout_name_table_with_size(INIT_NAMES_ALLOC_NUM);
Packit b89d10
      GlobalCalloutNameTable = t;
Packit b89d10
    }
Packit b89d10
    e = (CalloutNameEntry* )xmalloc(sizeof(CalloutNameEntry));
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(e);
Packit b89d10
Packit b89d10
    e->name = onigenc_strdup(enc, name, name_end);
Packit b89d10
    if (IS_NULL(e->name)) {
Packit b89d10
      xfree(e);  return ONIGERR_MEMORY;
Packit b89d10
    }
Packit b89d10
Packit b89d10
    r = st_insert_callout_name_table(t, enc, is_not_single,
Packit b89d10
                                     e->name, (e->name + (name_end - name)),
Packit b89d10
                                     (HashDataType )e);
Packit b89d10
    if (r < 0) return r;
Packit b89d10
Packit b89d10
#else
Packit b89d10
Packit b89d10
    int alloc;
Packit b89d10
Packit b89d10
    if (IS_NULL(t)) {
Packit b89d10
      alloc = INIT_NAMES_ALLOC_NUM;
Packit b89d10
      t = (CalloutNameTable* )xmalloc(sizeof(CalloutNameTable));
Packit b89d10
      CHECK_NULL_RETURN_MEMERR(t);
Packit b89d10
      t->e     = NULL;
Packit b89d10
      t->alloc = 0;
Packit b89d10
      t->num   = 0;
Packit b89d10
Packit b89d10
      t->e = (CalloutNameEntry* )xmalloc(sizeof(CalloutNameEntry) * alloc);
Packit b89d10
      if (IS_NULL(t->e)) {
Packit b89d10
        xfree(t);
Packit b89d10
        return ONIGERR_MEMORY;
Packit b89d10
      }
Packit b89d10
      t->alloc = alloc;
Packit b89d10
      GlobalCalloutNameTable = t;
Packit b89d10
      goto clear;
Packit b89d10
    }
Packit b89d10
    else if (t->num == t->alloc) {
Packit b89d10
      int i;
Packit b89d10
Packit b89d10
      alloc = t->alloc * 2;
Packit b89d10
      t->e = (CalloutNameEntry* )xrealloc(t->e, sizeof(CalloutNameEntry) * alloc);
Packit b89d10
      CHECK_NULL_RETURN_MEMERR(t->e);
Packit b89d10
      t->alloc = alloc;
Packit b89d10
Packit b89d10
    clear:
Packit b89d10
      for (i = t->num; i < t->alloc; i++) {
Packit b89d10
        t->e[i].name       = NULL;
Packit b89d10
        t->e[i].name_len   = 0;
Packit b89d10
        t->e[i].id         = 0;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    e = &(t->e[t->num]);
Packit b89d10
    t->num++;
Packit b89d10
    e->name = onigenc_strdup(enc, name, name_end);
Packit b89d10
    if (IS_NULL(e->name)) return ONIGERR_MEMORY;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
    CalloutNameIDCounter++;
Packit b89d10
    e->id = CalloutNameIDCounter;
Packit b89d10
    e->name_len = (int )(name_end - name);
Packit b89d10
  }
Packit b89d10
Packit b89d10
  *rentry = e;
Packit b89d10
  return e->id;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
is_allowed_callout_name(OnigEncoding enc, UChar* name, UChar* name_end)
Packit b89d10
{
Packit b89d10
  UChar* p;
Packit b89d10
  OnigCodePoint c;
Packit b89d10
Packit b89d10
  if (name >= name_end) return 0;
Packit b89d10
Packit b89d10
  p = name;
Packit b89d10
  while (p < name_end) {
Packit b89d10
    c = ONIGENC_MBC_TO_CODE(enc, p, name_end);
Packit b89d10
    if (! IS_ALLOWED_CODE_IN_CALLOUT_NAME(c))
Packit b89d10
      return 0;
Packit b89d10
Packit b89d10
    if (p == name) {
Packit b89d10
      if (c >= '0' && c <= '9') return 0;
Packit b89d10
    }
Packit b89d10
Packit b89d10
    p += ONIGENC_MBC_ENC_LEN(enc, p);
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 1;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
is_allowed_callout_tag_name(OnigEncoding enc, UChar* name, UChar* name_end)
Packit b89d10
{
Packit b89d10
  UChar* p;
Packit b89d10
  OnigCodePoint c;
Packit b89d10
Packit b89d10
  if (name >= name_end) return 0;
Packit b89d10
Packit b89d10
  p = name;
Packit b89d10
  while (p < name_end) {
Packit b89d10
    c = ONIGENC_MBC_TO_CODE(enc, p, name_end);
Packit b89d10
    if (! IS_ALLOWED_CODE_IN_CALLOUT_TAG_NAME(c))
Packit b89d10
      return 0;
Packit b89d10
Packit b89d10
    if (p == name) {
Packit b89d10
      if (c >= '0' && c <= '9') return 0;
Packit b89d10
    }
Packit b89d10
Packit b89d10
    p += ONIGENC_MBC_ENC_LEN(enc, p);
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 1;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_set_callout_of_name(OnigEncoding enc, OnigCalloutType callout_type,
Packit b89d10
                         UChar* name, UChar* name_end, int in,
Packit b89d10
                         OnigCalloutFunc start_func,
Packit b89d10
                         OnigCalloutFunc end_func,
Packit b89d10
                         int arg_num, unsigned int arg_types[],
Packit b89d10
                         int opt_arg_num, OnigValue opt_defaults[])
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int i;
Packit b89d10
  int j;
Packit b89d10
  int id;
Packit b89d10
  int is_not_single;
Packit b89d10
  CalloutNameEntry* e;
Packit b89d10
  CalloutNameListEntry* fe;
Packit b89d10
Packit b89d10
  if (callout_type != ONIG_CALLOUT_TYPE_SINGLE)
Packit b89d10
    return ONIGERR_INVALID_ARGUMENT;
Packit b89d10
Packit b89d10
  if (arg_num < 0 || arg_num > ONIG_CALLOUT_MAX_ARGS_NUM)
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_ARG;
Packit b89d10
Packit b89d10
  if (opt_arg_num < 0 || opt_arg_num > arg_num)
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_ARG;
Packit b89d10
Packit b89d10
  if (start_func == 0 && end_func == 0)
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_ARG;
Packit b89d10
Packit b89d10
  if ((in & ONIG_CALLOUT_IN_PROGRESS) == 0 && (in & ONIG_CALLOUT_IN_RETRACTION) == 0)
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_ARG;
Packit b89d10
Packit b89d10
  for (i = 0; i < arg_num; i++) {
Packit b89d10
    unsigned int t = arg_types[i];
Packit b89d10
    if (t == ONIG_TYPE_VOID)
Packit b89d10
      return ONIGERR_INVALID_CALLOUT_ARG;
Packit b89d10
    else {
Packit b89d10
      if (i >= arg_num - opt_arg_num) {
Packit b89d10
        if (t != ONIG_TYPE_LONG && t != ONIG_TYPE_CHAR && t != ONIG_TYPE_STRING &&
Packit b89d10
            t != ONIG_TYPE_TAG)
Packit b89d10
          return ONIGERR_INVALID_CALLOUT_ARG;
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        if (t != ONIG_TYPE_LONG) {
Packit b89d10
          t = t & ~ONIG_TYPE_LONG;
Packit b89d10
          if (t != ONIG_TYPE_CHAR && t != ONIG_TYPE_STRING && t != ONIG_TYPE_TAG)
Packit b89d10
            return ONIGERR_INVALID_CALLOUT_ARG;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (! is_allowed_callout_name(enc, name, name_end)) {
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_NAME;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  is_not_single = (callout_type != ONIG_CALLOUT_TYPE_SINGLE);
Packit b89d10
  id = callout_name_entry(&e, enc, is_not_single, name, name_end);
Packit b89d10
  if (id < 0) return id;
Packit b89d10
Packit b89d10
  r = ONIG_NORMAL;
Packit b89d10
  if (IS_NULL(GlobalCalloutNameList)) {
Packit b89d10
    r = make_callout_func_list(&GlobalCalloutNameList, 10);
Packit b89d10
    if (r != ONIG_NORMAL) return r;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  while (id >= GlobalCalloutNameList->n) {
Packit b89d10
    int rid;
Packit b89d10
    r = callout_func_list_add(GlobalCalloutNameList, &rid;;
Packit b89d10
    if (r != ONIG_NORMAL) return r;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  fe = GlobalCalloutNameList->v + id;
Packit b89d10
  fe->type         = callout_type;
Packit b89d10
  fe->in           = in;
Packit b89d10
  fe->start_func   = start_func;
Packit b89d10
  fe->end_func     = end_func;
Packit b89d10
  fe->arg_num      = arg_num;
Packit b89d10
  fe->opt_arg_num  = opt_arg_num;
Packit b89d10
  fe->name         = e->name;
Packit b89d10
Packit b89d10
  for (i = 0; i < arg_num; i++) {
Packit b89d10
    fe->arg_types[i] = arg_types[i];
Packit b89d10
  }
Packit b89d10
  for (i = arg_num - opt_arg_num, j = 0; i < arg_num; i++, j++) {
Packit b89d10
    if (fe->arg_types[i] == ONIG_TYPE_STRING) {
Packit b89d10
      OnigValue* val = opt_defaults + j;
Packit b89d10
      UChar* ds = onigenc_strdup(enc, val->s.start, val->s.end);
Packit b89d10
      CHECK_NULL_RETURN_MEMERR(ds);
Packit b89d10
Packit b89d10
      fe->opt_defaults[i].s.start = ds;
Packit b89d10
      fe->opt_defaults[i].s.end   = ds + (val->s.end - val->s.start);
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      fe->opt_defaults[i] = opt_defaults[j];
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  r = id;
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
get_callout_name_id_by_name(OnigEncoding enc, int is_not_single,
Packit b89d10
                            UChar* name, UChar* name_end, int* rid)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  CalloutNameEntry* e;
Packit b89d10
Packit b89d10
  if (! is_allowed_callout_name(enc, name, name_end)) {
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_NAME;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  e = callout_name_find(enc, is_not_single, name, name_end);
Packit b89d10
  if (IS_NULL(e)) {
Packit b89d10
    return ONIGERR_UNDEFINED_CALLOUT_NAME;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  r = ONIG_NORMAL;
Packit b89d10
  *rid = e->id;
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern OnigCalloutFunc
Packit b89d10
onig_get_callout_start_func(regex_t* reg, int callout_num)
Packit b89d10
{
Packit b89d10
  /* If used for callouts of contents, return 0. */
Packit b89d10
  CalloutListEntry* e;
Packit b89d10
Packit b89d10
  e = onig_reg_callout_list_at(reg, callout_num);
Packit b89d10
  return e->start_func;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern const UChar*
Packit b89d10
onig_get_callout_tag_start(regex_t* reg, int callout_num)
Packit b89d10
{
Packit b89d10
  CalloutListEntry* e = onig_reg_callout_list_at(reg, callout_num);
Packit b89d10
  return e->tag_start;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern const UChar*
Packit b89d10
onig_get_callout_tag_end(regex_t* reg, int callout_num)
Packit b89d10
{
Packit b89d10
  CalloutListEntry* e = onig_reg_callout_list_at(reg, callout_num);
Packit b89d10
  return e->tag_end;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
extern OnigCalloutType
Packit b89d10
onig_get_callout_type_by_name_id(int name_id)
Packit b89d10
{
Packit b89d10
  if (name_id < 0 || name_id >= GlobalCalloutNameList->n)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  return GlobalCalloutNameList->v[name_id].type;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern OnigCalloutFunc
Packit b89d10
onig_get_callout_start_func_by_name_id(int name_id)
Packit b89d10
{
Packit b89d10
  if (name_id < 0 || name_id >= GlobalCalloutNameList->n)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  return GlobalCalloutNameList->v[name_id].start_func;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern OnigCalloutFunc
Packit b89d10
onig_get_callout_end_func_by_name_id(int name_id)
Packit b89d10
{
Packit b89d10
  if (name_id < 0 || name_id >= GlobalCalloutNameList->n)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  return GlobalCalloutNameList->v[name_id].end_func;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_get_callout_in_by_name_id(int name_id)
Packit b89d10
{
Packit b89d10
  if (name_id < 0 || name_id >= GlobalCalloutNameList->n)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  return GlobalCalloutNameList->v[name_id].in;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
get_callout_arg_num_by_name_id(int name_id)
Packit b89d10
{
Packit b89d10
  return GlobalCalloutNameList->v[name_id].arg_num;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
get_callout_opt_arg_num_by_name_id(int name_id)
Packit b89d10
{
Packit b89d10
  return GlobalCalloutNameList->v[name_id].opt_arg_num;
Packit b89d10
}
Packit b89d10
Packit b89d10
static unsigned int
Packit b89d10
get_callout_arg_type_by_name_id(int name_id, int index)
Packit b89d10
{
Packit b89d10
  return GlobalCalloutNameList->v[name_id].arg_types[index];
Packit b89d10
}
Packit b89d10
Packit b89d10
static OnigValue
Packit b89d10
get_callout_opt_default_by_name_id(int name_id, int index)
Packit b89d10
{
Packit b89d10
  return GlobalCalloutNameList->v[name_id].opt_defaults[index];
Packit b89d10
}
Packit b89d10
Packit b89d10
extern UChar*
Packit b89d10
onig_get_callout_name_by_name_id(int name_id)
Packit b89d10
{
Packit b89d10
  if (name_id < 0 || name_id >= GlobalCalloutNameList->n)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  return GlobalCalloutNameList->v[name_id].name;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_global_callout_names_free(void)
Packit b89d10
{
Packit b89d10
  free_callout_func_list(GlobalCalloutNameList);
Packit b89d10
  GlobalCalloutNameList = 0;
Packit b89d10
Packit b89d10
  global_callout_name_table_free();
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
typedef st_table   CalloutTagTable;
Packit b89d10
typedef intptr_t   CalloutTagVal;
Packit b89d10
Packit b89d10
#define CALLOUT_TAG_LIST_FLAG_TAG_EXIST     (1<<0)
Packit b89d10
Packit b89d10
static int
Packit b89d10
i_callout_callout_list_set(UChar* key, CalloutTagVal e, void* arg)
Packit b89d10
{
Packit b89d10
  int num;
Packit b89d10
  RegexExt* ext = (RegexExt* )arg;
Packit b89d10
Packit b89d10
  num = (int )e - 1;
Packit b89d10
  ext->callout_list[num].flag |= CALLOUT_TAG_LIST_FLAG_TAG_EXIST;
Packit b89d10
  return ST_CONTINUE;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
setup_ext_callout_list_values(regex_t* reg)
Packit b89d10
{
Packit b89d10
  int i, j;
Packit b89d10
  RegexExt* ext;
Packit b89d10
Packit b89d10
  ext = REG_EXTP(reg);
Packit b89d10
  if (IS_NOT_NULL(ext->tag_table)) {
Packit b89d10
    onig_st_foreach((CalloutTagTable *)ext->tag_table, i_callout_callout_list_set,
Packit b89d10
                    (st_data_t )ext);
Packit b89d10
  }
Packit b89d10
Packit b89d10
  for (i = 0; i < ext->callout_num; i++) {
Packit b89d10
    CalloutListEntry* e = ext->callout_list + i;
Packit b89d10
    if (e->of == ONIG_CALLOUT_OF_NAME) {
Packit b89d10
      for (j = 0; j < e->u.arg.num; j++) {
Packit b89d10
        if (e->u.arg.types[j] == ONIG_TYPE_TAG) {
Packit b89d10
          UChar* start;
Packit b89d10
          UChar* end;
Packit b89d10
          int num;
Packit b89d10
          start = e->u.arg.vals[j].s.start;
Packit b89d10
          end   = e->u.arg.vals[j].s.end;
Packit b89d10
          num = onig_get_callout_num_by_tag(reg, start, end);
Packit b89d10
          if (num < 0) return num;
Packit b89d10
          e->u.arg.vals[j].tag = num;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_callout_tag_is_exist_at_callout_num(regex_t* reg, int callout_num)
Packit b89d10
{
Packit b89d10
  RegexExt* ext = REG_EXTP(reg);
Packit b89d10
Packit b89d10
  if (IS_NULL(ext) || IS_NULL(ext->callout_list)) return 0;
Packit b89d10
  if (callout_num > ext->callout_num) return 0;
Packit b89d10
Packit b89d10
  return (ext->callout_list[callout_num].flag &
Packit b89d10
          CALLOUT_TAG_LIST_FLAG_TAG_EXIST) != 0  ? 1 : 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
i_free_callout_tag_entry(UChar* key, CalloutTagVal e, void* arg ARG_UNUSED)
Packit b89d10
{
Packit b89d10
  xfree(key);
Packit b89d10
  return ST_DELETE;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_tag_table_clear(CalloutTagTable* t)
Packit b89d10
{
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    onig_st_foreach(t, i_free_callout_tag_entry, 0);
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_callout_tag_table_free(void* table)
Packit b89d10
{
Packit b89d10
  CalloutTagTable* t = (CalloutTagTable* )table;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    int r = callout_tag_table_clear(t);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
Packit b89d10
    onig_st_free_table(t);
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_get_callout_num_by_tag(regex_t* reg,
Packit b89d10
                            const UChar* tag, const UChar* tag_end)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  RegexExt* ext;
Packit b89d10
  CalloutTagVal e;
Packit b89d10
Packit b89d10
  ext = REG_EXTP(reg);
Packit b89d10
  if (IS_NULL(ext) || IS_NULL(ext->tag_table))
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_TAG_NAME;
Packit b89d10
Packit b89d10
  r = onig_st_lookup_strend(ext->tag_table, tag, tag_end,
Packit b89d10
                            (HashDataType* )((void* )(&e)));
Packit b89d10
  if (r == 0) return ONIGERR_INVALID_CALLOUT_TAG_NAME;
Packit b89d10
  return (int )e;
Packit b89d10
}
Packit b89d10
Packit b89d10
static CalloutTagVal
Packit b89d10
callout_tag_find(CalloutTagTable* t, const UChar* name, const UChar* name_end)
Packit b89d10
{
Packit b89d10
  CalloutTagVal e;
Packit b89d10
Packit b89d10
  e = -1;
Packit b89d10
  if (IS_NOT_NULL(t)) {
Packit b89d10
    onig_st_lookup_strend(t, name, name_end, (HashDataType* )((void* )(&e)));
Packit b89d10
  }
Packit b89d10
  return e;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_tag_table_new(CalloutTagTable** rt)
Packit b89d10
{
Packit b89d10
  CalloutTagTable* t;
Packit b89d10
Packit b89d10
  *rt = 0;
Packit b89d10
  t = onig_st_init_strend_table_with_size(INIT_TAG_NAMES_ALLOC_NUM);
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(t);
Packit b89d10
Packit b89d10
  *rt = t;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_tag_entry_raw(CalloutTagTable* t, UChar* name, UChar* name_end,
Packit b89d10
                      CalloutTagVal entry_val)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  CalloutTagVal val;
Packit b89d10
Packit b89d10
  if (name_end - name <= 0)
Packit b89d10
    return ONIGERR_INVALID_CALLOUT_TAG_NAME;
Packit b89d10
Packit b89d10
  val = callout_tag_find(t, name, name_end);
Packit b89d10
  if (val >= 0)
Packit b89d10
    return ONIGERR_MULTIPLEX_DEFINED_NAME;
Packit b89d10
Packit b89d10
  r = onig_st_insert_strend(t, name, name_end, (HashDataType )entry_val);
Packit b89d10
  if (r < 0) return r;
Packit b89d10
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
ext_ensure_tag_table(regex_t* reg)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  RegexExt* ext;
Packit b89d10
  CalloutTagTable* t;
Packit b89d10
Packit b89d10
  ext = onig_get_regex_ext(reg);
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(ext);
Packit b89d10
Packit b89d10
  if (IS_NULL(ext->tag_table)) {
Packit b89d10
    r = callout_tag_table_new(&t);
Packit b89d10
    if (r != ONIG_NORMAL) return r;
Packit b89d10
Packit b89d10
    ext->tag_table = t;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
callout_tag_entry(regex_t* reg, UChar* name, UChar* name_end,
Packit b89d10
                  CalloutTagVal entry_val)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  RegexExt* ext;
Packit b89d10
  CalloutListEntry* e;
Packit b89d10
Packit b89d10
  r = ext_ensure_tag_table(reg);
Packit b89d10
  if (r != ONIG_NORMAL) return r;
Packit b89d10
Packit b89d10
  ext = onig_get_regex_ext(reg);
Packit b89d10
  r = callout_tag_entry_raw(ext->tag_table, name, name_end, entry_val);
Packit b89d10
Packit b89d10
  e = onig_reg_callout_list_at(reg, (int )entry_val);
Packit b89d10
  e->tag_start = name;
Packit b89d10
  e->tag_end   = name_end;
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
#endif /* USE_CALLOUT */
Packit b89d10
Packit b89d10
Packit b89d10
#define INIT_SCANENV_MEMENV_ALLOC_SIZE   16
Packit b89d10
Packit b89d10
static void
Packit b89d10
scan_env_clear(ScanEnv* env)
Packit b89d10
{
Packit b89d10
  MEM_STATUS_CLEAR(env->capture_history);
Packit b89d10
  MEM_STATUS_CLEAR(env->bt_mem_start);
Packit b89d10
  MEM_STATUS_CLEAR(env->bt_mem_end);
Packit b89d10
  MEM_STATUS_CLEAR(env->backrefed_mem);
Packit b89d10
  env->error      = (UChar* )NULL;
Packit b89d10
  env->error_end  = (UChar* )NULL;
Packit b89d10
  env->num_call   = 0;
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  env->unset_addr_list = NULL;
Packit b89d10
  env->has_call_zero   = 0;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  env->num_mem    = 0;
Packit b89d10
  env->num_named  = 0;
Packit b89d10
  env->mem_alloc  = 0;
Packit b89d10
  env->mem_env_dynamic = (MemEnv* )NULL;
Packit b89d10
Packit b89d10
  xmemset(env->mem_env_static, 0, sizeof(env->mem_env_static));
Packit b89d10
Packit b89d10
  env->parse_depth         = 0;
Packit b89d10
  env->keep_num            = 0;
Packit b89d10
  env->save_num            = 0;
Packit b89d10
  env->save_alloc_num      = 0;
Packit b89d10
  env->saves               = 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
scan_env_add_mem_entry(ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int i, need, alloc;
Packit b89d10
  MemEnv* p;
Packit b89d10
Packit b89d10
  need = env->num_mem + 1;
Packit b89d10
  if (need > MaxCaptureNum && MaxCaptureNum != 0)
Packit b89d10
    return ONIGERR_TOO_MANY_CAPTURES;
Packit b89d10
Packit b89d10
  if (need >= SCANENV_MEMENV_SIZE) {
Packit b89d10
    if (env->mem_alloc <= need) {
Packit b89d10
      if (IS_NULL(env->mem_env_dynamic)) {
Packit b89d10
        alloc = INIT_SCANENV_MEMENV_ALLOC_SIZE;
Packit b89d10
        p = (MemEnv* )xmalloc(sizeof(MemEnv) * alloc);
Packit b89d10
        CHECK_NULL_RETURN_MEMERR(p);
Packit b89d10
        xmemcpy(p, env->mem_env_static, sizeof(env->mem_env_static));
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        alloc = env->mem_alloc * 2;
Packit b89d10
        p = (MemEnv* )xrealloc(env->mem_env_dynamic, sizeof(MemEnv) * alloc);
Packit b89d10
        CHECK_NULL_RETURN_MEMERR(p);
Packit b89d10
      }
Packit b89d10
Packit b89d10
      for (i = env->num_mem + 1; i < alloc; i++) {
Packit b89d10
        p[i].node = NULL_NODE;
Packit b89d10
#if 0
Packit b89d10
        p[i].in   = 0;
Packit b89d10
        p[i].recursion = 0;
Packit b89d10
#endif
Packit b89d10
      }
Packit b89d10
Packit b89d10
      env->mem_env_dynamic = p;
Packit b89d10
      env->mem_alloc = alloc;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  env->num_mem++;
Packit b89d10
  return env->num_mem;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
scan_env_set_mem_node(ScanEnv* env, int num, Node* node)
Packit b89d10
{
Packit b89d10
  if (env->num_mem >= num)
Packit b89d10
    SCANENV_MEMENV(env)[num].node = node;
Packit b89d10
  else
Packit b89d10
    return ONIGERR_PARSER_BUG;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern void
Packit b89d10
onig_node_free(Node* node)
Packit b89d10
{
Packit b89d10
 start:
Packit b89d10
  if (IS_NULL(node)) return ;
Packit b89d10
Packit b89d10
#ifdef DEBUG_NODE_FREE
Packit b89d10
  fprintf(stderr, "onig_node_free: %p\n", node);
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_STRING:
Packit b89d10
    if (STR_(node)->capa != 0 &&
Packit b89d10
        IS_NOT_NULL(STR_(node)->s) && STR_(node)->s != STR_(node)->buf) {
Packit b89d10
      xfree(STR_(node)->s);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    onig_node_free(NODE_CAR(node));
Packit b89d10
    {
Packit b89d10
      Node* next_node = NODE_CDR(node);
Packit b89d10
Packit b89d10
      xfree(node);
Packit b89d10
      node = next_node;
Packit b89d10
      goto start;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    {
Packit b89d10
      CClassNode* cc = CCLASS_(node);
Packit b89d10
Packit b89d10
      if (cc->mbuf)
Packit b89d10
        bbuf_free(cc->mbuf);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    if (IS_NOT_NULL(BACKREF_(node)->back_dynamic))
Packit b89d10
      xfree(BACKREF_(node)->back_dynamic);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    if (NODE_BODY(node))
Packit b89d10
      onig_node_free(NODE_BODY(node));
Packit b89d10
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
      if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        onig_node_free(en->te.Then);
Packit b89d10
        onig_node_free(en->te.Else);
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (NODE_BODY(node))
Packit b89d10
      onig_node_free(NODE_BODY(node));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CTYPE:
Packit b89d10
  case NODE_CALL:
Packit b89d10
  case NODE_GIMMICK:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  xfree(node);
Packit b89d10
}
Packit b89d10
Packit b89d10
static void
Packit b89d10
cons_node_free_alone(Node* node)
Packit b89d10
{
Packit b89d10
  NODE_CAR(node) = 0;
Packit b89d10
  NODE_CDR(node) = 0;
Packit b89d10
  onig_node_free(node);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern void
Packit b89d10
list_node_free_not_car(Node* node)
Packit b89d10
{
Packit b89d10
  Node* next_node;
Packit b89d10
Packit b89d10
 start:
Packit b89d10
  if (IS_NULL(node)) return;
Packit b89d10
Packit b89d10
  next_node = NODE_CDR(node);
Packit b89d10
  xfree(node);
Packit b89d10
  node = next_node;
Packit b89d10
  goto start;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new(void)
Packit b89d10
{
Packit b89d10
  Node* node;
Packit b89d10
Packit b89d10
  node = (Node* )xmalloc(sizeof(Node));
Packit b89d10
  xmemset(node, 0, sizeof(*node));
Packit b89d10
Packit b89d10
#ifdef DEBUG_NODE_FREE
Packit b89d10
  fprintf(stderr, "node_new: %p\n", node);
Packit b89d10
#endif
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
static void
Packit b89d10
initialize_cclass(CClassNode* cc)
Packit b89d10
{
Packit b89d10
  BITSET_CLEAR(cc->bs);
Packit b89d10
  cc->flags = 0;
Packit b89d10
  cc->mbuf  = NULL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_cclass(void)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_CCLASS);
Packit b89d10
  initialize_cclass(CCLASS_(node));
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_ctype(int type, int not, OnigOptionType options)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_CTYPE);
Packit b89d10
  CTYPE_(node)->ctype   = type;
Packit b89d10
  CTYPE_(node)->not     = not;
Packit b89d10
  CTYPE_(node)->options = options;
Packit b89d10
  CTYPE_(node)->ascii_mode = IS_ASCII_MODE_CTYPE_OPTION(type, options);
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_anychar(void)
Packit b89d10
{
Packit b89d10
  Node* node = node_new_ctype(CTYPE_ANYCHAR, 0, ONIG_OPTION_NONE);
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_anychar_with_fixed_option(OnigOptionType option)
Packit b89d10
{
Packit b89d10
  CtypeNode* ct;
Packit b89d10
  Node* node;
Packit b89d10
Packit b89d10
  node = node_new_anychar();
Packit b89d10
  ct = CTYPE_(node);
Packit b89d10
  ct->options = option;
Packit b89d10
  NODE_STATUS_ADD(node, NST_FIXED_OPTION);
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
node_new_no_newline(Node** node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  Node* n;
Packit b89d10
Packit b89d10
  n = node_new_anychar_with_fixed_option(ONIG_OPTION_NONE);
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(n);
Packit b89d10
  *node = n;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
node_new_true_anychar(Node** node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  Node* n;
Packit b89d10
Packit b89d10
  n = node_new_anychar_with_fixed_option(ONIG_OPTION_MULTILINE);
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(n);
Packit b89d10
  *node = n;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_list(Node* left, Node* right)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_LIST);
Packit b89d10
  NODE_CAR(node)  = left;
Packit b89d10
  NODE_CDR(node) = right;
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern Node*
Packit b89d10
onig_node_new_list(Node* left, Node* right)
Packit b89d10
{
Packit b89d10
  return node_new_list(left, right);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern Node*
Packit b89d10
onig_node_list_add(Node* list, Node* x)
Packit b89d10
{
Packit b89d10
  Node *n;
Packit b89d10
Packit b89d10
  n = onig_node_new_list(x, NULL);
Packit b89d10
  if (IS_NULL(n)) return NULL_NODE;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(list)) {
Packit b89d10
    while (IS_NOT_NULL(NODE_CDR(list)))
Packit b89d10
      list = NODE_CDR(list);
Packit b89d10
Packit b89d10
    NODE_CDR(list) = n;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return n;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern Node*
Packit b89d10
onig_node_new_alt(Node* left, Node* right)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_ALT);
Packit b89d10
  NODE_CAR(node)  = left;
Packit b89d10
  NODE_CDR(node) = right;
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
make_list_or_alt(NodeType type, int n, Node* ns[])
Packit b89d10
{
Packit b89d10
  Node* r;
Packit b89d10
Packit b89d10
  if (n <= 0) return NULL_NODE;
Packit b89d10
Packit b89d10
  if (n == 1) {
Packit b89d10
    r = node_new();
Packit b89d10
    CHECK_NULL_RETURN(r);
Packit b89d10
    NODE_SET_TYPE(r, type);
Packit b89d10
    NODE_CAR(r) = ns[0];
Packit b89d10
    NODE_CDR(r) = NULL_NODE;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    Node* right;
Packit b89d10
Packit b89d10
    r = node_new();
Packit b89d10
    CHECK_NULL_RETURN(r);
Packit b89d10
Packit b89d10
    right = make_list_or_alt(type, n - 1, ns + 1);
Packit b89d10
    if (IS_NULL(right)) {
Packit b89d10
      onig_node_free(r);
Packit b89d10
      return NULL_NODE;
Packit b89d10
    }
Packit b89d10
Packit b89d10
    NODE_SET_TYPE(r, type);
Packit b89d10
    NODE_CAR(r) = ns[0];
Packit b89d10
    NODE_CDR(r) = right;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
make_list(int n, Node* ns[])
Packit b89d10
{
Packit b89d10
  return make_list_or_alt(NODE_LIST, n, ns);
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
make_alt(int n, Node* ns[])
Packit b89d10
{
Packit b89d10
  return make_list_or_alt(NODE_ALT, n, ns);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern Node*
Packit b89d10
onig_node_new_anchor(int type, int ascii_mode)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_ANCHOR);
Packit b89d10
  ANCHOR_(node)->type       = type;
Packit b89d10
  ANCHOR_(node)->char_len   = -1;
Packit b89d10
  ANCHOR_(node)->ascii_mode = ascii_mode;
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_backref(int back_num, int* backrefs, int by_name,
Packit b89d10
#ifdef USE_BACKREF_WITH_LEVEL
Packit b89d10
                 int exist_level, int nest_level,
Packit b89d10
#endif
Packit b89d10
                 ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  Node* node = node_new();
Packit b89d10
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_BACKREF);
Packit b89d10
  BACKREF_(node)->back_num = back_num;
Packit b89d10
  BACKREF_(node)->back_dynamic = (int* )NULL;
Packit b89d10
  if (by_name != 0)
Packit b89d10
    NODE_STATUS_ADD(node, NST_BY_NAME);
Packit b89d10
Packit b89d10
#ifdef USE_BACKREF_WITH_LEVEL
Packit b89d10
  if (exist_level != 0) {
Packit b89d10
    NODE_STATUS_ADD(node, NST_NEST_LEVEL);
Packit b89d10
    BACKREF_(node)->nest_level  = nest_level;
Packit b89d10
  }
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  for (i = 0; i < back_num; i++) {
Packit b89d10
    if (backrefs[i] <= env->num_mem &&
Packit b89d10
        IS_NULL(SCANENV_MEMENV(env)[backrefs[i]].node)) {
Packit b89d10
      NODE_STATUS_ADD(node, NST_RECURSION);   /* /...(\1).../ */
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (back_num <= NODE_BACKREFS_SIZE) {
Packit b89d10
    for (i = 0; i < back_num; i++)
Packit b89d10
      BACKREF_(node)->back_static[i] = backrefs[i];
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    int* p = (int* )xmalloc(sizeof(int) * back_num);
Packit b89d10
    if (IS_NULL(p)) {
Packit b89d10
      onig_node_free(node);
Packit b89d10
      return NULL;
Packit b89d10
    }
Packit b89d10
    BACKREF_(node)->back_dynamic = p;
Packit b89d10
    for (i = 0; i < back_num; i++)
Packit b89d10
      p[i] = backrefs[i];
Packit b89d10
  }
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_backref_checker(int back_num, int* backrefs, int by_name,
Packit b89d10
#ifdef USE_BACKREF_WITH_LEVEL
Packit b89d10
                         int exist_level, int nest_level,
Packit b89d10
#endif
Packit b89d10
                         ScanEnv* env)
Packit b89d10
{
Packit b89d10
  Node* node;
Packit b89d10
Packit b89d10
  node = node_new_backref(back_num, backrefs, by_name,
Packit b89d10
#ifdef USE_BACKREF_WITH_LEVEL
Packit b89d10
                          exist_level, nest_level,
Packit b89d10
#endif
Packit b89d10
                          env);
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_STATUS_ADD(node, NST_CHECKER);
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
static Node*
Packit b89d10
node_new_call(UChar* name, UChar* name_end, int gnum, int by_number)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_CALL);
Packit b89d10
  CALL_(node)->by_number   = by_number;
Packit b89d10
  CALL_(node)->name        = name;
Packit b89d10
  CALL_(node)->name_end    = name_end;
Packit b89d10
  CALL_(node)->group_num   = gnum;
Packit b89d10
  CALL_(node)->entry_count = 1;
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_quantifier(int lower, int upper, int by_number)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_QUANT);
Packit b89d10
  QUANT_(node)->lower  = lower;
Packit b89d10
  QUANT_(node)->upper  = upper;
Packit b89d10
  QUANT_(node)->greedy = 1;
Packit b89d10
  QUANT_(node)->body_empty_info = QUANT_BODY_IS_NOT_EMPTY;
Packit b89d10
  QUANT_(node)->head_exact      = NULL_NODE;
Packit b89d10
  QUANT_(node)->next_head_exact = NULL_NODE;
Packit b89d10
  QUANT_(node)->is_refered      = 0;
Packit b89d10
  if (by_number != 0)
Packit b89d10
    NODE_STATUS_ADD(node, NST_BY_NUMBER);
Packit b89d10
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_enclosure(enum EnclosureType type)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_ENCLOSURE);
Packit b89d10
  ENCLOSURE_(node)->type = type;
Packit b89d10
Packit b89d10
  switch (type) {
Packit b89d10
  case ENCLOSURE_MEMORY:
Packit b89d10
    ENCLOSURE_(node)->m.regnum       =  0;
Packit b89d10
    ENCLOSURE_(node)->m.called_addr  = -1;
Packit b89d10
    ENCLOSURE_(node)->m.entry_count  =  1;
Packit b89d10
    ENCLOSURE_(node)->m.called_state =  0;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ENCLOSURE_OPTION:
Packit b89d10
    ENCLOSURE_(node)->o.options =  0;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ENCLOSURE_STOP_BACKTRACK:
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ENCLOSURE_IF_ELSE:
Packit b89d10
    ENCLOSURE_(node)->te.Then = 0;
Packit b89d10
    ENCLOSURE_(node)->te.Else = 0;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  ENCLOSURE_(node)->opt_count = 0;
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern Node*
Packit b89d10
onig_node_new_enclosure(int type)
Packit b89d10
{
Packit b89d10
  return node_new_enclosure(type);
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_enclosure_if_else(Node* cond, Node* Then, Node* Else)
Packit b89d10
{
Packit b89d10
  Node* n;
Packit b89d10
  n = node_new_enclosure(ENCLOSURE_IF_ELSE);
Packit b89d10
  CHECK_NULL_RETURN(n);
Packit b89d10
Packit b89d10
  NODE_BODY(n) = cond;
Packit b89d10
  ENCLOSURE_(n)->te.Then = Then;
Packit b89d10
  ENCLOSURE_(n)->te.Else = Else;
Packit b89d10
  return n;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_memory(int is_named)
Packit b89d10
{
Packit b89d10
  Node* node = node_new_enclosure(ENCLOSURE_MEMORY);
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
  if (is_named != 0)
Packit b89d10
    NODE_STATUS_ADD(node, NST_NAMED_GROUP);
Packit b89d10
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_option(OnigOptionType option)
Packit b89d10
{
Packit b89d10
  Node* node = node_new_enclosure(ENCLOSURE_OPTION);
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
  ENCLOSURE_(node)->o.options = option;
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
node_new_fail(Node** node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  *node = node_new();
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(*node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(*node, NODE_GIMMICK);
Packit b89d10
  GIMMICK_(*node)->type = GIMMICK_FAIL;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
node_new_save_gimmick(Node** node, enum SaveType save_type, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int id;
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  r = save_entry(env, save_type, &id;;
Packit b89d10
  if (r != ONIG_NORMAL) return r;
Packit b89d10
Packit b89d10
  *node = node_new();
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(*node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(*node, NODE_GIMMICK);
Packit b89d10
  GIMMICK_(*node)->id   = id;
Packit b89d10
  GIMMICK_(*node)->type = GIMMICK_SAVE;
Packit b89d10
  GIMMICK_(*node)->detail_type = (int )save_type;
Packit b89d10
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
node_new_update_var_gimmick(Node** node, enum UpdateVarType update_var_type,
Packit b89d10
                            int id, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  *node = node_new();
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(*node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(*node, NODE_GIMMICK);
Packit b89d10
  GIMMICK_(*node)->id   = id;
Packit b89d10
  GIMMICK_(*node)->type = GIMMICK_UPDATE_VAR;
Packit b89d10
  GIMMICK_(*node)->detail_type = (int )update_var_type;
Packit b89d10
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
node_new_keep(Node** node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  r = node_new_save_gimmick(node, SAVE_KEEP, env);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  env->keep_num++;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
#ifdef USE_CALLOUT
Packit b89d10
Packit b89d10
extern void
Packit b89d10
onig_free_reg_callout_list(int n, CalloutListEntry* list)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
  int j;
Packit b89d10
Packit b89d10
  if (IS_NULL(list)) return ;
Packit b89d10
Packit b89d10
  for (i = 0; i < n; i++) {
Packit b89d10
    if (list[i].of == ONIG_CALLOUT_OF_NAME) {
Packit b89d10
      for (j = 0; j < list[i].u.arg.passed_num; j++) {
Packit b89d10
        if (list[i].u.arg.types[j] == ONIG_TYPE_STRING) {
Packit b89d10
          if (IS_NOT_NULL(list[i].u.arg.vals[j].s.start))
Packit b89d10
            xfree(list[i].u.arg.vals[j].s.start);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    else { /* ONIG_CALLOUT_OF_CONTENTS */
Packit b89d10
      if (IS_NOT_NULL(list[i].u.content.start)) {
Packit b89d10
        xfree((void* )list[i].u.content.start);
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  xfree(list);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern CalloutListEntry*
Packit b89d10
onig_reg_callout_list_at(regex_t* reg, int num)
Packit b89d10
{
Packit b89d10
  RegexExt* ext = REG_EXTP(reg);
Packit b89d10
  CHECK_NULL_RETURN(ext);
Packit b89d10
Packit b89d10
  if (num <= 0 || num > ext->callout_num)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  num--;
Packit b89d10
  return ext->callout_list + num;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
reg_callout_list_entry(ScanEnv* env, int* rnum)
Packit b89d10
{
Packit b89d10
#define INIT_CALLOUT_LIST_NUM  3
Packit b89d10
Packit b89d10
  int num;
Packit b89d10
  CalloutListEntry* list;
Packit b89d10
  CalloutListEntry* e;
Packit b89d10
  RegexExt* ext;
Packit b89d10
Packit b89d10
  ext = onig_get_regex_ext(env->reg);
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(ext);
Packit b89d10
Packit b89d10
  if (IS_NULL(ext->callout_list)) {
Packit b89d10
    list = (CalloutListEntry* )xmalloc(sizeof(*list) * INIT_CALLOUT_LIST_NUM);
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(list);
Packit b89d10
Packit b89d10
    ext->callout_list = list;
Packit b89d10
    ext->callout_list_alloc = INIT_CALLOUT_LIST_NUM;
Packit b89d10
    ext->callout_num = 0;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  num = ext->callout_num + 1;
Packit b89d10
  if (num > ext->callout_list_alloc) {
Packit b89d10
    int alloc = ext->callout_list_alloc * 2;
Packit b89d10
    list = (CalloutListEntry* )xrealloc(ext->callout_list,
Packit b89d10
                                        sizeof(CalloutListEntry) * alloc);
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(list);
Packit b89d10
Packit b89d10
    ext->callout_list       = list;
Packit b89d10
    ext->callout_list_alloc = alloc;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  e = ext->callout_list + (num - 1);
Packit b89d10
Packit b89d10
  e->flag             = 0;
Packit b89d10
  e->of               = 0;
Packit b89d10
  e->in               = ONIG_CALLOUT_OF_CONTENTS;
Packit b89d10
  e->type             = 0;
Packit b89d10
  e->tag_start        = 0;
Packit b89d10
  e->tag_end          = 0;
Packit b89d10
  e->start_func       = 0;
Packit b89d10
  e->end_func         = 0;
Packit b89d10
  e->u.arg.num        = 0;
Packit b89d10
  e->u.arg.passed_num = 0;
Packit b89d10
Packit b89d10
  ext->callout_num = num;
Packit b89d10
  *rnum = num;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
node_new_callout(Node** node, OnigCalloutOf callout_of, int num, int id,
Packit b89d10
                 ScanEnv* env)
Packit b89d10
{
Packit b89d10
  *node = node_new();
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(*node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(*node, NODE_GIMMICK);
Packit b89d10
  GIMMICK_(*node)->id          = id;
Packit b89d10
  GIMMICK_(*node)->num         = num;
Packit b89d10
  GIMMICK_(*node)->type        = GIMMICK_CALLOUT;
Packit b89d10
  GIMMICK_(*node)->detail_type = (int )callout_of;
Packit b89d10
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
static int
Packit b89d10
make_extended_grapheme_cluster(Node** node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int i;
Packit b89d10
  Node* x;
Packit b89d10
  Node* ns[2];
Packit b89d10
Packit b89d10
  /* \X == (?>\O(?:\Y\O)*) */
Packit b89d10
Packit b89d10
  ns[1] = NULL_NODE;
Packit b89d10
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
  ns[0] = onig_node_new_anchor(ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY, 0);
Packit b89d10
  if (IS_NULL(ns[0])) goto err;
Packit b89d10
Packit b89d10
  r = node_new_true_anychar(&ns[1], env);
Packit b89d10
  if (r != 0) goto err1;
Packit b89d10
Packit b89d10
  x = make_list(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err;
Packit b89d10
  ns[0] = x;
Packit b89d10
  ns[1] = NULL_NODE;
Packit b89d10
Packit b89d10
  x = node_new_quantifier(0, REPEAT_INFINITE, 1);
Packit b89d10
  if (IS_NULL(x)) goto err;
Packit b89d10
Packit b89d10
  NODE_BODY(x) = ns[0];
Packit b89d10
  ns[0] = NULL_NODE;
Packit b89d10
  ns[1] = x;
Packit b89d10
Packit b89d10
  r = node_new_true_anychar(&ns[0], env);
Packit b89d10
  if (r != 0) goto err1;
Packit b89d10
Packit b89d10
  x = make_list(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err;
Packit b89d10
Packit b89d10
  ns[0] = x;
Packit b89d10
  ns[1] = NULL_NODE;
Packit b89d10
Packit b89d10
  x = node_new_enclosure(ENCLOSURE_STOP_BACKTRACK);
Packit b89d10
  if (IS_NULL(x)) goto err;
Packit b89d10
Packit b89d10
  NODE_BODY(x) = ns[0];
Packit b89d10
Packit b89d10
  *node = x;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
Packit b89d10
 err:
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
 err1:
Packit b89d10
  for (i = 0; i < 2; i++) onig_node_free(ns[i]);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
make_absent_engine(Node** node, int pre_save_right_id, Node* absent,
Packit b89d10
                   Node* step_one, int lower, int upper, int possessive,
Packit b89d10
                   int is_range_cutter, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int i;
Packit b89d10
  int id;
Packit b89d10
  Node* x;
Packit b89d10
  Node* ns[4];
Packit b89d10
Packit b89d10
  for (i = 0; i < 4; i++) ns[i] = NULL_NODE;
Packit b89d10
Packit b89d10
  ns[1] = absent;
Packit b89d10
  ns[3] = step_one; /* for err */
Packit b89d10
  r = node_new_save_gimmick(&ns[0], SAVE_S, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  id = GIMMICK_(ns[0])->id;
Packit b89d10
  r = node_new_update_var_gimmick(&ns[2], UPDATE_VAR_RIGHT_RANGE_FROM_S_STACK,
Packit b89d10
                                  id, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  r = node_new_fail(&ns[3], env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  x = make_list(4, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  ns[0] = x;
Packit b89d10
  ns[1] = step_one;
Packit b89d10
  ns[2] = ns[3] = NULL_NODE;
Packit b89d10
Packit b89d10
  x = make_alt(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  ns[0] = x;
Packit b89d10
Packit b89d10
  x = node_new_quantifier(lower, upper, 0);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  NODE_BODY(x) = ns[0];
Packit b89d10
  ns[0] = x;
Packit b89d10
Packit b89d10
  if (possessive != 0) {
Packit b89d10
    x = node_new_enclosure(ENCLOSURE_STOP_BACKTRACK);
Packit b89d10
    if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
    NODE_BODY(x) = ns[0];
Packit b89d10
    ns[0] = x;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  r = node_new_update_var_gimmick(&ns[1], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,
Packit b89d10
                                  pre_save_right_id, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  r = node_new_fail(&ns[2], env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  x = make_list(2, ns + 1);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  ns[1] = x; ns[2] = NULL_NODE;
Packit b89d10
Packit b89d10
  x = make_alt(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  if (is_range_cutter != 0)
Packit b89d10
    NODE_STATUS_ADD(x, NST_SUPER);
Packit b89d10
Packit b89d10
  *node = x;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
Packit b89d10
 err0:
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
 err:
Packit b89d10
  for (i = 0; i < 4; i++) onig_node_free(ns[i]);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
make_absent_tail(Node** node1, Node** node2, int pre_save_right_id,
Packit b89d10
                 ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int id;
Packit b89d10
  Node* save;
Packit b89d10
  Node* x;
Packit b89d10
  Node* ns[2];
Packit b89d10
Packit b89d10
  *node1 = *node2 = NULL_NODE;
Packit b89d10
  save = ns[0] = ns[1] = NULL_NODE;
Packit b89d10
Packit b89d10
  r = node_new_save_gimmick(&save, SAVE_RIGHT_RANGE, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  id = GIMMICK_(save)->id;
Packit b89d10
  r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,
Packit b89d10
                                  id, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  r = node_new_fail(&ns[1], env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  x = make_list(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  ns[0] = NULL_NODE; ns[1] = x;
Packit b89d10
Packit b89d10
  r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,
Packit b89d10
                                  pre_save_right_id, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  x = make_alt(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  *node1 = save;
Packit b89d10
  *node2 = x;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
Packit b89d10
 err0:
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
 err:
Packit b89d10
  onig_node_free(save);
Packit b89d10
  onig_node_free(ns[0]);
Packit b89d10
  onig_node_free(ns[1]);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
make_range_clear(Node** node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int id;
Packit b89d10
  Node* save;
Packit b89d10
  Node* x;
Packit b89d10
  Node* ns[2];
Packit b89d10
Packit b89d10
  *node = NULL_NODE;
Packit b89d10
  save = ns[0] = ns[1] = NULL_NODE;
Packit b89d10
Packit b89d10
  r = node_new_save_gimmick(&save, SAVE_RIGHT_RANGE, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  id = GIMMICK_(save)->id;
Packit b89d10
  r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,
Packit b89d10
                                  id, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  r = node_new_fail(&ns[1], env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  x = make_list(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  ns[0] = NULL_NODE; ns[1] = x;
Packit b89d10
Packit b89d10
  r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_INIT, 0, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  x = make_alt(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  NODE_STATUS_ADD(x, NST_SUPER);
Packit b89d10
Packit b89d10
  ns[0] = save;
Packit b89d10
  ns[1] = x;
Packit b89d10
  save = NULL_NODE;
Packit b89d10
  x = make_list(2, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  *node = x;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
Packit b89d10
 err0:
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
 err:
Packit b89d10
  onig_node_free(save);
Packit b89d10
  onig_node_free(ns[0]);
Packit b89d10
  onig_node_free(ns[1]);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
is_simple_one_char_repeat(Node* node, Node** rquant, Node** rbody,
Packit b89d10
                          int* is_possessive, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  Node* quant;
Packit b89d10
  Node* body;
Packit b89d10
Packit b89d10
  *rquant = *rbody = 0;
Packit b89d10
  *is_possessive = 0;
Packit b89d10
Packit b89d10
  if (NODE_TYPE(node) == NODE_QUANT) {
Packit b89d10
    quant = node;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    if (NODE_TYPE(node) == NODE_ENCLOSURE) {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
      if (en->type == ENCLOSURE_STOP_BACKTRACK) {
Packit b89d10
        *is_possessive = 1;
Packit b89d10
        quant = NODE_ENCLOSURE_BODY(en);
Packit b89d10
        if (NODE_TYPE(quant) != NODE_QUANT)
Packit b89d10
          return 0;
Packit b89d10
      }
Packit b89d10
      else
Packit b89d10
        return 0;
Packit b89d10
    }
Packit b89d10
    else
Packit b89d10
      return 0;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (QUANT_(quant)->greedy == 0)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  body = NODE_BODY(quant);
Packit b89d10
  switch (NODE_TYPE(body)) {
Packit b89d10
  case NODE_STRING:
Packit b89d10
    {
Packit b89d10
      int len;
Packit b89d10
      StrNode* sn = STR_(body);
Packit b89d10
      UChar *s = sn->s;
Packit b89d10
Packit b89d10
      len = 0;
Packit b89d10
      while (s < sn->end) {
Packit b89d10
        s += enclen(env->enc, s);
Packit b89d10
        len++;
Packit b89d10
      }
Packit b89d10
      if (len != 1)
Packit b89d10
        return 0;
Packit b89d10
    }
Packit b89d10
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    return 0;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (node != quant) {
Packit b89d10
    NODE_BODY(node) = 0;
Packit b89d10
    onig_node_free(node);
Packit b89d10
  }
Packit b89d10
  NODE_BODY(quant) = NULL_NODE;
Packit b89d10
  *rquant = quant;
Packit b89d10
  *rbody  = body;
Packit b89d10
  return 1;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
make_absent_tree_for_simple_one_char_repeat(Node** node, Node* absent, Node* quant,
Packit b89d10
                                            Node* body, int possessive, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int i;
Packit b89d10
  int id1;
Packit b89d10
  int lower, upper;
Packit b89d10
  Node* x;
Packit b89d10
  Node* ns[4];
Packit b89d10
Packit b89d10
  *node = NULL_NODE;
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
  ns[0] = ns[1] = NULL_NODE;
Packit b89d10
  ns[2] = body, ns[3] = absent;
Packit b89d10
Packit b89d10
  lower = QUANT_(quant)->lower;
Packit b89d10
  upper = QUANT_(quant)->upper;
Packit b89d10
  onig_node_free(quant);
Packit b89d10
Packit b89d10
  r = node_new_save_gimmick(&ns[0], SAVE_RIGHT_RANGE, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  id1 = GIMMICK_(ns[0])->id;
Packit b89d10
Packit b89d10
  r = make_absent_engine(&ns[1], id1, absent, body, lower, upper, possessive,
Packit b89d10
                         0, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  ns[2] = ns[3] = NULL_NODE;
Packit b89d10
Packit b89d10
  r = node_new_update_var_gimmick(&ns[2], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,
Packit b89d10
                                  id1, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  x = make_list(3, ns);
Packit b89d10
  if (IS_NULL(x)) goto err0;
Packit b89d10
Packit b89d10
  *node = x;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
Packit b89d10
 err0:
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
 err:
Packit b89d10
  for (i = 0; i < 4; i++) onig_node_free(ns[i]);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
make_absent_tree(Node** node, Node* absent, Node* expr, int is_range_cutter,
Packit b89d10
                 ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int i;
Packit b89d10
  int id1, id2;
Packit b89d10
  int possessive;
Packit b89d10
  Node* x;
Packit b89d10
  Node* ns[7];
Packit b89d10
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
  for (i = 0; i < 7; i++) ns[i] = NULL_NODE;
Packit b89d10
  ns[4] = expr; ns[5] = absent;
Packit b89d10
Packit b89d10
  if (is_range_cutter == 0) {
Packit b89d10
    Node* quant;
Packit b89d10
    Node* body;
Packit b89d10
Packit b89d10
    if (expr == NULL_NODE) {
Packit b89d10
      /* default expr \O* */
Packit b89d10
      quant = node_new_quantifier(0, REPEAT_INFINITE, 0);
Packit b89d10
      if (IS_NULL(quant)) goto err0;
Packit b89d10
Packit b89d10
      r = node_new_true_anychar(&body, env);
Packit b89d10
      if (r != 0) {
Packit b89d10
        onig_node_free(quant);
Packit b89d10
        goto err;
Packit b89d10
      }
Packit b89d10
      possessive = 0;
Packit b89d10
      goto simple;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      if (is_simple_one_char_repeat(expr, &quant, &body, &possessive, env)) {
Packit b89d10
      simple:
Packit b89d10
        r = make_absent_tree_for_simple_one_char_repeat(node, absent, quant,
Packit b89d10
                                                        body, possessive, env);
Packit b89d10
        if (r != 0) {
Packit b89d10
          ns[4] = NULL_NODE;
Packit b89d10
          onig_node_free(quant);
Packit b89d10
          onig_node_free(body);
Packit b89d10
          goto err;
Packit b89d10
        }
Packit b89d10
Packit b89d10
        return ONIG_NORMAL;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  r = node_new_save_gimmick(&ns[0], SAVE_RIGHT_RANGE, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  id1 = GIMMICK_(ns[0])->id;
Packit b89d10
Packit b89d10
  r = node_new_save_gimmick(&ns[1], SAVE_S, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  id2 = GIMMICK_(ns[1])->id;
Packit b89d10
Packit b89d10
  r = node_new_true_anychar(&ns[3], env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  possessive = 1;
Packit b89d10
  r = make_absent_engine(&ns[2], id1, absent, ns[3], 0, REPEAT_INFINITE,
Packit b89d10
                         possessive, is_range_cutter, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  ns[3] = NULL_NODE;
Packit b89d10
  ns[5] = NULL_NODE;
Packit b89d10
Packit b89d10
  r = node_new_update_var_gimmick(&ns[3], UPDATE_VAR_S_FROM_STACK, id2, env);
Packit b89d10
  if (r != 0) goto err;
Packit b89d10
Packit b89d10
  if (is_range_cutter != 0) {
Packit b89d10
    x = make_list(4, ns);
Packit b89d10
    if (IS_NULL(x)) goto err0;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    r = make_absent_tail(&ns[5], &ns[6], id1, env);
Packit b89d10
    if (r != 0) goto err;
Packit b89d10
  
Packit b89d10
    x = make_list(7, ns);
Packit b89d10
    if (IS_NULL(x)) goto err0;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  *node = x;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
Packit b89d10
 err0:
Packit b89d10
  r = ONIGERR_MEMORY;
Packit b89d10
 err:
Packit b89d10
  for (i = 0; i < 7; i++) onig_node_free(ns[i]);
Packit b89d10
  return r;  
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_node_str_cat(Node* node, const UChar* s, const UChar* end)
Packit b89d10
{
Packit b89d10
  int addlen = (int )(end - s);
Packit b89d10
Packit b89d10
  if (addlen > 0) {
Packit b89d10
    int len  = (int )(STR_(node)->end - STR_(node)->s);
Packit b89d10
Packit b89d10
    if (STR_(node)->capa > 0 || (len + addlen > NODE_STRING_BUF_SIZE - 1)) {
Packit b89d10
      UChar* p;
Packit b89d10
      int capa = len + addlen + NODE_STRING_MARGIN;
Packit b89d10
Packit b89d10
      if (capa <= STR_(node)->capa) {
Packit b89d10
        onig_strcpy(STR_(node)->s + len, s, end);
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        if (STR_(node)->s == STR_(node)->buf)
Packit b89d10
          p = strcat_capa_from_static(STR_(node)->s, STR_(node)->end,
Packit b89d10
                                      s, end, capa);
Packit b89d10
        else
Packit b89d10
          p = strcat_capa(STR_(node)->s, STR_(node)->end, s, end, capa);
Packit b89d10
Packit b89d10
        CHECK_NULL_RETURN_MEMERR(p);
Packit b89d10
        STR_(node)->s    = p;
Packit b89d10
        STR_(node)->capa = capa;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      onig_strcpy(STR_(node)->s + len, s, end);
Packit b89d10
    }
Packit b89d10
    STR_(node)->end = STR_(node)->s + len + addlen;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_node_str_set(Node* node, const UChar* s, const UChar* end)
Packit b89d10
{
Packit b89d10
  onig_node_str_clear(node);
Packit b89d10
  return onig_node_str_cat(node, s, end);
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
node_str_cat_char(Node* node, UChar c)
Packit b89d10
{
Packit b89d10
  UChar s[1];
Packit b89d10
Packit b89d10
  s[0] = c;
Packit b89d10
  return onig_node_str_cat(node, s, s + 1);
Packit b89d10
}
Packit b89d10
Packit b89d10
extern void
Packit b89d10
onig_node_conv_to_str_node(Node* node, int flag)
Packit b89d10
{
Packit b89d10
  NODE_SET_TYPE(node, NODE_STRING);
Packit b89d10
  STR_(node)->flag = flag;
Packit b89d10
  STR_(node)->capa = 0;
Packit b89d10
  STR_(node)->s    = STR_(node)->buf;
Packit b89d10
  STR_(node)->end  = STR_(node)->buf;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern void
Packit b89d10
onig_node_str_clear(Node* node)
Packit b89d10
{
Packit b89d10
  if (STR_(node)->capa != 0 &&
Packit b89d10
      IS_NOT_NULL(STR_(node)->s) && STR_(node)->s != STR_(node)->buf) {
Packit b89d10
    xfree(STR_(node)->s);
Packit b89d10
  }
Packit b89d10
Packit b89d10
  STR_(node)->capa = 0;
Packit b89d10
  STR_(node)->flag = 0;
Packit b89d10
  STR_(node)->s    = STR_(node)->buf;
Packit b89d10
  STR_(node)->end  = STR_(node)->buf;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_str(const UChar* s, const UChar* end)
Packit b89d10
{
Packit b89d10
  Node* node = node_new();
Packit b89d10
  CHECK_NULL_RETURN(node);
Packit b89d10
Packit b89d10
  NODE_SET_TYPE(node, NODE_STRING);
Packit b89d10
  STR_(node)->capa = 0;
Packit b89d10
  STR_(node)->flag = 0;
Packit b89d10
  STR_(node)->s    = STR_(node)->buf;
Packit b89d10
  STR_(node)->end  = STR_(node)->buf;
Packit b89d10
  if (onig_node_str_cat(node, s, end)) {
Packit b89d10
    onig_node_free(node);
Packit b89d10
    return NULL;
Packit b89d10
  }
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern Node*
Packit b89d10
onig_node_new_str(const UChar* s, const UChar* end)
Packit b89d10
{
Packit b89d10
  return node_new_str(s, end);
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_str_raw(UChar* s, UChar* end)
Packit b89d10
{
Packit b89d10
  Node* node = node_new_str(s, end);
Packit b89d10
  NODE_STRING_SET_RAW(node);
Packit b89d10
  return node;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_empty(void)
Packit b89d10
{
Packit b89d10
  return node_new_str(NULL, NULL);
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
node_new_str_raw_char(UChar c)
Packit b89d10
{
Packit b89d10
  UChar p[1];
Packit b89d10
Packit b89d10
  p[0] = c;
Packit b89d10
  return node_new_str_raw(p, p + 1);
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
str_node_split_last_char(StrNode* sn, OnigEncoding enc)
Packit b89d10
{
Packit b89d10
  const UChar *p;
Packit b89d10
  Node* n = NULL_NODE;
Packit b89d10
Packit b89d10
  if (sn->end > sn->s) {
Packit b89d10
    p = onigenc_get_prev_char_head(enc, sn->s, sn->end);
Packit b89d10
    if (p && p > sn->s) { /* can be split. */
Packit b89d10
      n = node_new_str(p, sn->end);
Packit b89d10
      if ((sn->flag & STRING_RAW) != 0)
Packit b89d10
        NODE_STRING_SET_RAW(n);
Packit b89d10
Packit b89d10
      sn->end = (UChar* )p;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  return n;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
str_node_can_be_split(StrNode* sn, OnigEncoding enc)
Packit b89d10
{
Packit b89d10
  if (sn->end > sn->s) {
Packit b89d10
    return ((enclen(enc, sn->s) < sn->end - sn->s)  ?  1 : 0);
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
#ifdef USE_PAD_TO_SHORT_BYTE_CHAR
Packit b89d10
static int
Packit b89d10
node_str_head_pad(StrNode* sn, int num, UChar val)
Packit b89d10
{
Packit b89d10
  UChar buf[NODE_STRING_BUF_SIZE];
Packit b89d10
  int i, len;
Packit b89d10
Packit b89d10
  len = sn->end - sn->s;
Packit b89d10
  onig_strcpy(buf, sn->s, sn->end);
Packit b89d10
  onig_strcpy(&(sn->s[num]), buf, buf + len);
Packit b89d10
  sn->end += num;
Packit b89d10
Packit b89d10
  for (i = 0; i < num; i++) {
Packit b89d10
    sn->s[i] = val;
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_scan_unsigned_number(UChar** src, const UChar* end, OnigEncoding enc)
Packit b89d10
{
Packit b89d10
  unsigned int num, val;
Packit b89d10
  OnigCodePoint c;
Packit b89d10
  UChar* p = *src;
Packit b89d10
  PFETCH_READY;
Packit b89d10
Packit b89d10
  num = 0;
Packit b89d10
  while (! PEND) {
Packit b89d10
    PFETCH(c);
Packit b89d10
    if (IS_CODE_DIGIT_ASCII(enc, c)) {
Packit b89d10
      val = (unsigned int )DIGITVAL(c);
Packit b89d10
      if ((INT_MAX_LIMIT - val) / 10UL < num)
Packit b89d10
        return -1;  /* overflow */
Packit b89d10
Packit b89d10
      num = num * 10 + val;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      PUNFETCH;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  *src = p;
Packit b89d10
  return num;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int minlen,
Packit b89d10
                                 int maxlen, OnigEncoding enc)
Packit b89d10
{
Packit b89d10
  OnigCodePoint c;
Packit b89d10
  unsigned int num, val;
Packit b89d10
  int n;
Packit b89d10
  UChar* p = *src;
Packit b89d10
  PFETCH_READY;
Packit b89d10
Packit b89d10
  num = 0;
Packit b89d10
  n = 0;
Packit b89d10
  while (! PEND && n < maxlen) {
Packit b89d10
    PFETCH(c);
Packit b89d10
    if (IS_CODE_XDIGIT_ASCII(enc, c)) {
Packit b89d10
      n++;
Packit b89d10
      val = (unsigned int )XDIGITVAL(enc,c);
Packit b89d10
      if ((INT_MAX_LIMIT - val) / 16UL < num)
Packit b89d10
        return ONIGERR_TOO_BIG_NUMBER; /* overflow */
Packit b89d10
Packit b89d10
      num = (num << 4) + XDIGITVAL(enc,c);
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      PUNFETCH;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (n < minlen)
Packit b89d10
    return ONIGERR_INVALID_CODE_POINT_VALUE;
Packit b89d10
Packit b89d10
  *src = p;
Packit b89d10
  return num;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
scan_unsigned_octal_number(UChar** src, UChar* end, int maxlen,
Packit b89d10
                           OnigEncoding enc)
Packit b89d10
{
Packit b89d10
  OnigCodePoint c;
Packit b89d10
  unsigned int num, val;
Packit b89d10
  UChar* p = *src;
Packit b89d10
  PFETCH_READY;
Packit b89d10
Packit b89d10
  num = 0;
Packit b89d10
  while (! PEND && maxlen-- != 0) {
Packit b89d10
    PFETCH(c);
Packit b89d10
    if (IS_CODE_DIGIT_ASCII(enc, c) && c < '8') {
Packit b89d10
      val = ODIGITVAL(c);
Packit b89d10
      if ((INT_MAX_LIMIT - val) / 8UL < num)
Packit b89d10
        return -1;  /* overflow */
Packit b89d10
Packit b89d10
      num = (num << 3) + val;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      PUNFETCH;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  *src = p;
Packit b89d10
  return num;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
#define BB_WRITE_CODE_POINT(bbuf,pos,code) \
Packit b89d10
    BB_WRITE(bbuf, pos, &(code), SIZE_CODE_POINT)
Packit b89d10
Packit b89d10
/* data format:
Packit b89d10
     [n][from-1][to-1][from-2][to-2] ... [from-n][to-n]
Packit b89d10
     (all data size is OnigCodePoint)
Packit b89d10
 */
Packit b89d10
static int
Packit b89d10
new_code_range(BBuf** pbuf)
Packit b89d10
{
Packit b89d10
#define INIT_MULTI_BYTE_RANGE_SIZE  (SIZE_CODE_POINT * 5)
Packit b89d10
  int r;
Packit b89d10
  OnigCodePoint n;
Packit b89d10
  BBuf* bbuf;
Packit b89d10
Packit b89d10
  bbuf = *pbuf = (BBuf* )xmalloc(sizeof(BBuf));
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(bbuf);
Packit b89d10
  r = BB_INIT(bbuf, INIT_MULTI_BYTE_RANGE_SIZE);
Packit b89d10
  if (r != 0) {
Packit b89d10
    xfree(bbuf);
Packit b89d10
    *pbuf = 0;
Packit b89d10
    return r;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  n = 0;
Packit b89d10
  BB_WRITE_CODE_POINT(bbuf, 0, n);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_code_range_to_buf(BBuf** pbuf, OnigCodePoint from, OnigCodePoint to)
Packit b89d10
{
Packit b89d10
  int r, inc_n, pos;
Packit b89d10
  int low, high, bound, x;
Packit b89d10
  OnigCodePoint n, *data;
Packit b89d10
  BBuf* bbuf;
Packit b89d10
Packit b89d10
  if (from > to) {
Packit b89d10
    n = from; from = to; to = n;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (IS_NULL(*pbuf)) {
Packit b89d10
    r = new_code_range(pbuf);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    bbuf = *pbuf;
Packit b89d10
    n = 0;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    bbuf = *pbuf;
Packit b89d10
    GET_CODE_POINT(n, bbuf->p);
Packit b89d10
  }
Packit b89d10
  data = (OnigCodePoint* )(bbuf->p);
Packit b89d10
  data++;
Packit b89d10
Packit b89d10
  for (low = 0, bound = n; low < bound; ) {
Packit b89d10
    x = (low + bound) >> 1;
Packit b89d10
    if (from > data[x*2 + 1])
Packit b89d10
      low = x + 1;
Packit b89d10
    else
Packit b89d10
      bound = x;
Packit b89d10
  }
Packit