├── 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 |
--------------------------------------------------------------------------------