return 0;
}
+static int
+add_save_type(regex_t* reg, enum SaveType type)
+{
+ SaveType t = (SaveType )type;
+
+ BBUF_ADD(reg, &t, SIZE_SAVE_TYPE);
+ return 0;
+}
+
+static int
+add_update_var_type(regex_t* reg, enum UpdateVarType type)
+{
+ UpdateVarType t = (UpdateVarType )type;
+
+ BBUF_ADD(reg, &t, SIZE_UPDATE_VAR_TYPE);
+ return 0;
+}
+
static int
add_opcode_rel_addr(regex_t* reg, int opcode, int addr)
{
return r;
}
+static int
+compile_gimmick_node(GimmickNode* node, regex_t* reg)
+{
+ int r;
+
+ switch (node->type) {
+ case GIMMICK_KEEP:
+ r = add_opcode(reg, OP_PUSH_SAVE_VAL);
+ if (r != 0) return r;
+ r = add_save_type(reg, SAVE_KEEP);
+ if (r != 0) return r;
+ r = add_mem_num(reg, node->id);
+ break;
+ }
+
+ return r;
+}
+
+static int
+compile_length_gimmick_node(GimmickNode* node, regex_t* reg)
+{
+ int len;
+
+ switch (node->type) {
+ case GIMMICK_KEEP:
+ len = SIZE_OP_PUSH_SAVE_VAL;
+ break;
+ }
+
+ return len;
+}
+
static int
compile_length_tree(Node* node, regex_t* reg)
{
r = compile_length_anchor_node(ANCHOR_(node), reg);
break;
+ case NODE_GIMMICK:
+ r = compile_length_gimmick_node(GIMMICK_(node), reg);
+ break;
+
default:
return ONIGERR_TYPE_BUG;
break;
r = compile_anchor_node(ANCHOR_(node), reg, env);
break;
+ case NODE_GIMMICK:
+ r = compile_gimmick_node(GIMMICK_(node), reg);
+ break;
+
default:
#ifdef ONIG_DEBUG
fprintf(stderr, "compile_tree: undefined node type %d\n", NODE_TYPE(node));
break;
case NODE_ANCHOR:
+ case NODE_GIMMICK:
break;
case NODE_BACKREF:
n = get_head_value_node(NODE_BODY(node), exact, reg);
break;
+ case NODE_GIMMICK:
default:
break;
}
r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);
break;
+ case NODE_GIMMICK:
default:
break;
}
break;
case NODE_ANCHOR:
+ case NODE_GIMMICK:
default:
break;
}
break;
case NODE_ANCHOR:
+ case NODE_GIMMICK:
default:
break;
}
case NODE_CTYPE:
case NODE_CCLASS:
case NODE_ANCHOR:
+ case NODE_GIMMICK:
default:
break;
}
case NODE_STR:
case NODE_CTYPE:
case NODE_CCLASS:
+ case NODE_GIMMICK:
default:
break;
}
#endif
case NODE_CTYPE:
case NODE_CCLASS:
+ case NODE_GIMMICK:
default:
break;
}
}
break;
+ case NODE_GIMMICK:
+ break;
+
default:
#ifdef ONIG_DEBUG
fprintf(stderr, "optimize_node_left: undefined node type %d\n", NODE_TYPE(node));
r = compile_tree(root, reg, &scan_env);
if (r == 0) {
+ if (scan_env.keep_num > 0) {
+ r = add_opcode(reg, OP_UPDATE_VAR);
+ if (r != 0) goto err;
+ r = add_update_var_type(reg, UPDATE_VAR_KEEP_FROM_STACK_LAST);
+ if (r != 0) goto err;
+ }
+
r = add_opcode(reg, OP_END);
#ifdef USE_CALL
if (scan_env.num_call > 0) {
extern int
onig_reg_init(regex_t* reg, OnigOptionType option,
- OnigCaseFoldType case_fold_flag,
- OnigEncoding enc, OnigSyntaxType* syntax)
+ OnigCaseFoldType case_fold_flag,
+ OnigEncoding enc, OnigSyntaxType* syntax)
{
int r;
{ OP_FAIL_LOOK_BEHIND_NOT, "fail-look-behind-not", ARG_NON },
{ OP_CALL, "call", ARG_ABSADDR },
{ OP_RETURN, "return", ARG_NON },
+ { OP_PUSH_SAVE_VAL, "push-save-val", ARG_SPECIAL },
+ { OP_UPDATE_VAR, "update-var", ARG_SPECIAL },
{ OP_STATE_CHECK_PUSH, "state-check-push", ARG_SPECIAL },
{ OP_STATE_CHECK_PUSH_OR_JUMP, "state-check-push-or-jump", ARG_SPECIAL },
{ OP_STATE_CHECK, "state-check", ARG_STATE_CHECK },
p_rel_addr(f, addr, bp, start);
break;
+ case OP_PUSH_SAVE_VAL:
+ {
+ SaveType type;
+ GET_SAVE_TYPE_INC(type, bp);
+ GET_MEMNUM_INC(mem, bp);
+ fprintf(f, ":%d:%d", type, mem);
+ }
+ break;
+
+ case OP_UPDATE_VAR:
+ {
+ UpdateVarType type;
+ GET_UPDATE_VAR_TYPE_INC(type, bp);
+ fprintf(f, ":%d", type);
+ }
+ break;
+
default:
fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n",
*--bp);
print_indent_tree(f, NODE_BODY(node), indent + add);
break;
+ case NODE_GIMMICK:
+ fprintf(f, "<gimmick:%p> ", node);
+ switch (GIMMICK_(node)->type) {
+ case GIMMICK_KEEP:
+ fprintf(f, "keep:%d", GIMMICK_(node)->id);
+ break;
+ }
+ break;
+
default:
fprintf(f, "print_indent_tree: undefined node type %d\n", NODE_TYPE(node));
break;
#define STACK_GET_SAVE_VAL_TYPE_LAST(stype, sval) do {\
StackType *k = stk;\
- while (1) {\
+ while (k > stk_base) {\
k--;\
STACK_BASE_CHECK(k, "STACK_GET_SAVE_VAL_TYPE_LAST"); \
if (k->type == STK_SAVE_VAL && k->u.val.type == (stype)) {\
#endif
case OP_PUSH_SAVE_VAL: MOP_IN(OP_PUSH_SAVE_VAL);
- GET_MEMNUM_INC(mem, p); /* mem: save id */
- STACK_PUSH_SAVE_VAL(mem, SAVE_KEEP, keep);
+ {
+ SaveType type;
+ GET_SAVE_TYPE_INC(type, p);
+ GET_MEMNUM_INC(mem, p); /* mem: save id */
+ switch ((enum SaveType )type) {
+ case SAVE_KEEP:
+ STACK_PUSH_SAVE_VAL(mem, type, s);
+ break;
+ }
+ }
MOP_OUT;
continue;
break;
case OP_UPDATE_VAR: MOP_IN(OP_UPDATE_VAR);
- GET_MEMNUM_INC(mem, p); /* mem: update var type */
- switch ((enum UpdateVarType )mem) {
- case UPDATE_VAR_KEEP_FROM_STACK_LAST:
- STACK_GET_SAVE_VAL_TYPE_LAST(SAVE_KEEP, keep);
- break;
+ {
+ UpdateVarType type;
+ GET_UPDATE_VAR_TYPE_INC(type, p);
+ switch ((enum UpdateVarType )type) {
+ case UPDATE_VAR_KEEP_FROM_STACK_LAST:
+ STACK_GET_SAVE_VAL_TYPE_LAST(SAVE_KEEP, keep);
+ break;
+ }
}
MOP_OUT;
continue;
typedef int MemNumType;
typedef short int StateCheckNumType;
typedef void* PointerType;
+typedef int SaveType;
+typedef int UpdateVarType;
#define SIZE_OPCODE 1
#define SIZE_RELADDR sizeof(RelAddrType)
#define SIZE_OPTION sizeof(OnigOptionType)
#define SIZE_CODE_POINT sizeof(OnigCodePoint)
#define SIZE_POINTER sizeof(PointerType)
-
+#define SIZE_SAVE_TYPE sizeof(SaveType)
+#define SIZE_UPDATE_VAR_TYPE sizeof(UpdateVarType)
#define GET_RELADDR_INC(addr,p) PLATFORM_GET_INC(addr, p, RelAddrType)
#define GET_ABSADDR_INC(addr,p) PLATFORM_GET_INC(addr, p, AbsAddrType)
#define GET_OPTION_INC(option,p) PLATFORM_GET_INC(option, p, OnigOptionType)
#define GET_POINTER_INC(ptr,p) PLATFORM_GET_INC(ptr, p, PointerType)
#define GET_STATE_CHECK_NUM_INC(num,p) PLATFORM_GET_INC(num, p, StateCheckNumType)
+#define GET_SAVE_TYPE_INC(type,p) PLATFORM_GET_INC(type, p, SaveType)
+#define GET_UPDATE_VAR_TYPE_INC(type,p) PLATFORM_GET_INC(type, p, UpdateVarType)
/* code point's address must be aligned address. */
#define GET_CODE_POINT(code,p) code = *((OnigCodePoint* )(p))
#define SIZE_OP_FAIL_LOOK_BEHIND_NOT SIZE_OPCODE
#define SIZE_OP_CALL (SIZE_OPCODE + SIZE_ABSADDR)
#define SIZE_OP_RETURN SIZE_OPCODE
+#define SIZE_OP_PUSH_SAVE_VAL (SIZE_OPCODE + SIZE_SAVE_TYPE + SIZE_MEMNUM)
+#define SIZE_OP_UPDATE_VAR (SIZE_OPCODE + SIZE_UPDATE_VAR_TYPE)
#ifdef USE_COMBINATION_EXPLOSION_CHECK
#define SIZE_OP_STATE_CHECK (SIZE_OPCODE + SIZE_STATE_CHECK_NUM)