Exetools

Exetools (https://forum.exetools.com/index.php)
-   General Discussion (https://forum.exetools.com/forumdisplay.php?f=2)
-   -   Ioncube 7 Decode (https://forum.exetools.com/showthread.php?t=15091)

bytexorer 07-01-2014 18:11

Any news on reversing ioncube?
also,while on this topic, any body knows how plesk .php and .php3 files are encrypted?

giv 07-01-2014 18:51

You can ask Narciszu.

Mahmoudnia 07-05-2014 05:06

I don't have any encoded file with v7, but if you have, maybe i can help you. A few years ago I had the same question but there was no helpfull reference.
guys I'm not a decoder service!!!, just for testing decoded file.

uranus64 07-05-2014 16:32

Encoded files with version 7 of Ioncube Encoder are more or less usefull these days. Exist already many tools able to decode encoded files with version 8 of the encoder.

I have last version of encoder with legit license. I have also source code for old version 6 that was leaked (and still exist on the internet). I have some tools able to decode version 8 via patched ioncube loader dll. I patched myself version 4.6.1 of loader - last one.

PHP is open source. We need to modify and recompile PHP engine for good results. All free decoder that exist today are based on modified PHP engine (old dezend engine). Differences between original php.exe and modified one need to be this: original php.exe executes instructions on web server but modified one needs to output source code instead of executes.

None decoders are able to deobfuscate functions and/or variable names if developer used this option in encoding process.

We need a motivated group in order to make a new valuable decoder for this.

Mahmoudnia 07-05-2014 23:01

I found ionCube v6.0 leaked version and ionCube v7.0 cracked version by yoza and also I have a decoder that works on ionCube v8.0. So, for decoding functions we need to patch ionCube loader dll and modify php.exe ? becuase I'm working on Truebug right now.

could you please more details narciszu ? ionCube loader is a normal DLL ? can we use dynamic debugging?

CryptXor 10-10-2015 23:06

I do not know if this qualifies as digging up an old post or not; but I think the following code would be useful to someone somehow :) I have an updated version specifically for ionCube 6 & 7 if I can find it...
Code:

/***********************************************************************/
/*                                                                    */
/*  FILE        :dezender.c                                            */
/*  DATE        :2005/08/10                                            */
/*  DESCRIPTION :opcode->php source code                              */
/*  PROJECT    :deZender                                              */
/*                                                                    */
/***********************************************************************/


#include "php.h"
#include "ext/standard/url.h"


#if 0
#define ZEND_NOP                                        0                                /* NOP */
#define ZEND_ADD                                        1                                /* + */
#define ZEND_SUB                                        2                                /* - */
#define ZEND_MUL                                        3                                /* * */
#define ZEND_DIV                                        4                                /* / */
#define ZEND_MOD                                        5                                /* % */
#define ZEND_SL                                                6                                /* << */
#define ZEND_SR                                                7                                /* >> */
#define ZEND_CONCAT                                        8                                /* . */
#define ZEND_BW_OR                                        9                                /* | */
#define ZEND_BW_AND                                        10                                /* & */
#define ZEND_BW_XOR                                        11                                /* ^ */
#define ZEND_BW_NOT                                        12                                /* ~ */
#define ZEND_BOOL_NOT                                13                                /* ! */
#define ZEND_BOOL_XOR                                14                                /* XOR */
#define ZEND_IS_IDENTICAL                        15                                /* === */
#define ZEND_IS_NOT_IDENTICAL                16                                /* !== */
#define ZEND_IS_EQUAL                                17                                /* == */
#define ZEND_IS_NOT_EQUAL                        18                                /* != */
#define ZEND_IS_SMALLER                                19                                /* < */
#define ZEND_IS_SMALLER_OR_EQUAL        20                                /* <= */
#define ZEND_CAST                                        21                                /* (int), (real), (string), (array), (object), (bool), (unset) */
#define ZEND_QM_ASSIGN                                22                                /* a?b:c */
#define ZEND_ASSIGN_ADD                                23                                /* += */
#define ZEND_ASSIGN_SUB                                24                                /* -= */
#define ZEND_ASSIGN_MUL                                25                                /* *= */
#define ZEND_ASSIGN_DIV                                26                                /* /= */
#define ZEND_ASSIGN_MOD                                27                                /* %= */
#define ZEND_ASSIGN_SL                                28                                /* <<= */
#define ZEND_ASSIGN_SR                                29                                /* >>= */
#define ZEND_ASSIGN_CONCAT                        30                                /* .= */
#define ZEND_ASSIGN_BW_OR                        31                                /* |= */
#define ZEND_ASSIGN_BW_AND                        32                                /* &= */
#define ZEND_ASSIGN_BW_XOR                        33                                /* ^= */
#define ZEND_PRE_INC                                34                                /* ++a */
#define ZEND_PRE_DEC                                35                                /* --a */
#define ZEND_POST_INC                                36                                /* a++ */
#define ZEND_POST_DEC                                37                                /* a-- */
#define ZEND_ASSIGN                                        38                                /* = */
#define ZEND_ASSIGN_REF                                39                                /* =&a */
#define ZEND_ECHO                                        40                                /* echo */
#define ZEND_PRINT                                        41                                /* print */
#define ZEND_JMP                                        42                                /* JMP */
#define ZEND_JMPZ                                        43                                /* JMPZ */
#define ZEND_JMPNZ                                        44                                /* JMPNZ */
#define ZEND_JMPZNZ                                        45                                /* JMPZNZ */
#define ZEND_JMPZ_EX                                46                                /* JMPZ_EX */
#define ZEND_JMPNZ_EX                                47                                /* JMPNZ_EX */
#define ZEND_CASE                                        48                                /* case */
#define ZEND_SWITCH_FREE                        49                                /* return, foreach, switch */
#define ZEND_BRK                                        50                                /* break */
#define ZEND_CONT                                        51                                /* continue */
#define ZEND_BOOL                                        52                                /* ||, &&, switch(expr), default:  */
#define ZEND_INIT_STRING                        53                                /* '' */
#define ZEND_ADD_CHAR                                54                                /* . */
#define ZEND_ADD_STRING                                55                                /* . */
#define ZEND_ADD_VAR                                56                                /* . */
#define ZEND_BEGIN_SILENCE                        57                                /* @:begin */
#define ZEND_END_SILENCE                        58                                /* @:end */
#define ZEND_INIT_FCALL_BY_NAME                59                                /* call function */
#define ZEND_DO_FCALL                                60                                /* call function */
#define ZEND_DO_FCALL_BY_NAME                61                                /* call function */
#define ZEND_RETURN                                        62                                /* return */
#define ZEND_RECV                                        63                                /* function parameter */
#define ZEND_RECV_INIT                                64                                /* function parameter: static? */
#define ZEND_SEND_VAL                                65                                /* function call parameter: without variable  */
#define ZEND_SEND_VAR                                66                                /* function call parameter: variable */
#define ZEND_SEND_REF                                67                                /* function call parameter: &variable */
#define ZEND_NEW                                        68                                /* new */
#define ZEND_JMP_NO_CTOR                        69                                /* free, end of new */
#define ZEND_FREE                                        70                                /* free */
#define ZEND_INIT_ARRAY                                71                                /* array pair list (a => b, ...) */
#define ZEND_ADD_ARRAY_ELEMENT                72                                /* array pair list (a => b, ...) */
#define ZEND_INCLUDE_OR_EVAL                73                                /* include, include_once, evel, require, require_once */
#define ZEND_UNSET_VAR                                74                                /* unset variable */
#define ZEND_UNSET_DIM_OBJ                        75                                /* unset dim, unset object */
#define ZEND_ISSET_ISEMPTY                        76                                /* isset, empty */
#define ZEND_FE_RESET                                77                                /* foreach */
#define ZEND_FE_FETCH                                78                                /* foreach */
#define ZEND_EXIT                                        79                                /* exit */
#define ZEND_FETCH_R                                80                                /* fetch variable: read mode */
#define ZEND_FETCH_DIM_R                        81                                /* fetch dim: read mode */
#define ZEND_FETCH_OBJ_R                        82                                /* fetch object: read mode */
#define ZEND_FETCH_W                                83                                /* fetch variable: write mode */
#define ZEND_FETCH_DIM_W                        84                                /* fetch dim: write mode */
#define ZEND_FETCH_OBJ_W                        85                                /* fetch object: write mode */
#define ZEND_FETCH_RW                                86                                /* fetch variable: read/write mode */
#define ZEND_FETCH_DIM_RW                        87                                /* fetch dim: read/write mode */
#define ZEND_FETCH_OBJ_RW                        88                                /* fetch object: read/write mode */
#define ZEND_FETCH_IS                                89                                /* fetch variable: is mode */
#define ZEND_FETCH_DIM_IS                        90                                /* fetch dim: is mode */
#define ZEND_FETCH_OBJ_IS                        91                                /* fetch object: is mode */
#define ZEND_FETCH_FUNC_ARG                        92                                /* fetch variable: argument mode */
#define ZEND_FETCH_DIM_FUNC_ARG                93                                /* fetch dim: argument mode */
#define ZEND_FETCH_OBJ_FUNC_ARG                94                                /* fetch object: argument mode */
#define ZEND_FETCH_UNSET                        95                                /* fetch unset variable */
#define ZEND_FETCH_DIM_UNSET                96                                /* fetch unset dim */
#define ZEND_FETCH_OBJ_UNSET                97                                /* fetch unset object */
#define ZEND_FETCH_DIM_TMP_VAR                98                                /* list, foreach */
#define ZEND_FETCH_CONSTANT                        99                                /* constant declaration */
#define ZEND_DECLARE_FUNCTION_OR_CLASS        100                        /* function, class */
#define ZEND_EXT_STMT                                101                                /* ??? */
#define ZEND_EXT_FCALL_BEGIN                102                                /* ??? */
#define ZEND_EXT_FCALL_END                        103                                /* ??? */
#define ZEND_EXT_NOP                                104                                /* ??? */
#define ZEND_TICKS                                        105                                /* declare (ticks=?) */
#define ZEND_SEND_VAR_NO_REF                106                                /* function call parameter: no reference */
#endif

/*-- for php 5.0.4 --*/
#define ZEND_CATCH                                        107
#define ZEND_THROW                                        108
#define ZEND_FETCH_CLASS                        109
#define ZEND_CLONE                                        110
#define ZEND_INIT_CTOR_CALL                        111
#define ZEND_INIT_METHOD_CALL                112
#define ZEND_INIT_STATIC_METHOD_CALL 113
#define ZEND_ISSET_ISEMPTY_VAR                114
#define ZEND_ISSET_ISEMPTY_DIM_OBJ        115
#define        ZEND_IMPORT_FUNCTION                116
#define        ZEND_IMPORT_CLASS                        117
#define        ZEND_IMPORT_CONST                        118
#define ZEND_PRE_INC_OBJ                        132
#define ZEND_PRE_DEC_OBJ                        133
#define ZEND_POST_INC_OBJ                        134
#define ZEND_POST_DEC_OBJ                        135
#define ZEND_ASSIGN_OBJ                                136
#define ZEND_OP_DATA                                137
#define ZEND_INSTANCEOF                                138
//#define ZEND_DECLARE_CLASS                                139
//#define ZEND_DECLARE_INHERITED_CLASS        140
//#define ZEND_DECLARE_FUNCTION                        141
#define ZEND_RAISE_ABSTRACT_ERROR        142


#define DEZ_OP_NOP                                                0                        /* NOP */
#define DEZ_OP_ADD                                                1                  /* + */
#define DEZ_OP_SUB                                                2                  /* - */
#define DEZ_OP_MUL                                                3                  /* * */
#define DEZ_OP_DIV                                                4                  /* / */
#define DEZ_OP_MOD                                                5                  /* % */
#define DEZ_OP_SL                                                6                  /* << */
#define DEZ_OP_SR                                                7                  /* >> */
#define DEZ_OP_CONCAT                                        8                  /* . */
#define DEZ_OP_BW_OR                                        9                  /* | */
#define DEZ_OP_BW_AND                                        10                  /* & */
#define DEZ_OP_BW_XOR                                        11                  /* ^ */
#define DEZ_OP_BW_NOT                                        12                  /* ~ */
#define DEZ_OP_BOOL_NOT                                        13                  /* ! */
#define DEZ_OP_IS_IDENTICAL                                14                  /* === */
#define DEZ_OP_IS_NOT_IDENTICAL                        15                  /* !== */
#define DEZ_OP_IS_EQUAL                                        16                  /* == */
#define DEZ_OP_IS_NOT_EQUAL                                17                  /* != */
#define DEZ_OP_IS_SMALLER                                18                  /* < */
#define DEZ_OP_IS_SMALLER_OR_EQUAL                19                  /* <= */
#define        DEZ_OP_CAST                                                20                  /* (double)a, (string)a, (array)a, (object)a, (bool)a, (unset)a */
#define DEZ_OP_QM_ASSIGN                                21                  /* a?b:c */
#define DEZ_OP_ASSIGN_ADD                                22                  /* += */
#define DEZ_OP_ASSIGN_SUB                                23                  /* -= */
#define DEZ_OP_ASSIGN_MUL                                24                  /* *= */
#define DEZ_OP_ASSIGN_DIV                                25                  /* /= */
#define DEZ_OP_ASSIGN_MOD                                26                  /* %= */
#define DEZ_OP_ASSIGN_SL                                27                  /* <<= */
#define DEZ_OP_ASSIGN_SR                                28                  /* >>= */
#define DEZ_OP_ASSIGN_CONCAT                        29                  /* .= */
#define DEZ_OP_ASSIGN_BW_OR                                30                  /* |= */
#define DEZ_OP_ASSIGN_BW_AND                        31                  /* &= */
#define DEZ_OP_ASSIGN_BW_XOR                        32                  /* ^= */
#define DEZ_OP_PRE_INC                                        33                  /* ++a */
#define DEZ_OP_PRE_DEC                                        34                  /* --a */
#define DEZ_OP_POST_INC                                        35                  /* a++ */
#define DEZ_OP_POST_DEC                                        36                  /* a-- */
#define DEZ_OP_ASSIGN                                        37                  /* = */
#define DEZ_OP_ASSIGN_REF                                38                  /* =&a, static, global */
#define DEZ_OP_ECHO                                                39                  /* echo */
#define DEZ_OP_PRINT                                        40                  /* print */
#define        DEZ_OP_INCLUDE_OR_EVAL                        41                  /* include, include_once, eval, require, require_once */
#define        DEZ_OP_LOGICAL_OR                                42                  /* OR */
#define        DEZ_OP_LOGICAL_XOR                                43                  /* XOR */
#define        DEZ_OP_LOGICAL_AND                                44                  /* AND */
#define        DEZ_OP_NEW                                                45                  /* new */
#define        DEZ_OP_EXIT                                                46                  /* exit */
#define        DEZ_OP_IF                                                47                  /* if */
#define        DEZ_OP_ELSEIF                                        48                  /* elseif */
#define        DEZ_OP_ELSE                                                49                  /* else */
#define        DEZ_OP_DO                                                50                  /* do */
#define        DEZ_OP_WHILE                                        51                  /* while */
#define        DEZ_OP_FOR                                                52                  /* for */
#define        DEZ_OP_FOREACH                                        53                  /* foreach */
#define        DEZ_OP_DECLARE                                        54                  /* declare */
#define        DEZ_OP_AS                                                55                  /* as */
#define        DEZ_OP_SWITCH                                        56                  /* switch */
#define        DEZ_OP_CASE                                                57                  /* case */
#define        DEZ_OP_DEFAULT                                        58                  /* default */
#define        DEZ_OP_BREAK                                        59                  /* break */
#define        DEZ_OP_CONTINUE                                        60                  /* continue */
#define        DEZ_OP_OLD_FUNCTION                                61                  /* old_function */
#define        DEZ_OP_FUNCTION                                        62                  /* function */
#define        DEZ_OP_CONST                                        63                  /* const */
#define        DEZ_OP_RETURN                                        64                  /* return */
#define        DEZ_OP_USE                                                65                  /* use */
#define        DEZ_OP_VAR                                                66                  /* var */
#define        DEZ_OP_UNSET                                        67                  /* unset */
#define        DEZ_OP_ISSET                                        68                  /* isset */
#define        DEZ_OP_EMPTY                                        69                  /* empty */
#define        DEZ_OP_CLASS                                        70                  /* class */
#define        DEZ_OP_EXTENDS                                        71                  /* extends */
#define        DEZ_OP_OBJECT_OPERATOR                        72                  /* a->b */
#define        DEZ_OP_DOUBLE_ARROW                                73                  /* a=>b */
#define        DEZ_OP_LIST                                                74                  /* list */
#define        DEZ_OP_ARRAY                                        75                  /* array */
#define        DEZ_OP_CLASS_C                                        76                  /* __CLASS__ */
#define        DEZ_OP_FUNC_C                                        77                  /* __FUNCTION__ */
#define        DEZ_OP_LINE                                                78                  /* __LINE__ */
#define        DEZ_OP_FILE                                                79                  /* __FILE__ */
#define        DEZ_OP_COMMENT                                        80                  /* comment */
#define        DEZ_OP_HEREDOC                                        81                  /* <<< */
#define        DEZ_OP_DOLLAR_OPEN_CURLY_BRACES        82                  /* ${...} */
#define        DEZ_OP_PAAMAYIM_NEKUDOTAYIM                83                  /* :: */
#define DEZ_OP_CALL_PARAM                                84                  /* parameter of function calling */
#define DEZ_OP_CALL_INIT                                85                  /* initialize function calling */
#define DEZ_OP_CALL                                                86                  /* function call */
#define DEZ_OP_CALL_EX                                        87                  /* function call (ex) */
#define DEZ_OP_BOOL                                                88                  /* end of OR, AND, ... */
#define DEZ_OP_FETCH_DIM                                89                  /* fetch dim */
#define DEZ_OP_INIT_STRING                                90                  /* init string */
#define DEZ_OP_FETCH                                        91                  /* fetch variable */
#define DEZ_OP_FETCH_CONSTANT                        92                  /* fetch constant */
#define DEZ_OP_JMP                                                93                  /* jmp */
#define DEZ_OP_FUNC_PARAM                                94                  /* parameter of function */
#define DEZ_OP_BEGIN_SILENCE                        95                  /* @: begin */
#define DEZ_OP_END_SILENCE                                96                  /* @: end */
#define DEZ_OP_LE                                                97                  /* list element */
#define DEZ_OP_UNKNOWN                                        98                  /* unknown op */

#define DEZ_IS_OPLINE                                        (1<<15)
#define DEZ_IS_CLASS                                        (1<<16)

#define OPC_STACK_SIZE                                        1024
#define OPCS_MAX_LEN                                        16
#define DEZ_VARS_NUM                                        1024
#define NODE_STACK_SIZE                                        2048


#define DEZ_ADD_NODE(x)                                        \
        m_dez_op_prev        = (x);                                \
        (x)->prev                = m_dez_op_current;        \
        (x)->next                = NULL;                                \
        if (m_dez_op_current != NULL)                \
        {                                                                        \
                m_dez_op_current->next        = (x);        \
        }                                                                        \
        m_dez_op_current                = (x);


#define DEZ_DEL_NODE(x)                                                                                                \
        if ((x)->prev != NULL) (x)->prev->next = (x)->next;                                \
        if ((x)->next != NULL) (x)->next->prev = (x)->prev;                                \
        (x)->next = NULL;                                                                                                \
        if (m_dez_op_current == (x)) m_dez_op_current = (x)->prev;                \
        dez_node_specs[(x)->dez_op].dez_node_free_func(x);


#define DEZ_DEL_CURRENT_NODE()                        \
        m_dez_op_current                = m_dez_op_current->prev;        \
        dez_node_specs[m_dez_op_current->next->dez_op].dez_node_free_func(m_dez_op_current->next);        \
        m_dez_op_current->next        = NULL;


#define ZEND_LINENUM(x)                                        \
        ((x) == NULL ? 0 : ((x) >= (zend_op *)m_zend_op_dup && (x) < (zend_op *)(m_zend_op_dup+m_zend_op_dup_num) ? *((int *)((x)+1)) : ((x) - m_zend_op_start)))


typedef struct
{
        zend_op zop;
        int linenum;
} DEZ_ZEND_OP_DUP;

typedef struct
{
        int index;
        char varname[1024];
} DEZ_VAR;

typedef struct DEZ_EG_VAR_NAME_t
{
        unsigned type;
        char *var;
        unsigned len;
        unsigned other;
} DEZ_EG_VAR_NAME;

typedef struct DEZ_EG_FUNC_NAME_t
{
        unsigned type;
        char *func;
        unsigned len;
        unsigned other;
} DEZ_EG_FUNC_NAME;

typedef struct DEZ_EG_FUNC_t
{
        DEZ_EG_FUNC_NAME *funcs;
        unsigned func_num;
        unsigned r2;
        unsigned r3;
} DEZ_EG_FUNC;

typedef struct DEZ_EG_E_t
{
        unsigned r1;
        unsigned r2;
        unsigned r3;
        unsigned r4;
        unsigned r5;
        unsigned r6;
        void *p1;
        unsigned char *zop2op;
        void *p2;
        unsigned r7;
        void *p3;
        unsigned r8;
} DEZ_EG_E;

typedef struct DEZ_EG_RESERVED_t
{
        DEZ_EG_VAR_NAME        *vars;
        unsigned                var_num;
        unsigned                r1;
        DEZ_EG_FUNC                *funcs;
        unsigned                r2;
        DEZ_EG_E                *e;
        void                        *p3;
} DEZ_EG_RESERVED;

/*-- type: dez node --*/
typedef struct DEZ_NODE_s
{
        unsigned char dez_op;                                                        /* dez op code */
        zend_op *zop;
        void *content;                                                                        /* dez node content */
        struct DEZ_NODE_s *prev;                                                /* pointer the previous dez node */
        struct DEZ_NODE_s *next;                                                /* pointer the next dez node */
} DEZ_NODE;

/*-- dez node content: expression --*/
typedef struct DEZ_NODE_EXPR_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        DEZ_NODE *op1_node;
        DEZ_NODE *op2_node;
} DEZ_NODE_EXPR;

/*-- dez node content: if --*/
typedef struct DEZ_NODE_IF_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        DEZ_NODE *op1_node;
        DEZ_NODE *op2_node;
        int dest;
} DEZ_NODE_IF;

/*-- dez node content: for --*/
typedef struct DEZ_NODE_FOR_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        DEZ_NODE *before_node;
        DEZ_NODE *cond_node;
        DEZ_NODE *after_node;
} DEZ_NODE_FOR;

/*-- dez node content: => --*/
typedef struct DEZ_NODE_DA_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        DEZ_NODE *key_node;
        DEZ_NODE *value_node;
        DEZ_NODE *next_node;
} DEZ_NODE_DA;

/*-- dez node content: foreach --*/
typedef struct DEZ_NODE_FOREACH_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        DEZ_NODE *source_node;
        DEZ_NODE *key_node;
        DEZ_NODE *value_node;
} DEZ_NODE_FOREACH;

/*-- dez node content: function --*/
typedef struct DEZ_NODE_FUNCTION_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        DEZ_NODE *param_node;
        char *name;
        DEZ_VAR m_dez_vars[DEZ_VARS_NUM];
        int m_dez_var_num;
        zend_op_array *op_array;
} DEZ_NODE_FUNCTION;

/*-- dez node content: class --*/
typedef struct DEZ_NODE_CLASS_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        char *name;
        zend_class_entry *parent;
} DEZ_NODE_CLASS;

/*-- dez node content: var --*/
typedef struct DEZ_NODE_VAR_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        Bucket *property;
} DEZ_NODE_VAR;

/*-- dez node content: list element --*/
typedef struct DEZ_NODE_LE_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        DEZ_NODE *a_node;
        int pos;
} DEZ_NODE_LE;

/*-- dez node content: list --*/
typedef struct DEZ_NODE_LIST_s
{
        DEZ_NODE *branch_node;                                                        /* must is first one */
        DEZ_NODE *le_node;
        DEZ_NODE *dest_node;
        int level;
} DEZ_NODE_LIST;


typedef int (*DEZ_NODE_CVT_FUNC)(unsigned char dez_op, zend_op *pzop);
typedef int (*DEZ_NODE_OUTPUT_FUNC)(DEZ_NODE *pdez_node);
typedef void (*DEZ_NODE_FREE_FUNC)(DEZ_NODE *pdez_node);


static int dez_node_cvt_nop  (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_expr (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_qm_assign (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_if (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_do (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_for (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_foreach (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_case (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_default (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_function_or_class (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_double_arrow (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_array (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_heredoc (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_dollar_open_curly_braces (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_call (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_bool (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_jmp (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_func_param (unsigned char dez_op, zend_op *pzop);
static int dez_node_cvt_unknown (unsigned char dez_op, zend_op *pzop);

static int dez_node_output_nop(DEZ_NODE *pdez_node);
static int dez_node_output_expr(DEZ_NODE *pdez_node);
static int dez_node_output_cast(DEZ_NODE *pdez_node);
static int dez_node_output_pre(DEZ_NODE *pdez_node);
static int dez_node_output_pre2(DEZ_NODE *pdez_node);
static int dez_node_output_post(DEZ_NODE *pdez_node);
static int dez_node_output_qm_assign(DEZ_NODE *pdez_node);
static int dez_node_output_assign(DEZ_NODE *pdez_node);
static int dez_node_output_assign_ref(DEZ_NODE *pdez_node);
static int dez_node_output_include_or_eval(DEZ_NODE *pdez_node);
static int dez_node_output_or_and(DEZ_NODE *pdez_node);
static int dez_node_output_new(DEZ_NODE *pdez_node);
static int dez_node_output_exit(DEZ_NODE *pdez_node);
static int dez_node_output_if(DEZ_NODE *pdez_node);
static int dez_node_output_do(DEZ_NODE *pdez_node);
static int dez_node_output_for(DEZ_NODE *pdez_node);
static int dez_node_output_foreach(DEZ_NODE *pdez_node);
static int dez_node_output_declare(DEZ_NODE *pdez_node);
static int dez_node_output_case(DEZ_NODE *pdez_node);
static int dez_node_output_default(DEZ_NODE *pdez_node);
static int dez_node_output_function(DEZ_NODE *pdez_node);
static int dez_node_output_var(DEZ_NODE *pdez_node);
static int dez_node_output_unset(DEZ_NODE *pdez_node);
static int dez_node_output_isset_or_empty(DEZ_NODE *pdez_node);
static int dez_node_output_class(DEZ_NODE *pdez_node);
static int dez_node_output_double_arrow(DEZ_NODE *pdez_node);
static int dez_node_output_list(DEZ_NODE *pdez_node);
static int dez_node_output_array(DEZ_NODE *pdez_node);
static int dez_node_output_heredoc(DEZ_NODE *pdez_node);
static int dez_node_output_dollar_open_curly_braces(DEZ_NODE *pdez_node);
static int dez_node_output_call_param(DEZ_NODE *pdez_node);
static int dez_node_output_call_init(DEZ_NODE *pdez_node);
static int dez_node_output_call(DEZ_NODE *pdez_node);
static int dez_node_output_call_ex(DEZ_NODE *pdez_node);
static int dez_node_output_fetch_dim(DEZ_NODE *pdez_node);
static int dez_node_output_init_string(DEZ_NODE *pdez_node);
static int dez_node_output_fetch_constant(DEZ_NODE *pdez_node);
static int dez_node_output_func_param(DEZ_NODE *pdez_node);
static int dez_node_output_property(DEZ_NODE *pdez_node);
static int dez_node_output_le(DEZ_NODE *pdez_node);
static int dez_node_output_unknown(DEZ_NODE *pdez_node);

static void dez_node_free_nop (DEZ_NODE *pdez_node);
static void dez_node_free_expr (DEZ_NODE *pdez_node);
static void dez_node_free_if (DEZ_NODE *pdez_node);
static void dez_node_free_for (DEZ_NODE *pdez_node);
static void dez_node_free_foreach (DEZ_NODE *pdez_node);
static void dez_node_free_case (DEZ_NODE *pdez_node);
static void dez_node_free_default (DEZ_NODE *pdez_node);
static void dez_node_free_function (DEZ_NODE *pdez_node);
static void dez_node_free_var (DEZ_NODE *pdez_node);
static void dez_node_free_class (DEZ_NODE *pdez_node);
static void dez_node_free_da (DEZ_NODE *pdez_node);
static void dez_node_free_list (DEZ_NODE *pdez_node);
static void dez_node_free_heredoc (DEZ_NODE *pdez_node);
static void dez_node_free_dollar_open_curly_braces (DEZ_NODE *pdez_node);
static void dez_node_free_property(DEZ_NODE *pdez_node);
static void dez_node_free_le (DEZ_NODE *pdez_node);
static void dez_node_free_unknown (DEZ_NODE *pdez_node);


typedef struct
{
        char *desc;
        DEZ_NODE_CVT_FUNC                dez_node_cvt_func;                        /* the node convert function */
        DEZ_NODE_OUTPUT_FUNC        dez_node_output_func;                /* the node output function */
        DEZ_NODE_FREE_FUNC                dez_node_free_func;                        /* the node free function */
} DEZ_NODE_SPEC;

typedef struct
{
        unsigned char dez_op;                                                        /* dez op code */
        short opcs_len;                                                /* the length of opcs[] */
        unsigned char opcs[OPCS_MAX_LEN];                                /* the matching zend op codes */
} DEZ_OP_TYPE;

typedef struct DEZ_BRK_CNT_NODE_s
{
        const DEZ_NODE *node;                                                        /* pointer to if(false) node */
        struct DEZ_BRK_CNT_NODE_s *prev;
        struct DEZ_BRK_CNT_NODE_s *next;
} DEZ_BRK_CNT_NODE;


static DEZ_VAR m_dez_vars[DEZ_VARS_NUM];
static int m_dez_var_num = 0;

static char *ZEND_OP_STRING[] =
{
        "ZEND_NOP                        ",
        "ZEND_ADD                        ",
        "ZEND_SUB                        ",
        "ZEND_MUL                        ",
        "ZEND_DIV                        ",
        "ZEND_MOD                        ",
        "ZEND_SL                          ",
        "ZEND_SR                          ",
        "ZEND_CONCAT                      ",
        "ZEND_BW_OR                      ",
        "ZEND_BW_AND                      ",
        "ZEND_BW_XOR                      ",
        "ZEND_BW_NOT                      ",
        "ZEND_BOOL_NOT                    ",
        "ZEND_BOOL_XOR                    ",
        "ZEND_IS_IDENTICAL                ",
        "ZEND_IS_NOT_IDENTICAL            ",
        "ZEND_IS_EQUAL                    ",
        "ZEND_IS_NOT_EQUAL                ",
        "ZEND_IS_SMALLER                  ",
        "ZEND_IS_SMALLER_OR_EQUAL        ",
        "ZEND_CAST                        ",
        "ZEND_QM_ASSIGN                  ",
        "ZEND_ASSIGN_ADD                  ",
        "ZEND_ASSIGN_SUB                  ",
        "ZEND_ASSIGN_MUL                  ",
        "ZEND_ASSIGN_DIV                  ",
        "ZEND_ASSIGN_MOD                  ",
        "ZEND_ASSIGN_SL                  ",
        "ZEND_ASSIGN_SR                  ",
        "ZEND_ASSIGN_CONCAT              ",
        "ZEND_ASSIGN_BW_OR                ",
        "ZEND_ASSIGN_BW_AND              ",
        "ZEND_ASSIGN_BW_XOR              ",
        "ZEND_PRE_INC                    ",
        "ZEND_PRE_DEC                    ",
        "ZEND_POST_INC                    ",
        "ZEND_POST_DEC                    ",
        "ZEND_ASSIGN                      ",
        "ZEND_ASSIGN_REF                  ",
        "ZEND_ECHO                        ",
        "ZEND_PRINT                      ",
        "ZEND_JMP                        ",
        "ZEND_JMPZ                        ",
        "ZEND_JMPNZ                      ",
        "ZEND_JMPZNZ                      ",
        "ZEND_JMPZ_EX                    ",
        "ZEND_JMPNZ_EX                    ",
        "ZEND_CASE                        ",
        "ZEND_SWITCH_FREE                ",
        "ZEND_BRK                        ",
        "ZEND_CONT                        ",
        "ZEND_BOOL                        ",
        "ZEND_INIT_STRING                ",
        "ZEND_ADD_CHAR                    ",
        "ZEND_ADD_STRING                  ",
        "ZEND_ADD_VAR                    ",
        "ZEND_BEGIN_SILENCE              ",
        "ZEND_END_SILENCE                ",
        "ZEND_INIT_FCALL_BY_NAME          ",
        "ZEND_DO_FCALL                    ",
        "ZEND_DO_FCALL_BY_NAME            ",
        "ZEND_RETURN                      ",
        "ZEND_RECV                        ",
        "ZEND_RECV_INIT                  ",
        "ZEND_SEND_VAL                    ",
        "ZEND_SEND_VAR                    ",
        "ZEND_SEND_REF                    ",
        "ZEND_NEW                        ",
        "ZEND_JMP_NO_CTOR                ",
        "ZEND_FREE                        ",
        "ZEND_INIT_ARRAY                  ",
        "ZEND_ADD_ARRAY_ELEMENT          ",
        "ZEND_INCLUDE_OR_EVAL            ",
        "ZEND_UNSET_VAR                  ",
        "ZEND_UNSET_DIM_OBJ              ",
        "ZEND_ISSET_ISEMPTY              ",
        "ZEND_FE_RESET                    ",
        "ZEND_FE_FETCH                    ",
        "ZEND_EXIT                        ",
        "ZEND_FETCH_R                    ",
        "ZEND_FETCH_DIM_R                ",
        "ZEND_FETCH_OBJ_R                ",
        "ZEND_FETCH_W                    ",
        "ZEND_FETCH_DIM_W                ",
        "ZEND_FETCH_OBJ_W                ",
        "ZEND_FETCH_RW                    ",
        "ZEND_FETCH_DIM_RW                ",
        "ZEND_FETCH_OBJ_RW                ",
        "ZEND_FETCH_IS                    ",
        "ZEND_FETCH_DIM_IS                ",
        "ZEND_FETCH_OBJ_IS                ",
        "ZEND_FETCH_FUNC_ARG              ",
        "ZEND_FETCH_DIM_FUNC_ARG          ",
        "ZEND_FETCH_OBJ_FUNC_ARG          ",
        "ZEND_FETCH_UNSET                ",
        "ZEND_FETCH_DIM_UNSET            ",
        "ZEND_FETCH_OBJ_UNSET            ",
        "ZEND_FETCH_DIM_TMP_VAR          ",
        "ZEND_FETCH_CONSTANT              ",
        "ZEND_DECLARE_FUNCTION_OR_CLASS  ",
        "ZEND_EXT_STMT                    ",
        "ZEND_EXT_FCALL_BEGIN            ",
        "ZEND_EXT_FCALL_END              ",
        "ZEND_EXT_NOP                    ",
        "ZEND_TICKS                      ",
        "ZEND_SEND_VAR_NO_REF            ",
        "ZEND_CATCH                              ",
        "ZEND_THROW                              ",
        "ZEND_FETCH_CLASS                      ",
        "ZEND_CLONE                              ",
        "ZEND_INIT_CTOR_CALL                  ",
        "ZEND_INIT_METHOD_CALL                  ",
        "ZEND_INIT_STATIC_METHOD_CALL    ",
        "ZEND_ISSET_ISEMPTY_VAR                  ",
        "ZEND_ISSET_ISEMPTY_DIM_OBJ              ",
        "ZEND_IMPORT_FUNCTION                  ",
        "ZEND_IMPORT_CLASS                      ",
        "ZEND_IMPORT_CONST                      ",
        "ZEND_PRE_INC_OBJ                      ",
        "ZEND_PRE_DEC_OBJ                      ",
        "ZEND_POST_INC_OBJ                      ",
        "ZEND_POST_DEC_OBJ                      ",
        "ZEND_ASSIGN_OBJ                      ",
        "ZEND_OP_DATA                          ",
        "ZEND_INSTANCEOF                      ",
        "ZEND_DECLARE_CLASS                      ",
        "ZEND_DECLARE_INHERITED_CLASS          ", 
        "ZEND_DECLARE_FUNCTION                  ", 
        "ZEND_RAISE_ABSTRACT_ERROR              "
};


static DEZ_NODE_SPEC dez_node_specs[] =
{
        {"", dez_node_cvt_nop, dez_node_output_nop, dez_node_free_nop},                                          /* DEZ_OP_NOP*/
        {" + ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                        /* DEZ_OP_ADD*/
        {" - ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                        /* DEZ_OP_SUB*/
        {" * ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                        /* DEZ_OP_MUL*/
        {" / ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                        /* DEZ_OP_DIV*/
        {" % ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                        /* DEZ_OP_MOD*/
        {" << ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                            /* DEZ_OP_SL*/
        {" >> ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                            /* DEZ_OP_SR*/
        {".", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                    /* DEZ_OP_CONCAT*/
        {" | ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                      /* DEZ_OP_BW_OR    */
        {" & ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                    /* DEZ_OP_BW_AND*/
        {" ^ ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                    /* DEZ_OP_BW_XOR*/
        {"~", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                    /* DEZ_OP_BW_NOT*/
        {"!", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                /* DEZ_OP_BOOL_NOT    */
        {" === ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                        /* DEZ_OP_IS_IDENTICAL    */
        {" !== ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                /* DEZ_OP_IS_NOT_IDENTICAL    */
        {" == ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                /* DEZ_OP_IS_EQUAL    */
        {" != ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                        /* DEZ_OP_IS_NOT_EQUAL    */
        {" < ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                            /* DEZ_OP_IS_SMALLER*/
        {" <= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                  /* DEZ_OP_IS_SMALLER_OR_EQUAL*/
        {"(xxx)a", dez_node_cvt_expr, dez_node_output_cast, dez_node_free_expr},                                        /* DEZ_OP_CAST    */
        {"a?b:c", dez_node_cvt_qm_assign, dez_node_output_qm_assign, dez_node_free_expr},                              /* DEZ_OP_QM_ASSIGN    */
        {" += ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                            /* DEZ_OP_ASSIGN_ADD*/
        {" -= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                            /* DEZ_OP_ASSIGN_SUB*/
        {" *= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                            /* DEZ_OP_ASSIGN_MUL*/
        {" /= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                            /* DEZ_OP_ASSIGN_DIV*/
        {" %= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                            /* DEZ_OP_ASSIGN_MOD*/
        {" <<= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                              /* DEZ_OP_ASSIGN_SL    */
        {" >>= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                              /* DEZ_OP_ASSIGN_SR    */
        {" .= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                      /* DEZ_OP_ASSIGN_CONCAT    */
        {" |= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                        /* DEZ_OP_ASSIGN_BW_OR    */
        {" &= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                      /* DEZ_OP_ASSIGN_BW_AND    */
        {" ^= ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                      /* DEZ_OP_ASSIGN_BW_XOR    */
        {"++", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr},                                  /* DEZ_OP_PRE_INC*/
        {"--", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr},                                  /* DEZ_OP_PRE_DEC*/
        {"++", dez_node_cvt_expr, dez_node_output_post, dez_node_free_expr},                                /* DEZ_OP_POST_INC    */
        {"--", dez_node_cvt_expr, dez_node_output_post, dez_node_free_expr},                                /* DEZ_OP_POST_DEC    */
        {" = ", dez_node_cvt_expr, dez_node_output_assign, dez_node_free_expr},                                    /* DEZ_OP_ASSIGN*/
        {" = &", dez_node_cvt_expr, dez_node_output_assign_ref, dez_node_free_expr},                            /* DEZ_OP_ASSIGN_REF*/
        {"echo ", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr},                                        /* DEZ_OP_ECHO    */
        {"print ", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr},                                      /* DEZ_OP_PRINT    */
        {"", dez_node_cvt_expr, dez_node_output_include_or_eval, dez_node_free_expr},                  /* DEZ_OP_INCLUDE_OR_EVAL*/
        {" OR ", dez_node_cvt_expr, dez_node_output_or_and, dez_node_free_expr},                            /* DEZ_OP_LOGICAL_OR*/
        {" XOR ", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                          /* DEZ_OP_LOGICAL_XOR*/
        {" AND ", dez_node_cvt_expr, dez_node_output_or_and, dez_node_free_expr},                          /* DEZ_OP_LOGICAL_AND*/
        {"new ", dez_node_cvt_expr, dez_node_output_new, dez_node_free_expr},                                          /* DEZ_OP_NEW*/
        {"exit", dez_node_cvt_expr, dez_node_output_exit, dez_node_free_expr},                                        /* DEZ_OP_EXIT    */
        {"if ", dez_node_cvt_if, dez_node_output_if, dez_node_free_if},                                            /* DEZ_OP_IF*/
        {"elseif ", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                    /* DEZ_OP_ELSEIF*/
        {"else", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr},                                        /* DEZ_OP_ELSE    */
        {"do", dez_node_cvt_do, dez_node_output_do, dez_node_free_expr},                                            /* DEZ_OP_DO*/
        {"while ", dez_node_cvt_unknown, dez_node_output_if, dez_node_free_if},                                      /* DEZ_OP_WHILE    */
        {"for ", dez_node_cvt_for, dez_node_output_for, dez_node_free_for},                                          /* DEZ_OP_FOR*/
        {"foreach ", dez_node_cvt_foreach, dez_node_output_foreach, dez_node_free_foreach},                                  /* DEZ_OP_FOREACH*/
        {"declare ", dez_node_cvt_expr, dez_node_output_declare, dez_node_free_expr},                                  /* DEZ_OP_DECLARE*/
        {"", dez_node_cvt_unknown, dez_node_output_pre, dez_node_free_expr},                                            /* DEZ_OP_AS*/
        {"switch ", dez_node_cvt_unknown, dez_node_output_if, dez_node_free_if},                                    /* DEZ_OP_SWITCH*/
        {"case ", dez_node_cvt_case, dez_node_output_case, dez_node_free_case},                                        /* DEZ_OP_CASE    */
        {"default:", dez_node_cvt_default, dez_node_output_default, dez_node_free_default},                                  /* DEZ_OP_DEFAULT*/
        {"break", dez_node_cvt_expr, dez_node_output_pre2, dez_node_free_expr},                                      /* DEZ_OP_BREAK    */
        {"continue", dez_node_cvt_expr, dez_node_output_pre2, dez_node_free_expr},                                /* DEZ_OP_CONTINUE    */
        {"old_function", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                        /* DEZ_OP_OLD_FUNCTION    */
        {"function ", dez_node_cvt_function_or_class, dez_node_output_function, dez_node_free_function},                                /* DEZ_OP_FUNCTION    */
        {"const", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                      /* DEZ_OP_CONST    */
        {"return ", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr},                                    /* DEZ_OP_RETURN*/
        {"use", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                          /* DEZ_OP_USE*/
        {"var ", dez_node_cvt_unknown, dez_node_output_var, dez_node_free_var},                                          /* DEZ_OP_VAR*/
        {"unset ", dez_node_cvt_expr, dez_node_output_unset, dez_node_free_expr},                                      /* DEZ_OP_UNSET    */
        {"isset ", dez_node_cvt_expr, dez_node_output_isset_or_empty, dez_node_free_expr},                                      /* DEZ_OP_ISSET    */
        {"empty ", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                      /* DEZ_OP_EMPTY    */
        {"class ", dez_node_cvt_function_or_class, dez_node_output_class, dez_node_free_class},                                      /* DEZ_OP_CLASS    */
        {"extends", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                  /* DEZ_OP_EXTENDS*/
        {"->", dez_node_cvt_expr, dez_node_output_expr, dez_node_free_expr},                                                  /* DEZ_OP_OBJECT_OPERATOR*/
        {" => ", dez_node_cvt_double_arrow, dez_node_output_double_arrow, dez_node_free_da},                        /* DEZ_OP_DOUBLE_ARROW    */
        {"list ", dez_node_cvt_unknown, dez_node_output_list, dez_node_free_list},                                        /* DEZ_OP_LIST    */
        {"array ", dez_node_cvt_array, dez_node_output_array, dez_node_free_da},                                      /* DEZ_OP_ARRAY    */
        {"__CLASS__", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                  /* DEZ_OP_CLASS_C*/
        {"__FUNCTION__", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                    /* DEZ_OP_FUNC_C*/
        {"__LINE__", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                        /* DEZ_OP_LINE    */
        {"__FILE__", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                        /* DEZ_OP_FILE    */
        {"", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                  /* DEZ_OP_COMMENT*/
/****/        {"<<<", dez_node_cvt_heredoc, dez_node_output_heredoc, dez_node_free_heredoc},                                  /* DEZ_OP_HEREDOC*/
/****/        {"", dez_node_cvt_dollar_open_curly_braces, dez_node_output_dollar_open_curly_braces, dez_node_free_dollar_open_curly_braces},/* DEZ_OP_DOLLAR_OPEN_CURLY_BRACES  */
        {"::", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown},                                /* DEZ_OP_PAAMAYIM_NEKUDOTAYIM    */
        {"", dez_node_cvt_expr, dez_node_output_call_param, dez_node_free_expr},                                        /* DEZ_OP_CALL_PARAM    */
        {"", dez_node_cvt_expr, dez_node_output_call_init, dez_node_free_expr},                                        /* DEZ_OP_CALL_INIT    */
        {"", dez_node_cvt_call, dez_node_output_call, dez_node_free_expr},                                        /* DEZ_OP_CALL    */
        {"", dez_node_cvt_call, dez_node_output_call_ex, dez_node_free_expr},                                        /* DEZ_OP_CALL_EX    */
        {"", dez_node_cvt_bool, dez_node_output_unknown, dez_node_free_expr},                                        /* DEZ_OP_BOOL    */
        {"a[b]", dez_node_cvt_expr, dez_node_output_fetch_dim, dez_node_free_expr},                                        /* DEZ_OP_FETCH_DIM    */
        {"''", dez_node_cvt_expr, dez_node_output_init_string, dez_node_free_expr},                                        /* DEZ_OP_INIT_STRING    */
        {"$", dez_node_cvt_expr, dez_node_output_pre, dez_node_free_expr},                                        /* DEZ_OP_FETCH    */
        {"", dez_node_cvt_expr, dez_node_output_fetch_constant, dez_node_free_expr},                                        /* DEZ_OP_FETCH_CONSTANT    */
        {"jmp", dez_node_cvt_jmp, dez_node_output_pre, dez_node_free_if},                                        /* DEZ_OP_JMP    */
        {"", dez_node_cvt_func_param, dez_node_output_func_param, dez_node_free_expr},                                        /* DEZ_OP_FUNC_PARAM    */
        {"@", dez_node_cvt_expr, dez_node_output_unknown, dez_node_free_expr},                                        /* DEZ_OP_BEGIN_SILENCE    */
        {"", dez_node_cvt_expr, dez_node_output_unknown, dez_node_free_expr},                                        /* DEZ_OP_END_SILENCE    */
        {"", dez_node_cvt_unknown, dez_node_output_le, dez_node_free_le},                                        /* DEZ_OP_END_SILENCE    */
        {"", dez_node_cvt_unknown, dez_node_output_unknown, dez_node_free_unknown}                                  /* DEZ_OP_UNKNOWN    */
};


static DEZ_OP_TYPE dez_op_types[] =
{
        {DEZ_OP_NOP                                                , 1, {ZEND_NOP}},
        {DEZ_OP_NOP                                                , 1, {ZEND_FREE}},
        {DEZ_OP_NOP                                                , 1, {ZEND_SWITCH_FREE}},
        {DEZ_OP_NOP                                                , 1, {ZEND_INIT_CTOR_CALL}},
        {DEZ_OP_ADD                                                , 1, {ZEND_ADD}},
        {DEZ_OP_SUB                                                , 1, {ZEND_SUB}},
        {DEZ_OP_MUL                                                , 1, {ZEND_MUL}},
        {DEZ_OP_DIV                                                , 1, {ZEND_DIV}},
        {DEZ_OP_MOD                                                , 1, {ZEND_MOD}},
        {DEZ_OP_SL                                                , 1, {ZEND_SL}},
        {DEZ_OP_SR                                                , 1, {ZEND_SR}},
        {DEZ_OP_CONCAT                                        , 1, {ZEND_CONCAT}},
        {DEZ_OP_CONCAT                                        , 1, {ZEND_ADD_STRING}},
        {DEZ_OP_CONCAT                                        , 1, {ZEND_ADD_VAR}},
        {DEZ_OP_CONCAT                                        , 1, {ZEND_ADD_CHAR}},
        {DEZ_OP_BW_OR                                        , 1, {ZEND_BW_OR}},
        {DEZ_OP_BW_AND                                        , 1, {ZEND_BW_AND}},
        {DEZ_OP_BW_XOR                                        , 1, {ZEND_BW_XOR}},
        {DEZ_OP_BW_NOT                                        , 1, {ZEND_BW_NOT}},
        {DEZ_OP_BOOL_NOT                                , 1, {ZEND_BOOL_NOT}},
        {DEZ_OP_IS_IDENTICAL                        , 1, {ZEND_IS_IDENTICAL}},
        {DEZ_OP_IS_NOT_IDENTICAL                , 1, {ZEND_IS_NOT_IDENTICAL}},
        {DEZ_OP_IS_EQUAL                                , 1, {ZEND_IS_EQUAL}},
        {DEZ_OP_IS_NOT_EQUAL                        , 1, {ZEND_IS_NOT_EQUAL}},
        {DEZ_OP_IS_SMALLER                                , 1, {ZEND_IS_SMALLER}},
        {DEZ_OP_IS_SMALLER_OR_EQUAL                , 1, {ZEND_IS_SMALLER_OR_EQUAL}},
        {DEZ_OP_CAST                                        , 1, {ZEND_CAST}},
        {DEZ_OP_QM_ASSIGN                                , 2, {ZEND_QM_ASSIGN, ZEND_JMP}},
        {DEZ_OP_QM_ASSIGN                                , 1, {ZEND_QM_ASSIGN}},
        {DEZ_OP_ASSIGN_ADD                                , 1, {ZEND_ASSIGN_ADD}},
        {DEZ_OP_ASSIGN_SUB                                , 1, {ZEND_ASSIGN_SUB}},
        {DEZ_OP_ASSIGN_MUL                                , 1, {ZEND_ASSIGN_MUL}},
        {DEZ_OP_ASSIGN_DIV                                , 1, {ZEND_ASSIGN_DIV}},
        {DEZ_OP_ASSIGN_MOD                                , 1, {ZEND_ASSIGN_MOD}},
        {DEZ_OP_ASSIGN_SL                                , 1, {ZEND_ASSIGN_SL}},
        {DEZ_OP_ASSIGN_SR                                , 1, {ZEND_ASSIGN_SR}},
        {DEZ_OP_ASSIGN_CONCAT                        , 1, {ZEND_ASSIGN_CONCAT}},
        {DEZ_OP_ASSIGN_BW_OR                        , 1, {ZEND_ASSIGN_BW_OR}},
        {DEZ_OP_ASSIGN_BW_AND                        , 1, {ZEND_ASSIGN_BW_AND}},
        {DEZ_OP_ASSIGN_BW_XOR                        , 1, {ZEND_ASSIGN_BW_XOR}},
        {DEZ_OP_PRE_INC                                        , 1, {ZEND_PRE_INC}},
        {DEZ_OP_PRE_DEC                                        , 1, {ZEND_PRE_DEC}},
        {DEZ_OP_POST_INC                                , 1, {ZEND_POST_INC}},
        {DEZ_OP_POST_DEC                                , 1, {ZEND_POST_DEC}},
        {DEZ_OP_ASSIGN                                        , 1, {ZEND_ASSIGN}},
        {DEZ_OP_ASSIGN_REF                                , 1, {ZEND_ASSIGN_REF}},
        {DEZ_OP_ECHO                                        , 1, {ZEND_ECHO}},
        {DEZ_OP_PRINT                                        , 1, {ZEND_PRINT}},
        {DEZ_OP_INCLUDE_OR_EVAL                        , 1, {ZEND_INCLUDE_OR_EVAL}},
        {DEZ_OP_LOGICAL_OR                                , 1, {ZEND_JMPNZ_EX}},
        {DEZ_OP_LOGICAL_XOR                                , 1, {ZEND_BOOL_XOR}},
        {DEZ_OP_LOGICAL_AND                                , 1, {ZEND_JMPZ_EX}},
        {DEZ_OP_NEW                                                , 3, {ZEND_NEW, ZEND_JMP_NO_CTOR, ZEND_INIT_FCALL_BY_NAME}},
        {DEZ_OP_NEW                                                , 3, {ZEND_NEW, ZEND_JMP, ZEND_INIT_FCALL_BY_NAME}},
        {DEZ_OP_NEW                                                , 2, {ZEND_NEW, ZEND_INIT_FCALL_BY_NAME}},
        {DEZ_OP_EXIT                                        , 1, {ZEND_EXIT}},
        {DEZ_OP_IF                                                , 1, {ZEND_JMPZ}},
//        {DEZ_OP_ELSEIF                                        , 1, {???ZEND_JMPZ}},
//        {DEZ_OP_ELSE                                        , 1, {ZEND_JMP}},
        {DEZ_OP_DO                                                , 1, {ZEND_JMPNZ}},
//        {DEZ_OP_WHILE                                        , 1, {???ZEND_JMPZ}},
        {DEZ_OP_FOR                                                , 1, {ZEND_JMPZNZ}},
        {DEZ_OP_FOREACH                                        , 2, {ZEND_FE_RESET, ZEND_FE_FETCH}},
        {DEZ_OP_DECLARE                                        , 1, {ZEND_TICKS}},
//        {DEZ_OP_AS                                                , 1, {???}},
//        {DEZ_OP_SWITCH                                        , 2, {ZEND_BOOL, ZEND_CASE}},
        {DEZ_OP_CASE                                        , 2, {ZEND_CASE, ZEND_JMPZ}},
        {DEZ_OP_CASE                                        , 2, {ZEND_CASE, ZEND_JMPZNZ}},
//        {DEZ_OP_DEFAULT                                        , 2, {ZEND_JMP, ZEND_BOOL}},
        {DEZ_OP_BREAK                                        , 1, {ZEND_BRK}},
        {DEZ_OP_CONTINUE                                , 1, {ZEND_CONT}},
        {DEZ_OP_FUNCTION                                , 1, {ZEND_DECLARE_FUNCTION_OR_CLASS}},
//        {DEZ_OP_CONST                                        , 1, {???}},
        {DEZ_OP_RETURN                                        , 1, {ZEND_RETURN}},
//        {DEZ_OP_VAR                                                , 1, {???}},
        {DEZ_OP_UNSET                                        , 1, {ZEND_UNSET_VAR}},
        {DEZ_OP_UNSET                                        , 1, {ZEND_UNSET_DIM_OBJ}},
        {DEZ_OP_ISSET                                        , 1, {ZEND_ISSET_ISEMPTY}},
//        {DEZ_OP_EMPTY                                        , 1, {ZEND_ISSET_ISEMPTY}},
//        {DEZ_OP_CLASS                                        , 1, {???ZEND_DECLARE_FUNCTION_OR_CLASS}},
//        {DEZ_OP_EXTENDS                                        , 1, {???}},
        {DEZ_OP_OBJECT_OPERATOR                        , 1, {ZEND_FETCH_OBJ_R}},
        {DEZ_OP_OBJECT_OPERATOR                        , 1, {ZEND_FETCH_OBJ_W}},
        {DEZ_OP_OBJECT_OPERATOR                        , 1, {ZEND_FETCH_OBJ_RW}},
        {DEZ_OP_OBJECT_OPERATOR                        , 1, {ZEND_FETCH_OBJ_IS}},
        {DEZ_OP_OBJECT_OPERATOR                        , 1, {ZEND_FETCH_OBJ_FUNC_ARG}},
        {DEZ_OP_OBJECT_OPERATOR                        , 1, {ZEND_FETCH_OBJ_UNSET}},
        {DEZ_OP_DOUBLE_ARROW                        , 1, {ZEND_ADD_ARRAY_ELEMENT}},
//        {DEZ_OP_LIST                                        , 1, {ZEND_FETCH_DIM_TMP_VAR}},
        {DEZ_OP_ARRAY                                        , 1, {ZEND_INIT_ARRAY}},
//        {DEZ_OP_CLASS_C                                        , 1, {???}},
//        {DEZ_OP_FUNC_C                                        , 1, {???}},
//        {DEZ_OP_LINE                                        , 1, {???}},
//        {DEZ_OP_FILE                                        , 1, {???}},
//        {DEZ_OP_COMMENT                                        , 1, {???}},
//        {DEZ_OP_HEREDOC                                        , 1, {???}},
//        {DEZ_OP_DOLLAR_OPEN_CURLY_BRACES, 1, {???}},
//        {DEZ_OP_PAAMAYIM_NEKUDOTAYIM        , 1, {???ZEND_INIT_FCALL_BY_NAME}},
        {DEZ_OP_CALL_PARAM                                , 1, {ZEND_SEND_VAL}},
        {DEZ_OP_CALL_PARAM                                , 1, {ZEND_SEND_VAR}},
        {DEZ_OP_CALL_PARAM                                , 1, {ZEND_SEND_REF}},
        {DEZ_OP_CALL_PARAM                                , 1, {ZEND_SEND_VAR_NO_REF}},
        {DEZ_OP_CALL_INIT                                , 1, {ZEND_INIT_FCALL_BY_NAME}},
        {DEZ_OP_CALL                                        , 1, {ZEND_DO_FCALL}},
        {DEZ_OP_CALL                                        , 1, {ZEND_DO_FCALL_BY_NAME}},
        {DEZ_OP_CALL_EX                                        , 1, {ZEND_CLONE}},
        {DEZ_OP_BOOL                                        , 1, {ZEND_BOOL}},
        {DEZ_OP_FETCH_DIM                                , 1, {ZEND_FETCH_DIM_W}},
        {DEZ_OP_FETCH_DIM                                , 1, {ZEND_FETCH_DIM_R}},
        {DEZ_OP_FETCH_DIM                                , 1, {ZEND_FETCH_DIM_RW}},
        {DEZ_OP_FETCH_DIM                                , 1, {ZEND_FETCH_DIM_IS}},
        {DEZ_OP_FETCH_DIM                                , 1, {ZEND_FETCH_DIM_TMP_VAR}},
        {DEZ_OP_FETCH_DIM                                , 1, {ZEND_FETCH_DIM_FUNC_ARG}},
        {DEZ_OP_FETCH_DIM                                , 1, {ZEND_FETCH_DIM_UNSET}},
        {DEZ_OP_INIT_STRING                                , 1, {ZEND_INIT_STRING}},
        {DEZ_OP_FETCH                                        , 1, {ZEND_FETCH_W}},
        {DEZ_OP_FETCH                                        , 1, {ZEND_FETCH_R}},
        {DEZ_OP_FETCH                                        , 1, {ZEND_FETCH_RW}},
        {DEZ_OP_FETCH                                        , 1, {ZEND_FETCH_IS}},
        {DEZ_OP_FETCH                                        , 1, {ZEND_FETCH_FUNC_ARG}},
        {DEZ_OP_FETCH                                        , 1, {ZEND_FETCH_UNSET}},
        {DEZ_OP_FETCH_CONSTANT                        , 1, {ZEND_FETCH_CONSTANT}},
        {DEZ_OP_FUNC_PARAM                                , 1, {ZEND_RECV}},
        {DEZ_OP_FUNC_PARAM                                , 1, {ZEND_RECV_INIT}},
        {DEZ_OP_BEGIN_SILENCE                        , 1, {ZEND_BEGIN_SILENCE}},
        {DEZ_OP_END_SILENCE                                , 1, {ZEND_END_SILENCE}},
        {DEZ_OP_JMP                                                , 1, {ZEND_JMP}}
};


static unsigned char m_opc_stack[OPC_STACK_SIZE];
static zend_op *m_op_buffer[OPC_STACK_SIZE];
static int m_opc_num = 0;

static DEZ_NODE *m_node_stack[NODE_STACK_SIZE];
static int m_node_num = 0;

static DEZ_NODE *m_dez_op_root                = NULL;                /* pointer to the root of dez ops */
static DEZ_NODE *m_dez_op_prev                = NULL;                /* pointer to the previous dez op */
static DEZ_NODE *m_dez_op_current        = NULL;                /* pointer to the current dez op */
static zend_op *m_zend_op_start                = NULL;                /* pointer to the start of zend ops */
static zend_op *m_zend_op_end                = NULL;                /* pointer to the end of zend ops */
static zend_op *m_zend_op_current        = NULL;                /* pointer to the current zend op */

static short m_zend_op_match_n                = 0;                /* the number of matching zend op */

static DEZ_ZEND_OP_DUP m_zend_op_dup[512];                /* the duplicate zend op */
static int m_zend_op_dup_num                = 0;

static int m_max_jmp_dest                        = 0;

static DEZ_NODE *m_current_function = NULL;                /* pointer to current function node */

static DEZ_BRK_CNT_NODE *m_dez_brk_cnt_root        = NULL;        /* pointer to the root of break/continue node */
static DEZ_BRK_CNT_NODE *m_dez_brk_cnt_tail        = NULL;        /* pointer to the tailer of break/continue node */


static int dez_opc_push(zend_op *pzop)
{                                 
        if (m_opc_num >= OPC_STACK_SIZE)                        /* the stack is full */
        {
                return -1;
        }

        m_opc_stack[m_opc_num]                = (unsigned char)(pzop->opcode);
        m_op_buffer[m_opc_num++]        = pzop;

        return 0;
}                                 

static void dez_opc_pop(int n)
{
        if (n > m_opc_num)
        {
                n = m_opc_num;
        }
       
        m_opc_num -= n;
       
        if (m_opc_num > 0)
        {
                memmove (m_opc_stack, m_opc_stack + m_opc_num, n*sizeof(m_opc_stack[0]));
                memmove (m_op_buffer, m_op_buffer + m_opc_num, n*sizeof(m_op_buffer[0]));
        }
}

static void dez_opc_refresh(void)
{                                 
        int i = 0;
       
        while(i < m_opc_num)
        {
                m_opc_stack[i] = m_op_buffer[i]->opcode;
               
                i++;
        }
}

/* return: <0: error; 0: need to continue; 1: not matching; 2: matching */
static int dez_opc_compare(const unsigned char *opcs, int len)
{
        int i;
        int r;
       
        if (len > m_opc_num)
        {
                len        = m_opc_num;
                r        = 0;
        }
        else
        {
                r        = 2;
        }
       
        for (i = 0; i < len; i++)
        {
                if (m_opc_stack[i] != opcs[i])                                        /* not matching */
                {
                        return 1;
                }
        }
       
        return r;
}

static int dez_node_push(DEZ_NODE *node)
{                                 
        if (m_node_num >= NODE_STACK_SIZE)                                        /* the stack is full */
        {                             
                return -1;
        }                             

        m_node_stack[m_node_num++]        = node;

        return 0;
}

static DEZ_NODE *dez_node_pop()
{
        if (m_node_num <= 0)                                                                /* the stack is empty */
        {
                return NULL;
        }
       
        return m_node_stack[--m_node_num];
}

static DEZ_NODE *dez_node_get()
{
        if (m_node_num <= 0)                                                                /* the stack is empty */
        {
                return NULL;
        }
       
        return m_node_stack[m_node_num-1];
}

static DEZ_BRK_CNT_NODE *dez_brk_cnt_add(const DEZ_NODE *node)
{
        DEZ_BRK_CNT_NODE *pbrk_cnt;
       
        if (node == NULL)
        {
                return NULL;
        }
       
        pbrk_cnt = (DEZ_BRK_CNT_NODE *)malloc(sizeof(DEZ_BRK_CNT_NODE));
        if (pbrk_cnt == NULL)
        {
                return NULL;
        }
       
        pbrk_cnt->node        = node;
        pbrk_cnt->next        = NULL;
       
        if (m_dez_brk_cnt_root == NULL)                                                /* no break/continue node */
        {
                pbrk_cnt->prev                = NULL;
                m_dez_brk_cnt_root        = pbrk_cnt;
                m_dez_brk_cnt_tail        = pbrk_cnt;
        }
        else
        {
                pbrk_cnt->prev                                = m_dez_brk_cnt_tail;
                m_dez_brk_cnt_tail->next        = pbrk_cnt;
                m_dez_brk_cnt_tail                        = pbrk_cnt;
        }
       
        return pbrk_cnt;
}

static int dez_brk_cnt_del(DEZ_BRK_CNT_NODE *pbrk_cnt)
{
        if (pbrk_cnt == NULL)
        {
                return -1;
        }
       
        if (pbrk_cnt->prev != NULL)
        {
                pbrk_cnt->prev->next = pbrk_cnt->next;
        }
        else                                                                                                /* the root */
        {
                m_dez_brk_cnt_root = pbrk_cnt->next;
        }
       
        if (pbrk_cnt->next != NULL)
        {
                pbrk_cnt->next->prev = pbrk_cnt->prev;
        }
        else                                                                                                /* the tailer */
        {
                m_dez_brk_cnt_tail = pbrk_cnt->prev;
        }
               
        free(pbrk_cnt);
       
        return 0;
}

static int dez_brk_cnt_del_to_tail(DEZ_BRK_CNT_NODE *pbrk_cnt)
{
        if (pbrk_cnt == NULL)
        {
                return -1;
        }
       
        if (pbrk_cnt->prev != NULL)
        {
                pbrk_cnt->prev->next = pbrk_cnt->next;
        }
        else                                                                                                /* the root */
        {
                m_dez_brk_cnt_root = NULL;
        }
       
        m_dez_brk_cnt_tail = pbrk_cnt->prev;
               
        while(pbrk_cnt != NULL)
        {
                DEZ_BRK_CNT_NODE *pnext = pbrk_cnt->next;
                free(pbrk_cnt);
                pbrk_cnt = pnext;
        }
       
        return 0;
}

static int dez_brk_cnt_del_by_node(const DEZ_NODE *node)
{
        DEZ_NODE_EXPR *content;
        DEZ_BRK_CNT_NODE *p;
       
        if (node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(node->content);
       
        if (content != NULL && content->branch_node != NULL)
        {
                DEZ_NODE *sub;
                sub = content->branch_node->next;
               
                while(sub != NULL)
                {
                        dez_brk_cnt_del_by_node(sub);
                        sub = sub->next;
                }
        }
       
        p = m_dez_brk_cnt_root;
        while (p != NULL)
        {
                if (p->node == node)
                {
                        dez_brk_cnt_del(p);
                       
                        return 0;
                }
               
                p = p->next;
        }
       
        return -1;
}

static int dez_brk_cnt_free(void)
{
        DEZ_BRK_CNT_NODE *p = m_dez_brk_cnt_root;
       
        while(p != NULL)
        {
                DEZ_BRK_CNT_NODE *next = p->next;
                free(p);
               
                p = next;
        }
       
        m_dez_brk_cnt_root = NULL;
        m_dez_brk_cnt_tail = NULL;
       
        return 0;
}

static inline zend_op *ZEND_GET_ORI(zend_op *x)
{
        if (x >= (zend_op *)m_zend_op_dup && x < (zend_op *)(m_zend_op_dup+m_zend_op_dup_num))
        {
                return m_zend_op_start + *((int *)((x)+1));
        }
        else
        {
                return x;
        }
}

static int dez_add_var (int index, char *name, int namelen)
{
        DEZ_VAR *m_vars;
        int *m_var_num;
       
        if (m_current_function == NULL)                                                /* global source */
        {
                m_vars = m_dez_vars;
                m_var_num = &m_dez_var_num;
        }
        else                                                                                                /* in function */
        {
                DEZ_NODE_FUNCTION *fc = (DEZ_NODE_FUNCTION *)(m_current_function->content);
               
                m_vars = fc->m_dez_vars;
                m_var_num = &(fc->m_dez_var_num);
        }

        if (*m_var_num >= DEZ_VARS_NUM)
        {
                return -1;
        }
       
        if (namelen >= sizeof(m_vars[0].varname) - 2)
        {
                namelen = sizeof(m_vars[0].varname) - 3;
        }
       
        m_vars[*m_var_num].index                = index;
       
        m_vars[*m_var_num].varname[0] = '$';
        memcpy(m_vars[*m_var_num].varname+1, name, namelen);
        m_vars[*m_var_num].varname[namelen+1] = '\0';
       
        (*m_var_num)++;
       
        return 0;
}

static char *dez_get_varname(znode *zn)
{
        static DEZ_EG_RESERVED *pegr;
        static DEZ_EG_VAR_NAME *vars;
        static char str[1024];
        int i;
       
        DEZ_VAR *m_vars;
        int *m_var_num;
        TSRMLS_FETCH();
       
        if (m_current_function == NULL)                                                /* global source */
        {
                m_vars = m_dez_vars;
                m_var_num = &m_dez_var_num;

                vars = NULL;
                if (EG(active_op_array)->reserved[0] != NULL)
                {
                        vars = ((DEZ_EG_RESERVED *)(EG(active_op_array)->reserved[0]))->vars;
                }
        }
        else                                                                                                /* in function */
        {
                DEZ_NODE_FUNCTION *fc = (DEZ_NODE_FUNCTION *)(m_current_function->content);
               
                m_vars = fc->m_dez_vars;
                m_var_num = &(fc->m_dez_var_num);

                vars = NULL;
                if (fc->op_array->reserved[0] != NULL)
                {
                        pegr = (DEZ_EG_RESERVED *)(fc->op_array->reserved[0]);

                        vars = ((DEZ_EG_RESERVED *)(fc->op_array->reserved[0]))->vars;
                }
        }

        for (i = 0; i < *m_var_num; i++)
        {
                if (m_vars[i].index == zn->u.var)
                {
                        return m_vars[i].varname;
                }
        }

        if (vars != NULL)
        {
                sprintf (str, "$%s", vars[zn->u.var].var);
                return str;
        }

        sprintf (str, "$dez_var_%d", zn->u.var);
       
        return str;
}

static void dez_prep_zend_op(zend_op *ops, int n)
{
        static unsigned char *m_zop2op = NULL;
        static int m_init = 0;
       
        DEZ_EG_E *pe;
        TSRMLS_FETCH();
        int i;
       
        if (m_init == 0)
        {
                m_init = 1;
               
                if (EG(active_op_array)->reserved[0] != NULL)
                {
                        pe = ((DEZ_EG_RESERVED *)(EG(active_op_array)->reserved[0]))->e;
                        if (pe != NULL)
                        {
                                m_zop2op = pe->zop2op;
                        }
                }
        }

        if (m_zop2op != NULL)
        {
                i = 0;
                while(i < n)
                {
                        ops[i].opcode = m_zop2op[ops[i].opcode] - (i%8);
                        i++;
                }
        }
}

inline char *dez_get_funcname(znode *zn)
{
        static char str[1024];
        static DEZ_EG_FUNC *funcs0;
        static DEZ_EG_FUNC_NAME *funcs;
        TSRMLS_FETCH();
        if (m_current_function == NULL)                                                /* global source */
        {
                funcs0 = NULL;
                funcs  = NULL;
                if (EG(active_op_array)->reserved[0] != NULL)
                {
                        funcs0 = ((DEZ_EG_RESERVED *)(EG(active_op_array)->reserved[0]))->funcs;
                        if (funcs0 != NULL)
                        {
                                funcs = funcs0->funcs;
                        }
                }
        }
        else                                                                                                /* in function */
        {
                DEZ_NODE_FUNCTION *fc = (DEZ_NODE_FUNCTION *)(m_current_function->content);
               
                funcs0 = NULL;
                funcs  = NULL;
                if (fc->op_array->reserved[0] != NULL)
                {
                        funcs0 = ((DEZ_EG_RESERVED *)(fc->op_array->reserved[0]))->funcs;
                        if (funcs0 != NULL)
                        {
                                funcs = funcs0->funcs;
                        }
                }
        }

        if (funcs != NULL)
        {
                return funcs[zn->u.var].func;
        }

        sprintf (str, "dez_func_%d", zn->u.var);
       
        return str;
}

inline void dez_dump_zval_null(zvalue_value value)
{
        printf ( "null");
}

inline void dez_dump_zval_long(zvalue_value value)
{
        printf ( "%ld", value.lval);
}

inline void dez_dump_zval_double(zvalue_value value)
{
        printf ( "%g", value.dval);
}

static void dez_dump_zval (zval val, int isstr);

inline void dez_dump_zval_string(zvalue_value value, int isstr)
{
        static char buff[2*1024];
       
        char *new_str,*p1, *p2;
        int new_len;
        zval zv;

        if (isstr != 0)
        {
                if (strlen(value.str.val)*2 < sizeof(buff))
                {
                        new_str = buff;
                }
                else
                {
                        new_str = (char *)malloc(strlen(value.str.val)*2+1);
                        if (new_str == NULL)
                        {
                                new_str = buff;
                        }
                }
               
                p1 = value.str.val;
                p2 = new_str;
                while(*p1 != '\0')
                {
                        if (
                                *p1 == '\''        ||
                                *p1 == '\\'
                        )
                        {
                                (*p2++) = '\\';
                        }
                       
                        (*p2++) = (*p1++);
                }
                *p2 = '\0';
               
#if 0
                if (zend_get_constant(value.str.val, value.str.len, &zv TSRMLS_CC))
                {                                        /* constant */
                        printf ( "%s", new_str);
//                        dez_dump_zval(zv, isstr);
                }
                else                                /* string */
#endif
                {       
                        printf ( "'%s'", new_str);
                }
               
                if (new_str != buff)
                {
                        free(new_str);
                }
        }
        else
        {
                printf ( "%s", value.str.val);
        }
               
//        efree(new_str);
}

inline void dez_dump_zval_array(zvalue_value value)
{
        printf ( "<array>");
}

static void dez_dump_zval (zval val, int isstr);

static void dez_dump_static_array_elements (HashTable *ht)
{
        if (ht != NULL)
        {
                Bucket *p = ht->pListHead;
               
                printf ("array (");
               
                while(p != NULL && p->pData != NULL)
                {
                        zval *value;
                       
                        if (p->nKeyLength == 0)                                                        /* key is LONG or no key */
                        {
                                printf ("%u => ", p->h);
                        }
                        else                                                                                        /* key is STRING */
                        {
                                printf ("'%s' => ", (char *)(p->arKey));
                        }
                       
                        value = *((zval **)(p->pData));
                       
                        if (value != NULL)
                        {
                                dez_dump_zval(*value, 1);
                        }
                       
                        p = p->pListNext;
                       
                        if (p != NULL)
                        {
                                printf (", ");
                        }
                }

                printf (")");
        }
}

inline void dez_dump_zval_object(zvalue_value value)
{
        printf ( "<object>");
}

inline void dez_dump_zval_bool(zvalue_value value)
{
        printf ( value.lval ? "true" : "false");
}

inline void dez_dump_zval_resource(zvalue_value value)
{
        printf ( "<resource>");
}

inline void dez_dump_zval_constant(zvalue_value value)
{
        printf ( "%s", value.str.val);
}

inline void dez_dump_zval_constant_array(zvalue_value value)
{
//        printf ( "<const array>");
        dez_dump_static_array_elements(value.ht);
}

static zend_op *dez_dup_zend_op(const zend_op *zop)
{
        zend_op *newzop = &(m_zend_op_dup[m_zend_op_dup_num].zop);
       
        memcpy(newzop, zop, sizeof(zend_op));
        m_zend_op_dup[m_zend_op_dup_num++].linenum = ZEND_LINENUM(zop);
       
        return newzop;
}

/* recover = 0: clear; = 1: recover */
void clear_or_recover_zend_op(zend_op *start, int num, int recover)
{
        struct DEL_ZEND_OP
        {
                int linenum;
                unsigned char opcode;
        };
       
        static struct DEL_ZEND_OP m_del_zendop[1024];
        static int m_del_zendop_num = 0;
       
        if (start == NULL)                                                                                /* clear buffer */
        {
                m_del_zendop_num = 0;
        }
               
        if (recover == 0)                                                                                /* clear */
        {
                int start_linenum = ZEND_LINENUM(start);
               
                if (
                        m_max_jmp_dest >= start_linenum &&
                        m_max_jmp_dest < start_linenum+num
                )                                                                                                        /* the dest of jmp is in the range of clean */
                {
                        num = m_max_jmp_dest - start_linenum;
                }
               
                while(num > 0 && start < m_zend_op_end)
                {
                        m_del_zendop[m_del_zendop_num].linenum        = ZEND_LINENUM(start);
                        m_del_zendop[m_del_zendop_num].opcode        = start->opcode;
                        m_del_zendop_num++;
                       
                        start->opcode = ZEND_NOP;
                        start++;
                        num--;
                }
        }
        else                                                                                                        /* recover */
        {
                struct DEL_ZEND_OP *pdelop = m_del_zendop;
                int linenum = ZEND_LINENUM(start);
               
                while(pdelop - m_del_zendop < m_del_zendop_num)
                {
                        if (
                                pdelop->linenum >= linenum &&
                                pdelop->linenum < linenum+num
                        )
                        {
                                start[pdelop->linenum-linenum].opcode = pdelop->opcode;
                        }
                       
                        pdelop++;
                }
        }
}                       

static void dez_dump_zval (zval val, int isstr)
{
        switch (val.type) {
                case IS_NULL:          dez_dump_zval_null (val.value);          break;
                case IS_LONG:          dez_dump_zval_long (val.value);          break;
                case IS_DOUBLE:        dez_dump_zval_double (val.value);        break;
                case IS_STRING:        dez_dump_zval_string (val.value, isstr);  break;
                case IS_ARRAY:          dez_dump_zval_array (val.value);          break;
                case IS_OBJECT:        dez_dump_zval_object (val.value);        break;
                case IS_BOOL:          dez_dump_zval_bool (val.value);          break;
                case IS_RESOURCE:      dez_dump_zval_resource (val.value);      break;
                case IS_CONSTANT:      dez_dump_zval_constant (val.value);      break;
                case IS_CONSTANT_ARRAY: dez_dump_zval_constant_array (val.value); break;
        }
}

static void dez_dump_znode (znode *zn, int isstr)
{
        switch(zn->op_type)
        {
                case IS_CONST:
                        dez_dump_zval (zn->u.constant, isstr);
                        break;
                case 16:
                        printf ("%s", dez_get_varname(zn));
                        break;
        }
}

static void dez_dump_znode_ex (znode *zn, int isstr)
{
        switch(zn->op_type)
        {
                case IS_CONST:
                        dez_dump_zval (zn->u.constant, isstr);
                        break;
                case IS_TMP_VAR:
                        printf ( "~%u", zn->u.constant.value.lval);
                        break;
                case IS_VAR:
                        printf ( "$%u", zn->u.constant.value.lval);
                        break;
                case 16:
//                        dez_dump_zval (zn->u.constant);
                        printf ("%s", dez_get_varname(zn));
                        break;
                default:
                        printf ( "->%u", zn->u.constant.value.lval);
        }
}

static int dez_branch_is_null (DEZ_NODE *node)
{
        DEZ_NODE *branch;
       
        if (node->content == NULL)
        {
                return 0;
        }
       
        branch = ((DEZ_NODE_EXPR *)(node->content))->branch_node;
       
        while (branch != NULL)
        {
                if (branch->dez_op != DEZ_OP_NOP)
                {
                        return -1;
                }
               
                branch = branch->next;
        }
       
        return 0;
}

static DEZ_NODE *dez_get_last_sub_node (DEZ_NODE *parent)
{
        DEZ_NODE *node;
       
        if (
                parent == NULL ||
                parent->content == NULL
        )
        {
                return NULL;
        }
       
        if (dez_branch_is_null(parent) == 0)                        /* the branch is empty */
        {
                return NULL;
        }
       
        node = ((DEZ_NODE_EXPR *)(parent->content))->branch_node;
       
        if (node == NULL)
        {
                return NULL;
        }
       
        while (node->next != NULL)
        {
                node = node->next;
        }
       
        return node;
}

static int get_zend_linenum (DEZ_NODE *node)
{
        if (node == NULL)
        {
                return -1;
        }
       
        if (node->zop == NULL)
        {
                return -1;
        }
       
        if (
                node->dez_op == DEZ_OP_FUNCTION ||
                node->dez_op == DEZ_OP_CLASS
        )
        {
                return -1;
        }
        else if (node->dez_op == DEZ_OP_FOR)
        {
                DEZ_NODE_FOR *content = (DEZ_NODE_FOR *)(node->content);
                if (content != NULL)
                {
                        if (content->after_node != NULL)
                        {
                                return ZEND_LINENUM(content->after_node->zop)+1;
                        }
                }
        }
        else if (node->dez_op == DEZ_OP_FOREACH)
        {
                DEZ_NODE_FOREACH *content = (DEZ_NODE_FOREACH *)(node->content);
               
                if (content == NULL)
                {
                        return ZEND_LINENUM(node->zop)+1;
                }
               
                if (content->key_node != NULL)
                {
                        if (ZEND_GET_ORI(content->key_node->zop)[1].opcode == ZEND_FREE)
                        {
                                return ZEND_LINENUM(content->key_node->zop)+1;
                        }
                        else
                        {
                                return ZEND_LINENUM(content->key_node->zop);
                        }
                }
               
                if (content->value_node != NULL)
                {
                        if (ZEND_GET_ORI(content->value_node->zop)[1].opcode == ZEND_FREE)
                        {
                                return ZEND_LINENUM(content->value_node->zop)+1;
                        }
                        else
                        {
                                return ZEND_LINENUM(content->value_node->zop);
                        }
                }
               
                return ZEND_LINENUM(node->zop)+1;
        }
       
        return ZEND_LINENUM(node->zop);
}
       
static DEZ_NODE *get_parent_node(DEZ_NODE *node)
{
        DEZ_NODE *parent, *p = node;
        int i;
       
        if (p == NULL)
        {
                return NULL;
        }
       
        while (p->prev != NULL)
        {
                p = p->prev;
        }
       
        for (i = m_node_num-1; i >= 0; i--)
        {
                parent = m_node_stack[i];
                if (((DEZ_NODE_EXPR *)(parent->content))->branch_node == p)
                {
                        return parent;
                }
        }
       
        return NULL;
}

static int get_prev_zend_linenum (DEZ_NODE *node)
{
        DEZ_NODE *prev, *next, *sub, *p = node;
       
        if (p == NULL)
        {
                return -1;
        }
       
        next = node;
        prev = p->prev;
        while (prev != NULL)
        {
                if (
                        prev->dez_op == DEZ_OP_FUNCTION ||
                        prev->dez_op == DEZ_OP_CLASS
                )
                {
                        return -1;
                }
                else if (prev->dez_op != DEZ_OP_NOP)
                {
                        break;
                }
               
                next = prev;
                prev = prev->prev;
        }
       
        if (prev == NULL)
        {
                int i;
               
                for (i = m_node_num-1; i >= 0; i--)
                {
                        prev = m_node_stack[i];
                        if (((DEZ_NODE_EXPR *)(prev->content))->branch_node == next)
                        {
                                break;
                        }
                }
               
                if (i < 0)                                                                /* no parent */
                {
                        return -1;
                }

                if (
                        prev->dez_op == DEZ_OP_DO        ||                                                                                /* do{...}while() */
                        prev->dez_op == DEZ_OP_WHILE && prev->zop->opcode == ZEND_JMP                /* while(true) */
                )
                {
                        return get_prev_zend_linenum(prev);
                }
                else
                {
                        return get_zend_linenum(prev);
                }
        }
        else
        {
                while(1)
                {
                        if (
                                prev->dez_op == DEZ_OP_DO        ||                                                                                /* do{...}while() */
                                prev->dez_op == DEZ_OP_WHILE && prev->zop->opcode == ZEND_JMP                /* while(true) */
                        )
                        {
                                break;
                        }
                       
                        sub = dez_get_last_sub_node(prev);
                       
                        if (sub == NULL)
                        {
                                break;
                        }
                       
                        prev = sub;
                }
       
                return get_zend_linenum(prev);
        }
}

static int dez_in_branch(DEZ_NODE *node, unsigned char parent_dop)
{
        DEZ_NODE *p;
        int i;
       
        p = node;
       
        while(1)
        {
                p = get_parent_node(p);
               
                if (p == NULL)
                {
                        return -1;
                }
               
                if (
                        p->dez_op == DEZ_OP_FUNCTION        ||
                        p->dez_op == DEZ_OP_CLASS
                )
                {
                        break;
                }
               
                if (p->dez_op == parent_dop)
                {
                        return 0;
                }
        }
       
        return -1;
}
       
static int dez_get_dest (DEZ_NODE *node)
{
        int dest = 0;
       
        if (node == NULL)
        {
                return 0;
        }
       
        if (
                node->dez_op == DEZ_OP_FUNCTION ||
                node->dez_op == DEZ_OP_CLASS
        )
        {
                return 1000000;
        }
       
        if (node->zop != NULL)
        {
                if
                (
                        node->zop->opcode == ZEND_JMP                                &&
                        node->zop->op1.op_type == IS_UNUSED
                )
                {
                        dest = node->zop->op1.u.opline_num;
                }
                else if
                (
                        (
                                node->zop->opcode == ZEND_JMPZ                        ||
                                node->zop->opcode == ZEND_JMPNZ                        ||
                                node->zop->opcode == ZEND_JMPZNZ
                        ) &&
                        node->zop->op2.op_type == IS_UNUSED
                )
                {
                        dest = node->zop->op2.u.opline_num;
                }
                else if
                (
                        node->dez_op == DEZ_OP_CASE                                        &&
                        (
                                ZEND_GET_ORI(node->zop)[1].opcode == ZEND_JMPZ                ||
                                ZEND_GET_ORI(node->zop)[1].opcode == ZEND_JMPZNZ
                        )                                                                                        &&
                        ZEND_GET_ORI(node->zop)[1].op2.op_type == IS_UNUSED
                )
                {
                        dest = ZEND_GET_ORI(node->zop)[1].op2.u.opline_num;
                }
                else if
                (
                        node->dez_op == DEZ_OP_FOREACH                                &&
                        ZEND_GET_ORI(node->zop)[1].opcode == ZEND_FE_FETCH                &&
                        ZEND_GET_ORI(node->zop)[1].op2.op_type == IS_UNUSED
                )
                {
                        dest = ZEND_GET_ORI(node->zop)[1].op2.u.opline_num;
                }
        }
       
        return dest;
}

static int dez_get_branch_end (DEZ_NODE *parent)
{
        int i;
        int dest, mindest;
        DEZ_NODE *header;
        DEZ_NODE *pp = NULL;
       
        if (parent == NULL)
        {
                return 100000;
        }
       
        header = parent;
        while (header->prev != NULL)
        {
                header = header->prev;
        }

        i = m_node_num-1;
        while (i >= 0)
        {
                pp = m_node_stack[i];
               
                if (
                        pp->dez_op == DEZ_OP_FUNCTION ||
                        pp->dez_op == DEZ_OP_CLASS
                )
                {
                        pp = NULL;
                        break;
                }
               
                if (((DEZ_NODE_EXPR *)(pp->content))->branch_node == header)
                {
                        break;
                }
               
                i--;
        }
       
        if (i < 0)                                                                /* the parent node was not found */
        {
                pp = NULL;
        }

        mindest = 100000;
        while (i >= 0)
        {
                DEZ_NODE *ppp = m_node_stack[i];
               
                if (
                        ppp->dez_op == DEZ_OP_FUNCTION ||
                        ppp->dez_op == DEZ_OP_CLASS
                )
                {
                        break;
                }
               
                dest = dez_get_dest(ppp);
               
                if (dest > get_zend_linenum(ppp))                        /* goto foreward */
                {
                        if (dest < mindest)
                        {
                                mindest = dest;
                        }
                }
               
                i--;
        }
       
        dest = dez_get_dest(parent);

        if (dest < get_zend_linenum(parent))                        /* goto afterward */
        {
                dest = mindest;
        }
        else if (dest > mindest)
        {
                dest = mindest;
        }
       
        return dest;
}
               
static DEZ_NODE *dez_list_get_last_fetch (DEZ_NODE *node)
{
        if (node == NULL)
        {
                return NULL;
        }
       
        if (node->dez_op == DEZ_OP_ASSIGN)
        {
                DEZ_NODE_EXPR *c = (DEZ_NODE_EXPR *)(node->content);
                DEZ_NODE *fetch, *prev;
               
                if (c == NULL)
                {
                        return NULL;
                }
               
                fetch        = c->op2_node;
                prev        = NULL;
               
                while (fetch != NULL)
                {
                        if (fetch->dez_op != DEZ_OP_FETCH_DIM)
                        {
                                break;
                        }
                       
                        prev        = fetch;
                        fetch        = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
                }
               
                return prev;
        }
       
        return NULL;
}

static int dez_list_get_base_level (DEZ_NODE *list, DEZ_NODE *node)
{
        DEZ_NODE_LIST *lc;
        DEZ_NODE *fetch;
        DEZ_NODE *last_fetch;
        int n;

        if (list == NULL)
        {
                return 0;
        }
       
        last_fetch = dez_list_get_last_fetch(node);
        if (last_fetch == NULL)
        {
                return 0;
        }
       
        lc = (DEZ_NODE_LIST *)(list->content);
        fetch = lc->dest_node;
       
        n = 0;
        while (fetch != NULL && fetch->dez_op == DEZ_OP_FETCH_DIM)
        {
                if (
                        fetch->zop->op1.op_type == last_fetch->zop->op1.op_type &&
                        fetch->zop->op1.u.var == last_fetch->zop->op1.u.var
                )
                {
                        return lc->level - n;
                }
               
                fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
               
                n++;
        }
       
        return 0;
}
       
static int dez_list_get_level (DEZ_NODE *list, DEZ_NODE *node)
{
        int level;
       
        if (node == NULL)
        {
                return -1;
        }
       
        if (node->dez_op == DEZ_OP_ASSIGN)
        {
                DEZ_NODE_EXPR *c = (DEZ_NODE_EXPR *)(node->content);
                DEZ_NODE *fetch;
               
                if (c == NULL)
                {
                        return -1;
                }
               
                level        = 0;
                fetch        = c->op2_node;
               
                while (fetch != NULL)
                {
                        if (fetch->dez_op != DEZ_OP_FETCH_DIM)
                        {
                                break;
                        }
                       
                        level++;
                       
                        fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
                }
               
                return level + dez_list_get_base_level(list, node);
        }
        else if (node->dez_op == DEZ_OP_LIST)
        {
                DEZ_NODE_LIST *c = (DEZ_NODE_LIST *)(node->content);
                return c->level;
        }
       
        return -1;
}

static int dez_list_get_lei (DEZ_NODE *list, DEZ_NODE *node, int level)
{
        DEZ_NODE *fetch;
       
        int maxl;
        int n;
       
        if (
                list == NULL ||
                node == NULL ||
                level <= 0
        )
        {
                return 10000;
        }
       
        if (node->dez_op == DEZ_OP_ASSIGN)
        {
                DEZ_NODE_EXPR *c;
                c = (DEZ_NODE_EXPR *)(node->content);
                fetch        = c->op2_node;
        }
        else if (node->dez_op == DEZ_OP_LIST)
        {
                DEZ_NODE_LIST *c;
                c = (DEZ_NODE_LIST *)(node->content);
                fetch        = c->dest_node;
               
                if (fetch != NULL)
                {
                        fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
                }
        }
        else if (node->dez_op == DEZ_OP_LE)
        {
                if (level == ((DEZ_NODE_LIST *)(list->content))->level + 1)
                {
                        return ((DEZ_NODE_LE *)(node->content))->pos;
                }
               
                return 10000;
        }
       
        maxl = dez_list_get_level (list, node);
       
        if (maxl < level)
        {
                return 10000;
        }
       
        n = maxl - level;
       
        while (n > 0)
        {
                if (
                        fetch == NULL ||
                        fetch->dez_op != DEZ_OP_FETCH_DIM
                )
                {
                        return 10000;
                }
               
                fetch = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
               
                n--;
        }
       
        if (
                fetch == NULL ||
                fetch->dez_op != DEZ_OP_FETCH_DIM
        )
        {
                return 10000;
        }
       
        return fetch->zop->op2.u.var;
}

static DEZ_NODE *dez_list_fetch_sub_dest (DEZ_NODE *node)
{
        if (node == NULL)
        {
                return NULL;
        }
       
        if (node->dez_op == DEZ_OP_ASSIGN)
        {
                DEZ_NODE_EXPR *c = (DEZ_NODE_EXPR *)(node->content);
                DEZ_NODE *fetch;
               
                if (c == NULL)
                {
                        return NULL;
                }
               
                fetch        = c->op2_node;
               
                c->op2_node = NULL;
               
                return fetch;
        }
        else if (node->dez_op == DEZ_OP_LIST)
        {
                DEZ_NODE_LIST *c = (DEZ_NODE_LIST *)(node->content);
                DEZ_NODE *fetch;
               
                if (c->dest_node == NULL)
                {
                        return NULL;
                }
               
                fetch = ((DEZ_NODE_EXPR *)(c->dest_node->content))->op1_node;
                ((DEZ_NODE_EXPR *)(c->dest_node->content))->op1_node = NULL;
               
                return fetch;
        }
       
        return NULL;
}

static DEZ_NODE *dez_list_create (int level)
{
        DEZ_NODE *node;
        DEZ_NODE_LIST *content;
       
        content = (DEZ_NODE_LIST *)malloc(sizeof(DEZ_NODE_LIST));
        if (content == NULL)
        {
                return NULL;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return NULL;
        }
       
        content->branch_node        = NULL;
        content->le_node                = NULL;
        content->dest_node                = NULL;
        content->level                        = level;
       
        node->dez_op                        = DEZ_OP_LIST;
        node->zop                                = NULL;
        node->content                        = content;
        node->prev                                = NULL;
        node->next                                = NULL;
       
        return node;
}

static int dez_list_add_le (DEZ_NODE *list, DEZ_NODE *node, int node_level)
{
        DEZ_NODE *le, *sl;
        DEZ_NODE_LIST *lc;
        DEZ_NODE_LE *lec;
        int level;
       
        lc = (DEZ_NODE_LIST *)(list->content);
       
        if (node_level > 0)
        {
                level = node_level;
        }
        else
        {
                level = dez_list_get_level(list, node);
               
                if (level <= 0)
                {
                        return -1;
                }
        }
       
        if (level > lc->level+1)
        {
                /*-- search sub list --*/
                int lei = dez_list_get_lei(list, node, lc->level+1);
               
                le = lc->le_node;
                while (le != NULL)
                {
                        if (
                                ((DEZ_NODE_LE *)(le->content))->a_node->dez_op == DEZ_OP_LIST &&
                                lei == dez_list_get_lei (list, le, lc->level+1)
                        )
                        {
                                break;
                        }
                       
                        le = le->next;
                }
               
                if (le != NULL)                                                        /* the sub list is found --*/
                {
                        dez_list_add_le(((DEZ_NODE_LE *)(le->content))->a_node, node, level);
                }
                else
                {
                        sl = dez_list_create(lc->level+1);
                        dez_list_add_le(sl, node, level);
                        dez_list_add_le(list, sl, lc->level+1);
                }
        }
        else if (level == lc->level+1)
        {
                int lei;
               
                lec = (DEZ_NODE_LE *)malloc(sizeof(DEZ_NODE_LE));
                if (lec == NULL)
                {
                        return -1;
                }
               
                le = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                if (le == NULL)
                {
                        free(lec);
                        return -1;
                }
               
                lei = dez_list_get_lei(list, node, level);
               
                lec->branch_node        = NULL;
                lec->a_node                        = node;
                lec->pos                        = lei;
                le->dez_op                        = DEZ_OP_LE;
                le->zop                                = node->zop;
                le->content                        = lec;
                le->prev                        = NULL;
                le->next                        = NULL;
               
                if (lc->le_node == NULL)                                        /* the list is empty */
                {
                        lc->le_node                = le;
                        lc->dest_node        = dez_list_fetch_sub_dest(node);
                        list->zop                = node->zop;
                }
                else
                {
                        DEZ_NODE *prev, *le1;
                       
                        le1 = lc->le_node;
                        prev= NULL;
                       
                        while(le1 != NULL)
                        {
                                int le1_lei = dez_list_get_lei(list, le1, level);
                               
                                if (le1_lei == lei)                                        /* the element is exist */
                                {
                                        free(lec);
                                        free(le);
                                       
                                        return -1;
                                }
                                else if (le1_lei > lei)
                                {
                                        break;
                                }
                               
                                prev = le1;
                                le1 = le1->next;
                        }
                       
                        if (prev == NULL)                                                /* the first element added */
                        {
                                le->next                = lc->le_node;
                                lc->le_node                = le;
                                if (le->next != NULL) le->next->prev = le;
                        }
                        else
                        {
                                le->next                = prev->next;
                                le->prev                = prev;
                                if (le->next != NULL) le->next->prev = le;
                                if (le->prev != NULL) le->prev->next = le;
                        }
                }
        }
        else
        {
                sl = dez_list_create(lc->level-1);
               
                sl->next        = list->next;
                sl->prev        = list->prev;
                if (sl->next != NULL) sl->next->prev = sl;
                if (sl->prev != NULL) sl->prev->next = sl;
                list->next        = NULL;
                list->prev        = NULL;
               
                if (list == m_dez_op_current)
                {
                        m_dez_op_current = sl;
                }
               
                dez_list_add_le(sl, list, lc->level);
                dez_list_add_le(sl, node, level);
        }
       
        return 0;
}

static int dez_list_is_le (DEZ_NODE *node)
{
        DEZ_NODE *last_fetch;
        DEZ_NODE_EXPR *expr;
       
        last_fetch = dez_list_get_last_fetch(node);
       
        if (last_fetch == NULL)
        {
                return -1;
        }
       
        expr = (DEZ_NODE_EXPR *)(last_fetch->content);
       
        if (
                expr != NULL &&
                expr->op1_node == NULL &&
                (last_fetch->zop->op1.op_type == IS_TMP_VAR || last_fetch->zop->op1.op_type == IS_VAR)
        )
        {
                return 0;
        }
       
        return -1;
}

static DEZ_NODE *dez_list_find_dest (DEZ_NODE *le)
{
        DEZ_NODE *p = m_dez_op_current;
        DEZ_NODE *last_fetch = dez_list_get_last_fetch(le);
       
        if (last_fetch == NULL)
        {
                return NULL;
        }
       
        while(p != NULL)
        {
                DEZ_NODE_EXPR *c;
                DEZ_NODE *fetch;
               
                if (p->dez_op != DEZ_OP_ASSIGN)
                {
                        p = p->prev;
                        continue;
                }

                c = (DEZ_NODE_EXPR *)(p->content);
               
                if (c == NULL)
                {
                        p = p->prev;
                        continue;
                }
               
                fetch        = c->op2_node;
               
                while (fetch != NULL)
                {
                        if (
                                fetch->dez_op == DEZ_OP_FETCH_DIM &&
                                ((DEZ_NODE_EXPR *)(fetch->content))->op1_node != NULL &&
                                fetch->zop->op1.op_type == last_fetch->zop->op1.op_type &&
                                fetch->zop->op1.u.var == last_fetch->zop->op1.u.var
                        )
                        {
                                return p;
                        }
                       
                        fetch        = ((DEZ_NODE_EXPR *)(fetch->content))->op1_node;
                }

                p = p->prev;
        }

        return NULL;
}

static int dez_list_is_dest (DEZ_NODE *node, znode *zn)
{
        if (node->dez_op == DEZ_OP_LIST)
        {
                DEZ_NODE_LIST *c = (DEZ_NODE_LIST *)(node->content);
               
                if (
                        c != NULL                                                                                &&
                        c->dest_node != NULL                                                        &&
                        c->dest_node->zop != NULL                                                &&
                        c->dest_node->zop->op1.op_type == zn->op_type        &&
                        c->dest_node->zop->op1.u.var == zn->u.var
                )
                {
                        return 0;
                }
        }
       
        return -1;
}

static DEZ_NODE *find_tmp_node (znode *zn)
{
        DEZ_NODE *p = m_dez_op_current;
       
        while(p != NULL)
        {
                if (
                        p->zop != NULL                                                        &&
                        p->zop->result.op_type == zn->op_type        &&
                        p->zop->result.u.var == zn->u.var
                )
                {
                        return p;
                }
               
                p = p->prev;
        }
       
        return NULL;
}

static DEZ_NODE *fetch_node (DEZ_NODE *node)
{
        if (node == NULL || node->prev == NULL)
        {
                return NULL;
        }
       
        node->prev->next = node->next;
        if (node->next != NULL) node->next->prev = node->prev;
       
        if (node == m_dez_op_current)
        {
                m_dez_op_current = node->prev;
        }
       
        node->prev = NULL;
        node->next = NULL;
       
        return node;
}

static DEZ_NODE *fetch_current_node (void)
{
        DEZ_NODE *p = m_dez_op_current;
       
        if (p == NULL || p->prev == NULL)
        {
                return NULL;
        }
       
        p->prev->next = NULL;
        m_dez_op_current = p->prev;
       
        p->prev = NULL;
       
        return p;
}

static DEZ_NODE *fetch_tmp_node (znode *zn)
{
        DEZ_NODE *p = m_dez_op_current;
        zend_op *zop = m_zend_op_current-m_opc_num;
       
        if (zn->op_type == IS_TMP_VAR || zn->op_type == IS_VAR)
        {
                while (zop >= m_zend_op_start)
                {
                        if (
                                zop->result.op_type == zn->op_type        &&
                                zop->result.u.var == zn->u.var
                        )
                        {
                                break;
                        }
                       
                        zop--;
                }
               
                if (zop < m_zend_op_start)                                                /* not found */
                {
                        return NULL;
                }
               
                while(p != NULL)
                {
                        if (p->zop != NULL)
                        {
                                if (p->zop < zop)
                                {
                                        break;
                                }
                                else if (
                                        p->zop->result.op_type == zn->op_type        &&
                                        p->zop->result.u.var == zn->u.var
                                )
                                {
                                        if (p->prev != NULL) p->prev->next = p->next;
                                        if (p->next != NULL) p->next->prev = p->prev;
                                       
                                        if (p == m_dez_op_current)
                                        {
                                                m_dez_op_current = p->prev;
                                        }
                                       
                                        p->prev        = NULL;
                                        p->next        = NULL;
                                       
                                        return p;
                                }
                        }
                       
                        p = p->prev;
                }
        }
       
        /*-- fetch list node --*/
        p = m_dez_op_current;
        if(p != NULL)
        {
                if (dez_list_is_dest(p, zn) == 0)
                {
                        if (p->prev != NULL) p->prev->next = p->next;
                        if (p->next != NULL) p->next->prev = p->prev;
                       
                        m_dez_op_current = p->prev;
                       
                        p->prev        = NULL;
                        p->next        = NULL;
                       
                        return p;
                }
        }
       
        return NULL;
}

static DEZ_NODE *fetch_call_ini_node (znode *zn)
{
        DEZ_NODE *p = fetch_tmp_node(zn);
       
        if (p != NULL)
        {
                return p;
        }
       
        if (
                zn->op_type == IS_CONST &&
                zn->u.constant.type == IS_STRING
        )
        {
                p = m_dez_op_current;
               
                while(p != NULL)
                {
                        if (
                                p->dez_op == DEZ_OP_CALL_INIT                        &&
                                p->zop != NULL                                                        &&
                                p->zop->op2.op_type == IS_CONST                        &&
                                p->zop->op2.u.constant.type == IS_STRING&&
                                strcmp((char *)(p->zop->op2.u.var), (char *)(zn->u.var)) == 0
                        )
                        {
                                return fetch_node(p);
                        }
                       
                        p = p->prev;
                }
        }
        else
        {
                p = m_dez_op_current;
               
                while(p != NULL)
                {
                        if (
                                p->dez_op == DEZ_OP_CALL_INIT                        &&
                                p->zop != NULL                                                        &&
                                p->zop->op2.op_type == zn->op_type                &&
//                                p->zop->op2.u.constant.type == zn->u.constant.type &&
                                p->zop->op2.u.var == zn->u.var
                        )
                        {
                                return fetch_node(p);
                        }
                       
                        p = p->prev;
                }
        }
       
        return NULL;
}

static DEZ_NODE *fetch_jmp_src_node (int jmpcode, int dest)
{
        DEZ_NODE *p = m_dez_op_current;
       
        while(p != NULL)
        {
                if (
                        p->zop != NULL                                                        &&
                        p->zop->opcode == jmpcode                                &&
                        p->zop->op2.op_type == IS_UNUSED                &&
                        p->zop->op2.u.opline_num == dest
                )
                {
                        if (p->prev != NULL) p->prev->next = p->next;
                        if (p->next != NULL) p->next->prev = p->prev;
                       
                        if (p == m_dez_op_current)
                        {
                                m_dez_op_current = p->prev;
                        }
                       
                        p->prev        = NULL;
                        p->next        = NULL;
                       
                        return p;
                }
               
                p = p->prev;
        }
       
        return NULL;
}

static DEZ_NODE *get_jmp_dest_node (int dest)
{
        DEZ_NODE *p = m_dez_op_current;
       
        if (
                p->zop != NULL                                                                &&
                get_zend_linenum(p) < dest
        )
        {
                return NULL;
        }
       
        while(p->prev != NULL)
        {
                if (
                        p->prev->zop != NULL                                        &&
                        get_zend_linenum(p->prev) < dest
                )
                {
                        break;
                }
               
                p = p->prev;
        }
       
        if (p->prev == NULL)
        {
                p = p->next;
        }
       
        return p;
}

static DEZ_NODE *fetch_jmp_dest_node (int dest)
{
        DEZ_NODE *p = get_jmp_dest_node(dest);
       
        if (p == NULL)
        {
                return NULL;
        }
       
        m_dez_op_current = p->prev;
        m_dez_op_current->next = NULL;
       
        p->prev        = NULL;
       
        return p;
}

static DEZ_NODE *find_last_node (int dez_op)
{
        DEZ_NODE *p = m_dez_op_current;
       
        while(p != NULL)
        {
                if (p->dez_op == dez_op)
                {
                        break;
                }
               
                p = p->prev;
        }
       
        return p;
}

static DEZ_NODE *find_last_node_ex (int dez_op, znode *result, znode *op1, znode *op2)
{
        DEZ_NODE *p = m_dez_op_current;
        znode *zn;
       
        while(p != NULL)
        {
                if (p->dez_op == dez_op)
                {
                        int found = 1;
                       
                        if (result != NULL)
                        {
                                zn = &(p->zop->result);
                               
                                if (
                                        zn->op_type != result->op_type                ||
                                        zn->u.var != result->u.var
                                )
                                {
                                        found = 0;
                                }
                        }
                       
                        if (op1 != NULL)
                        {
                                zn = &(p->zop->op1);
                               
                                if (
                                        zn->op_type != op1->op_type                ||
                                        zn->u.var != op1->u.var
                                )
                                {
                                        found = 0;
                                }
                        }
                       
                        if (op2 != NULL)
                        {
                                zn = &(p->zop->op2);
                               
                                if (
                                        zn->op_type != op2->op_type                ||
                                        zn->u.var != op2->u.var
                                )
                                {
                                        found = 0;
                                }
                        }
                       
                        if (found != 0)
                        {
                                return p;
                        }
                }
               
                p = p->prev;
        }
       
        return NULL;
}

static int dez_is_first_node (DEZ_NODE *node)
{
        if (node == NULL)
        {
                return 0;
        }
       
        node = node->prev;
       
        while (node != NULL)
        {
                if (node->dez_op != DEZ_OP_NOP)
                {
                        return -1;
                }
               
                node = node->prev;
        }
       
        return 0;
}

static int dez_branch_get_range (DEZ_NODE *parent, int *header, int *tailer)
{
        if (
                parent == NULL                        ||
                parent->content == NULL        ||
                header == NULL                        ||
                tailer == NULL
        )
        {
                return -1;
        }
       
        if (parent->dez_op == DEZ_OP_FOR)
        {
                DEZ_NODE *before_node = ((DEZ_NODE_FOR *)(parent->content))->before_node;
               
                if (before_node != NULL)
                {
                        *header = get_zend_linenum(before_node)+1;
                }
                else
                {
                        *header = get_prev_zend_linenum(parent)+1;
                }
        }
        else
        {
                *header = get_prev_zend_linenum(parent)+1;
        }
       
        if (
                parent->dez_op == DEZ_OP_DO        ||                                                                                        /* do{...}while() */
                parent->dez_op == DEZ_OP_WHILE && parent->zop->opcode == ZEND_JMP                /* while(true) */
        )
        {
                *tailer = get_zend_linenum(parent);
        }
        else
        {
                DEZ_NODE *lastnode;
               
                lastnode = parent;
               
                while(1)
                {
                        DEZ_NODE *sub;
                       
                        sub = dez_get_last_sub_node(lastnode);
                       
                        if (sub == NULL)                                                                                                /* no sub node */
                        {
                                break;
                        }
                       
                        lastnode = sub;
                       
                        if (
                                lastnode->dez_op == DEZ_OP_DO        ||                                                                                /* do{...}while() */
                                lastnode->dez_op == DEZ_OP_WHILE && lastnode->zop->opcode == ZEND_JMP        /* while(true) */
                        )
                        {
                                break;
                        }
                }
               
                *tailer = get_zend_linenum(lastnode);
        }
       
        return 0;
}

static int dez_enter_branch (void)
{
        DEZ_NODE_EXPR *content;
       
        content = (DEZ_NODE_EXPR *)(m_dez_op_current->content);
       
        if (content->branch_node == NULL)
        {
                content->branch_node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                if (content->branch_node == NULL)
                {
                        return -1;
                }
               
                content->branch_node->dez_op        = DEZ_OP_NOP;
                content->branch_node->zop                = NULL;
                content->branch_node->content        = NULL;
                content->branch_node->prev                = NULL;
                content->branch_node->next                = NULL;
        }
       
        dez_node_push(m_dez_op_current);
        m_dez_op_current = content->branch_node;
               
        return 0;
}

static int dez_enter_branch_ex (DEZ_NODE *node)
{
        DEZ_NODE_EXPR *content;
       
        content = (DEZ_NODE_EXPR *)(node->content);
        content->branch_node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (content->branch_node == NULL)
        {
                return -1;
        }
       
        dez_node_push(node);
       
        content->branch_node->dez_op        = DEZ_OP_NOP;
        content->branch_node->zop                = NULL;
        content->branch_node->content        = NULL;
        content->branch_node->prev                = NULL;
        content->branch_node->next                = node->next;
        if (content->branch_node->next != NULL) content->branch_node->next->prev = content->branch_node;
       
        if (node == m_dez_op_current)
        {
                m_dez_op_current = content->branch_node;
        }
       
        return 0;
}

// enterelse = 0: don't enter else node, 1: enter else node
static int dez_exit_branch (int enterelse)
{
        DEZ_NODE *node, *els, *tmp, *m_dez_op_current2;
        DEZ_NODE_EXPR *content;
        int nextline, dest;
        int remove_node = 0;
        int dup_jmp = 0;
        zend_op *cur_zop;
       
        node = dez_node_pop();
       
        if (node == NULL)
        {
                return -1;
        }
       
        cur_zop = ZEND_GET_ORI(m_zend_op_current) - m_opc_num + m_zend_op_match_n;
       
        content = (DEZ_NODE_EXPR *)(node->content);
       
        m_dez_op_current2 = NULL;
        els = NULL;
        nextline = ZEND_LINENUM(cur_zop) + 1;
       
        if (node->dez_op  == DEZ_OP_IF)                                                        /* if */
        {
                if (
                        enterelse == 1        &&                                                                /* need enter else node */
                        node->zop->opcode != ZEND_JMP                                        /* not if (false) */
                )
                {
                        int dest;
                       
                        dest = dez_get_dest(node);
                       
                        if (dest == nextline)                                                        /* there maybe is else node */
                        {
                                DEZ_NODE *lastnode = NULL;
                                int jmpdest;
                               
                                tmp = dez_get_last_sub_node(node);
                               
                                while(tmp != NULL)
                                {
                                        lastnode = tmp;
                                        tmp = dez_get_last_sub_node(tmp);
                                }
                               
                                jmpdest = dez_get_dest(lastnode);
                               
                                if (
                                        lastnode != NULL        &&
                                        lastnode->dez_op == DEZ_OP_IF        &&                        /* if */
                                        lastnode->zop->opcode == ZEND_JMP &&                /* if (false) */
                                        (jmpdest > dest || jmpdest <= get_prev_zend_linenum(node)) &&        /* has some zend ops */
//                                        dez_get_branch_end(lastnode) > dest &&                /* has some zend ops */
                                        dez_branch_is_null(lastnode) == 0                        /* the sub branch is null */
                                )
                                {
                                        m_dez_op_current = node;
                                       
                                        dez_node_cvt_if(DEZ_OP_ELSE, lastnode->zop);/* add else node */
                                        dez_enter_branch();                                                        /* enter else node */
                                       
                                        return 0;
                                }
                        }
                }
        }
        else if (
                node->dez_op == DEZ_OP_CASE                ||                                        /* case of switch */
                node->dez_op == DEZ_OP_DEFAULT                                                /* default of switch */
        )
        {
                m_dez_op_current2 = content->op1_node;                                /* return to switch node */
        }
        else if (node->dez_op == DEZ_OP_ELSE)                                        /* else node */
        {
                if (dez_branch_is_null(node) == 0)                                        /* the branch is null */
                {
                        tmp = node->prev;
                        tmp->next = node->next;
                        node->prev = NULL;
                       
                        m_dez_op_current2 = tmp;
                       
                        remove_node = 1;
                }
        }

        if (m_dez_op_current2 == NULL)
        {
                m_dez_op_current = node;
        }
        else
        {
                m_dez_op_current = m_dez_op_current2;
        }
       
        if (node != NULL)
        {
                DEZ_NODE *lastsubnode = dez_get_last_sub_node(node);
                       
                dest = dez_get_dest(node);

#if 0
                if (
                        dest >= nextline &&
                        node->dez_op == DEZ_OP_IF && node->zop->opcode == ZEND_JMP &&        /* maybe break */
                        lastsubnode != NULL        &&
                        lastsubnode->dez_op == DEZ_OP_IF && lastsubnode->zop->opcode == ZEND_JMP        /* if (false) */
                )
                {
                        DEZ_NODE *pp = dez_node_get();
                       
                        if (
                                pp != NULL        &&
                                pp->dez_op == DEZ_OP_IF && pp->zop->opcode != ZEND_JMP
                        )
                        {
                                int ppbegin = get_prev_zend_linenum(pp);
                                int ppend = dez_get_branch_end(pp);
                               
                                if (
                                        (int)(node->zop->op1.u.opline_num) <= ppbegin &&
                                        (int)(node->zop->op1.u.opline_num) > ppend &&                /* jmp out of branch of node */
                                        (int)(lastsubnode->zop->op1.u.opline_num) <= ZEND_LINENUM(pp->zop) &&
                                        (int)(lastsubnode->zop->op1.u.opline_num) > ppbegin        /* jmp to header of pp */
                                )
                                {
                                        dez_node_cvt_jmp(DEZ_OP_JMP, lastsubnode->zop);
                                        return 0;
                                }
                        }
                }
#endif
               
                if (dest <= get_zend_linenum(node))                                                                /* jump afterward */
                {
                        dup_jmp = 1;
                }
                else if (dest >= nextline)
                {
//                        if (cur_zop->opcode == ZEND_JMP)
                        if (
                                lastsubnode != NULL        &&
                                lastsubnode->dez_op == DEZ_OP_IF && lastsubnode->zop->opcode == ZEND_JMP        /* if (false) */
                        )
                        {
                                int dest_is_case_default = 0;
                                zend_op *zop_dest = m_zend_op_start + lastsubnode->zop->op1.u.opline_num;
                               
                                if (
                                        (zop_dest[-1].opcode == ZEND_JMPZ || zop_dest[-1].opcode == ZEND_JMPZNZ)        &&
                                        zop_dest[-2].opcode == ZEND_CASE
                                )                                                                                                                /* the dest is 'case' */
                                {
                                        dest_is_case_default = 1;
                                }
                                else if (
                                        zop_dest[-1].opcode == ZEND_BOOL        &&
                                        zop_dest[-2].opcode == ZEND_JMP
                                )                                                                                                                /* the dest is 'default' */
                                {
                                        dest_is_case_default = 1;
                                }
                               
                                if (
                                        !(
                                                node->dez_op == DEZ_OP_ELSE                                &&
                                                dez_in_branch(node, DEZ_OP_CASE) == 0        &&                /* within case branch */
                                                dest_is_case_default                                                        /* the dest node is case or default node */
                                        )
                                )
                                {
                                        dup_jmp = 1;
                                }
                        }
                }

                if (dup_jmp != 0)
                {
                        zend_op *dupzop;
                       
                        dupzop = dez_dup_zend_op(cur_zop);
                        dupzop->opcode = ZEND_JMP;
                        dupzop->op1.op_type = IS_UNUSED;
                        dupzop->op1.u.opline_num = dest;
                        dupzop->op2.op_type = IS_UNUSED;
                        dupzop->op2.u.opline_num = 0;
                        dupzop->result.op_type = IS_UNUSED;
                        dupzop->result.u.opline_num = 0;
                       
                        dez_node_cvt_jmp(DEZ_OP_JMP, dupzop);
                }
        }

        if (remove_node != 0)
        {       
                dez_node_specs[node->dez_op].dez_node_free_func(node);        /* remove the else node */
        }
       
        return 0;
}

static int dez_check_exit_branch (void)
{
        DEZ_NODE *node;
        int nextline,dest;
        int i;
       
        nextline = ZEND_LINENUM(m_zend_op_current) - m_opc_num + m_zend_op_match_n + 1;
       
        for (i = 0; i < m_node_num; i++)
        {
                node = m_node_stack[i];
               
                if (
                        node->dez_op == DEZ_OP_FUNCTION ||
                        node->dez_op == DEZ_OP_CLASS
                )
                {
                        continue;
                }
               
                dest = dez_get_branch_end(node);
               
                if (dest <= nextline)
                {
                        break;
                }
        }
       
#if 0
        if (i < m_node_num)                                                                                                /* found */
        {
                int n = m_node_num - 1;
               
                /*-- exit child branch tree --*/
                while (n > i)
                {
                        dez_exit_branch(0);
                        n--;
                }
               
                dez_exit_branch(1);                                                                                        /* exit self */
        }
#endif
       
        while (i+1 < m_node_num)
        {
                dez_exit_branch(0);
        }
       
        if (i < m_node_num)
        {
                dez_exit_branch(1);
        }
       
        return 0;
}

static int dez_check_exit_all (void)
{
        while(m_node_num > 0)
        {
                DEZ_NODE *node = dez_node_get();
               
                if (
                        node->dez_op == DEZ_OP_FUNCTION        ||
                        node->dez_op == DEZ_OP_CLASS
                )
                {
                        break;
                }
               
                dez_exit_branch(0);
        }
       
        return 0;
}
       
#if 0
static int dez_check_exit_branch (void)
{
        int nextline;
        DEZ_NODE *tmp, *node, *els;
        DEZ_NODE_EXPR *content;
        int i,j;
       
        nextline = ZEND_LINENUM(m_zend_op_current - m_opc_num) + 1;
       
        for (i = 0; i < m_node_num; i++)
        {
                int dest;
               
                node = m_node_stack[i];
               
                if (
                        node->dez_op == DEZ_OP_FUNCTION ||
                        node->dez_op == DEZ_OP_CLASS
                )
                {
                        continue;
                }
               
                content = (DEZ_NODE_EXPR *)(node->content);
               
                dest = dez_get_dest(node);
               
                if (
                        dest > get_zend_linenum(node) &&                                                /* jump forward */
                        dest <= nextline
                )
                {
                        m_dez_op_current = node;
                       
                        els = NULL;
                       
                        if (
                                node->dez_op  == DEZ_OP_IF &&                                                /* if */
                                node->zop->opcode != ZEND_JMP                                                /* not if (false) */
                        )
                        {
                                tmp = dez_node_get();
                               
                                if (
                                        node != tmp &&
                                        tmp != NULL        &&
                                        tmp->dez_op == DEZ_OP_IF        &&                                /* if */
                                        tmp->zop->opcode == ZEND_JMP &&                                /* if (false) */
                                        dez_get_dest(tmp) > nextline &&                                /* has some zend ops */
                                        dez_branch_is_null(tmp) == 0                                /* the sub branch is null */
                                )
                                {
                                        els = dez_node_pop();
                                        els->dez_op = DEZ_OP_ELSE;
                                        els = fetch_node(els);
                                }
                        }
                        else if (
                                node->dez_op == DEZ_OP_CASE                ||                                /* case of switch */
                                node->dez_op == DEZ_OP_DEFAULT                                        /* default of switch */
                        )
                        {
                                m_dez_op_current = content->op1_node;                        /* return to switch node */
                        }

                        /*-- exit all child branchs --*/
                        while (m_node_num > i)
                        {
                                node = m_node_stack[m_node_num-1];
                               
                                if (node->dez_op == DEZ_OP_ELSE)                        /* else node */
                                {
                                        if (dez_branch_is_null(node) == 0)                /* the branch is null */
                                        {
                                                tmp = node->prev;
                                               
                                                if (m_dez_op_current == node)
                                                {
                                                        m_dez_op_current = tmp;
                                                }
                                               
                                                tmp->next = node->next;
                                                node->prev = NULL;
                                               
                                                dez_node_specs[node->dez_op].dez_node_free_func(node);        /* remove the else node */
                                                node = tmp;
                                        }
                                }
                                else if (node->dez_op == DEZ_OP_IF && node->zop->opcode == ZEND_JMP)        /* if (false) */
                                {
                                        DEZ_NODE_IF *ifc = (DEZ_NODE_IF *)(node->content);
#if 0                                       
                                        node->next = ifc->branch_node->next;                /* moveup all sub node */
                                       
                                        ifc->branch_node->next = NULL;
                                        dez_node_specs[ifc->branch_node->dez_op].dez_node_free_func(ifc->branch_node);
                                        ifc->branch_node = NULL;
#endif                                       
                                        node->dez_op = DEZ_OP_JMP;                                        /* change this node into JMP (maybe break) */
                                }
                               
                                m_node_num--;
                        }
                                       
                        if (els != NULL)
                        {
                                DEZ_ADD_NODE(els);
                               
                                dez_enter_branch();                                                                /* enter else branch */
                        }
                       
                        break;
                }
        }
       
        return 0;
}
#endif

/*-- convertor for DEZ_NODE_NOP --*/
static int dez_node_cvt_nop (unsigned char dez_op, zend_op *pzop)
{
        return 0;
}

/*-- convertor for expr --*/
static int dez_node_cvt_expr (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *parent, *node;
        DEZ_NODE_EXPR *content, *c;
       
        parent = dez_node_get();
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->op1_node                = fetch_tmp_node(&(pzop->op1));
        content->op2_node                = fetch_tmp_node(&(pzop->op2));
       
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;
        node->prev                = NULL;
        node->next                = NULL;

        if (
                dez_op == DEZ_OP_ASSIGN                                &&
                parent != NULL                                                &&
                parent->dez_op == DEZ_OP_FOREACH
        )
        {
                DEZ_NODE_FOREACH *fe = (DEZ_NODE_FOREACH *)(parent->content);
               
                if (
                        content->op2_node != NULL &&
                        content->op2_node->zop->opcode == ZEND_FETCH_DIM_TMP_VAR &&
                        content->op2_node->zop->op1.op_type == ZEND_GET_ORI(parent->zop)[1].result.op_type &&
                        content->op2_node->zop->op1.u.var == ZEND_GET_ORI(parent->zop)[1].result.u.var
                )
                {
                        if (
                                fe->value_node == NULL &&
                                content->op2_node->zop->op2.u.var == 0
                        )
                        {
                                node->dez_op = DEZ_OP_AS;
                                fe->value_node = node;
                               
                                return 0;
                        }
                        else if
                        (
                                fe->key_node == NULL &&
                                content->op2_node->zop->op2.u.var == 1
                        )
                        {
                                node->dez_op = DEZ_OP_AS;
                                fe->key_node = node;
                               
                                return 0;
                        }
                       
                }
                else if (content->op2_node == NULL)
                {
                        if (
                                fe->value_node == NULL &&
                                pzop->op2.op_type == ZEND_GET_ORI(parent->zop)[1].result.op_type &&
                                pzop->op2.u.var == ZEND_GET_ORI(parent->zop)[1].result.u.var
                        )
                        {
                                node->dez_op = DEZ_OP_AS;
                                fe->value_node = node;
                               
                                return 0;
                        }
                }
        }
       
        if (
                dez_op == DEZ_OP_ASSIGN                                &&
                content->op2_node != NULL                        &&
                content->op2_node->dez_op == DEZ_OP_FETCH_DIM
        )
        {
                DEZ_NODE *fetch = dez_list_get_last_fetch(node);
               
                if (fetch != NULL)
                {
                        c = (DEZ_NODE_EXPR *)(fetch->content);
                       
                        if (
                                c->op1_node != NULL &&
                                c->op1_node->dez_op == DEZ_OP_LIST                                /* list element */
                        )
                        {
                                DEZ_NODE *list = c->op1_node;
                                c->op1_node = NULL;
                               
                                DEZ_ADD_NODE(list);
                               
                                dez_list_add_le(list, node, -1);                                /* add element into list */
                               
                                return 0;
                        }
                }
        }
       
        if (dez_list_is_le(node) == 0)                                                                /* list element */
        {
                int level;
                DEZ_NODE *list, *dest;
               
                dest = dez_list_find_dest(node);
               
                if (dest != NULL)
                {
                        fetch_node(dest);
                       
                        level = dez_list_get_level(NULL, dest);
                        list = dez_list_create(level-1);                                        /* create an empty list */
                        dez_list_add_le(list, dest, level);
                       
                        DEZ_ADD_NODE(list);
                }
                else
                {
                        list = find_last_node(DEZ_OP_LIST);
                }
               
                if (list != NULL)
                {
                        dez_list_add_le(list, node, -1);
                       
                        return 0;
                }
        }
       
        DEZ_ADD_NODE(node);

        if (dez_op == DEZ_OP_QM_ASSIGN && (m_opc_num < 2 || ZEND_GET_ORI(pzop)[1].opcode != ZEND_JMP))                        /* qm false */
        {
                return 2;                                        /* exit branch */
        }
        else
        {
                return 0;
        }
}

/*-- convertor for if --*/
static int dez_node_cvt_if (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *parent, *node;
        DEZ_NODE_IF *content;
       
        parent = dez_node_get();
       
        if (dez_op == DEZ_OP_IF && pzop->opcode != ZEND_JMP)
        {
                DEZ_NODE *current_node = m_dez_op_current;
               
                while(current_node != NULL)
                {
                        if (
                                current_node->dez_op == DEZ_OP_IF &&
                                current_node->zop->opcode == ZEND_JMP
                        )                                                                                                                /* if (false) */
                        {
                                current_node = current_node->prev;
                                continue;
                        }
                        else if
                        (
                                current_node->dez_op == DEZ_OP_FUNCTION ||
                                current_node->dez_op == DEZ_OP_CLASS
                        )
                        {
                                current_node = NULL;
                        }
                       
                        break;
                }
               
                node = find_tmp_node(&(pzop->op1));
               
               
                if (
                        node != NULL                                        &&
                        node->dez_op == DEZ_OP_SWITCH        &&
                        current_node == node                        &&
                        ZEND_LINENUM(pzop) >= pzop->op2.u.opline_num                        /* ZEND_JMPZ: goto afterward */
                )        /* the end of default of switch */
                {
                        return 0;
                }
        }

        content = (DEZ_NODE_IF *)malloc(sizeof(DEZ_NODE_IF));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
       
        if (pzop->opcode == ZEND_JMP)                                                                /* if (false) or else */
        {
                content->op1_node                = NULL;
                content->op2_node                = NULL;
                content->dest                        = pzop->op1.u.opline_num;
        }
        else
        {
                content->op1_node                = fetch_tmp_node(&(pzop->op1));
                content->op2_node                = fetch_tmp_node(&(pzop->op2));
                content->dest                        = pzop->op2.u.opline_num;
        }
       
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;
        node->prev                = NULL;
        node->next                = NULL;

        DEZ_ADD_NODE(node);

        if (dez_op == DEZ_OP_IF)
        {
                return 1;                                        /* enter branch */
        }
        else
        {
                return 0;
        }
}

/*-- convertor for DEZ_OP_QM_ASSIGN --*/
static int dez_node_cvt_qm_assign (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node;
        DEZ_NODE_EXPR *content;
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->op1_node                = fetch_tmp_node(&(pzop->op1));
       
        if (m_opc_num >= 2 && ZEND_GET_ORI(pzop)[1].opcode == ZEND_JMP)                        /* qm true */
        {
                DEZ_NODE *cond;
               
                /*-- fetch qm condition node --*/
//                content->op2_node = fetch_jmp_src_node (ZEND_JMPZ, (ZEND_LINENUM(pzop)+2);
                cond = dez_node_get();
                if (
                        cond != NULL &&
                        cond->dez_op == DEZ_OP_IF &&
                        ((DEZ_NODE_IF *)(cond->content))->dest == ZEND_LINENUM(pzop)+2
                )
                {
                        content->op2_node = dez_node_pop();                                        /* fetch the condition node */
               
                        m_dez_op_current = content->op2_node->prev;
                        content->op2_node->prev = NULL;
                }
                else
                {
                        content->op2_node = NULL;
                }
        }
        else                                                                                                                /* qm false */
        {
                /*-- fetch qm true node --*/
                content->op2_node = fetch_tmp_node (&(pzop->result));
        }
               
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;

        DEZ_ADD_NODE(node);

        return 0;
}

/*-- convertor for DEZ_OP_DO --*/
static int dez_node_cvt_do (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node;
        DEZ_NODE_EXPR *content;
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->op1_node = fetch_tmp_node(&(pzop->op1));
        content->op2_node = NULL;
        content->branch_node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
       
        if (content->branch_node == NULL)
        {
                return -1;
        }
       
        content->branch_node->dez_op        = DEZ_OP_NOP;
        content->branch_node->zop                = NULL;
        content->branch_node->content        = NULL;
        content->branch_node->prev                = NULL;
        content->branch_node->next                = fetch_jmp_dest_node(pzop->op2.u.opline_num);
        if (content->branch_node->next != NULL) content->branch_node->next->prev = content->branch_node;
       
        DEZ_ADD_NODE(node);

        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;

        return 0;
}

/*-- convertor for DEZ_OP_FOR --*/
static int dez_node_cvt_for (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node;
        DEZ_NODE_FOR *content;
       
        content = (DEZ_NODE_FOR *)malloc(sizeof(DEZ_NODE_FOR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->cond_node                = fetch_tmp_node(&(pzop->op1));
       
        if (m_dez_op_current->dez_op == DEZ_OP_ASSIGN)
        {
                content->before_node        = fetch_current_node();
        }
        else
        {
                content->before_node        = NULL;
        }
       
        content->after_node                = NULL;
       
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;

        DEZ_ADD_NODE(node);

        return 1;                                        /* enter branch */
}

/*-- convertor for DEZ_OP_FOREACH --*/
static int dez_node_cvt_foreach (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node;
        DEZ_NODE_FOREACH *content;
       
        content = (DEZ_NODE_FOREACH *)malloc(sizeof(DEZ_NODE_FOREACH));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
       
        content->source_node        = fetch_tmp_node(&(pzop->op1));
        content->key_node                = NULL;
        content->value_node                = NULL;
       
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;

        DEZ_ADD_NODE(node);

        return 1;                                        /* enter branch */
}

/*-- convertor for DEZ_OP_CASE --*/
static int dez_node_cvt_case (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node, *parent, *branch;
        DEZ_NODE_EXPR *content, *swcontent;
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->op1_node                = fetch_tmp_node(&(pzop->op1));
        content->op2_node                = fetch_tmp_node(&(pzop->op2));
       
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;
        node->prev                = NULL;
        node->next                = NULL;

        parent = find_tmp_node(&(pzop->result));
       
        if (parent == NULL)
        {
                return -1;
        }
       
        if (parent->dez_op == DEZ_OP_BOOL)
        {
                if (
                        parent->zop->op1.op_type == IS_CONST                        &&
                        parent->zop->op1.u.constant.type == IS_BOOL                &&
                        parent->zop->op1.u.constant.value.lval == 0
                )
                {
                        parent->dez_op        = DEZ_OP_SWITCH;
       
                        /* set the condition of switch */
                        swcontent = (DEZ_NODE_EXPR *)(parent->content);
                        swcontent->op1_node = content->op1_node;
                        parent->zop->op1 = pzop->op1;
                        content->op1_node = NULL;
                       
                        branch = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                        if (branch == NULL)
                        {
                                return -1;
                        }
                       
                        branch->dez_op                = DEZ_OP_NOP;
                        branch->zop                        = NULL;
                        branch->content                = NULL;
                        branch->prev                = NULL;
                        branch->next                = NULL;
                       
                        swcontent->branch_node = branch;
                }
                else
                {
                        return -1;
                }
        }
        else if (parent->dez_op == DEZ_OP_SWITCH)
        {
                branch = ((DEZ_NODE_EXPR *)(parent->content))->branch_node;
               
                while(branch->next != NULL) branch = branch->next;
        }
        else
        {
                return -1;
        }
       
        content->op1_node        = parent;                                                        /* pointer to switch node */
       
        branch->next        = node;
        node->prev                = branch;
       
        m_dez_op_current= node;
       
        return 1;                                                                                /* enter case branch */
}

/*-- convertor for DEZ_OP_DEFAULT --*/
static int dez_node_cvt_default (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node, *parent, *branch;
        DEZ_NODE_EXPR *content, *swcontent;
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->op1_node                = NULL;
        content->op2_node                = NULL;
       
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;
        node->prev                = NULL;
        node->next                = NULL;

        while (1)
        {
                DEZ_NODE *tmp;
               
                parent = find_tmp_node(&(ZEND_GET_ORI(pzop)[1].result));
               
                if (parent != NULL)
                {
                        break;
                }
               
                tmp = dez_node_get();
               
                if (tmp == NULL)
                {
                        free(content);
                        free(node);
                       
                        return 0;
                }
               
                if (
                        (tmp->dez_op == DEZ_OP_IF && tmp->zop->opcode == ZEND_JMP)        ||                /* if(false) */
                        tmp->dez_op == DEZ_OP_CASE                                                                        ||                /* case */
                        dez_get_dest(tmp) >= ZEND_LINENUM(pzop)+2                                                        /* the dest of parent is next node */
                )
                {
                        if (ZEND_GET_ORI(pzop) == ZEND_GET_ORI(tmp->zop))                                        /* is ZEND_JMP of default */
                        {
                                m_dez_op_current = dez_node_pop();
                        }
                        else
                        {
                                dez_exit_branch(0);                        //m_dez_op_current = dez_node_pop();
                        }
                }
                else
                {
                        free(content);
                        free(node);
                       
                        return 0;
                }
        }
       
        if (parent->dez_op == DEZ_OP_BOOL)
        {
                if (
                        parent->zop->op1.op_type == IS_CONST                        &&
                        parent->zop->op1.u.constant.type == IS_BOOL                &&
                        parent->zop->op1.u.constant.value.lval == 0
                )
                {
                        parent->dez_op        = DEZ_OP_SWITCH;
                       
                        swcontent = (DEZ_NODE_EXPR *)(parent->content);
                       
                        branch = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                        if (branch == NULL)
                        {
                                return -1;
                        }
                       
                        branch->dez_op                = DEZ_OP_NOP;
                        branch->zop                        = NULL;
                        branch->content                = NULL;
                        branch->prev                = NULL;
                        branch->next                = NULL;
                       
                        swcontent->branch_node = branch;
                }
                else
                {
                        return -1;
                }
        }
        else if (parent->dez_op == DEZ_OP_SWITCH)
        {
                branch = ((DEZ_NODE_EXPR *)(parent->content))->branch_node;
               
                while(branch->next != NULL) branch = branch->next;
        }
        else
        {
                return -1;
        }
       
        content->op1_node        = parent;                                                        /* pointer to switch node */
       
        branch->next        = node;
        node->prev                = branch;
       
        m_dez_op_current= node;
       
        return 1;                                                                                                /* enter default branch */
}

/*-- convertor for DEZ_OP_FUNCTION or DEZ_OP_CLASS --*/
static int dez_node_cvt_function_or_class (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node;
       
        node = m_dez_op_root;
       
        while(node != NULL)
        {
                if (pzop->extended_value == ZEND_DECLARE_FUNCTION)
                {
                        if (node->dez_op == DEZ_OP_FUNCTION)
                        {
                                DEZ_NODE_FUNCTION *content;
                               
                                content = (DEZ_NODE_FUNCTION *)(node->content);
                               
                                if (0 == strcmp(content->name, pzop->op2.u.constant.value.str.val))
                                {
                                        fetch_node(node);
                                       
                                        DEZ_ADD_NODE(node);
                                       
                                        return 0;
                                }
                        }
                }
                else if
                (
                        pzop->extended_value == ZEND_DECLARE_CLASS        ||
                        pzop->extended_value == ZEND_DECLARE_INHERITED_CLASS
                )                /* declare class */
                {
                        if (node->dez_op == DEZ_OP_CLASS)
                        {
                                DEZ_NODE_CLASS *content;
                               
                                content = (DEZ_NODE_CLASS *)(node->content);
                               
                                if (0 == strcmp(content->name, pzop->op2.u.constant.value.str.val))
                                {
                                        fetch_node(node);
                                       
                                        DEZ_ADD_NODE(node);
                                       
                                        return 0;
                                }
                        }
                }
               
                node = node->next;
        }
       
        return 0;
}

/*-- convertor for DEZ_OP_DOUBLE_ARROW --*/
static int dez_node_cvt_double_arrow (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node, *parent;
        DEZ_NODE_DA *content;
       
        content = (DEZ_NODE_DA *)malloc(sizeof(DEZ_NODE_DA));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        parent = fetch_tmp_node(&(pzop->result));
       
        content->branch_node        = NULL;
        content->key_node                = fetch_tmp_node(&(pzop->op2));
        content->value_node                = fetch_tmp_node(&(pzop->op1));
        content->next_node                = parent;
        if (parent != NULL) parent->prev = node;
       
        node->dez_op        = DEZ_OP_ARRAY;
        node->zop                = pzop;
        node->content        = content;
        node->prev                = NULL;
        node->next                = NULL;

        DEZ_ADD_NODE(node);

        return 0;
}

/*-- convertor for DEZ_OP_ARRAY --*/
static int dez_node_cvt_array (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node;
        DEZ_NODE_DA *content;
       
        content = (DEZ_NODE_DA *)malloc(sizeof(DEZ_NODE_DA));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->key_node                = fetch_tmp_node(&(pzop->op2));
        content->value_node                = fetch_tmp_node(&(pzop->op1));
        content->next_node                = NULL;
       
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;

        DEZ_ADD_NODE(node);

        return 0;
}

/*-- convertor for DEZ_OP_HEREDOC --*/
static int dez_node_cvt_heredoc (unsigned char dez_op, zend_op *pzop)
{
        /**********/
        return 0;
}

/*-- convertor for DEZ_OP_DOLLAR_OPEN_CURLY_BRACES --*/
static int dez_node_cvt_dollar_open_curly_braces (unsigned char dez_op, zend_op *pzop)
{
        /**********/
        return 0;
}

/*-- convertor for DEZ_OP_CALL --*/
static int dez_node_cvt_call (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node, *param, *tmp;
        DEZ_NODE_EXPR *content;
        int param_num;
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->op1_node                = fetch_call_ini_node(&(pzop->op1));
       
        param = NULL;
        tmp = m_dez_op_current;
        param_num = pzop->extended_value;
       
        while (tmp != NULL && param_num > 0)
        {
                DEZ_NODE *prev = tmp->prev;
               
                if (tmp->dez_op == DEZ_OP_CALL_PARAM)
                {
                        if (tmp == m_dez_op_current)
                        {
                                m_dez_op_current = prev;
                        }
                       
                        if (tmp->prev != NULL)
                        {
                                tmp->prev->next = tmp->next;
                                tmp->prev = NULL;
                        }
                       
                        if (tmp->next != NULL)
                        {
                                tmp->next->prev = prev;
                                tmp->next = NULL;
                        }
                       
                        tmp->next = param;
                        param = tmp;

                        param_num--;
                }
               
                tmp = prev;
        }
       
        content->op2_node = param;
       
        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;
        node->next                = NULL;

        if (pzop->opcode == ZEND_DO_FCALL_BY_NAME)
        {
                if (m_dez_op_current->dez_op == DEZ_OP_NEW)
                {
                        content = (DEZ_NODE_EXPR *)(m_dez_op_current->content);
                       
                        if (content->op1_node != NULL)
                        {
                                ((DEZ_NODE_EXPR *)(node->content))->op1_node = content->op1_node;
                        }
                       
                        content->op1_node = node;
                       
                        return 0;
                }
        }
       
        DEZ_ADD_NODE(node);

        return 0;
}

/*-- convertor for DEZ_OP_BOOL --*/
static int dez_node_cvt_bool (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *node, *tmp;
        DEZ_NODE_EXPR *content;
       
        if (
                pzop->op1.op_type == IS_CONST &&
                pzop->op1.u.constant.type == IS_BOOL &&
                pzop->op1.u.constant.value.lval == 1 &&
                ZEND_GET_ORI(pzop)[-1].opcode == ZEND_JMP
        )                                                                /* default of switch */
        {
                return dez_node_cvt_default(DEZ_OP_DEFAULT, ZEND_GET_ORI(pzop)-1);
        }               
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->op1_node                = NULL;
        content->op2_node                = NULL;

        node->dez_op                        = dez_op;
        node->zop                                = pzop;
        node->content                        = content;
        node->prev                                = NULL;
        node->next                                = NULL;
       
        tmp = fetch_tmp_node(&(pzop->result));
       
        if (tmp == NULL)
        {
                DEZ_ADD_NODE(node);

                return 0;
        }
       
        if (tmp->dez_op == DEZ_OP_LOGICAL_OR || tmp->dez_op == DEZ_OP_LOGICAL_AND)
        {
                content->op1_node        = fetch_tmp_node(&(pzop->op1));        /* 2nd condition */
               
                content->op2_node        = tmp;                                                        /* 1st condition */
               
                node->dez_op                = tmp->dez_op;
               
                DEZ_ADD_NODE(node);

                return 0;
        }
        else
        {
                return -1;
        }
}


static int dez_add_jmp_node(zend_op *pzop)
{
        DEZ_NODE *node;
        DEZ_NODE_EXPR *content;
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->op1_node                = NULL;
        content->op2_node                = NULL;
       
        node->dez_op        = DEZ_OP_JMP;
        node->zop                = pzop;
        node->content        = content;
        node->prev                = NULL;
        node->next                = NULL;
       
        DEZ_ADD_NODE(node);
       
        return 0;
}       

/*-- convertor for DEZ_OP_JMP --*/
static int dez_node_cvt_jmp (unsigned char dez_op, zend_op *pzop)
{
        DEZ_NODE *parent;
        int p_linenum;
       
        parent        = dez_node_get();
        if (parent == NULL)
        {
                p_linenum = -1;
        }
        else
        {
                p_linenum = get_zend_linenum(parent);
        }
       
        if (ZEND_LINENUM(pzop) < (int)(pzop->op1.u.opline_num))                        /* goto forward */
        {
                if (m_max_jmp_dest < pzop->op1.u.opline_num)
                {
                        m_max_jmp_dest = pzop->op1.u.opline_num;
                }
               
                if (
                        parent != NULL                                                &&
                        parent->dez_op == DEZ_OP_CASE
                )
                {
                        zend_op *dest;
                       
                        dest = m_zend_op_start + pzop->op1.u.opline_num;
                       
                        if (
                                (dest[-1].opcode == ZEND_JMPZ || dest[-1].opcode == ZEND_JMPZNZ)        &&
                                dest[-2].opcode == ZEND_CASE
                        )                                                                                                                /* the dest is 'case' */
                        {
                                dez_exit_branch(0);                                                                        /* exit the case branch */
                                return 0;
                        }
                        else if (
                                dest[-1].opcode == ZEND_BOOL        &&
                                dest[-2].opcode == ZEND_JMP
                        )                                                                                                                /* the dest is 'default' */
                        {
                                dez_exit_branch(0);                                                                        /* exit the case branch */
                                return 0;
                        }
                }
               
                return dez_node_cvt_if(DEZ_OP_IF, pzop);                                        /* add if (false) node */
        }
        else                                                                                                                        /* goto afterware */
        {
                int header_linenum;
                if (
                        parent != NULL && parent->dez_op == DEZ_OP_FOR &&
                        ((DEZ_NODE_FOR *)(parent->content))->before_node != NULL
                )
                {
                        header_linenum = get_zend_linenum(((DEZ_NODE_FOR *)(parent->content))->before_node);
                }
                else
                {
                        header_linenum = get_prev_zend_linenum(parent);
                }
               
                if ((int)(pzop->op1.u.opline_num) > p_linenum)                                /* within this branch */
                {
                        DEZ_NODE *node, *branch;
                        DEZ_NODE_IF *content;
                        int dest;
                       
                        if (
                                parent != NULL                                                &&
                                parent->dez_op == DEZ_OP_FOR
                        )
                        {
                                DEZ_NODE_FOR *content;
                               
                                content = (DEZ_NODE_FOR *)(parent->content);
                                if (content == NULL)
                                {
                                        return -1;
                                }
                               
                                if (
                                        content->after_node != NULL &&
                                        pzop->op1.u.opline_num <= get_zend_linenum(content->after_node)
                                )
                                {
                                        return 0;
                                }
                        }
#if 0
                        else if (
                                parent != NULL                                                &&
                                parent->dez_op == DEZ_OP_FOREACH
                        )
                        {
                                DEZ_NODE *dest;
                               
                                if (pzop->op1.u.opline_num == p_linenum+1)
                                {
                                        return 2;                                                                                /* exit foreach branch */
                                }
                        }
#endif
                       
                        content = (DEZ_NODE_IF *)malloc(sizeof(DEZ_NODE_IF));
                        if (content == NULL)
                        {
                                return -1;
                        }
                       
                        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                        if (node == NULL)
                        {
                                free(content);
                                return -1;
                        }
                       
                        branch = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                        if (branch == NULL)
                        {
                                return -1;
                        }
                       
                        branch->dez_op        = DEZ_OP_NOP;
                        branch->zop                = NULL;
                        branch->content        = NULL;
                        branch->prev        = NULL;
                        branch->next        = fetch_jmp_dest_node(pzop->op1.u.opline_num);
                        if (branch->next != NULL) branch->next->prev = branch;
                       
                        content->branch_node        = branch;
                        content->op1_node                = NULL;
                        content->op2_node                = NULL;
                        content->dest                        = ZEND_LINENUM(pzop);
                       
                        node->dez_op        = DEZ_OP_WHILE;
                        node->zop                = pzop;/*branch->next->zop;*/
                        node->content        = content;
                        node->prev                = NULL;
                        node->next                = NULL;
                       
                        dest = dez_get_branch_end(parent);

//                        dez_node_cvt_if(DEZ_OP_IF, pzop);                                        /* add if (false) */

                        clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, dest-ZEND_LINENUM(pzop)-1, 1);                /* recover the remainder opcodes in this branch */

                        DEZ_ADD_NODE(node);                                                                        /* add while (true) */
       
                        return 0;
                }
                else if (
                        (int)(pzop->op1.u.opline_num) <= p_linenum &&
                        (int)(pzop->op1.u.opline_num) > header_linenum
                )                                                                                                                /* the dest is the header of this branch */
                {
                        int dest;
                       
                        if (parent == NULL)
                        {
                                return 0;
                        }
                       
                        dest = dez_get_branch_end(parent);
                       
                        if (parent->dez_op == DEZ_OP_IF)
                        {
                                DEZ_NODE *pp;
                                int n = dest-ZEND_LINENUM(pzop)-1;
                               
                                if (parent->zop->opcode != ZEND_JMP)                        /* not if (false) */
                                {
                                        parent->dez_op = DEZ_OP_WHILE;
                                }
                               
                                if (dez_in_branch(parent, DEZ_OP_CASE) == 0)        /* the while() is in case branch */
                                {
                                        int i;
                                        zend_op *zp = ZEND_GET_ORI(pzop)+1;
                                       
                                        i = 0;
                                        while(i < n)
                                        {
                                                if (
                                                        (
                                                                zp[i].opcode == ZEND_JMP        &&
                                                                zp[i+1].opcode == ZEND_BOOL
                                                        )        ||                                                                /* default node */
                                                        (
                                                                zp[i].opcode == ZEND_CASE        &&
                                                                (zp[i+1].opcode == ZEND_JMPZ || zp[i+1].opcode == ZEND_JMPZNZ)
                                                        )                                                                        /* case node */
                                                )
                                                {
                                                        break;
                                                }
                                               
                                                i++;
                                        }
                                       
                                        if (i < n)                                                                        /* the case or default node was found */
                                        {
                                                zend_op *dupzop;
                                               
                                                dupzop = dez_dup_zend_op(pzop);
                                                dupzop->op1.u.opline_num = dest;
                                               
//                                                dez_node_cvt_jmp(DEZ_OP_JMP, dupzop);        /* add if (false) */
                                               
                                                n = i;
                                        }
                                }
                               
                                clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, n, 0);        /* clear the remainder opcodes in this branch */
       
                                dez_node_cvt_if(DEZ_OP_IF, pzop);                                /* add if (false) */

                                dez_exit_branch(0);                                                                /* exit the branch */
                               
                                return 0;
                        }
                        else if (parent->dez_op == DEZ_OP_FOR)
                        {
                                DEZ_NODE_FOR *content;
                               
                                content = (DEZ_NODE_FOR *)(parent->content);
                                if (content == NULL)
                                {
                                        return -1;
                                }
                               
                                if (content->after_node == NULL)
                                {
                                        content->after_node = fetch_jmp_dest_node(pzop->op1.u.opline_num);
                                }
                                else if (pzop->op1.u.opline_num == get_zend_linenum(content->after_node))
                                {
                                        clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, dest-ZEND_LINENUM(pzop)-1, 0);                /* clear the remainder opcodes in this branch */
                                       
                                        dez_node_cvt_if(DEZ_OP_IF, pzop);                        /* add if (false) */

                                        dez_exit_branch(0);                                                        /* exit the branch */
                                       
//                                        return dez_node_specs[DEZ_OP_CONTINUE].dez_node_cvt_func (DEZ_OP_CONTINUE, pzop);        /* add continue node */
                                }
                               
                                return 0;
                        }
                        else if (parent->dez_op == DEZ_OP_FOREACH)
                        {
                                clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, dest-ZEND_LINENUM(pzop)-1, 0);                        /* clear the remainder opcodes in this branch */
                               
                                dez_node_cvt_if(DEZ_OP_IF, pzop);                                /* add if (false) */

//                                return dez_node_specs[DEZ_OP_CONTINUE].dez_node_cvt_func (DEZ_OP_CONTINUE, pzop);                /* add continue node */
                        }
                       
                        return 0;
                }
                else                                                                                                        /* the dest is without this branch */
                {
                        int dest;
                        zend_op *prev_zop;
                       
                        dest = dez_get_branch_end(parent);
                        clear_or_recover_zend_op(ZEND_GET_ORI(pzop)+1, dest-ZEND_LINENUM(pzop)-1, 0);                                /* clear the remainder opcodes in this branch */

                        dest = dez_get_dest(parent);                                                // dez_get_branch_end(parent);
                       
                        if (
                                dest > ZEND_LINENUM(pzop) &&                                        /* jump foreward away */
                                parent != NULL        &&
                                parent->dez_op == DEZ_OP_ELSE
                        )                                                                                                        /* break? */
                        {
                                DEZ_NODE_EXPR *c;
                               
                                dez_exit_branch(0);                                                                /* exit this branch */
                               
                                /*-- fetch the sub branch and add them into m_dez_op_current --*/
                                c = (DEZ_NODE_EXPR *)(parent->content);
                                if (c != NULL && c->branch_node != NULL)                /* the sub branch is exist */
                                {
                                        m_dez_op_current->next = c->branch_node->next;
                                        if (c->branch_node->next != NULL) c->branch_node->next->prev = m_dez_op_current;
                                       
                                        free(c->branch_node);
                                        c->branch_node = NULL;
                                       
                                        while(m_dez_op_current->next != NULL) m_dez_op_current = m_dez_op_current->next;
                                }
                               
                                DEZ_DEL_NODE(parent);                                                        /* remove the else node */
                               
                                return dez_node_cvt_jmp(DEZ_OP_JMP, pzop);
                        }
                       
                        prev_zop = ZEND_GET_ORI(pzop)-1;
                        if (
                                m_dez_op_current->dez_op == DEZ_OP_WHILE && m_dez_op_current->zop->opcode == ZEND_JMP &&        /* the previous node is while(true) */
                                prev_zop->opcode == ZEND_JMP                                        &&
                                (int)(prev_zop->op1.u.opline_num) <= p_linenum        &&                        /* jmp to header */
                                (int)(prev_zop->op1.u.opline_num) > header_linenum                        /* ------------- */
                        )
                        {
                                /* do nothing */
                        }
                        else
                        {       
                                dez_node_cvt_if(DEZ_OP_IF, pzop);                                /* add if (false) node */
                        }

                        dez_exit_branch(1);                                                                        /* exit this branch */

                        return 0;
                }
        }
       
        return dez_node_cvt_expr (dez_op, pzop);                                        /* add jmp node */
}

/*-- convertor for DEZ_OP_FUNC_PARAM --*/
static int dez_node_cvt_func_param (unsigned char dez_op, zend_op *pzop)
{
        static char paramname[1024];
       
        DEZ_NODE *node, *parent, *param;
        DEZ_NODE_EXPR *content;
        DEZ_NODE_FUNCTION *funcc;
       
        parent = dez_node_get();
       
        if (parent == NULL)
        {
                return -1;
        }
       
        if (parent->dez_op != DEZ_OP_FUNCTION)
        {
                return -1;
        }
       
        funcc = (DEZ_NODE_FUNCTION *)(parent->content);
       
        if (funcc == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)malloc(sizeof(DEZ_NODE_EXPR));
        if (content == NULL)
        {
                return -1;
        }
       
        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (node == NULL)
        {
                free(content);
                return -1;
        }
       
        content->branch_node        = NULL;
        content->op1_node                = fetch_tmp_node(&(pzop->result));
       
#if 0
        if (content->op1_node == NULL)
        {
                sprintf(paramname, "dez_param_%u", pzop->result.u.var);
                dez_add_var(pzop->result.u.var, paramname, strlen(paramname));
        }
#endif
       
        if (pzop->opcode == ZEND_RECV_INIT)
        {
                content->op2_node = fetch_tmp_node(&(pzop->op2));
        }
        else
        {
                content->op2_node = NULL;
        }

        node->dez_op        = dez_op;
        node->zop                = pzop;
        node->content        = content;
        node->prev                = NULL;
        node->next                = NULL;
       
        param = funcc->param_node;
       
        if (param == NULL)
        {
                funcc->param_node = node;
        }
        else
        {
                while(param->next != NULL)
                {
                        param = param->next;
                }
       
                param->next                = node;
                node->prev                = param;
        }
       
        return 0;
}

/*-- convertor for DEZ_OP_UNKNOWN --*/
static int dez_node_cvt_unknown (unsigned char dez_op, zend_op *pzop)
{
        /**********/
        return 0;
}


static int dez_node_output_nop(DEZ_NODE *pdez_node)
{
        /******************/
        return 0;
}

static int dez_node_output_expr(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (
                pdez_node->dez_op == DEZ_OP_BW_NOT                        ||                /* ~ */
                pdez_node->dez_op == DEZ_OP_BOOL_NOT                                /* ! */
        )
        {
                printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
               
                if (content->op1_node != NULL)
                {
                        dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
                }
                else
                {
                        dez_dump_znode(&(pdez_node->zop->op1), 1);
                }
        }
        else if (
                pdez_node->dez_op == DEZ_OP_CONCAT                        &&
                pdez_node->zop->opcode == ZEND_ADD_CHAR
        )
        {
                printf ( "(");
               
                if (content->op1_node != NULL)
                {
                        dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
                }
                else
                {
                        dez_dump_znode(&(pdez_node->zop->op1), 1);
                }
               
                printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
               
                if (content->op2_node != NULL)
                {
                        dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
                }
                else
                {
                        printf ( "'%c'", (char)(pdez_node->zop->op2.u.constant.value.lval));
                }

                printf ( ")");
        }
        else
        {       
                if (
                        pdez_node->dez_op != DEZ_OP_OBJECT_OPERATOR
                )
                {
                        printf ( "(");
                }
               
                if (content->op1_node != NULL)
                {
                        dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
                }
                else
                {
                        dez_dump_znode(&(pdez_node->zop->op1), 1);
                }
               
                printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
               
                if (content->op2_node != NULL)
                {
                        dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
                }
                else
                {
                        dez_dump_znode(&(pdez_node->zop->op2), (pdez_node->dez_op == DEZ_OP_OBJECT_OPERATOR ? 0: 1));
                }
               
                if (
                        pdez_node->dez_op != DEZ_OP_OBJECT_OPERATOR
                )
                {
                        printf ( ")");
                }
        }
       
        return 0;
}

static int dez_node_output_cast(DEZ_NODE *pdez_node)
{
        static char *dez_cast_str[] =
        {
                "(unset)",
                "(int)",
                "(double)",
                "(string)",
                "(array)",
                "(object)",
                "(bool)"
        };
       
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_cast_str[pdez_node->zop->extended_value]);
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        return 0;
}

static int dez_node_output_qm_assign(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;
        DEZ_NODE *qm_true;
        DEZ_NODE_EXPR *content1;
        DEZ_NODE *qm_cond;
        DEZ_NODE_EXPR *content2;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        qm_true = content->op2_node;
        if (qm_true == NULL)
        {
                return -1;
        }
       
        content1 = (DEZ_NODE_EXPR *)(qm_true->content);
        if (content1 == NULL)
        {
                return -1;
        }
       
        printf ( "(");
       
        qm_cond = content1->op2_node;
        if (qm_cond == NULL)
        {
                printf ("true");
        }
        else
        {
                content2 = (DEZ_NODE_EXPR *)(qm_cond->content);
                if (content2 == NULL)
                {
                        return -1;
                }
               
                if (qm_cond->zop->opcode == ZEND_JMP)
                {
                        printf ("false");
                }
                else if (content2->op1_node != NULL)
                {
                        dez_node_specs[content2->op1_node->dez_op].dez_node_output_func (content2->op1_node);
                }
                else
                {
                        dez_dump_znode(&(qm_cond->zop->op1), 1);
                }
        }
       
        printf ( " ? ");
       
        if (content1->op1_node != NULL)
        {
                dez_node_specs[content1->op1_node->dez_op].dez_node_output_func (content1->op1_node);
        }
        else
        {
                dez_dump_znode(&(qm_true->zop->op1), 1);
        }
       
        printf ( " : ");
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_pre(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), (pdez_node->dez_op == DEZ_OP_FETCH ? 0 : 1));
        }
       
        return 0;
}

static int dez_node_output_pre2(DEZ_NODE *pdez_node)
{
        DEZ_NODE_IF *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_IF *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (pdez_node->dez_op == DEZ_OP_BREAK)
        {
                if (pdez_node->zop->opcode == ZEND_BRK)
                {
                        if (
                                pdez_node->zop->op2.op_type == IS_CONST &&
                                pdez_node->zop->op2.u.constant.type == IS_LONG &&
                                pdez_node->zop->op2.u.constant.value.lval == 1
                        )
                        {
                                /* do nothing */
                        }
                        else
                        {
                                printf (" ");
                               
                                if (content->op2_node != NULL)
                                {
                                        dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
                                }
                                else
                                {
                                        dez_dump_znode(&(pdez_node->zop->op2), 1);
                                }
                        }
                }
                else                                                /* ZEND_JMP */
                {
                        if (content->dest > 1)
                        {
                                printf (" %u", content->dest);
                        }
                }
        }
       
        return 0;
}

static int dez_node_output_post(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        return 0;
}

static int dez_node_output_assign(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (content->op2_node != NULL)
        {
                dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op2), 1);
        }
       
        return 0;
}

static int dez_node_output_assign_ref(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;
        zend_op *zop;
        zval **tmp;
        TSRMLS_FETCH();
        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (content->op2_node != NULL)
        {
                zop = content->op2_node->zop;
               
                if (zop->opcode == ZEND_FETCH_W && zop->op2.u.fetch_type == ZEND_FETCH_STATIC)                        /* static variable */
                {
                        zend_op_array *op_array;
                       
                        printf ( "static ");
                       
                        if (content->op1_node != NULL)
                        {
                                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
                        }
                        else
                        {
                                dez_dump_znode(&(pdez_node->zop->op1), 1);
                        }
                       
/*
                        dez_add_var (pdez_node->zop->op1.u.var, zop->op1.u.constant.value.str.val, zop->op1.u.constant.value.str.len);
                       
                        printf ( "static %s", dez_get_varname(&(pdez_node->zop->op1)));
*/

                                               
                        if (m_current_function == NULL)                                        /* main branch */
                        {
                                op_array = EG(active_op_array);
                        }
                        else
                        {
                                op_array = ((DEZ_NODE_FUNCTION *)(m_current_function->content))->op_array;
                        }
                       
                        tmp = NULL;
                        zend_hash_find(op_array->static_variables, zop->op1.u.constant.value.str.val, zop->op1.u.constant.value.str.len+1, (void **)&tmp);
                        if (tmp != NULL)                /* init value assigned */
                        {
                                printf ( " = ");
                                dez_dump_zval(**tmp, 1);
                        }
                       
                        return 0;
                }
                else if (zop->opcode == ZEND_FETCH_W && zop->op2.u.fetch_type == ZEND_FETCH_GLOBAL)                /* global variable */
                {
                        printf ( "global ");

                        if (content->op1_node != NULL)
                        {
                                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
                        }
                        else
                        {
                                dez_dump_znode(&(pdez_node->zop->op1), 1);
                        }
                       
/*
                        dez_add_var (pdez_node->zop->op1.u.var, zop->op1.u.constant.value.str.val, zop->op1.u.constant.value.str.len);
                       
                        printf ( "global %s", dez_get_varname(&(pdez_node->zop->op1)));
*/
                       
                        return 0;
                }
#if 0
                else if (zop->opcode == ZEND_FETCH_W && zop->op2.u.fetch_type == ZEND_FETCH_LOCAL)                /* local variable */
                {
                        dez_add_var (pdez_node->zop->op1.u.var, zop->op1.u.constant.value.str.val, zop->op1.u.constant.value.str.len);
                       
                        printf ( "%s", dez_get_varname(&(pdez_node->zop->op1)));
                       
                        return 0;
                }
#endif
        }
       
        /*-- a = &b --*/
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (content->op2_node != NULL)
        {
                dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op2), 1);
        }
       
        return 0;
}

static int dez_node_output_include_or_eval(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;
        char *str;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        switch (pdez_node->zop->op2.u.constant.value.lval)
        {
                case ZEND_EVAL:
                        str = "eval (";
                        break;
                case ZEND_INCLUDE:
                        str = "include ";
                        break;
                case ZEND_INCLUDE_ONCE:
                        str = "include_once ";
                        break;
                case ZEND_REQUIRE:
                        str = "require ";
                        break;
                case ZEND_REQUIRE_ONCE:
                        str = "require_once ";
                        break;
        }
       
        printf ( str);
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        if (pdez_node->zop->op2.u.constant.value.lval == ZEND_EVAL)
        {
                printf ( ")");
        }
       
        return 0;
}

static int dez_node_output_or_and(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }

        printf ( "(");
       
        if (content->op2_node != NULL)
        {
                DEZ_NODE_EXPR *cond1 = (DEZ_NODE_EXPR *)(content->op2_node->content);
               
                if (cond1->op1_node != NULL)
                {
                        dez_node_specs[cond1->op1_node->dez_op].dez_node_output_func (cond1->op1_node);
                }
                else
                {
                        dez_dump_znode(&(content->op2_node->zop->op1), 1);
                }
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_new(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
               
/*
                switch(pdez_node->zop->op1.op_type)
                {
                        case IS_CONST:
                                printf ("%s", pdez_node->zop->op1.u.constant.value.str.val);
                                break;
                        case 16:
                                printf ("%s", dez_get_varname(&(pdez_node->zop->op1)));
                                break;
                }
*/
        }
       
        return 0;
}

static int dez_node_output_exit(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ( "exit (");
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_if(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        printf ( "(");
       
        if (pdez_node->zop->opcode == ZEND_JMP)
        {
                printf ( (pdez_node->dez_op == DEZ_OP_WHILE ? "true" : "false"));
        }
        else
        {
                if (content->op1_node != NULL)
                {
                        dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
                }
                else
                {
                        dez_dump_znode(&(pdez_node->zop->op1), 1);
                }
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_do(DEZ_NODE *pdez_node)
{
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        return 0;
}

static int dez_node_output_for(DEZ_NODE *pdez_node)
{
        DEZ_NODE *node;
        DEZ_NODE_FOR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_FOR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        printf ( "(");
       
        if (content->before_node != NULL)
        {
                dez_node_specs[content->before_node->dez_op].dez_node_output_func (content->before_node);
        }
       
        printf ( "; ");
       
        if (content->cond_node != NULL)
        {
                dez_node_specs[content->cond_node->dez_op].dez_node_output_func (content->cond_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ( "; ");
       
        node = content->after_node;
        while (node != NULL)
        {
                dez_node_specs[node->dez_op].dez_node_output_func (node);
               
                node = node->next;
               
                if (node != NULL)
                {
                        printf ( ", ");
                }
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_foreach(DEZ_NODE *pdez_node)
{
        DEZ_NODE *node;
        DEZ_NODE_FOREACH *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_FOREACH *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        printf ( "(");
       
        if (content->source_node != NULL)
        {
                dez_node_specs[content->source_node->dez_op].dez_node_output_func (content->source_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ( " as ");
       
        if (content->key_node != NULL)
        {
                dez_node_specs[content->key_node->dez_op].dez_node_output_func (content->key_node);
                printf ("%s", dez_node_specs[DEZ_OP_DOUBLE_ARROW].desc);
        }
       
        if (content->value_node != NULL)
        {
                dez_node_specs[content->value_node->dez_op].dez_node_output_func (content->value_node);
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_declare(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        printf ( "(");
       
        if (pdez_node->zop->opcode == ZEND_TICKS)
        {
                printf ( "ticks = ");
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_case(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (content->op2_node != NULL)
        {
                dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op2), 1);
        }
       
        printf ( ":");
       
        return 0;
}

static int dez_node_output_default(DEZ_NODE *pdez_node)
{
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        return 0;
}

static int dez_node_output_function(DEZ_NODE *pdez_node)
{
        DEZ_NODE *node;
        DEZ_NODE_FUNCTION *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_FUNCTION *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        printf ("%s", content->name);
       
        printf ( " (");
       
        for (node = content->param_node; node != NULL; node = node->next)
        {
                if (
                        content->op_array != NULL &&
                        content->op_array->arg_types != NULL &&
                        content->op_array->arg_types[node->zop->op1.u.constant.value.lval] == BYREF_FORCE
                )
                {
                        printf ("&");
                }

                dez_node_specs[node->dez_op].dez_node_output_func (node);
               
                if (node->next != NULL)
                {
                        printf ( ", ");
                }
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_var(DEZ_NODE *pdez_node)
{
        DEZ_NODE_VAR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_VAR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (content->property != NULL)
        {
                printf ("$%s", content->property->arKey);
               
                if (content->property->pData != NULL)
                {
                        printf ( " = ");
                       
                        dez_dump_zval(**((zval **)(content->property->pData)), 1);
                }
        }
       
        return 0;
}

static int dez_node_output_unset(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        printf ( "($");
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 0);
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_isset_or_empty(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (pdez_node->zop->op2.u.constant.value.lval == 1)
        {
                printf ("%s", dez_node_specs[DEZ_OP_ISSET].desc);
        }
        else
        {
                printf ("%s", dez_node_specs[DEZ_OP_EMPTY].desc);
        }
       
        printf ( "(");
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_class(DEZ_NODE *pdez_node)
{
        DEZ_NODE *node;
        DEZ_NODE_CLASS *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_CLASS *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        printf ("%s", content->name);
       
        if (content->parent != NULL)
        {
                printf ( " extends %s", content->parent->name);
        }
       
        return 0;
}

static int dez_node_output_double_arrow(DEZ_NODE *pdez_node)
{
        DEZ_NODE *node;
        DEZ_NODE_DA *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_DA *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (content->next_node != NULL)                                        /* is not the first element */
        {
                dez_node_output_double_arrow(content->next_node);
                printf ( ", ");
        }
       
        if (pdez_node->zop->op2.op_type != IS_UNUSED)
        {
                if (content->key_node != NULL)
                {
                        dez_node_specs[content->key_node->dez_op].dez_node_output_func (content->key_node);
                }
                else
                {
                        dez_dump_znode(&(pdez_node->zop->op2), 1);
                }
               
                printf ("%s", dez_node_specs[DEZ_OP_DOUBLE_ARROW].desc);
        }
       
        if (content->value_node != NULL)
        {
                if (content->value_node->zop->opcode == ZEND_FETCH_W)                        /* refrence variable */
                {
                        printf ( "&");
                }
               
                dez_node_specs[content->value_node->dez_op].dez_node_output_func (content->value_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        return 0;
}

static int dez_node_output_list(DEZ_NODE *pdez_node)
{
        DEZ_NODE_LIST *lc;
        DEZ_NODE *le;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        lc = (DEZ_NODE_LIST *)(pdez_node->content);
        if (lc == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
        printf ( "(");
       
        le = lc->le_node;
        while (le != NULL)
        {
                dez_node_specs[le->dez_op].dez_node_output_func (le);
               
                le = le->next;
               
                if (le != NULL)
                {
                        printf ( ", ");
                }
        }
       
        printf ( ")");
       
        if (lc->dest_node != NULL)
        {
                DEZ_NODE *last_fetch, *next;
                DEZ_NODE_EXPR *dc = (DEZ_NODE_EXPR *)(lc->dest_node->content);
               
                last_fetch = lc->dest_node;
                while (last_fetch != NULL)
                {
                        next = ((DEZ_NODE_EXPR *)(last_fetch->content))->op1_node;
                        if (
                                next == NULL ||
                                next->dez_op != DEZ_OP_FETCH_DIM
                        )
                        {
                                break;
                        }
                       
                        last_fetch = next;
                }
               
                if (
                        last_fetch != NULL &&
                        (
                                ((DEZ_NODE_EXPR *)(last_fetch->content))->op1_node != NULL ||
                                (last_fetch->zop->op1.op_type != IS_TMP_VAR && last_fetch->zop->op1.op_type != IS_VAR)
                        )
                )
                {
                        printf ("%s", dez_node_specs[DEZ_OP_ASSIGN].desc);
                       
                        if (dc->op1_node != NULL)
                        {
                                dez_node_specs[dc->op1_node->dez_op].dez_node_output_func (dc->op1_node);
                        }
                        else
                        {
                                dez_dump_znode(&(lc->dest_node->zop->op1), 1);
                        }
                }
        }

        return 0;
}

static int dez_node_output_le(DEZ_NODE *pdez_node)
{
        DEZ_NODE_LE *lec;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        lec = (DEZ_NODE_LE *)(pdez_node->content);
        if (lec == NULL)
        {
                return -1;
        }
       
        if (lec->a_node != NULL)
        {
                if (lec->a_node->dez_op == DEZ_OP_LIST)
                {
                        dez_node_specs[lec->a_node->dez_op].dez_node_output_func (lec->a_node);
                }
                else if (lec->a_node->dez_op == DEZ_OP_ASSIGN)
                {
                        DEZ_NODE_EXPR *ac = (DEZ_NODE_EXPR *)(lec->a_node->content);
                       
                        if (ac->op1_node != NULL)
                        {
                                dez_node_specs[ac->op1_node->dez_op].dez_node_output_func (ac->op1_node);
                        }
                        else
                        {
                                dez_dump_znode(&(lec->a_node->zop->op1), 1);
                        }
                }
        }
       
        return 0;
}

static int dez_node_output_array(DEZ_NODE *pdez_node)
{
        DEZ_NODE_DA *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_DA *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        printf ( "(");
       
        pdez_node->dez_op = DEZ_OP_DOUBLE_ARROW;
        dez_node_output_double_arrow(pdez_node);
        pdez_node->dez_op = DEZ_OP_ARRAY;
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_heredoc(DEZ_NODE *pdez_node)
{
        /******************/
        return 0;
}

static int dez_node_output_dollar_open_curly_braces(DEZ_NODE *pdez_node)
{
        /******************/
        return 0;
}

static int dez_node_output_call_param(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (pdez_node->zop->opcode == ZEND_SEND_REF)
        {
                printf ( "&");
        }
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        return 0;
}

static int dez_node_output_call_init(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (pdez_node->zop->op1.op_type != IS_UNUSED)
        {
                if (content->op1_node != NULL)
                {
                        dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
                       
                        printf ( "->");
                }
                else
                {
                        dez_dump_znode(&(pdez_node->zop->op1), 0);
                       
                        if (
                                pdez_node->zop->op1.op_type == IS_CONST                &&
                                pdez_node->zop->op1.u.constant.type == IS_STRING
                        )                                                                        /* class method calling */
                        {
                                printf ( "::");
                        }
                        else
                        {
                                printf ( "->");
                        }
                }
               
        }
       
        if (content->op2_node != NULL)
        {
                dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op2), 0);
        }
       
        return 0;
}

static int dez_node_output_call(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;
        DEZ_NODE *param;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 0);
        }
       
        printf ( " (");
       
        for (param = content->op2_node; param != NULL; param = param->next)
        {
                dez_node_specs[param->dez_op].dez_node_output_func (param);
               
                if (param->next != NULL)
                {
                        printf ( ", ");
                }
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_call_ex(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;
        DEZ_NODE *param;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_get_funcname(&(pdez_node->zop->op1)));
       
        printf ( " (");
       
        for (param = content->op2_node; param != NULL; param = param->next)
        {
                dez_node_specs[param->dez_op].dez_node_output_func (param);
               
                if (param->next != NULL)
                {
                        printf ( ", ");
                }
        }
       
        printf ( ")");
       
        return 0;
}

static int dez_node_output_fetch_dim(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op1), 1);
        }
       
        printf ( "[");
       
        if (content->op2_node != NULL)
        {
                dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->op2), 1);
        }
       
        printf ( "]");
       
        return 0;
}

static int dez_node_output_init_string(DEZ_NODE *pdez_node)
{
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        return 0;
}

static int dez_node_output_fetch_constant(DEZ_NODE *pdez_node)
{
        dez_dump_znode(&(pdez_node->zop->op1), 0);
       
        return 0;
}

static int dez_node_output_func_param(DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return -1;
        }
       
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content == NULL)
        {
                return -1;
        }
       
        printf ("%s", dez_node_specs[pdez_node->dez_op].desc);
       
        if (content->op1_node != NULL)
        {
                dez_node_specs[content->op1_node->dez_op].dez_node_output_func (content->op1_node);
        }
        else
        {
                dez_dump_znode(&(pdez_node->zop->result), 1);
        }
       
        if (pdez_node->zop->opcode == ZEND_RECV_INIT)
        {
                printf ( " = ");
               
                if (content->op2_node != NULL)
                {
                        dez_node_specs[content->op2_node->dez_op].dez_node_output_func (content->op2_node);
                }
                else
                {
                        dez_dump_znode(&(pdez_node->zop->op2), 1);
                }
        }
               
        return 0;
}


static int dez_node_output_unknown(DEZ_NODE *pdez_node)
{
        /******************/
        return 0;
}


/*-- free all dez nodes --*/
static void dez_node_free (void)
{
        if (m_dez_op_root != NULL)
        {
                dez_node_specs[m_dez_op_root->dez_op].dez_node_free_func(m_dez_op_root);
               
                m_dez_op_root = NULL;
        }
}


/*-- free function for DEZ_NODE_NOP node --*/
static void dez_node_free_nop (DEZ_NODE *pdez_node)
{
        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        if (pdez_node->content != NULL)
        {
                /**********/
               
                free(pdez_node->content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_expr (DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->op1_node) dez_node_specs[content->op1_node->dez_op].dez_node_free_func(content->op1_node);
                if (content->op2_node) dez_node_specs[content->op2_node->dez_op].dez_node_free_func(content->op2_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_if (DEZ_NODE *pdez_node)
{
        DEZ_NODE_IF *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_IF *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->op1_node) dez_node_specs[content->op1_node->dez_op].dez_node_free_func(content->op1_node);
                if (content->op2_node) dez_node_specs[content->op2_node->dez_op].dez_node_free_func(content->op2_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_for (DEZ_NODE *pdez_node)
{
        DEZ_NODE_FOR *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_FOR *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->before_node) dez_node_specs[content->before_node->dez_op].dez_node_free_func(content->before_node);
                if (content->cond_node) dez_node_specs[content->cond_node->dez_op].dez_node_free_func(content->cond_node);
                if (content->after_node) dez_node_specs[content->after_node->dez_op].dez_node_free_func(content->after_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_foreach (DEZ_NODE *pdez_node)
{
        DEZ_NODE_FOREACH *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_FOREACH *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->source_node) dez_node_specs[content->source_node->dez_op].dez_node_free_func(content->source_node);
                if (content->key_node) dez_node_specs[content->key_node->dez_op].dez_node_free_func(content->key_node);
                if (content->value_node) dez_node_specs[content->value_node->dez_op].dez_node_free_func(content->value_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_case (DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->op2_node) dez_node_specs[content->op2_node->dez_op].dez_node_free_func(content->op2_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_default (DEZ_NODE *pdez_node)
{
        DEZ_NODE_EXPR *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_EXPR *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_function (DEZ_NODE *pdez_node)
{
        DEZ_NODE_FUNCTION *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_FUNCTION *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->param_node) dez_node_specs[content->param_node->dez_op].dez_node_free_func(content->param_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_var (DEZ_NODE *pdez_node)
{
        DEZ_NODE_VAR *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_VAR *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_class (DEZ_NODE *pdez_node)
{
        DEZ_NODE_CLASS *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_CLASS *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_da (DEZ_NODE *pdez_node)
{
        DEZ_NODE_DA *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_DA *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->key_node) dez_node_specs[content->key_node->dez_op].dez_node_free_func(content->key_node);
                if (content->value_node) dez_node_specs[content->value_node->dez_op].dez_node_free_func(content->value_node);
                if (content->next_node) dez_node_specs[content->next_node->dez_op].dez_node_free_func(content->next_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_array (DEZ_NODE *pdez_node)
{
        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        if (pdez_node->content != NULL)
        {
                /**********/
               
                free(pdez_node->content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_list (DEZ_NODE *pdez_node)
{
        DEZ_NODE_LIST *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_LIST *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->le_node) dez_node_specs[content->le_node->dez_op].dez_node_free_func(content->le_node);
                if (content->dest_node) dez_node_specs[content->dest_node->dez_op].dez_node_free_func(content->dest_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_le (DEZ_NODE *pdez_node)
{
        DEZ_NODE_LE *content;

        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        content = (DEZ_NODE_LE *)(pdez_node->content);
        if (content != NULL)
        {
                if (content->branch_node) dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);
                if (content->a_node) dez_node_specs[content->a_node->dez_op].dez_node_free_func(content->a_node);
               
                free(content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_heredoc (DEZ_NODE *pdez_node)
{
        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        if (pdez_node->content != NULL)
        {
                /**********/
               
                free(pdez_node->content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_dollar_open_curly_braces (DEZ_NODE *pdez_node)
{
        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        if (pdez_node->content != NULL)
        {
                /**********/
               
                free(pdez_node->content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}

static void dez_node_free_unknown (DEZ_NODE *pdez_node)
{
        if (pdez_node == NULL)
        {
                return;
        }
       
        /*-- free the next node --*/
        if (pdez_node->next != NULL)
        {
                dez_node_specs[pdez_node->next->dez_op].dez_node_free_func(pdez_node->next);
        }
       
        /*-- free the node content --*/
        if (pdez_node->content != NULL)
        {
                /**********/
               
                free(pdez_node->content);
        }
       
        /*-- free the node self */
        free(pdez_node);
}


/**********************************************************
*  dez_dump_op: dump a dez op
*
*  @param dez_op: the dez op code need to be dumped
*  @return 0: normal, 1: enter a branch, 2: exit the branch, 3: need to continue -1: error
**********************************************************/
static int dez_dump_op (unsigned char dez_op)
{
        return dez_node_specs[dez_op].dez_node_cvt_func (dez_op, m_op_buffer[0]);
}


/**********************************************************
*  dez_dump_zend_op: dump a zend op
*
*  @param pzop:        pointer to the zend_op need to be dumped
*  @return 0: normal, 1: enter a branch, 2: exit the branch, -1: error
**********************************************************/
static int dez_dump_zend_op (zend_op *pzop)
{
//printf ( "%u,", pzop->opcode);
//return 0;

        printf ( "    %6u:", ZEND_LINENUM(pzop));
       
        if (pzop->opcode >= sizeof(ZEND_OP_STRING)/sizeof(ZEND_OP_STRING[0]))
        {
                printf ( "<%u>    ", pzop->opcode);
        }
        else
        {
                printf ("%s", ZEND_OP_STRING[pzop->opcode]);
        }

        dez_dump_znode_ex(&(pzop->result), 1);
        printf ( ", ");

        dez_dump_znode_ex(&(pzop->op1), 1);
        printf ( ", ");

        dez_dump_znode_ex(&(pzop->op2), 1);
        printf ( "\r\n");

        return 0;
       
//        return dez_node_specs[DEZ_OP_UNKNOWN].dez_node_cvt_func (DEZ_OP_UNKNOWN, pzop);
}


/**********************************************************
*  dez_deal_op: deal with a zend_op
*
*  @param pzop:        pointer to the zend_op would be dealed with. NULL means uninitialization
*  @param match_n: used to retreive the number of matching zend_op
*  @return 0: success, 1: enter a branch, 2: exit the branch, -1: error
**********************************************************/
static int dez_deal_op (zend_op *pzop, short *match_n)
{
        static unsigned char *op_masks = NULL;                                        /* each element: 0: need to continue, 1: not matching, 2: matching */
        static int op_num = 0;
       
        register int i;
        int needcontinues;
        short mn;
        int matching_i;
        int r;
       
        *match_n = 0;
       
        if (op_masks == NULL)                                                                        /* initialization */
        {
                op_masks = (unsigned char *)malloc(sizeof(dez_op_types)/sizeof(dez_op_types[0]));
                if (op_masks == NULL)                                                                /* fail to alloc memery */
                {
                        return -1;
                }
               
                op_num = sizeof(dez_op_types)/sizeof(dez_op_types[0]);
               
                memset (op_masks, 0, op_num);                                                /* initialize op_masks */
        }
       
        if (pzop != NULL)
        {
                if (dez_opc_push (pzop) != 0)                                                /* push the zend op into stack */
                {                                                                                                        /* fail */
                        return -1;
                }
        }
       
        needcontinues        = 0;
        mn                                = 0;
        for (i = 0; i < op_num; i++)
        {
                if (op_masks[i] == 0)                                                                /* need to continue */
                {
                        op_masks[i] = dez_opc_compare (dez_op_types[i].opcs, dez_op_types[i].opcs_len);
                }
               
                switch (op_masks[i])
                {
                        case 0:                                                                                        /* need to continue */
                                needcontinues++;
                                break;
                        case 1:                                                                                        /* not matching */
                                break;
                        case 2:                                                                                        /* matching */
                                if (mn < dez_op_types[i].opcs_len)
                                {
                                        mn                                = dez_op_types[i].opcs_len;
                                        matching_i                = i;
                                }
                                break;
                }
        }
       
        if (pzop == NULL)                                                                                /* uninitialization */
        {
                if (m_opc_num > 0)                                                                        /* the stack is not empty */
                {
                        if (mn > 0)                                                                                /* any dez op is matching */
                        {
                                *match_n = mn;
                                dez_dump_op (dez_op_types[matching_i].dez_op);        /* dump the matching dez op */
                        }
                        else                                                                                        /* all dez ops ara not matching */
                        {
                                mn = 1;
                                *match_n = mn;
                                dez_dump_zend_op (m_op_buffer[0]);                        /* dump the zend op at the top of stack */
                        }
                       
                        memset (op_masks, 0, op_num);                                        /* reset op_masks */
                       
                        dez_opc_pop(mn);
                       
                        dez_deal_op (NULL, match_n);
                }
                else
                {
                        if (op_masks != NULL)
                        {
                                free (op_masks);
                                op_masks = NULL;
                        }
                }
        }
        else if (needcontinues == 0)                                                        /* no one dez op need to continue */
        {
                if (mn > 0)                                                                                        /* any dez op is matching */
                {
                        *match_n = mn;
                       
                        do
                        {
                                r = dez_dump_op (dez_op_types[matching_i].dez_op);        /* dump the matching dez op */
                        } while(r == 3);                                                                /* continue to deal with the zend op */
                }
                else                                                                                                /* all dez ops ara not matching */
                {
                        mn = 1;
                        *match_n = mn;
                       
                        r = dez_dump_zend_op (m_op_buffer[0]);                        /* dump the zend op at the top of stack */
                }
               
                memset (op_masks, 0, op_num);                                                /* reset op_masks */
               
                return r;
        }
       
        return 0;
}


/**********************************************************
*  dez_deal_op_end: end process
*
*  @param header: the header of dez nodes
*  @param perant: the parent node
*  @return 0: success; other: failed
**********************************************************/
static int dez_deal_node_end(DEZ_NODE *header, DEZ_NODE *parent)
{
        DEZ_NODE_EXPR *content;
        DEZ_NODE *p, *next;
        int begin, end, prevcond;
        DEZ_BRK_CNT_NODE *pbcn_header, *pbcn, *pbcn_next;
       
        pbcn_header        = m_dez_brk_cnt_tail;
       
        begin                = 0;
        end                        = 100000;
        prevcond        = -1;
       
        dez_branch_get_range(parent, &begin, &end);

        if (parent != NULL && parent->dez_op == DEZ_OP_DO)
        {
                DEZ_NODE *prev, *sub;
               
                prev = dez_get_last_sub_node(parent);
               
                while(prev)
                {
                        if (
                                prev->dez_op == DEZ_OP_DO        ||                                                                                /* do{...}while() */
                                prev->dez_op == DEZ_OP_WHILE && prev->zop->opcode == ZEND_JMP                /* while(true) */
                        )
                        {
                                break;
                        }
                       
                        sub = dez_get_last_sub_node(prev);
                       
                        if (sub == NULL)
                        {
                                break;
                        }
                       
                        prev = sub;
                }
               
                if (prev == NULL)                                                        /* no sub branch */
                {
                        prevcond = get_prev_zend_linenum(parent);
                }
                else
                {
                        prevcond = get_zend_linenum(prev);
                }
        }
        else if (parent != NULL && parent->dez_op == DEZ_OP_FOR)
        {
                DEZ_NODE *before_node = ((DEZ_NODE_FOR *)(parent->content))->before_node;
               
                if (before_node != NULL)
                {
                        prevcond = get_zend_linenum(before_node);
                }
                else
                {
                        prevcond = get_prev_zend_linenum(parent);
                }
        }
        else
        {
                prevcond = get_prev_zend_linenum(parent);
        }
       
        p = header;
       
        while(p != NULL)
        {
                content = (DEZ_NODE_EXPR *)(p->content);
               
                if (p->dez_op == DEZ_OP_IF && p->zop->opcode == ZEND_JMP)        /* if (false) node */
                {
                        int dest;
                       
                        if (content != NULL && content->branch_node != NULL)        /* sub branch is exist */
                        {
                                dez_node_specs[content->branch_node->dez_op].dez_node_free_func(content->branch_node);        /* remove the sub branch */
                                content->branch_node = NULL;
                        }
                       
                        dest = p->zop->op1.u.opline_num;
                       
                        if (dest < begin || dest > end)                                                        /* jmp out of the branch */
                        {
                                if (p->next != NULL)
                                {
                                        dez_node_specs[p->next->dez_op].dez_node_free_func(p->next);        /* remove remainder nodes in this  branch */
                                        p->next = NULL;
                                }
                        }

                        ((DEZ_NODE_IF *)content)->dest = 0;                                                /* maybe break */
                        dez_brk_cnt_add(p);
                }
                else if (content != NULL && content->branch_node != NULL)        /* sub branch is exist */
                {
                        dez_node_push(p);                                                                                /* for get_prev_zend_linenum() */
                       
                        dez_deal_node_end(content->branch_node, p);                                /* deal with the sub branch */

                        dez_node_pop();                                                                                        /* for get_prev_zend_linenum() */
                }

                p = p->next;
        }
       
        if (pbcn_header != NULL)
        {
                pbcn = pbcn_header->next;
        }
        else
        {
                pbcn = m_dez_brk_cnt_root;
        }
       
        while(pbcn != NULL)
        {
                DEZ_NODE *n;
                DEZ_NODE_IF *c;
                int dest;
                int checked;
               
                pbcn_next = pbcn->next;
               
                n = (DEZ_NODE*)(pbcn->node);
                c = (DEZ_NODE_IF *)(n->content);
                dest = n->zop->op1.u.opline_num;
               
                checked = 0;
               
                if (
                        parent != NULL                                                        &&
                        (
                                parent->dez_op == DEZ_OP_WHILE                ||
                                parent->dez_op == DEZ_OP_DO                        ||
                                parent->dez_op == DEZ_OP_FOR                ||
                                parent->dez_op == DEZ_OP_FOREACH        ||
                                parent->dez_op == DEZ_OP_SWITCH
                        )
                )                                                                                                                /* loop or switch */
                {
                        int endcond;
                        if (parent->dez_op == DEZ_OP_WHILE && parent->zop->opcode == ZEND_JMP)        /* while(true) */
                        {
                                endcond = prevcond+1;
                        }
                        else
                        {
                                endcond = get_zend_linenum(parent);
                        }
                       
                        if (dest < begin || dest > end)                                                /* jmp out of the branch */
                        {
                                n->dez_op = DEZ_OP_BREAK;
                                c->dest++;
                               
                                checked = 1;
                        }
                        else if (
                                c->dest == 0                                        &&                                /* maybe continue */
                                dest > prevcond && dest <= endcond                                /* jmp to condition */
                        )
                        {
                                n->dez_op = DEZ_OP_CONTINUE;
                               
                                checked = 1;
                        }
                }
                else if (
                        parent != NULL                                                &&
                        parent->dez_op == DEZ_OP_IF
                )
                {
                        if (
                                n->dez_op == DEZ_OP_BREAK                &&
                                dest > prevcond                                        &&                                /* jmp to condition */
                                dest <= get_zend_linenum(parent)                                /*                  */
                        )
                        {
                                parent->dez_op = DEZ_OP_WHILE;                                        /* IF -> WHILE */
                        }
                }
               
                if (checked != 0)                                                                                /* break or continue was found */
                {
#if 0
                        if (c != NULL && c->branch_node != NULL)                        /* sub branch is exist */
                        {
                                DEZ_NODE *lastsubnode = c->branch_node;
                                while(lastsubnode->next != NULL)
                                {
                                        lastsubnode = lastsubnode->next;
                                }
                               
                                lastsubnode->next = n->next;
                                if (lastsubnode->next != NULL) lastsubnode->next->prev = lastsubnode;
                               
                                n->next = c->branch_node->next;
                                if (n->next != NULL) n->next->prev = n;
                               
                                c->branch_node->next = NULL;
                                free(c->branch_node);
                                c->branch_node = NULL;
                        }
#endif
                }
               
                if (dest >= begin && dest <= end)                                                /* jmp within the branch */
                {
                        dez_brk_cnt_del(pbcn);
                       
                        if (n->dez_op == DEZ_OP_IF)                                                        /* not break/continue */
                        {
                                DEZ_DEL_NODE(n);
                        }
                        else if(n->dez_op == DEZ_OP_CONTINUE)                                /* the continue node */
                        {
                                DEZ_NODE *lastsubnode = dez_get_last_sub_node(parent);
                                if (lastsubnode == n)                                                        /* the continue node is last node in branch */
                                {
                                        DEZ_DEL_NODE(n);
                                }
                        }
                }
               
                pbcn = pbcn_next;
        }
       
        return 0;
}

/**********************************************************
*  dez_decompile: decompile some zend ops
*
*  @param ops:        the array of zend_ops would be decompiled
*  @param n:        the number of ops
*  @return 0: success; other: failed
**********************************************************/
static int dez_decompile (zend_op *ops, int n)
{
        int r;
        DEZ_NODE_EXPR *content;
       
static struct _zend_executor_globals *zeg;
        TSRMLS_FETCH();
        dez_prep_zend_op(ops, n);                                                /* pre process the zend op */
               
        m_zend_op_start                = ops;
        m_zend_op_end                = ops+n;
       
        m_zend_op_current        = m_zend_op_start;

        while (m_zend_op_current < m_zend_op_end)
        {
zeg = (struct _zend_executor_globals *)&EG(return_value_ptr_ptr);
//dez_dump_zend_op(m_zend_op_current);        /****** for debug */
//m_zend_op_current++;
//continue;

                r = dez_deal_op (m_zend_op_current, &m_zend_op_match_n);        /* deal with a zend_op */

                if (r == 0)                                                                        /* success to deal with the zend_op */
                {
                        /* do nothing */
                }
                else if (r == 1)                                                        /* enter a branch */
                {
                        dez_enter_branch();
                }
                else if (r == 2)                                                        /* exit the branch */
                {
                        dez_exit_branch(1);                                                /* exit the branch */
                }
                else                                                                                /* error */
                {
                        return r;
                }
               
                dez_check_exit_branch();
               
                dez_opc_pop (m_zend_op_match_n);                        /* pop the matching zend op */

                if (m_opc_num > 0)                                                        /* some zend_ops is in stack */
                {
                        dez_opc_refresh();                                                /* update the opcodes in stack */
                }
               
                m_zend_op_current++;
        }
       
        dez_deal_op(NULL, &m_zend_op_match_n);                        /* process the remainder zend op in stack */
       
        dez_check_exit_all();                                                        /* exit all branch */

        dez_deal_node_end(m_dez_op_root, NULL);                        /* end process (make BREAK, CONTINUE node) */
       
        dez_brk_cnt_free();                                                                /* free the break/continue list */

        clear_or_recover_zend_op(NULL, 0, 0);                        /* clear the opcodes cleared */
       
        return 0;
}


/**********************************************************
*  dez_output: output the zend nodes
*
*  @param header: the header of dez nodes
*  @param perant: the parent node
*  @return 0: success; other: failed
**********************************************************/
static int dez_output (DEZ_NODE *header, DEZ_NODE *parent)
{
        static char m_tab[1024] = {' ',' ','\0'};
       
        static int m_dez_declare = 0;
        static int m_dez_silence = 0;

        DEZ_NODE_EXPR *content;
        DEZ_NODE *p, *next;
        DEZ_NODE *function_node;
       
        if (m_dez_declare > 0)
        {
                m_dez_declare++;
        }
       
        p = header;
       
        while(p != NULL)
        {
                next = p->next;
               
                if (
                        p->dez_op == DEZ_OP_NOP                ||
                        p->dez_op == DEZ_OP_DECLARE
                )
                {
                        p = next;
                        continue;
                }
                else if (p->dez_op == DEZ_OP_BEGIN_SILENCE)
                {
                        m_dez_silence = 1;
                       
                        p = next;
                        continue;
                }
                else if (p->dez_op == DEZ_OP_END_SILENCE)
                {
                        m_dez_silence = 0;
                       
                        p = next;
                        continue;
                }
               
                if (
                        next != NULL &&
                        next->dez_op == DEZ_OP_DECLARE
                )
                {
                        if (m_dez_declare == 0)
                        {
                                m_dez_declare = 1;                                                                        /* enter declare branch */
                                printf ("%s", m_tab);
                                dez_node_specs[next->dez_op].dez_node_output_func (next);
                                printf ("\r\n%s{\r\n", m_tab);
                                strcat(m_tab, "  ");
                        }
                }
                else
                {
                        if (m_dez_declare == 1)
                        {
                                m_dez_declare = 0;                                                                        /* exit declare branch */
                                m_tab[strlen(m_tab)-2] = '\0';
                                printf ("%s}\r\n\r\n", m_tab);
                        }
                }
               
                /*-- remove the last return in function() or main branch --*/
                if (
                        next == NULL &&
                        (parent == NULL || parent->dez_op == DEZ_OP_FUNCTION) &&
                        p->dez_op == DEZ_OP_RETURN
                )                                                                                                                        /* the last return */
                {
                        break;                                                                                                        /* skip the last return */
                }
               
                if (p->dez_op == DEZ_OP_FUNCTION)
                {
                        function_node = m_current_function;                                                /* save the old function node */
                        m_current_function = p;
                }

                printf ("%s", m_tab);
               
                if (m_dez_silence != 0)                                                                                /* silence */
                {
                        printf ("%s", dez_node_specs[DEZ_OP_BEGIN_SILENCE].desc);
                }
               
                dez_node_specs[p->dez_op].dez_node_output_func (p);
               
                content = (DEZ_NODE_EXPR *)(p->content);
               
                if (content != NULL && content->branch_node != NULL)                /* enter branch */
                {
                        printf ("\r\n%s{\r\n", m_tab);
                        strcat(m_tab, "  ");
                        dez_output (content->branch_node, p);                                        /* output the branch */
                        m_tab[strlen(m_tab)-2] = '\0';
                       
                        if (p->dez_op == DEZ_OP_DO)
                        {
                                printf ( "%s}", m_tab);
                                p->dez_op = DEZ_OP_WHILE;
                                dez_node_output_if(p);                                                                /* output while(...) */
                                p->dez_op = DEZ_OP_DO;
                                printf ( ";\r\n");
                        }
                        else
                        {
                                printf ( "%s}\r\n", m_tab);
                        }
                       
                        if (p->next != NULL && p->next->dez_op != DEZ_OP_ELSE)
                        {
                                printf ( "\r\n");
                        }
                }
                else
                {
                        printf ( ";\r\n");
                }

                if (p->dez_op == DEZ_OP_FUNCTION)
                {
                        m_current_function = function_node;                                                /* restore the old function node */
                }
               
                p = next;
        }
       
        if (m_dez_declare > 0)
        {
                m_dez_declare--;

                if (m_dez_declare == 0)                                                                                /* exit declare branch */
                {
                        m_tab[strlen(m_tab)-2] = '\0';
                        printf ( "%s}\r\n\r\n", m_tab);
                }
        }
       
        return 0;
}


/**********************************************************
*  dez_property: decompile properties
*
*  @param ht: properties
*  @return 0: success; other: failed
**********************************************************/
static int dez_property (HashTable *ht)
{
        DEZ_NODE *parent;
        DEZ_NODE_CLASS *ccontent;

        if (ht != NULL)
        {
                Bucket *p = ht->pListHead;
               
                parent = dez_node_get();
               
                /*-- decompile properties --*/
                while(p != NULL)
                {
                        DEZ_NODE *node;
                        DEZ_NODE_VAR *content;

                        if (
                                parent != NULL                &&
                                parent->dez_op == DEZ_OP_CLASS
                        )                                                                                        /* property declaration */
                        {
                                ccontent = (DEZ_NODE_CLASS *)(parent->content);
                               
                                if (ccontent->parent != NULL)                        /* extands */
                                {
                                        HashTable *pht = &(ccontent->parent->default_properties);
                                       
                                        Bucket *pp = pht->pListHead;
                                       
                                        while(pp != NULL)
                                        {
                                                if (
                                                        strcmp((char *)(pp->arKey), (char *)(p->arKey)) == 0 &&
                                                        *((zval **)(pp->pData)) == *((zval **)(p->pData))
                                                )                                                                /* property for parent class */
                                                {
                                                        break;
                                                }
                                               
                                                pp = pp->pListNext;
                                        }
                                       
                                        if (pp != NULL)                                                /* the method belongs parent class */
                                        {
                                                p = p->pListNext;
                                                continue;
                                        }
                                }
                        }

                        content = (DEZ_NODE_VAR *)malloc(sizeof(DEZ_NODE_VAR));
                        if (content == NULL)
                        {
                                return -1;
                        }
                       
                        node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                        if (node == NULL)
                        {
                                free(content);
                                return -1;
                        }
                       
                        content->branch_node        = NULL;
                        content->property                = p;
                       
                        node->dez_op                        = DEZ_OP_VAR;
                        node->zop                                = NULL;
                        node->content                        = content;
               
                        DEZ_ADD_NODE(node);
                       
                        p = p->pListNext;
                }
        }
       
        return 0;
}


/**********************************************************
*  dez_function: decompile functions
*
*  @param ht: function_table
*  @return 0: success; other: failed
**********************************************************/
static int dez_function (HashTable *ht)
{
        static zend_op_array *op_array;
        DEZ_NODE *parent;
        DEZ_NODE_CLASS *ccontent;

        if (ht != NULL)
        {
                Bucket *p = ht->pListHead;
               
                parent = dez_node_get();
               
                /*-- decompile the user functions --*/
                while(p != NULL)
                {
                        op_array = (zend_op_array *)(p->pData);
                       
                        if (
                                op_array != NULL        &&
                                op_array->type == 2                                        /* user function */
                        )
                        {
                                DEZ_NODE *node;
                                DEZ_NODE_FUNCTION *content;
                               
                                if (
                                        parent != NULL                &&
                                        parent->dez_op == DEZ_OP_CLASS
                                )                                                                        /* method declaration */
                                {
                                        ccontent = (DEZ_NODE_CLASS *)(parent->content);
                                       
                                        if (ccontent->parent != NULL)        /* extands */
                                        {
                                                HashTable *pht = &(ccontent->parent->function_table);
                                               
                                                Bucket *pp = pht->pListHead;
                                               
                                                while(pp != NULL)
                                                {
                                                        if (((zend_op_array *)(pp->pData))->opcodes == op_array->opcodes)        /* function for parent class */
                                                        {
                                                                break;
                                                        }
                                                       
                                                        pp = pp->pListNext;
                                                }
                                               
                                                if (pp != NULL)                                /* the method belongs parent class */
                                                {
                                                        p = p->pListNext;
                                                        continue;
                                                }
                                        }
                                }

                                content = (DEZ_NODE_FUNCTION *)malloc(sizeof(DEZ_NODE_FUNCTION));
                                if (content == NULL)
                                {
                                        return -1;
                                }
                               
                                node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                                if (node == NULL)
                                {
                                        free(content);
                                        return -1;
                                }
                               
                                content->branch_node        = NULL;
                                content->param_node                = NULL;
                                content->name                        = op_array->function_name;
                                content->m_dez_var_num        = 0;
                                content->op_array                = op_array;
                               
                                node->dez_op                        = DEZ_OP_FUNCTION;
                                node->zop                                = op_array->opcodes;
                                node->content                        = content;
                       
                                DEZ_ADD_NODE(node);
                               
//printf("*%s:\r\n", op_array->function_name);
                                m_current_function = node;
                               
                                dez_enter_branch();                                                                        /* enter function branch */
                               
                                dez_decompile (op_array->opcodes, op_array->size);        /* zend op -> dez op */
                               
                                dez_exit_branch(0);                                                                        /* exit function branch */
                               
                                m_current_function = NULL;
                        }
                       
                        p = p->pListNext;
                }
        }
       
        return 0;
}


/**********************************************************
*  dez_class: decompile classes
*
*  @param none
*  @return 0: success; other: failed
**********************************************************/
static int dez_class (void)
{
        static HashTable *ht;
        static zend_class_entry *c_entry;
        static zend_op_array *op_array;
        TSRMLS_FETCH();
        ht = (EG(class_table));
       
        if (ht != NULL)
        {
                Bucket *p = ht->pListHead;
               
                /*-- decompile the user functions --*/
                while(p != NULL)
                {
                        c_entry = (zend_class_entry *)(p->pData);
                       
                        if (
                                c_entry != NULL        &&
                                c_entry->type == ZEND_USER_CLASS                                /* user class */
                        )
                        {
                                DEZ_NODE *node;
                                DEZ_NODE_CLASS *content;
                               
                                content = (DEZ_NODE_CLASS *)malloc(sizeof(DEZ_NODE_CLASS));
                                if (content == NULL)
                                {
                                        return -1;
                                }
                               
                                node = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
                                if (node == NULL)
                                {
                                        free(content);
                                        return -1;
                                }
                               
                                content->branch_node        = NULL;
                                content->name                        = c_entry->name;
                                content->parent                        = c_entry->parent;
                               
                                node->dez_op                        = DEZ_OP_CLASS;

                                node->zop                                = NULL;
                                node->content                        = content;
                       
                                DEZ_ADD_NODE(node);
                               
//printf("class %s:\r\n", c_entry->name);
                               
                                dez_enter_branch();                                                                        /* enter class branch */
                               
                                dez_property (&(c_entry->default_properties));                /* decompile the properties */
                               
                                dez_function (&(c_entry->function_table));                        /* decompile the motheds */
                               
                                dez_exit_branch(0);                                                                        /* exit class branch */
                        }
                       
                        p = p->pListNext;
                }
        }
       
        return 0;
}


/**********************************************************
*  dez_global: decompile global source
*
*  @param none
*  @return 0: success; other: failed
**********************************************************/
static int dez_global (void)
{
        TSRMLS_FETCH();
        m_current_function = NULL;
       
        return dez_decompile (EG(active_op_array)->opcodes, EG(active_op_array)->size);        /* zend op -> dez op */
}


/**********************************************************
*  dez_main: decompile the zend op
*
*  @param none
*  @return 0: success; other: failed
**********************************************************/
int dez_main (void)
{
        TSRMLS_FETCH();
        static char *m_Header =
"/***********************************************************************/\r\n"
"/*                                                                    */\r\n"
"/*  This file is created by Dezender                                  */\r\n"
"/*                                                                    */\r\n"
"/*  Dezender (Decoder for Zend Encoder/SafeGuard):                    */\r\n"
"/*    Version:      0.9.0.1                                            */\r\n"
"/*    Author:      qinvent.com                                        */\r\n"
"/*    Release Date: 2005.10.04                                        */\r\n"
"/*                                                                    */\r\n"
"/***********************************************************************/\r\n"
"\r\n\r\n";

        m_dez_op_root = (DEZ_NODE *)malloc(sizeof(DEZ_NODE));
        if (m_dez_op_root == NULL)                                                /* fail to alloc memory */
        {
                return -1;
        }
       
        m_dez_op_root->dez_op        = DEZ_OP_NOP;
        m_dez_op_root->zop                = NULL;
        m_dez_op_root->content        = NULL;
        m_dez_op_root->prev                = NULL;
        m_dez_op_root->next                = NULL;
       
        m_dez_op_current                = m_dez_op_root;
       
        dez_class ();                                                                        /* decompile classes */
       
        dez_function (EG(function_table));                                /* decompile functions */
       
        dez_global ();                                                                        /* decompile global source */
       
        m_current_function = NULL;
       
        printf ( "<?php\r\n%s", m_Header);
       
        dez_output(m_dez_op_root, NULL);                                /* output the dez nodes */
       
        printf ( "?>\r\n");
       
        dez_node_free();                                                                /* free dez nodes */
       
        return 0;
}


/************************************************
 * @ dezender.c v1.0 log @
 *
 * Revision 1.0.0.0    lkq      2005/08/10
 * create the file
 *
 ***********************************************/


vilciucostel 06-05-2018 17:27

Maybe Narciszu holds more information.


All times are GMT +8. The time now is 08:50.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2026, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX