├── examples ├── compile_file.php ├── compile_string.php └── compile_string_show_errors.php ├── config.w32 ├── config.m4 ├── README ├── package.xml ├── php_parsekit.h └── parsekit.c /examples/compile_file.php: -------------------------------------------------------------------------------- 1 | 2 | 6 | parsekit 7 | pecl.php.net 8 | PHP Opcode Analyser 9 | Provides a userspace interpretation of the opcodes generated by the Zend engine compiler built into PHP. 10 | This extension is meant for development and debug purposes only and contains some code which is potentially non-threadsafe. 11 | 12 | 13 | Sean Coates 14 | sean 15 | sean@php.net 16 | yes 17 | 18 | 19 | Elizabeth M. Smith 20 | auroraeosrose 21 | auroraeosrose@php.net 22 | yes 23 | 24 | 25 | Sara Golemon 26 | pollita 27 | pollita@php.net 28 | no 29 | 30 | 31 | 2006-11-01 32 | 33 | 34 | 35 | 1.3.0 36 | 1.0 37 | 38 | 39 | stable 40 | stable 41 | 42 | PHP 43 | Builds on PHP 5.3 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 4.0.0 62 | 63 | 64 | 1.4.0b1 65 | 66 | 67 | 68 | parsekit 69 | 70 | 71 | 72 | 73 | 74 | 75 | 1.2 76 | 1.0 77 | 78 | 79 | stable 80 | stable 81 | 82 | PHP 83 | Bugfix #9143 84 | 85 | 86 | 87 | 88 | 1.1 89 | 1.0 90 | 91 | 92 | stable 93 | stable 94 | 95 | 2006-06-16 96 | PHP 97 | Make 5.1/5.2 compatable by ifdefing out more opcodes 98 | Output sensible data for IS_CV nodes 99 | 100 | 101 | 102 | 103 | 104 | 1.0 105 | 1.0 106 | 107 | 108 | stable 109 | stable 110 | 111 | 2004-10-31 112 | PHP 113 | #ifdef out extinct opcode constants and promote to stable 114 | 115 | 116 | 117 | 118 | 119 | 0.3.1 120 | 0.3.1 121 | 122 | 123 | beta 124 | beta 125 | 126 | 2004-08-28 127 | PHP 128 | Fix ZE1 segfault when popping classes. 129 | 130 | 131 | 132 | 133 | 134 | 0.3 135 | 0.3 136 | 137 | 138 | beta 139 | beta 140 | 141 | 2004-08-26 142 | PHP 143 | ZE1 fixes including arg_info emulation. 144 | Expose arg_info directly for real functions/methods. 145 | Add shorthand PARSEKIT_SIMPLE output. 146 | 147 | 148 | 149 | 150 | 151 | 0.2 152 | 0.2 153 | 154 | 155 | alpha 156 | alpha 157 | 158 | 2004-05-06 159 | PHP 160 | Initial Release 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /php_parsekit.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2006 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Sara Golemon | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id$ */ 20 | 21 | #ifndef PHP_PARSEKIT_H 22 | #define PHP_PARSEKIT_H 23 | 24 | #define PHP_PARSEKIT_VERSION "1.3.0" 25 | 26 | #ifdef ZTS 27 | #include "TSRM.h" 28 | #endif 29 | 30 | extern zend_module_entry parsekit_module_entry; 31 | #define phpext_parsekit_ptr &parsekit_module_entry 32 | 33 | PHP_MINIT_FUNCTION(parsekit); 34 | PHP_MSHUTDOWN_FUNCTION(parsekit); 35 | PHP_MINFO_FUNCTION(parsekit); 36 | 37 | PHP_FUNCTION(parsekit_compile_string); 38 | PHP_FUNCTION(parsekit_compile_file); 39 | PHP_FUNCTION(parsekit_opcode_flags); 40 | PHP_FUNCTION(parsekit_opcode_name); 41 | PHP_FUNCTION(parsekit_func_arginfo); 42 | 43 | ZEND_BEGIN_MODULE_GLOBALS(parsekit) 44 | int in_parsekit_compile; 45 | zval *compile_errors; 46 | ZEND_END_MODULE_GLOBALS(parsekit) 47 | 48 | #ifdef ZTS 49 | #define PARSEKIT_G(v) TSRMG(parsekit_globals_id, zend_parsekit_globals *, v) 50 | #else 51 | #define PARSEKIT_G(v) (parsekit_globals.v) 52 | #endif 53 | 54 | typedef struct _php_parsekit_define_list { 55 | long val; 56 | char *str; 57 | long flags; 58 | } php_parsekit_define_list; 59 | 60 | #ifdef ZEND_ENGINE_2 61 | #define PHP_PARSEKIT_TSRMLS_CC_ZE2ONLY TSRMLS_CC 62 | #else 63 | #define PHP_PARSEKIT_TSRMLS_CC_ZE2ONLY 64 | #endif 65 | 66 | #define PHP_PARSEKIT_QUIET 0 67 | #define PHP_PARSEKIT_ALWAYS_SET 1 68 | #define PHP_PARSEKIT_ALL_ELEMENTS 2 69 | #define PHP_PARSEKIT_SIMPLE 3 70 | 71 | #define PHP_PARSEKIT_UNKNOWN "UNKNOWN" 72 | #define PHP_PARSEKIT_OPCODE_UNKNOWN "Unknown Opcode" 73 | #define PHP_PARSEKIT_NODETYPE_UNKNOWN "Unknown Nodetype" 74 | #define PHP_PARSEKIT_FUNCTYPE_UNKNOWN "Unknown Functiontype" 75 | #define PHP_PARSEKIT_CLASSTYPE_UNKNOWN "Unknown Classtype" 76 | 77 | /* Opcode Flags */ 78 | 79 | #define PHP_PARSEKIT_RESULT_CONST 0x00000001 80 | #define PHP_PARSEKIT_RESULT_VAR 0x00000002 81 | #define PHP_PARSEKIT_RESULT_OPLINE 0x00000004 82 | #define PHP_PARSEKIT_RESULT_OPARRAY 0x00000008 83 | #define PHP_PARSEKIT_RESULT_JMP_ADDR 0x00000010 84 | #define PHP_PARSEKIT_RESULT_EA_TYPE 0x00000020 85 | 86 | #define PHP_PARSEKIT_RESULT_GETVAR (PHP_PARSEKIT_RESULT_CONST | PHP_PARSEKIT_RESULT_VAR) 87 | #define PHP_PARSEKIT_RESULT_USED 0x000000FF 88 | 89 | #define PHP_PARSEKIT_OP1_CONST 0x00000100 90 | #define PHP_PARSEKIT_OP1_VAR 0x00000200 91 | #define PHP_PARSEKIT_OP1_OPLINE 0x00000400 92 | #define PHP_PARSEKIT_OP1_OPARRAY 0x00000800 93 | #define PHP_PARSEKIT_OP1_JMP_ADDR 0x00001000 94 | #define PHP_PARSEKIT_OP1_EA_TYPE 0x00002000 95 | 96 | #define PHP_PARSEKIT_OP1_GETVAR (PHP_PARSEKIT_OP1_CONST | PHP_PARSEKIT_OP1_VAR) 97 | #define PHP_PARSEKIT_OP1_USED 0x0000FF00 98 | 99 | #define PHP_PARSEKIT_OP2_CONST 0x00010000 100 | #define PHP_PARSEKIT_OP2_VAR 0x00020000 101 | #define PHP_PARSEKIT_OP2_OPLINE 0x00040000 102 | #define PHP_PARSEKIT_OP2_OPARRAY 0x00080000 103 | #define PHP_PARSEKIT_OP2_JMP_ADDR 0x00100000 104 | #define PHP_PARSEKIT_OP2_EA_TYPE 0x00200000 105 | 106 | #define PHP_PARSEKIT_OP2_GETVAR (PHP_PARSEKIT_OP2_CONST | PHP_PARSEKIT_OP2_VAR) 107 | #define PHP_PARSEKIT_OP2_USED 0x00FF0000 108 | 109 | #define PHP_PARSEKIT_EXTENDED_VALUE 0x01000000 110 | 111 | #define PHP_PARSEKIT_USAGE_UNKNOWN 0xFFFFFFFF 112 | 113 | #define PHP_PARSEKIT_CONSY ( PHP_PARSEKIT_RESULT_CONST | PHP_PARSEKIT_OP1_CONST | PHP_PARSEKIT_OP2_CONST ) 114 | #define PHP_PARSEKIT_VAR ( PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_VAR | PHP_PARSEKIT_OP2_VAR ) 115 | #define PHP_PARSEKIT_OPLINE ( PHP_PARSEKIT_RESULT_OPLINE | PHP_PARSEKIT_OP1_OPLINE | PHP_PARSEKIT_OP2_OPLINE ) 116 | #define PHP_PARSEKIT_OPARRAY ( PHP_PARSEKIT_RESULT_OPARRAY | PHP_PARSEKIT_OP1_OPARRAY | PHP_PARSEKIT_OP2_OPARRAY ) 117 | #define PHP_PARSEKIT_JMP_ADDR ( PHP_PARSEKIT_RESULT_JMP_ADDR | PHP_PARSEKIT_OP1_JMP_ADDR | PHP_PARSEKIT_OP2_JMP_ADDR ) 118 | #define PHP_PARSEKIT_EA_TYPE ( PHP_PARSEKIT_RESULT_EA_TYPE | PHP_PARSEKIT_OP1_EA_TYPE | PHP_PARSEKIT_OP2_EA_TYPE ) 119 | 120 | static php_parsekit_define_list php_parsekit_opnode_flags[] = { 121 | { PHP_PARSEKIT_RESULT_CONST, "RESULT_CONST" }, 122 | { PHP_PARSEKIT_RESULT_VAR, "RESULT_VAR" }, 123 | { PHP_PARSEKIT_RESULT_OPLINE, "RESULT_OPLINE" }, 124 | { PHP_PARSEKIT_RESULT_OPARRAY, "RESULT_OPARRAY" }, 125 | { PHP_PARSEKIT_RESULT_JMP_ADDR, "RESULT_JMP_ADDR" }, 126 | { PHP_PARSEKIT_RESULT_EA_TYPE, "RESULT_EA_TYPE" }, 127 | { PHP_PARSEKIT_OP1_CONST, "OP1_CONST" }, 128 | { PHP_PARSEKIT_OP1_VAR, "OP1_VAR" }, 129 | { PHP_PARSEKIT_OP1_OPLINE, "OP1_OPLINE" }, 130 | { PHP_PARSEKIT_OP1_OPARRAY, "OP1_OPARRAY" }, 131 | { PHP_PARSEKIT_OP1_JMP_ADDR, "OP1_JMP_ADDR" }, 132 | { PHP_PARSEKIT_OP1_EA_TYPE, "OP1_EA_TYPE" }, 133 | { PHP_PARSEKIT_OP2_CONST, "OP2_CONST" }, 134 | { PHP_PARSEKIT_OP2_VAR, "OP2_VAR" }, 135 | { PHP_PARSEKIT_OP2_OPLINE, "OP2_OPLINE" }, 136 | { PHP_PARSEKIT_OP2_OPARRAY, "OP2_OPARRAY" }, 137 | { PHP_PARSEKIT_OP2_JMP_ADDR, "OP2_JMP_ADDR" }, 138 | { PHP_PARSEKIT_OP2_EA_TYPE, "OP2_EA_TYPE" }, 139 | { PHP_PARSEKIT_EXTENDED_VALUE, "EXTENDED_VALUE" }, 140 | { PHP_PARSEKIT_USAGE_UNKNOWN, "USAGE_UNKNOWN" }, 141 | { 0, NULL } 142 | }; 143 | 144 | static php_parsekit_define_list php_parsekit_class_types[] = { 145 | { ZEND_INTERNAL_CLASS, "ZEND_INTERNAL_CLASS" }, 146 | { ZEND_USER_CLASS, "ZEND_USER_CLASS" }, 147 | { 0, NULL } 148 | }; 149 | 150 | static php_parsekit_define_list php_parsekit_function_types[] = { 151 | { ZEND_INTERNAL_FUNCTION, "ZEND_INTERNAL_FUNCTION" }, 152 | { ZEND_USER_FUNCTION, "ZEND_USER_FUNCTION" }, 153 | { ZEND_OVERLOADED_FUNCTION, "ZEND_OVERLOADED_FUNCTION" }, 154 | { ZEND_EVAL_CODE, "ZEND_EVAL_CODE" }, 155 | #ifdef ZEND_OVERLOADED_FUNCTION_TEMPORARY 156 | /* ZE2 Only */ 157 | { ZEND_OVERLOADED_FUNCTION_TEMPORARY, "ZEND_OVERLOADED_FUNCTION_TEMPORARY" }, 158 | #endif 159 | { 0, NULL } 160 | }; 161 | 162 | static php_parsekit_define_list php_parsekit_nodetype_names[] = { 163 | { IS_CONST, "IS_CONST" }, 164 | { IS_TMP_VAR, "IS_TMP_VAR" }, 165 | { IS_VAR, "IS_VAR" }, 166 | { IS_UNUSED, "IS_UNUSED" }, 167 | #ifdef IS_CV 168 | /* PHP >= 5.1 */ 169 | { IS_CV, "IS_CV" }, 170 | #endif 171 | { 0, NULL } 172 | }; 173 | 174 | static php_parsekit_define_list php_parsekit_opcode_names[] = { 175 | { ZEND_NOP, "ZEND_NOP", 0 }, 176 | { ZEND_ADD, "ZEND_ADD", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 177 | { ZEND_SUB, "ZEND_SUB", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 178 | { ZEND_MUL, "ZEND_MUL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 179 | { ZEND_DIV, "ZEND_DIV", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 180 | { ZEND_MOD, "ZEND_MOD", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 181 | { ZEND_SL, "ZEND_SL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 182 | { ZEND_SR, "ZEND_SR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 183 | { ZEND_CONCAT, "ZEND_CONCAT", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 184 | { ZEND_BW_OR, "ZEND_BW_OR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 185 | { ZEND_BW_AND, "ZEND_BW_AND", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 186 | { ZEND_BW_XOR, "ZEND_BW_XOR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 187 | { ZEND_BW_NOT, "ZEND_BW_NOT", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 188 | { ZEND_BOOL_NOT, "ZEND_BOOL_NOT", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 189 | { ZEND_BOOL_XOR, "ZEND_BOOL_XOR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 190 | { ZEND_IS_IDENTICAL, "ZEND_IS_IDENTICAL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 191 | { ZEND_IS_NOT_IDENTICAL, "ZEND_IS_NOT_IDENTICAL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 192 | { ZEND_IS_EQUAL, "ZEND_IS_EQUAL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 193 | { ZEND_IS_NOT_EQUAL, "ZEND_IS_NOT_EQUAL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 194 | { ZEND_IS_SMALLER, "ZEND_IS_SMALLER", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 195 | { ZEND_IS_SMALLER_OR_EQUAL, "ZEND_IS_SMALLER_OR_EQUAL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 196 | { ZEND_CAST, "ZEND_CAST", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 197 | { ZEND_QM_ASSIGN, "ZEND_QM_ASSIGN", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 198 | { ZEND_ASSIGN_ADD, "ZEND_ASSIGN_ADD", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 199 | { ZEND_ASSIGN_SUB, "ZEND_ASSIGN_SUB", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 200 | { ZEND_ASSIGN_MUL, "ZEND_ASSIGN_MUL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 201 | { ZEND_ASSIGN_DIV, "ZEND_ASSIGN_DIV", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 202 | { ZEND_ASSIGN_MOD, "ZEND_ASSIGN_MOD", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 203 | { ZEND_ASSIGN_SL, "ZEND_ASSIGN_SL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 204 | { ZEND_ASSIGN_SR, "ZEND_ASSIGN_SR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 205 | { ZEND_ASSIGN_CONCAT, "ZEND_ASSIGN_CONCAT", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 206 | { ZEND_ASSIGN_BW_OR, "ZEND_ASSIGN_BW_OR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 207 | { ZEND_ASSIGN_BW_AND, "ZEND_ASSIGN_BW_AND", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 208 | { ZEND_ASSIGN_BW_XOR, "ZEND_ASSIGN_BW_XOR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 209 | { ZEND_PRE_INC, "ZEND_PRE_INC", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 210 | { ZEND_PRE_DEC, "ZEND_PRE_DEC", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 211 | { ZEND_POST_INC, "ZEND_POST_INC", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 212 | { ZEND_POST_DEC, "ZEND_POST_DEC", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 213 | { ZEND_ASSIGN, "ZEND_ASSIGN", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_RESULT_EA_TYPE | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 214 | { ZEND_ASSIGN_REF, "ZEND_ASSIGN_REF", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_RESULT_EA_TYPE | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 215 | { ZEND_ECHO, "ZEND_ECHO", PHP_PARSEKIT_OP1_GETVAR }, 216 | { ZEND_PRINT, "ZEND_PRINT", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 217 | { ZEND_JMP, "ZEND_JMP", PHP_PARSEKIT_OP1_OPLINE | PHP_PARSEKIT_OP1_JMP_ADDR }, 218 | { ZEND_JMPZ, "ZEND_JMPZ", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_OP2_JMP_ADDR }, 219 | { ZEND_JMPNZ, "ZEND_JMPNZ", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_OP2_JMP_ADDR }, 220 | { ZEND_JMPZNZ, "ZEND_JMPZNZ", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_OP2_JMP_ADDR | PHP_PARSEKIT_EXTENDED_VALUE }, 221 | { ZEND_JMPZ_EX, "ZEND_JMPZ_EX", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_OP2_JMP_ADDR }, 222 | { ZEND_JMPNZ_EX, "ZEND_JMPNZ_EX", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_OP2_JMP_ADDR }, 223 | { ZEND_CASE, "ZEND_CASE", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 224 | { ZEND_SWITCH_FREE, "ZEND_SWITCH_FREE", PHP_PARSEKIT_OP1_VAR | PHP_PARSEKIT_EXTENDED_VALUE }, 225 | { ZEND_BRK, "ZEND_BRK", PHP_PARSEKIT_OP1_VAR | PHP_PARSEKIT_OP1_OPLINE | PHP_PARSEKIT_OP2_GETVAR }, 226 | { ZEND_CONT, "ZEND_CONT", PHP_PARSEKIT_OP1_VAR | PHP_PARSEKIT_OP1_OPLINE | PHP_PARSEKIT_OP2_GETVAR }, 227 | { ZEND_BOOL, "ZEND_BOOL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 228 | { ZEND_INIT_STRING, "ZEND_INIT_STRING", PHP_PARSEKIT_RESULT_VAR }, 229 | { ZEND_ADD_CHAR, "ZEND_ADD_CHAR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_CONST }, 230 | { ZEND_ADD_STRING, "ZEND_ADD_STRING", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_CONST }, 231 | { ZEND_ADD_VAR, "ZEND_ADD_VAR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 232 | { ZEND_BEGIN_SILENCE, "ZEND_BEGIN_SILENCE", PHP_PARSEKIT_RESULT_VAR }, 233 | { ZEND_END_SILENCE, "ZEND_END_SILENCE", PHP_PARSEKIT_OP1_VAR }, 234 | { ZEND_INIT_FCALL_BY_NAME, "ZEND_INIT_FCALL_BY_NAME", PHP_PARSEKIT_OP2_GETVAR }, 235 | { ZEND_DO_FCALL, "ZEND_DO_FCALL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 236 | { ZEND_DO_FCALL_BY_NAME, "ZEND_DO_FCALL_BY_NAME", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_EXTENDED_VALUE }, 237 | { ZEND_RETURN, "ZEND_RETURN", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 238 | { ZEND_RECV, "ZEND_RECV", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_CONST }, 239 | { ZEND_RECV_INIT, "ZEND_RECV_INIT", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_CONST | PHP_PARSEKIT_OP2_CONST }, 240 | { ZEND_SEND_VAL, "ZEND_SEND_VAL", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_EXTENDED_VALUE }, 241 | { ZEND_SEND_VAR, "ZEND_SEND_VAR", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_EXTENDED_VALUE }, 242 | { ZEND_SEND_REF, "ZEND_SEND_REF", PHP_PARSEKIT_OP1_GETVAR }, 243 | { ZEND_NEW, "ZEND_NEW", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_VAR }, 244 | #ifdef ZEND_JMP_NO_CTOR 245 | /* Pre-PHP 5.1 only */ 246 | { ZEND_JMP_NO_CTOR, "ZEND_JMP_NO_CTOR", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE }, 247 | #endif 248 | { ZEND_FREE, "ZEND_FREE", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP1_EA_TYPE | PHP_PARSEKIT_OP2_OPLINE }, 249 | { ZEND_INIT_ARRAY, "ZEND_INIT_ARRAY", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 250 | { ZEND_ADD_ARRAY_ELEMENT, "ZEND_ADD_ARRAY_ELEMENT", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 251 | { ZEND_INCLUDE_OR_EVAL, "ZEND_INCLUDE_OR_EVAL", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_CONST }, 252 | { ZEND_UNSET_VAR, "ZEND_UNSET_VAR", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_EA_TYPE }, 253 | #ifdef ZEND_UNSET_DIM_OBJ 254 | /* Pre-PHP 5.1 only */ 255 | { ZEND_UNSET_DIM_OBJ, "ZEND_UNSET_DIM_OBJ", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 256 | #endif 257 | #ifdef ZEND_ISSET_ISEMPTY 258 | /* ZE1 Only */ 259 | { ZEND_ISSET_ISEMPTY, "ZEND_ISSET_ISEMPTY", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_CONST }, 260 | #endif 261 | { ZEND_FE_RESET, "ZEND_FE_RESET", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_EXTENDED_VALUE }, 262 | { ZEND_FE_FETCH, "ZEND_FE_FETCH", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_EXTENDED_VALUE }, 263 | { ZEND_EXIT, "ZEND_EXIT", PHP_PARSEKIT_OP1_GETVAR }, 264 | { ZEND_FETCH_R, "ZEND_FETCH_R", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_VAR | PHP_PARSEKIT_OP2_EA_TYPE }, 265 | { ZEND_FETCH_DIM_R, "ZEND_FETCH_DIM_R", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 266 | { ZEND_FETCH_OBJ_R, "ZEND_FETCH_OBJ_R", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 267 | { ZEND_FETCH_W, "ZEND_FETCH_W", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_VAR | PHP_PARSEKIT_OP2_EA_TYPE }, 268 | { ZEND_FETCH_DIM_W, "ZEND_FETCH_DIM_W", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 269 | { ZEND_FETCH_OBJ_W, "ZEND_FETCH_OBJ_W", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 270 | { ZEND_FETCH_RW, "ZEND_FETCH_RW", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_VAR | PHP_PARSEKIT_OP2_EA_TYPE }, 271 | { ZEND_FETCH_DIM_RW, "ZEND_FETCH_DIM_RW", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 272 | { ZEND_FETCH_OBJ_RW, "ZEND_FETCH_OBJ_RW", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP2_GETVAR }, 273 | { ZEND_FETCH_IS, "ZEND_FETCH_IS", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_EA_TYPE }, 274 | { ZEND_FETCH_DIM_IS, "ZEND_FETCH_DIM_IS", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 275 | { ZEND_FETCH_OBJ_IS, "ZEND_FETCH_OBJ_IS", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 276 | { ZEND_FETCH_FUNC_ARG, "ZEND_FETCH_FUNC_ARG", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_OP2_EA_TYPE | PHP_PARSEKIT_EXTENDED_VALUE }, 277 | { ZEND_FETCH_DIM_FUNC_ARG, "ZEND_FETCH_DIM_FUNC_ARG", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 278 | { ZEND_FETCH_OBJ_FUNC_ARG, "ZEND_FETCH_OBJ_FUNC_ARG", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 279 | { ZEND_FETCH_UNSET, "ZEND_FETCH_UNSET", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_VAR | PHP_PARSEKIT_OP2_EA_TYPE }, 280 | { ZEND_FETCH_DIM_UNSET, "ZEND_FETCH_DIM_UNSET", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 281 | { ZEND_FETCH_OBJ_UNSET, "ZEND_FETCH_OBJ_UNSET", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 282 | { ZEND_FETCH_DIM_TMP_VAR, "ZEND_FETCH_DIM_TMP_VAR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 283 | { ZEND_FETCH_CONSTANT, "ZEND_FETCH_CONSTANT", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_VAR | PHP_PARSEKIT_OP2_CONST }, 284 | { ZEND_EXT_STMT, "ZEND_EXT_STMT", PHP_PARSEKIT_USAGE_UNKNOWN }, 285 | { ZEND_EXT_FCALL_BEGIN, "ZEND_EXT_FCALL_BEGIN", PHP_PARSEKIT_USAGE_UNKNOWN }, 286 | { ZEND_EXT_FCALL_END, "ZEND_EXT_FCALL_END", PHP_PARSEKIT_USAGE_UNKNOWN }, 287 | { ZEND_EXT_NOP, "ZEND_EXT_NOP", PHP_PARSEKIT_USAGE_UNKNOWN }, 288 | { ZEND_TICKS, "ZEND_TICKS", PHP_PARSEKIT_OP1_CONST }, 289 | { ZEND_SEND_VAR_NO_REF, "ZEND_SEND_VAR_NO_REF", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_EXTENDED_VALUE }, 290 | #if PHP_MAJOR_VERSION >= 5 291 | { ZEND_CATCH, "ZEND_CATCH", PHP_PARSEKIT_OP1_VAR | PHP_PARSEKIT_OP1_EA_TYPE | PHP_PARSEKIT_OP2_OPLINE | PHP_PARSEKIT_EXTENDED_VALUE }, 292 | { ZEND_THROW, "ZEND_THROW", PHP_PARSEKIT_OP1_GETVAR }, 293 | { ZEND_FETCH_CLASS, "ZEND_FETCH_CLASS", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 294 | { ZEND_CLONE, "ZEND_CLONE", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR }, 295 | #ifdef ZEND_INIT_CTOR_CALL 296 | /* PHP 5.0 only */ 297 | { ZEND_INIT_CTOR_CALL, "ZEND_INIT_CTOR_CALL", PHP_PARSEKIT_OP1_GETVAR }, 298 | #endif 299 | { ZEND_INIT_METHOD_CALL, "ZEND_INIT_METHOD_CALL", PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 300 | { ZEND_INIT_STATIC_METHOD_CALL, "ZEND_INIT_STATIC_METHOD_CALL", PHP_PARSEKIT_OP1_VAR | PHP_PARSEKIT_OP2_GETVAR }, 301 | { ZEND_ISSET_ISEMPTY_VAR, "ZEND_ISSET_ISEMPTY_VAR", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_VAR | PHP_PARSEKIT_OP2_EA_TYPE }, 302 | { ZEND_ISSET_ISEMPTY_DIM_OBJ, "ZEND_ISSET_ISEMPTY_DIM_OBJ", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 303 | #ifdef ZEND_IMPORT_FUNCTION 304 | { ZEND_IMPORT_FUNCTION, "ZEND_IMPORT_FUNCTION", PHP_PARSEKIT_USAGE_UNKNOWN }, 305 | #endif 306 | #ifdef ZEND_IMPORT_CLASS 307 | { ZEND_IMPORT_CLASS, "ZEND_IMPORT_CLASS", PHP_PARSEKIT_USAGE_UNKNOWN }, 308 | #endif 309 | #ifdef ZEND_IMPORT_CONST 310 | { ZEND_IMPORT_CONST, "ZEND_IMPORT_CONST", PHP_PARSEKIT_USAGE_UNKNOWN }, 311 | #endif 312 | { ZEND_PRE_INC_OBJ, "ZEND_PRE_INC_OBJ", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 313 | { ZEND_PRE_DEC_OBJ, "ZEND_PRE_DEC_OBJ", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 314 | { ZEND_POST_INC_OBJ, "ZEND_POST_INC_OBJ", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 315 | { ZEND_POST_DEC_OBJ, "ZEND_POST_DEC_OBJ", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 316 | { ZEND_ASSIGN_OBJ, "ZEND_ASSIGN_OBJ", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR }, 317 | { ZEND_OP_DATA, "ZEND_OP_DATA", PHP_PARSEKIT_USAGE_UNKNOWN }, 318 | { ZEND_INSTANCEOF, "ZEND_INSTANCEOF", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_VAR }, 319 | { ZEND_DECLARE_CLASS, "ZEND_DECLARE_CLASS", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_CONST | PHP_PARSEKIT_OP2_CONST }, 320 | { ZEND_DECLARE_INHERITED_CLASS, "ZEND_DECLARE_INHERITED_CLASS", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_CONST | PHP_PARSEKIT_OP2_CONST }, 321 | { ZEND_DECLARE_FUNCTION, "ZEND_DECLARE_FUNCTION", PHP_PARSEKIT_OP1_CONST | PHP_PARSEKIT_OP2_CONST }, 322 | { ZEND_RAISE_ABSTRACT_ERROR, "ZEND_RAISE_ABSTRACT_ERROR", PHP_PARSEKIT_USAGE_UNKNOWN }, 323 | { ZEND_ADD_INTERFACE, "ZEND_ADD_INTERFACE", PHP_PARSEKIT_OP1_VAR | PHP_PARSEKIT_OP2_VAR | PHP_PARSEKIT_EXTENDED_VALUE }, 324 | { ZEND_VERIFY_ABSTRACT_CLASS, "ZEND_VERIFY_ABSTRACT_CLASS", PHP_PARSEKIT_OP1_VAR }, 325 | { ZEND_ASSIGN_DIM, "ZEND_ASSIGN_DIM", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 326 | { ZEND_ISSET_ISEMPTY_PROP_OBJ, "ZEND_ISSET_ISEMPTY_PROP_OBJ", PHP_PARSEKIT_RESULT_VAR | PHP_PARSEKIT_OP1_GETVAR | PHP_PARSEKIT_OP2_GETVAR | PHP_PARSEKIT_EXTENDED_VALUE }, 327 | { ZEND_HANDLE_EXCEPTION, "ZEND_HANDLE_EXCEPTION", 0 }, 328 | #endif 329 | { 0, NULL } 330 | }; 331 | 332 | #else 333 | 334 | #define phpext_parsekit_ptr &parsekit_module_entry 335 | 336 | #endif /* PHP_PARSEKIT_H */ 337 | 338 | 339 | /* 340 | * Local variables: 341 | * tab-width: 4 342 | * c-basic-offset: 4 343 | * End: 344 | * vim600: noet sw=4 ts=4 fdm=marker 345 | * vim<600: noet sw=4 ts=4 346 | */ 347 | 348 | -------------------------------------------------------------------------------- /parsekit.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2006 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Sara Golemon | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id$ */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include "config.h" 23 | #endif 24 | 25 | #include "php.h" 26 | #include "php_ini.h" 27 | #include "ext/standard/info.h" 28 | #include "php_parsekit.h" 29 | 30 | #ifndef Z_REFCOUNT_P 31 | #define Z_REFCOUNT_P(pz) (pz)->refcount 32 | #endif 33 | 34 | #ifndef Z_SET_REFCOUNT_P 35 | #define Z_SET_REFCOUNT_P(pz, rc) (pz)->refcount = rc 36 | #endif 37 | 38 | ZEND_DECLARE_MODULE_GLOBALS(parsekit) 39 | /* Potentially thread-unsafe, see MINIT_FUNCTION */ 40 | void (*php_parsekit_original_error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); 41 | 42 | /* Parsekit Workhorse */ 43 | 44 | /* {{{ php_parsekit_define_name */ 45 | static char* php_parsekit_define_name_ex(long val, php_parsekit_define_list *lookup_list, long *pflags, char *unknown_default) 46 | { 47 | php_parsekit_define_list *names; 48 | 49 | for(names = lookup_list; names->str; names++) { 50 | if (names->val == val) { 51 | if (pflags) { 52 | *pflags = names->flags; 53 | } 54 | return names->str; 55 | } 56 | } 57 | 58 | return unknown_default ? unknown_default : PHP_PARSEKIT_UNKNOWN; 59 | } 60 | 61 | #define php_parsekit_define_name(val, lookup_list, unknown_default) \ 62 | php_parsekit_define_name_ex((val), (lookup_list), NULL, (unknown_default)) 63 | /* }}} */ 64 | 65 | /* {{{ php_parsekit_parse_node */ 66 | static void php_parsekit_parse_node(zval *return_value, zend_op_array *op_array, znode *node, long flags, long options TSRMLS_DC) 67 | { 68 | array_init(return_value); 69 | add_assoc_long(return_value, "type", node->op_type); 70 | add_assoc_string(return_value, "type_name", php_parsekit_define_name(node->op_type, php_parsekit_nodetype_names, PHP_PARSEKIT_NODETYPE_UNKNOWN), 1); 71 | if (node->op_type == IS_CONST) { 72 | zval *tmpzval; 73 | MAKE_STD_ZVAL(tmpzval); 74 | *tmpzval = node->u.constant; 75 | zval_copy_ctor(tmpzval); 76 | Z_SET_REFCOUNT_P(tmpzval, 1); 77 | add_assoc_zval(return_value, "constant", tmpzval); 78 | #ifdef IS_CV 79 | /* PHP >= 5.1 */ 80 | } else if (node->op_type == IS_CV) { 81 | add_assoc_long(return_value, "var", node->u.var); 82 | add_assoc_stringl(return_value, "varname", op_array->vars[node->u.var].name, op_array->vars[node->u.var].name_len, 1); 83 | #endif 84 | } else { 85 | /* IS_VAR || IS_TMP_VAR || IS_UNUSED */ 86 | char sop[(sizeof(void *) * 2) + 1]; 87 | 88 | snprintf(sop, (sizeof(void *) * 2) + 1, "%X", (unsigned int)node->u.var); 89 | 90 | if ((flags & PHP_PARSEKIT_VAR) || 91 | (options & PHP_PARSEKIT_ALL_ELEMENTS)) { 92 | add_assoc_long(return_value, "var", node->u.var / sizeof(temp_variable)); 93 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 94 | add_assoc_null(return_value, "var"); 95 | } 96 | 97 | if ((flags & PHP_PARSEKIT_OPLINE) || 98 | (options & PHP_PARSEKIT_ALL_ELEMENTS)) { 99 | add_assoc_string(return_value, "opline_num", sop, 1); 100 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 101 | add_assoc_null(return_value, "opline_num"); 102 | } 103 | 104 | if ((flags & PHP_PARSEKIT_OPARRAY) || 105 | (options & PHP_PARSEKIT_ALL_ELEMENTS)) { 106 | add_assoc_string(return_value, "op_array", sop, 1); 107 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 108 | add_assoc_null(return_value, "op_array"); 109 | } 110 | 111 | #ifdef ZEND_ENGINE_2 112 | /* ZE2 Only */ 113 | if ((flags & PHP_PARSEKIT_JMP_ADDR) || 114 | (options & PHP_PARSEKIT_ALL_ELEMENTS)) { 115 | add_assoc_string(return_value, "jmp_addr", sop, 1); 116 | snprintf(sop, sizeof(sop)-1, "%u", 117 | ((unsigned int)((char*)node->u.var - (char*)op_array->opcodes))/sizeof(zend_op)); 118 | add_assoc_string(return_value, "jmp_offset", sop, 1); 119 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 120 | add_assoc_null(return_value, "jmp_addr"); 121 | } 122 | #endif 123 | 124 | if ((flags & PHP_PARSEKIT_EA_TYPE) || 125 | (options & PHP_PARSEKIT_ALL_ELEMENTS)) { 126 | add_assoc_long(return_value, "EA.type", node->u.EA.type); 127 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 128 | add_assoc_null(return_value, "EA.type"); 129 | } 130 | } 131 | } 132 | /* }}} */ 133 | 134 | /* {{{ php_parsekit_parse_op */ 135 | static void php_parsekit_parse_op(zval *return_value, zend_op_array *op_array, zend_op *op, long options TSRMLS_DC) 136 | { 137 | zval *result, *op1, *op2; 138 | long flags = 0; 139 | 140 | array_init(return_value); 141 | 142 | /* op->handler */ 143 | add_assoc_long(return_value, "address", (unsigned int)(&(op->opcode))); 144 | add_assoc_long(return_value, "opcode", op->opcode); 145 | add_assoc_string(return_value, "opcode_name", php_parsekit_define_name_ex(op->opcode, php_parsekit_opcode_names, &flags, PHP_PARSEKIT_OPCODE_UNKNOWN) , 1); 146 | add_assoc_long(return_value, "flags", flags); 147 | 148 | /* args: result, op1, op2 */ 149 | if ((options & PHP_PARSEKIT_ALL_ELEMENTS) || 150 | (flags & PHP_PARSEKIT_RESULT_USED)) { 151 | MAKE_STD_ZVAL(result); 152 | php_parsekit_parse_node(result, op_array, &(op->result), flags & PHP_PARSEKIT_RESULT_USED, options TSRMLS_CC); 153 | add_assoc_zval(return_value, "result", result); 154 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 155 | add_assoc_null(return_value, "result"); 156 | } 157 | 158 | if ((options & PHP_PARSEKIT_ALL_ELEMENTS) || 159 | (flags & PHP_PARSEKIT_OP1_USED)) { 160 | MAKE_STD_ZVAL(op1); 161 | php_parsekit_parse_node(op1, op_array, &(op->op1), flags & PHP_PARSEKIT_OP1_USED, options TSRMLS_CC); 162 | add_assoc_zval(return_value, "op1", op1); 163 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 164 | add_assoc_null(return_value, "op1"); 165 | } 166 | 167 | if ((options & PHP_PARSEKIT_ALL_ELEMENTS) || 168 | (flags & PHP_PARSEKIT_OP2_USED)) { 169 | MAKE_STD_ZVAL(op2); 170 | php_parsekit_parse_node(op2, op_array, &(op->op2), flags & PHP_PARSEKIT_OP2_USED, options TSRMLS_CC); 171 | add_assoc_zval(return_value, "op2", op2); 172 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 173 | add_assoc_null(return_value, "op2"); 174 | } 175 | 176 | if ((options & PHP_PARSEKIT_ALL_ELEMENTS) || 177 | (flags & PHP_PARSEKIT_EXTENDED_VALUE)) { 178 | add_assoc_long(return_value, "extended_value", op->extended_value); 179 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 180 | add_assoc_null(return_value, "extended_value"); 181 | } 182 | 183 | add_assoc_long(return_value, "lineno", op->lineno); 184 | } 185 | /* }}} */ 186 | 187 | #ifdef ZEND_ENGINE_2 188 | /* {{{ php_parsekit_parse_arginfo */ 189 | static void php_parsekit_parse_arginfo(zval *return_value, zend_uint num_args, zend_arg_info *arginfo, long options TSRMLS_DC) 190 | { 191 | zend_uint i; 192 | 193 | array_init(return_value); 194 | 195 | for(i = 0; i < num_args; i++) { 196 | zval *tmpzval; 197 | 198 | MAKE_STD_ZVAL(tmpzval); 199 | array_init(tmpzval); 200 | add_assoc_stringl(tmpzval, "name", arginfo[i].name, arginfo[i].name_len, 1); 201 | if (arginfo[i].class_name_len) { 202 | add_assoc_stringl(tmpzval, "class_name", arginfo[i].class_name, arginfo[i].class_name_len, 1); 203 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 204 | add_assoc_null(tmpzval, "class_name"); 205 | } 206 | add_assoc_bool(tmpzval, "allow_null", arginfo[i].allow_null); 207 | add_assoc_bool(tmpzval, "pass_by_reference", arginfo[i].pass_by_reference); 208 | 209 | add_next_index_zval(return_value, tmpzval); 210 | } 211 | } 212 | /* }}} */ 213 | #else 214 | /* {{{ php_parsekit_derive_arginfo 215 | ZE1 Func Arg loading is done via opcodes "RECV"ing from the caller */ 216 | static void php_parsekit_derive_arginfo(zval *return_value, zend_op_array *op_array, long options TSRMLS_DC) 217 | { 218 | int i; 219 | zend_op *opcodes = op_array->opcodes; 220 | 221 | array_init(return_value); 222 | 223 | /* Received vars come in pairs: 224 | A ZEND_FETCH_W, and a ZEND_RECV */ 225 | for(i = 0; i < op_array->arg_types[0]; i++) { 226 | if (opcodes[i*2].opcode == ZEND_FETCH_W && 227 | opcodes[i*2].op1.op_type == IS_CONST && 228 | opcodes[i*2].op1.u.constant.type == IS_STRING && 229 | (opcodes[(i*2)+1].opcode == ZEND_RECV || opcodes[(i*2)+1].opcode == ZEND_RECV_INIT)) { 230 | zval *tmpzval; 231 | 232 | MAKE_STD_ZVAL(tmpzval); 233 | array_init(tmpzval); 234 | 235 | add_assoc_stringl(tmpzval, "name", opcodes[i*2].op1.u.constant.value.str.val, opcodes[i*2].op1.u.constant.value.str.len, 1); 236 | add_assoc_bool(tmpzval, "pass_by_reference", op_array->arg_types[i+1]); 237 | if (opcodes[(i*2)+1].opcode == ZEND_RECV_INIT && 238 | opcodes[(i*2)+1].op2.op_type == IS_CONST) { 239 | zval *def; 240 | 241 | MAKE_STD_ZVAL(def); 242 | *def = opcodes[(i*2)+1].op2.u.constant; 243 | zval_copy_ctor(def); 244 | add_assoc_zval(tmpzval, "default", def); 245 | Z_SET_REFCOUNT_P(tmpzval, 1); 246 | } 247 | 248 | add_next_index_zval(return_value, tmpzval); 249 | } 250 | } 251 | } 252 | /* }}} */ 253 | #endif 254 | 255 | /* {{{ php_parsekit_parse_op_array */ 256 | static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops, long options TSRMLS_DC) 257 | { 258 | zend_op *op; 259 | zval *tmpzval; 260 | int i = 0; 261 | 262 | /* TODO: Reorder / Organize */ 263 | 264 | array_init(return_value); 265 | 266 | add_assoc_long(return_value, "type", (long)(ops->type)); 267 | add_assoc_string(return_value, "type_name", php_parsekit_define_name(ops->type, php_parsekit_function_types, PHP_PARSEKIT_FUNCTYPE_UNKNOWN), 1); 268 | if (ops->function_name) { 269 | add_assoc_string(return_value, "function_name", ops->function_name, 1); 270 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 271 | add_assoc_null(return_value, "function_name"); 272 | } 273 | 274 | #ifdef ZEND_ENGINE_2 275 | /* ZE2 op_array members */ 276 | if (ops->scope && ops->scope->name) { 277 | add_assoc_stringl(return_value, "scope", ops->scope->name, ops->scope->name_length, 1); 278 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 279 | add_assoc_null(return_value, "scope"); 280 | } 281 | add_assoc_long(return_value, "fn_flags", ops->fn_flags); 282 | if (ops->function_name && ops->prototype) { 283 | MAKE_STD_ZVAL(tmpzval); 284 | array_init(tmpzval); 285 | add_assoc_long(tmpzval, "type", ops->prototype->type); 286 | add_assoc_string(return_value, "type_name", php_parsekit_define_name(ops->prototype->type, php_parsekit_function_types, PHP_PARSEKIT_FUNCTYPE_UNKNOWN), 1); 287 | if (ops->prototype->common.function_name) { 288 | add_assoc_string(tmpzval, "function_name", ops->prototype->common.function_name, 1); 289 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 290 | add_assoc_null(tmpzval, "function_name"); 291 | } 292 | if (ops->prototype->common.scope && ops->prototype->common.scope->name) { 293 | add_assoc_stringl(tmpzval, "scope", ops->prototype->common.scope->name, ops->prototype->common.scope->name_length, 1); 294 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 295 | add_assoc_null(tmpzval, "scope"); 296 | } 297 | add_assoc_zval(return_value, "prototype", tmpzval); 298 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 299 | add_assoc_null(return_value, "prototype"); 300 | } 301 | add_assoc_long(return_value, "num_args", ops->num_args); 302 | add_assoc_long(return_value, "required_num_args", ops->required_num_args); 303 | add_assoc_bool(return_value, "pass_rest_by_reference", ops->pass_rest_by_reference); 304 | 305 | if (ops->num_args && ops->arg_info) { 306 | MAKE_STD_ZVAL(tmpzval); 307 | php_parsekit_parse_arginfo(tmpzval, ops->num_args, ops->arg_info, options TSRMLS_CC); 308 | add_assoc_zval(return_value, "arg_info", tmpzval); 309 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 310 | add_assoc_null(return_value, "arg_info"); 311 | } 312 | 313 | if (ops->last_try_catch > 0) { 314 | MAKE_STD_ZVAL(tmpzval); 315 | array_init(tmpzval); 316 | for(i = 0; i < ops->last_try_catch; i++) { 317 | zval *tmp_zval; 318 | 319 | MAKE_STD_ZVAL(tmp_zval); 320 | array_init(tmp_zval); 321 | add_assoc_long(tmp_zval, "try_op", ops->try_catch_array[i].try_op); 322 | add_assoc_long(tmp_zval, "catch_op", ops->try_catch_array[i].catch_op); 323 | add_index_zval(tmpzval, i, tmp_zval); 324 | } 325 | add_assoc_zval(return_value, "try_catch_array", tmpzval); 326 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 327 | add_assoc_null(return_value, "try_catch_array"); 328 | } 329 | 330 | #ifndef ZEND_ACC_CLOSURE 331 | /* PHP<5.3 */ 332 | add_assoc_bool(return_value, "uses_this", ops->uses_this); 333 | #endif 334 | add_assoc_long(return_value, "line_start", ops->line_start); 335 | add_assoc_long(return_value, "line_end", ops->line_end); 336 | 337 | if (ops->doc_comment && ops->doc_comment_len) { 338 | add_assoc_stringl(return_value, "doc_comment", ops->doc_comment, ops->doc_comment_len, 1); 339 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 340 | add_assoc_null(return_value, "doc_comment"); 341 | } 342 | 343 | #else 344 | /* ZE1 op_array members */ 345 | 346 | if (ops->arg_types) { 347 | zend_uchar *arg_types = ops->arg_types; 348 | int numargs = *(ops->arg_types); 349 | 350 | MAKE_STD_ZVAL(tmpzval); 351 | array_init(tmpzval); 352 | add_assoc_long(tmpzval, "arg_count", numargs); 353 | 354 | for(i = 0; i < numargs; i++) { 355 | add_next_index_long(tmpzval, arg_types[i+1]); 356 | } 357 | 358 | add_assoc_zval(return_value, "arg_types", tmpzval); 359 | 360 | /* Emulated arg_info */ 361 | MAKE_STD_ZVAL(tmpzval); 362 | php_parsekit_derive_arginfo(tmpzval, ops, options TSRMLS_CC); 363 | add_assoc_zval(return_value, "arg_info", tmpzval); 364 | } else { 365 | MAKE_STD_ZVAL(tmpzval); 366 | array_init(tmpzval); 367 | add_assoc_long(tmpzval, "arg_count", 0); 368 | 369 | add_assoc_zval(return_value, "arg_types", tmpzval); 370 | add_assoc_null(return_value, "arg_info"); 371 | } 372 | 373 | add_assoc_bool(return_value, "uses_global", ops->uses_globals); 374 | #endif 375 | /* ZE1 and ZE2 */ 376 | 377 | add_assoc_bool(return_value, "return_reference", ops->return_reference); 378 | add_assoc_long(return_value, "refcount", *(ops->refcount)); 379 | add_assoc_long(return_value, "last", ops->last); 380 | add_assoc_long(return_value, "size", ops->size); 381 | add_assoc_long(return_value, "T", ops->T); 382 | add_assoc_long(return_value, "last_brk_cont", ops->last_brk_cont); 383 | add_assoc_long(return_value, "current_brk_cont", ops->current_brk_cont); 384 | add_assoc_long(return_value, "backpatch_count", ops->backpatch_count); 385 | add_assoc_bool(return_value, "done_pass_two", ops->done_pass_two); 386 | 387 | if (ops->last_brk_cont > 0) { 388 | MAKE_STD_ZVAL(tmpzval); 389 | array_init(tmpzval); 390 | for(i = 0; i < ops->last_brk_cont; i++) { 391 | zval *tmp_zval; 392 | 393 | MAKE_STD_ZVAL(tmp_zval); 394 | array_init(tmp_zval); 395 | add_assoc_long(tmp_zval, "cont", ops->brk_cont_array[i].cont); 396 | add_assoc_long(tmp_zval, "brk", ops->brk_cont_array[i].brk); 397 | add_assoc_long(tmp_zval, "parent", ops->brk_cont_array[i].parent); 398 | add_index_zval(tmpzval, i, tmp_zval); 399 | } 400 | add_assoc_zval(return_value, "brk_cont_array", tmpzval); 401 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 402 | add_assoc_null(return_value, "brk_cont_array"); 403 | } 404 | 405 | if (ops->static_variables) { 406 | zval *tmp_zval; 407 | 408 | MAKE_STD_ZVAL(tmpzval); 409 | array_init(tmpzval); 410 | zend_hash_copy(HASH_OF(tmpzval), ops->static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *)); 411 | add_assoc_zval(return_value, "static_variables", tmpzval); 412 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 413 | add_assoc_null(return_value, "static_variables"); 414 | } 415 | 416 | if (ops->start_op) { 417 | char sop[(sizeof(void *) * 2) + 1]; 418 | 419 | snprintf(sop, sizeof(sop), "%X", (unsigned int)ops->start_op); 420 | add_assoc_string(return_value, "start_op", sop, 1); 421 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 422 | add_assoc_null(return_value, "start_op"); 423 | } 424 | 425 | if (ops->filename) { 426 | add_assoc_string(return_value, "filename", ops->filename, 1); 427 | } else { 428 | add_assoc_null(return_value, "filename"); 429 | } 430 | 431 | /* Leave this last, it simplifies readability */ 432 | MAKE_STD_ZVAL(tmpzval); 433 | array_init(tmpzval); 434 | for(op = ops->opcodes, i = 0; op && i < ops->size; op++, i++) { 435 | zval *zop; 436 | 437 | MAKE_STD_ZVAL(zop); 438 | php_parsekit_parse_op(zop, ops, op, options TSRMLS_CC); 439 | add_next_index_zval(tmpzval, zop); 440 | } 441 | add_assoc_zval(return_value, "opcodes", tmpzval); 442 | 443 | } 444 | /* }}} */ 445 | 446 | /* {{{ php_parsekit_parse_node_simple */ 447 | static int php_parsekit_parse_node_simple(char **pret, zend_op_array *op_array, znode *node, zend_op_array *oparray TSRMLS_DC) 448 | { 449 | if (node->op_type == IS_UNUSED) { 450 | if (node->u.var) { 451 | #ifdef ZEND_ENGINE_2 452 | if (node->u.jmp_addr >= oparray->opcodes && 453 | node->u.jmp_addr <= (oparray->opcodes + (sizeof(zend_op) * oparray->size))) 454 | { 455 | spprintf(pret, 0, "#%d", node->u.jmp_addr - oparray->opcodes); 456 | } 457 | else 458 | #endif 459 | { 460 | spprintf(pret, 0, "0x%X", node->u.var); 461 | } 462 | return 1; 463 | } else { 464 | *pret = "UNUSED"; 465 | return 0; 466 | } 467 | } 468 | if (node->op_type == IS_CONST) { 469 | switch (node->u.constant.type) { 470 | case IS_NULL: 471 | *pret = "NULL"; 472 | return 0; 473 | break; 474 | case IS_BOOL: 475 | if (node->u.constant.value.lval) { 476 | *pret = "TRUE"; 477 | } else { 478 | *pret = "FALSE"; 479 | } 480 | return 0; 481 | break; 482 | case IS_LONG: 483 | spprintf(pret, 0, "%ld", node->u.constant.value.lval); 484 | return 1; 485 | break; 486 | case IS_DOUBLE: 487 | spprintf(pret, 0, "%f", node->u.constant.value.dval); 488 | return 1; 489 | break; 490 | case IS_STRING: 491 | if (node->u.constant.value.str.len > 15) { 492 | spprintf(pret, 0, "'%12s...'", node->u.constant.value.str.val); 493 | } else { 494 | spprintf(pret, 0, "'%s'", node->u.constant.value.str.val); 495 | } 496 | return 1; 497 | break; 498 | /* Should these ever occur? */ 499 | case IS_RESOURCE: 500 | spprintf(pret, 0, "Resource ID#%ld", node->u.constant.value.lval); 501 | return 1; 502 | break; 503 | case IS_ARRAY: 504 | *pret = "Array"; 505 | return 0; 506 | break; 507 | case IS_OBJECT: 508 | *pret = "Object"; 509 | return 0; 510 | break; 511 | default: 512 | *pret = "Unknown"; 513 | return 0; 514 | } 515 | } 516 | 517 | spprintf(pret, 0, "T(%d)", node->u.var / sizeof(temp_variable)); 518 | return 1; 519 | } 520 | /* }}} */ 521 | 522 | /* {{{ php_parsekit_parse_op_array_simple */ 523 | static void php_parsekit_parse_op_array_simple(zval *return_value, zend_op_array *ops, long options TSRMLS_DC) 524 | { 525 | zend_op *op; 526 | int i; 527 | long flags; 528 | 529 | array_init(return_value); 530 | 531 | for (op = ops->opcodes, i = 0; op && i < ops->size; op++, i++) { 532 | char *opline, *result, *op1, *op2; 533 | int opline_len, freeit = 0; 534 | 535 | if (php_parsekit_parse_node_simple(&result, ops, &(op->result), ops TSRMLS_CC)) { 536 | freeit |= 1; 537 | } 538 | if (php_parsekit_parse_node_simple(&op1, ops, &(op->op1), ops TSRMLS_CC)) { 539 | freeit |= 2; 540 | } 541 | if (php_parsekit_parse_node_simple(&op2, ops, &(op->op2), ops TSRMLS_CC)) { 542 | freeit |= 4; 543 | } 544 | 545 | opline_len = spprintf(&opline, 0, "%s %s %s %s", 546 | php_parsekit_define_name_ex(op->opcode, php_parsekit_opcode_names, &flags, PHP_PARSEKIT_OPCODE_UNKNOWN), 547 | result, op1, op2); 548 | 549 | if (freeit & 1) efree(result); 550 | if (freeit & 2) efree(op1); 551 | if (freeit & 4) efree(op2); 552 | 553 | add_next_index_stringl(return_value, opline, opline_len, 0); 554 | } 555 | } 556 | /* }}} */ 557 | 558 | /* {{{ php_parsekit_pop_functions */ 559 | static int php_parsekit_pop_functions(zval *return_value, HashTable *function_table, int target_count, long options TSRMLS_DC) 560 | { 561 | HashPosition pos; 562 | 563 | array_init(return_value); 564 | 565 | zend_hash_internal_pointer_end_ex(function_table, &pos); 566 | while (target_count < zend_hash_num_elements(function_table)) { 567 | long func_index; 568 | unsigned int func_name_len; 569 | char *func_name; 570 | zend_function *function; 571 | zval *function_ops; 572 | 573 | if (zend_hash_get_current_data_ex(function_table, (void **)&function, &pos) == FAILURE) { 574 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from function table: Illegal function entry found."); 575 | return FAILURE; 576 | } 577 | if (function->type == ZEND_INTERNAL_FUNCTION) { 578 | /* Inherited internal method */ 579 | zend_hash_move_backwards_ex(function_table, &pos); 580 | target_count++; 581 | continue; 582 | } else if (function->type != ZEND_USER_FUNCTION) { 583 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from function table: %s%s%s - " 584 | "Found %s where ZEND_USER_FUNCTION was expected.", 585 | function->common.scope ? function->common.scope->name : "", 586 | function->common.scope ? "::" : "", 587 | function->common.function_name, 588 | php_parsekit_define_name(function->type, php_parsekit_function_types, PHP_PARSEKIT_FUNCTYPE_UNKNOWN)); 589 | return FAILURE; 590 | } 591 | MAKE_STD_ZVAL(function_ops); 592 | if (options == PHP_PARSEKIT_SIMPLE) { 593 | php_parsekit_parse_op_array_simple(function_ops, &(function->op_array), options TSRMLS_CC); 594 | } else { 595 | php_parsekit_parse_op_array(function_ops, &(function->op_array), options TSRMLS_CC); 596 | } 597 | add_assoc_zval(return_value, function->common.function_name, function_ops); 598 | 599 | if (zend_hash_get_current_key_ex(function_table, &func_name, &func_name_len, &func_index, 0, &pos) == HASH_KEY_IS_STRING) { 600 | zend_hash_move_backwards_ex(function_table, &pos); 601 | 602 | /* TODO: dispose of the function properly */ 603 | if (zend_hash_del(function_table, func_name, func_name_len) == FAILURE) { 604 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from function table: Unknown hash_del failure."); 605 | return FAILURE; 606 | } 607 | } else { 608 | /* Absolutely no reason this should ever occur */ 609 | zend_hash_move_backwards_ex(function_table, &pos); 610 | zend_hash_index_del(function_table, func_index); 611 | } 612 | } 613 | 614 | return SUCCESS; 615 | } 616 | /* }}} */ 617 | 618 | /* {{{ php_parsekit_parse_class_entry */ 619 | static int php_parsekit_parse_class_entry(zval *return_value, zend_class_entry *ce, long options TSRMLS_DC) 620 | { 621 | zval *tmpzval; 622 | #ifdef ZEND_ENGINE_2 623 | int i; 624 | #endif 625 | 626 | array_init(return_value); 627 | 628 | add_assoc_long(return_value, "type", ce->type); 629 | add_assoc_string(return_value, "type_name", php_parsekit_define_name(ce->type, php_parsekit_class_types, PHP_PARSEKIT_CLASSTYPE_UNKNOWN), 1); 630 | add_assoc_stringl(return_value, "name", ce->name, ce->name_length, 1); 631 | if (ce->parent) { 632 | add_assoc_stringl(return_value, "parent", ce->parent->name, ce->parent->name_length, 1); 633 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 634 | add_assoc_null(return_value, "parent"); 635 | } 636 | add_assoc_bool(return_value, "constants_updated", ce->constants_updated); 637 | #ifdef ZEND_ENGINE_2 638 | /* ZE2 class_entry members */ 639 | add_assoc_long(return_value, "ce_flags", ce->ce_flags); 640 | 641 | /* function table pop destorys entries! */ 642 | if (ce->constructor) { 643 | add_assoc_string(return_value, "constructor", ce->constructor->common.function_name, 1); 644 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 645 | add_assoc_null(return_value, "constructor"); 646 | } 647 | 648 | if (ce->clone) { 649 | add_assoc_string(return_value, "clone", ce->clone->common.function_name, 1); 650 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 651 | add_assoc_null(return_value, "clone"); 652 | } 653 | 654 | if (ce->__get) { 655 | add_assoc_string(return_value, "__get", ce->__get->common.function_name, 1); 656 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 657 | add_assoc_null(return_value, "__get"); 658 | } 659 | 660 | if (ce->__set) { 661 | add_assoc_string(return_value, "__set", ce->__set->common.function_name, 1); 662 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 663 | add_assoc_null(return_value, "__set"); 664 | } 665 | 666 | if (ce->__call) { 667 | add_assoc_string(return_value, "__call", ce->__call->common.function_name, 1); 668 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 669 | add_assoc_null(return_value, "__call"); 670 | } 671 | 672 | if (zend_hash_num_elements(&(ce->properties_info)) > 0) { 673 | zend_property_info *property_info; 674 | 675 | MAKE_STD_ZVAL(tmpzval); 676 | array_init(tmpzval); 677 | for(zend_hash_internal_pointer_reset(&(ce->properties_info)); 678 | zend_hash_get_current_data(&(ce->properties_info), (void **)&property_info) == SUCCESS; 679 | zend_hash_move_forward(&(ce->properties_info))) { 680 | zval *tmp_zval; 681 | 682 | MAKE_STD_ZVAL(tmp_zval); 683 | array_init(tmp_zval); 684 | add_assoc_long(tmp_zval, "flags", property_info->flags); 685 | add_assoc_stringl(tmp_zval, "name", property_info->name, property_info->name_length, 1); 686 | add_assoc_long(tmp_zval, "h", property_info->h); 687 | add_next_index_zval(tmpzval, tmp_zval); 688 | } 689 | add_assoc_zval(return_value, "properties_info", tmpzval); 690 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 691 | add_assoc_null(return_value, "properties_info"); 692 | } 693 | 694 | if (ce->static_members && zend_hash_num_elements(ce->static_members) > 0) { 695 | zval *tmp_zval; 696 | 697 | MAKE_STD_ZVAL(tmpzval); 698 | array_init(tmpzval); 699 | zend_hash_copy(HASH_OF(tmpzval), ce->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *)); 700 | add_assoc_zval(return_value, "static_members", tmpzval); 701 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 702 | add_assoc_null(return_value, "static_members"); 703 | } 704 | 705 | if (zend_hash_num_elements(&(ce->constants_table)) > 0) { 706 | zval *tmp_zval; 707 | 708 | MAKE_STD_ZVAL(tmpzval); 709 | array_init(tmpzval); 710 | zend_hash_copy(HASH_OF(tmpzval), &(ce->constants_table), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *)); 711 | add_assoc_zval(return_value, "constants_table", tmpzval); 712 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 713 | add_assoc_null(return_value, "constants_table"); 714 | } 715 | 716 | if (ce->num_interfaces > 0) { 717 | MAKE_STD_ZVAL(tmpzval); 718 | array_init(tmpzval); 719 | for(i = 0; i < ce->num_interfaces; i++) { 720 | add_next_index_stringl(tmpzval, ce->interfaces[i]->name, ce->interfaces[i]->name_length, 1); 721 | } 722 | add_assoc_zval(return_value, "interfaces", tmpzval); 723 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 724 | add_assoc_null(return_value, "interfaces"); 725 | } 726 | 727 | add_assoc_string(return_value, "filename", ce->filename, 1); 728 | add_assoc_long(return_value, "line_start", ce->line_start); 729 | add_assoc_long(return_value, "line_end", ce->line_end); 730 | if (ce->doc_comment) { 731 | add_assoc_stringl(return_value, "doc_comment", ce->doc_comment, ce->doc_comment_len, 1); 732 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 733 | add_assoc_null(return_value, "doc_comment"); 734 | } 735 | 736 | add_assoc_long(return_value, "refcount", Z_REFCOUNT_P(ce)); 737 | 738 | #else 739 | /* ZE1 class_entry members */ 740 | if (ce->refcount) { 741 | add_assoc_long(return_value, "refcount", *(ce->refcount)); 742 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 743 | add_assoc_null(return_value, "refcount"); 744 | } 745 | 746 | #endif 747 | /* ZE1 and ZE2 */ 748 | 749 | if (zend_hash_num_elements(&(ce->function_table)) > 0) { 750 | MAKE_STD_ZVAL(tmpzval); 751 | if (php_parsekit_pop_functions(tmpzval, &(ce->function_table), 0, options TSRMLS_CC) == FAILURE) { 752 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to cleanup class %s: Error scrubbing function_table", ce->name); 753 | return FAILURE; 754 | } 755 | add_assoc_zval(return_value, "function_table", tmpzval); 756 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 757 | add_assoc_null(return_value, "function_table"); 758 | } 759 | 760 | if (zend_hash_num_elements(&(ce->default_properties)) > 0) { 761 | zval *tmp_zval; 762 | 763 | MAKE_STD_ZVAL(tmpzval); 764 | array_init(tmpzval); 765 | zend_hash_copy(HASH_OF(tmpzval), &(ce->default_properties), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *)); 766 | add_assoc_zval(return_value, "default_properties", tmpzval); 767 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 768 | add_assoc_null(return_value, "default_properties"); 769 | } 770 | 771 | return SUCCESS; 772 | } 773 | /* }}} */ 774 | 775 | /* {{{ php_parsekit_pop_classes */ 776 | static int php_parsekit_pop_classes(zval *return_value, HashTable *class_table, int target_count, long options TSRMLS_DC) 777 | { 778 | array_init(return_value); 779 | 780 | while (target_count < zend_hash_num_elements(class_table)) { 781 | long class_index; 782 | unsigned int class_name_len; 783 | char *class_name; 784 | zend_class_entry *class_entry, **pce; 785 | zval *class_data; 786 | 787 | zend_hash_internal_pointer_end(class_table); 788 | if (zend_hash_get_current_data(class_table, (void **)&pce) == FAILURE || !pce || !(*pce)) { 789 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from class table: Illegal class entry found."); 790 | return FAILURE; 791 | } 792 | #ifdef ZEND_ENGINE_2 793 | class_entry = *pce; 794 | #else 795 | class_entry = (zend_class_entry*)pce; 796 | #endif 797 | if (class_entry->type != ZEND_USER_CLASS) { 798 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from class table: %s - " 799 | "Found %s where ZEND_USER_CLASS was expected.", class_entry->name, 800 | php_parsekit_define_name(class_entry->type, php_parsekit_class_types, PHP_PARSEKIT_CLASSTYPE_UNKNOWN)); 801 | return FAILURE; 802 | } 803 | MAKE_STD_ZVAL(class_data); 804 | if (php_parsekit_parse_class_entry(class_data, class_entry, options TSRMLS_CC) == FAILURE) { 805 | return FAILURE; /* Exit gracefully even though the E_ERROR condition will clean up after us */ 806 | } 807 | add_assoc_zval(return_value, class_entry->name, class_data); 808 | 809 | if (zend_hash_get_current_key_ex(class_table, &class_name, &class_name_len, &class_index, 0, NULL) == HASH_KEY_IS_STRING) { 810 | /* TODO: dispose of the class properly */ 811 | if (zend_hash_del(class_table, class_name, class_name_len) == FAILURE) { 812 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from class table: Unknown hash_del failure."); 813 | return FAILURE; 814 | } 815 | } else { 816 | /* Absolutely no reason this should ever occur */ 817 | zend_hash_index_del(class_table, class_index); 818 | } 819 | } 820 | return SUCCESS; 821 | } 822 | /* }}} */ 823 | 824 | /* {{{ php_parsekit_common */ 825 | static void php_parsekit_common(zval *return_value, int original_num_functions, int original_num_classes, zend_op_array *ops, long options TSRMLS_DC) 826 | { 827 | zval *declared_functions, *declared_classes; 828 | 829 | /* main() */ 830 | if (options == PHP_PARSEKIT_SIMPLE) { 831 | php_parsekit_parse_op_array_simple(return_value, ops, options TSRMLS_CC); 832 | } else { 833 | php_parsekit_parse_op_array(return_value, ops, options TSRMLS_CC); 834 | } 835 | 836 | if (original_num_functions < zend_hash_num_elements(EG(function_table))) { 837 | /* The compiled code introduced new functions, get them out of there! */ 838 | MAKE_STD_ZVAL(declared_functions); 839 | php_parsekit_pop_functions(declared_functions, EG(function_table), original_num_functions, options TSRMLS_CC); 840 | add_assoc_zval(return_value, "function_table", declared_functions); 841 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 842 | add_assoc_null(return_value, "function_table"); 843 | } 844 | 845 | if (original_num_classes < zend_hash_num_elements(EG(class_table))) { 846 | /* The compiled code introduced new classes, get them out of here */ 847 | MAKE_STD_ZVAL(declared_classes); 848 | php_parsekit_pop_classes(declared_classes, EG(class_table), original_num_classes, options TSRMLS_CC); 849 | add_assoc_zval(return_value, "class_table", declared_classes); 850 | } else if (options & PHP_PARSEKIT_ALWAYS_SET) { 851 | add_assoc_null(return_value, "class_table"); 852 | } 853 | } 854 | /* }}} */ 855 | 856 | /* ****************************************** */ 857 | /* Module Housekeeping and Userland Functions */ 858 | /* ****************************************** */ 859 | 860 | /* {{{ proto array parsekit_compile_string(string phpcode[, array &errors[, int options]]) 861 | Return array of opcodes compiled from phpcode */ 862 | PHP_FUNCTION(parsekit_compile_string) 863 | { 864 | int original_num_functions = zend_hash_num_elements(EG(function_table)); 865 | int original_num_classes = zend_hash_num_elements(EG(class_table)); 866 | zend_uchar original_compiler_options; 867 | zend_op_array *ops; 868 | zval *zcode, *zerrors = NULL; 869 | long options = PHP_PARSEKIT_QUIET; 870 | 871 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &zcode, &zerrors, &options) == FAILURE) { 872 | RETURN_FALSE; 873 | } 874 | 875 | if (zerrors) { 876 | zval_dtor(zerrors); 877 | ZVAL_NULL(zerrors); 878 | PARSEKIT_G(compile_errors) = zerrors; 879 | } 880 | 881 | convert_to_string(zcode); 882 | #ifdef ZEND_COMPILE_HANDLE_OP_ARRAY 883 | original_compiler_options = CG(compiler_options); 884 | CG(compiler_options) = CG(compiler_options) & ~ZEND_COMPILE_HANDLE_OP_ARRAY; 885 | #else 886 | original_compiler_options = CG(handle_op_arrays); 887 | CG(handle_op_arrays) = 0; 888 | #endif 889 | PARSEKIT_G(in_parsekit_compile) = 1; 890 | 891 | zend_try { 892 | ops = compile_string(zcode, "Parsekit Compiler" TSRMLS_CC); 893 | } zend_catch { 894 | ops = NULL; 895 | } zend_end_try(); 896 | 897 | PARSEKIT_G(in_parsekit_compile) = 0; 898 | PARSEKIT_G(compile_errors) = NULL; 899 | 900 | #ifdef ZEND_COMPILE_HANDLE_OP_ARRAY 901 | CG(compiler_options) = original_compiler_options; 902 | #else 903 | CG(handle_op_arrays) = original_compiler_options; 904 | #endif 905 | 906 | if (ops) { 907 | php_parsekit_common(return_value, original_num_functions, original_num_classes, ops, options TSRMLS_CC); 908 | destroy_op_array(ops PHP_PARSEKIT_TSRMLS_CC_ZE2ONLY); 909 | efree(ops); 910 | } else { 911 | RETURN_FALSE; 912 | } 913 | } 914 | /* }}} */ 915 | 916 | /* {{{ proto array parsekit_compile_file(string filename[, array &errors[, int options]]) 917 | Return array of opcodes compiled from phpfile */ 918 | PHP_FUNCTION(parsekit_compile_file) 919 | { 920 | int original_num_functions = zend_hash_num_elements(EG(function_table)); 921 | int original_num_classes = zend_hash_num_elements(EG(class_table)); 922 | zend_uchar original_compiler_options; 923 | zend_op_array *ops; 924 | zval *zfilename, *zerrors = NULL; 925 | long options = PHP_PARSEKIT_QUIET; 926 | 927 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &zfilename, &zerrors, &options) == FAILURE) { 928 | RETURN_FALSE; 929 | } 930 | 931 | if (zerrors) { 932 | zval_dtor(zerrors); 933 | ZVAL_NULL(zerrors); 934 | PARSEKIT_G(compile_errors) = zerrors; 935 | } 936 | 937 | convert_to_string(zfilename); 938 | #ifdef ZEND_COMPILE_HANDLE_OP_ARRAY 939 | original_compiler_options = CG(compiler_options); 940 | CG(compiler_options) = CG(compiler_options) & ~ZEND_COMPILE_HANDLE_OP_ARRAY; 941 | #else 942 | original_compiler_options = CG(handle_op_arrays); 943 | CG(handle_op_arrays) = 0; 944 | #endif 945 | PARSEKIT_G(in_parsekit_compile) = 1; 946 | 947 | zend_try { 948 | ops = compile_filename(ZEND_INCLUDE, zfilename TSRMLS_CC); 949 | } zend_catch { 950 | ops = NULL; 951 | } zend_end_try(); 952 | 953 | PARSEKIT_G(in_parsekit_compile) = 0; 954 | PARSEKIT_G(compile_errors) = NULL; 955 | 956 | #ifdef ZEND_COMPILE_HANDLE_OP_ARRAY 957 | CG(compiler_options) = original_compiler_options; 958 | #else 959 | CG(handle_op_arrays) = original_compiler_options; 960 | #endif 961 | 962 | if (ops) { 963 | php_parsekit_common(return_value, original_num_functions, original_num_classes, ops, options TSRMLS_CC); 964 | 965 | destroy_op_array(ops PHP_PARSEKIT_TSRMLS_CC_ZE2ONLY); 966 | efree(ops); 967 | } else { 968 | RETURN_FALSE; 969 | } 970 | } 971 | /* }}} */ 972 | 973 | /* {{{ proto long parsekit_opcode_flags(long opcode) 974 | Return the flags associated with an opcode */ 975 | PHP_FUNCTION(parsekit_opcode_flags) 976 | { 977 | long opcode; 978 | php_parsekit_define_list *opcodes = php_parsekit_opcode_names; 979 | 980 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &opcode) == FAILURE) { 981 | RETURN_FALSE; 982 | } 983 | 984 | while (opcodes) { 985 | if (opcodes->val == opcode) { 986 | RETURN_LONG(opcodes->flags); 987 | } 988 | } 989 | 990 | RETURN_FALSE; 991 | } 992 | /* }}} */ 993 | 994 | /* {{{ proto string parsekit_opcode_name(long opcode) 995 | Return the name of a given opcode */ 996 | PHP_FUNCTION(parsekit_opcode_name) 997 | { 998 | long opcode; 999 | 1000 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &opcode) == FAILURE) { 1001 | RETURN_FALSE; 1002 | } 1003 | 1004 | RETURN_STRING(php_parsekit_define_name(opcode, php_parsekit_opcode_names, PHP_PARSEKIT_OPCODE_UNKNOWN), 1); 1005 | } 1006 | /* }}} */ 1007 | 1008 | /* {{{ proto array parsekit_func_arginfo(mixed function) 1009 | Return the arg_info data for a given user function/method */ 1010 | PHP_FUNCTION(parsekit_func_arginfo) 1011 | { 1012 | zval *function; 1013 | char *class = NULL, *fname = NULL; 1014 | int class_len = 0, fname_len = 0; 1015 | HashTable *function_table = NULL; 1016 | zend_function *fe = NULL; 1017 | 1018 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function) == FAILURE) { 1019 | RETURN_FALSE; 1020 | } 1021 | 1022 | switch (Z_TYPE_P(function)) { 1023 | case IS_STRING: 1024 | fname = Z_STRVAL_P(function); 1025 | fname_len = Z_STRLEN_P(function); 1026 | function_table = EG(function_table); 1027 | break; 1028 | case IS_ARRAY: 1029 | { 1030 | zval **classname; 1031 | zval **funcname; 1032 | 1033 | zend_hash_internal_pointer_reset(HASH_OF(function)); 1034 | 1035 | /* Name that class */ 1036 | if (zend_hash_get_current_data(HASH_OF(function), (void **)&classname) == FAILURE) { 1037 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting string or array containing two elements."); 1038 | RETURN_FALSE; 1039 | } 1040 | if (!classname || !*classname || (Z_TYPE_PP(classname) != IS_STRING && Z_TYPE_PP(classname) != IS_OBJECT)) { 1041 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid class name given"); 1042 | RETURN_FALSE; 1043 | } 1044 | if (Z_TYPE_PP(classname) == IS_STRING) { 1045 | class = Z_STRVAL_PP(classname); 1046 | class_len = Z_STRLEN_PP(classname); 1047 | } else { 1048 | class = Z_OBJCE_PP(classname)->name; 1049 | class_len = Z_OBJCE_PP(classname)->name_length; 1050 | 1051 | /* Save looking it up later! */ 1052 | function_table = &(Z_OBJCE_PP(classname)->function_table); 1053 | } 1054 | 1055 | zend_hash_move_forward(HASH_OF(function)); 1056 | 1057 | /* Name that function */ 1058 | if (zend_hash_get_current_data(HASH_OF(function), (void **)&funcname) == FAILURE) { 1059 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting string or array containing two elements."); 1060 | RETURN_FALSE; 1061 | } 1062 | if (!funcname || !*funcname || Z_TYPE_PP(funcname) != IS_STRING) { 1063 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid method name given"); 1064 | RETURN_FALSE; 1065 | } 1066 | fname = Z_STRVAL_PP(funcname); 1067 | fname_len = Z_STRLEN_PP(funcname); 1068 | 1069 | break; 1070 | } 1071 | default: 1072 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting string or array containing two elements."); 1073 | RETURN_FALSE; 1074 | } 1075 | 1076 | if (class && !function_table) { 1077 | zend_class_entry **pce; 1078 | #ifndef ZEND_ENGINE_2 1079 | zend_class_entry *ce; 1080 | #endif 1081 | 1082 | /* Fetch class's method table */ 1083 | #ifdef ZEND_ENGINE_2 1084 | if (zend_lookup_class(class, class_len, &pce TSRMLS_CC) == FAILURE) { 1085 | #else 1086 | pce = &ce; 1087 | if (zend_hash_find(EG(class_table), class, class_len + 1, (void**)&ce) == FAILURE) { 1088 | #endif 1089 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown class: %s", class); 1090 | RETURN_FALSE; 1091 | } 1092 | if (!pce || !*pce) { 1093 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fetch class entry."); 1094 | RETURN_FALSE; 1095 | } 1096 | 1097 | function_table = &((*pce)->function_table); 1098 | } 1099 | 1100 | if (!function_table) { 1101 | /* Should never happen */ 1102 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error locating function table"); 1103 | RETURN_FALSE; 1104 | } 1105 | 1106 | if (zend_hash_find(function_table, fname, fname_len + 1, (void **)&fe) == FAILURE) { 1107 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s%s() not found.", class ? class : "", class ? "::" : "", fname); 1108 | RETURN_FALSE; 1109 | } 1110 | 1111 | if (fe->type != ZEND_USER_FUNCTION) { 1112 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only user defined functions support reflection"); 1113 | RETURN_FALSE; 1114 | } 1115 | 1116 | #ifdef ZEND_ENGINE_2 1117 | php_parsekit_parse_arginfo(return_value, fe->common.num_args, fe->common.arg_info, 0 TSRMLS_CC); 1118 | #else 1119 | php_parsekit_derive_arginfo(return_value, &fe->op_array, 0 TSRMLS_CC); 1120 | #endif 1121 | } 1122 | /* }}} */ 1123 | 1124 | #ifdef ZEND_ENGINE_2 1125 | ZEND_BEGIN_ARG_INFO(php_parsekit_second_arg_force_ref, 0) 1126 | ZEND_ARG_PASS_INFO(0) 1127 | ZEND_ARG_PASS_INFO(1) 1128 | ZEND_END_ARG_INFO() 1129 | #else 1130 | static unsigned char php_parsekit_second_arg_force_ref[] = { 3, BYREF_NONE, BYREF_FORCE }; 1131 | #endif 1132 | 1133 | /* {{{ zend_function_entry */ 1134 | zend_function_entry parsekit_functions[] = { 1135 | PHP_FE(parsekit_compile_string, php_parsekit_second_arg_force_ref) 1136 | PHP_FE(parsekit_compile_file, php_parsekit_second_arg_force_ref) 1137 | PHP_FE(parsekit_opcode_flags, NULL) 1138 | PHP_FE(parsekit_opcode_name, NULL) 1139 | PHP_FE(parsekit_func_arginfo, NULL) 1140 | {NULL, NULL, NULL} 1141 | }; 1142 | /* }}} */ 1143 | 1144 | /* {{{ parsekit_module_entry 1145 | */ 1146 | zend_module_entry parsekit_module_entry = { 1147 | #if ZEND_MODULE_API_NO >= 20010901 1148 | STANDARD_MODULE_HEADER, 1149 | #endif 1150 | "parsekit", 1151 | parsekit_functions, 1152 | PHP_MINIT(parsekit), 1153 | PHP_MSHUTDOWN(parsekit), 1154 | NULL, /* RINIT */ 1155 | NULL, /* RSHUTDOWN */ 1156 | PHP_MINFO(parsekit), 1157 | #if ZEND_MODULE_API_NO >= 20010901 1158 | PHP_PARSEKIT_VERSION, 1159 | #endif 1160 | STANDARD_MODULE_PROPERTIES 1161 | }; 1162 | /* }}} */ 1163 | 1164 | #ifdef COMPILE_DL_PARSEKIT 1165 | ZEND_GET_MODULE(parsekit) 1166 | #endif 1167 | 1168 | /* {{{ php_parsekit_error_cb 1169 | Capture error messages and locations while suppressing otherwise fatal (non-core) errors */ 1170 | static void php_parsekit_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) 1171 | { 1172 | char *buffer; 1173 | int buffer_len; 1174 | zval *tmpzval; 1175 | TSRMLS_FETCH(); 1176 | 1177 | if (!PARSEKIT_G(in_parsekit_compile) || type == E_CORE_ERROR) { 1178 | /* Some normal (or massively abnormal) event triggered this error. */ 1179 | php_parsekit_original_error_function(type, (char *)error_filename, error_lineno, format, args); 1180 | return; 1181 | } 1182 | 1183 | if (!PARSEKIT_G(compile_errors)) { 1184 | /* All errors ignored */ 1185 | return; 1186 | } 1187 | 1188 | /* If an error gets triggered in here, revert to normal handling to avoid potential loop */ 1189 | PARSEKIT_G(in_parsekit_compile) = 0; 1190 | MAKE_STD_ZVAL(tmpzval); 1191 | array_init(tmpzval); 1192 | add_assoc_long(tmpzval, "errno", type); 1193 | add_assoc_string(tmpzval, "filename", (char *)error_filename, 1); 1194 | add_assoc_long(tmpzval, "lineno", error_lineno); 1195 | buffer_len = vspprintf(&buffer, PG(log_errors_max_len), format, args); 1196 | add_assoc_stringl(tmpzval, "errstr", buffer, buffer_len, 1); 1197 | 1198 | if (Z_TYPE_P(PARSEKIT_G(compile_errors)) == IS_NULL) { 1199 | array_init(PARSEKIT_G(compile_errors)); 1200 | } 1201 | add_next_index_zval(PARSEKIT_G(compile_errors), tmpzval); 1202 | 1203 | /* Restore compiler state */ 1204 | PARSEKIT_G(in_parsekit_compile) = 1; 1205 | } 1206 | /* }}} */ 1207 | 1208 | #define REGISTER_PARSEKIT_CONSTANTS(define_list) \ 1209 | { \ 1210 | char const_name[96]; \ 1211 | int const_name_len; \ 1212 | php_parsekit_define_list *defines = (define_list); \ 1213 | while (defines->str) { \ 1214 | /* the macros don't like variable constant names */ \ 1215 | const_name_len = snprintf(const_name, sizeof(const_name), "PARSEKIT_%s", defines->str); \ 1216 | zend_register_long_constant(const_name, const_name_len+1, defines->val, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC); \ 1217 | defines++; \ 1218 | } \ 1219 | } 1220 | 1221 | /* {{{ php_parsekit_init_globals 1222 | */ 1223 | static void php_parsekit_init_globals(zend_parsekit_globals *parsekit_globals) 1224 | { 1225 | parsekit_globals->in_parsekit_compile = 0; 1226 | parsekit_globals->compile_errors = NULL; 1227 | } 1228 | /* }}} */ 1229 | 1230 | /* {{{ PHP_MINIT_FUNCTION 1231 | */ 1232 | PHP_MINIT_FUNCTION(parsekit) 1233 | { 1234 | REGISTER_PARSEKIT_CONSTANTS(php_parsekit_class_types); 1235 | REGISTER_PARSEKIT_CONSTANTS(php_parsekit_function_types); 1236 | REGISTER_PARSEKIT_CONSTANTS(php_parsekit_nodetype_names); 1237 | REGISTER_PARSEKIT_CONSTANTS(php_parsekit_opcode_names); 1238 | REGISTER_PARSEKIT_CONSTANTS(php_parsekit_opnode_flags); 1239 | 1240 | REGISTER_LONG_CONSTANT("PARSEKIT_QUIET", PHP_PARSEKIT_QUIET, CONST_CS | CONST_PERSISTENT ); 1241 | REGISTER_LONG_CONSTANT("PARSEKIT_SIMPLE", PHP_PARSEKIT_SIMPLE, CONST_CS | CONST_PERSISTENT ); 1242 | 1243 | ZEND_INIT_MODULE_GLOBALS(parsekit, php_parsekit_init_globals, NULL); 1244 | 1245 | /* Changing zend_error_cb isn't threadsafe, 1246 | so we'll have to just change it for everybody 1247 | and track whether or not we're in parsekit_compile() 1248 | on a perthread basis and go from there. 1249 | DANGER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1250 | This could tank if another module does this same hack 1251 | before us then unloads. */ 1252 | php_parsekit_original_error_function = zend_error_cb; 1253 | zend_error_cb = php_parsekit_error_cb; 1254 | 1255 | return SUCCESS; 1256 | } 1257 | /* }}} */ 1258 | 1259 | /* {{{ PHP_MSHUTDOWN_FUNCTION 1260 | */ 1261 | PHP_MSHUTDOWN_FUNCTION(parsekit) 1262 | { 1263 | zend_error_cb = php_parsekit_original_error_function; 1264 | 1265 | return SUCCESS; 1266 | } 1267 | /* }}} */ 1268 | 1269 | /* {{{ PHP_MINFO_FUNCTION 1270 | */ 1271 | PHP_MINFO_FUNCTION(parsekit) 1272 | { 1273 | php_info_print_table_start(); 1274 | php_info_print_table_header(2, "parsekit support", "enabled"); 1275 | php_info_print_table_row(2, "version", PHP_PARSEKIT_VERSION); 1276 | php_info_print_table_end(); 1277 | } 1278 | /* }}} */ 1279 | 1280 | 1281 | /* 1282 | * Local variables: 1283 | * tab-width: 4 1284 | * c-basic-offset: 4 1285 | * End: 1286 | * vim600: noet sw=4 ts=4 fdm=marker 1287 | * vim<600: noet sw=4 ts=4 1288 | */ 1289 | --------------------------------------------------------------------------------