1 /*
2  * Copyright (c) 2014 Jakub Zelenka. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  *
22  */
23 
24 
25 #ifndef PHPC_H
26 #define	PHPC_H
27 
28 #if PHP_VERSION_ID < 50199
29 #error "Only PHP 5.2+ supported"
30 #endif
31 
32 /* no operation */
33 #define PHPC_NOOP ((void) 0)
34 
35 /* COMMON (used definitions) */
36 
37 /* common object macros */
38 #define PHPC_CLASS_TYPE _phpc_class_type
39 #define PHPC_SELF       _phpc_self
40 #define PHPC_OBJ_STRUCT_NAME(_name) struct _phpc_##_name##__obj
41 #define PHPC_OBJ_STRUCT_DECLARE(_name, _ptr) PHPC_OBJ_STRUCT_NAME(_name) *_ptr
42 #define PHPC_OBJ_GET_HANDLER_FCE(_name, _type) _name##__##_type
43 #define PHPC_OBJ_DEFINE_HANDLER_FCE(_rtype, _name, _type) \
44 	static _rtype PHPC_OBJ_GET_HANDLER_FCE(_name, _type)
45 #define PHPC_OBJ_GET_HANDLER_FCE_INLINE_DEF(_rtype, _name, _type) \
46 	PHPC_OBJ_DEFINE_HANDLER_FCE(inline _rtype, _name, _type)
47 #define PHPC_OBJ_GET_HANDLER_VAR_NAME(_name) _phpc_##_name##__handlers
48 #define PHPC_OBJ_DEFINE_HANDLER_VAR(_name) \
49 	static zend_object_handlers PHPC_OBJ_GET_HANDLER_VAR_NAME(_name)
50 #define PHPC_OBJ_INIT_HANDLERS(_name) \
51 	memcpy(&PHPC_OBJ_GET_HANDLER_VAR_NAME(_name), \
52 		zend_get_std_object_handlers(), sizeof(zend_object_handlers))
53 #define PHPC_CLASS_SET_HANDLER_CREATE(_class_entry, _name) \
54 	_class_entry.create_object = PHPC_OBJ_GET_HANDLER_FCE(_name, create)
55 #define PHPC_OBJ_SET_HANDLER_CLONE(_name) \
56 	PHPC_OBJ_GET_HANDLER_VAR_NAME(_name).clone_obj = PHPC_OBJ_GET_HANDLER_FCE(_name, clone)
57 #define PHPC_OBJ_SET_HANDLER_COMPARE(_name) \
58 	PHPC_OBJ_GET_HANDLER_VAR_NAME(_name).compare_objects = PHPC_OBJ_GET_HANDLER_FCE(_name, compare)
59 #if PHP_VERSION_ID < 50399
60 #define PHPC_OBJ_SET_HANDLER_GET_GC(_name) PHPC_NOOP
61 #else
62 #define PHPC_OBJ_SET_HANDLER_GET_GC(_name) \
63 	PHPC_OBJ_GET_HANDLER_VAR_NAME(_name).get_gc = PHPC_OBJ_GET_HANDLER_FCE(_name, get_gc)
64 #endif
65 #define PHPC_OBJ_SET_HANDLER_GET_DEBUG_INFO(_name) \
66 	PHPC_OBJ_GET_HANDLER_VAR_NAME(_name).get_debug_info = PHPC_OBJ_GET_HANDLER_FCE(_name, get_debug_info)
67 #define PHPC_OBJ_SET_HANDLER_GET_PROPERTIES(_name) \
68 	PHPC_OBJ_GET_HANDLER_VAR_NAME(_name).get_properties = PHPC_OBJ_GET_HANDLER_FCE(_name, get_properties)
69 
70 /* initializing properties in obejct (object_properties_init was added in PHP 5.4) */
71 #if PHP_VERSION_ID < 50399
72 #define PHPC_OBJ_PROPERTIES_INIT(zo, class_type) \
73 	{ \
74 		zval *tmp; \
75 		zend_hash_copy((*(zo)).properties, \
76 			&(class_type)->default_properties, \
77 			(copy_ctor_func_t) zval_add_ref, \
78 			(void *) &tmp, \
79 			sizeof(zval *)); \
80 	}
81 #else
82 #define PHPC_OBJ_PROPERTIES_INIT object_properties_init
83 #endif
84 
85 /* common fcall macros */
86 #define PHPC_FCALL_PARAMS_NAME(_pname) _phpc_fcall_params__ ## _pname
87 
88 /* integer conversions */
89 #define PHPC_CONVERT_NUMBER(_pn, _n, _exc_over, _exc_under, _type_from, _type_to, _max, _min) \
90 	if (_pn > (_type_from) _max) { \
91 		_exc_over; \
92 	} else if (_pn < (_type_from) _min) { \
93 		_exc_under; \
94 	} \
95 	_n = (_type_to) _pn
96 
97 #define PHPC_CONVERT_NUMBER_SIGNED(_pn, _n, _exc_over, _type_from, _type_to, _max) \
98 	if (_pn > (_type_from) _max) { \
99 		_exc_over; \
100 	} \
101 	_n = (_type_to) _pn
102 
103 #define PHPC_LONG_TO_INT_EX2(_plv, _lv, _exc_over, _exc_under) \
104 	PHPC_CONVERT_NUMBER(_plv, _lv, _exc_over, _exc_under, long, int, INT_MAX, INT_MIN)
105 #define PHPC_LONG_TO_INT_EX(_plv, _lv, _exc) \
106 	PHPC_LONG_TO_INT_EX2(_plv, _lv, _exc, _exc)
107 #define PHPC_LONG_TO_INT(_plv, _lv) \
108 	PHPC_LONG_TO_INT_EX2(_plv, _lv, _lv = INT_MAX, _lv = INT_MIN)
109 
110 
111 #if PHP_MAJOR_VERSION == 5
112 
113 
114 /* INTEGER */
115 
116 /* long type */
117 typedef long  phpc_long_t;
118 /* unsigned long type */
119 typedef unsigned long phpc_ulong_t;
120 /* offset type */
121 typedef off_t phpc_off_t;
122 /* string length type */
123 typedef int phpc_str_size_t;
124 
125 #define PHPC_LONG_TO_LONG_EX2(_plv, _lv, _exc_over, _exc_under) \
126 	_lv = _plv
127 #define PHPC_LONG_TO_LONG_EX(_plv, _lv, _exc) \
128 	_lv = _plv
129 #define PHPC_LONG_TO_LONG(_plv, _lv) \
130 	_lv = _plv
131 
132 #define PHPC_SIZE_TO_LONG_EX  PHPC_LONG_TO_LONG_EX
133 #define PHPC_SIZE_TO_LONG     PHPC_LONG_TO_LONG
134 
135 #define PHPC_SIZE_TO_INT_EX  PHPC_LONG_TO_LONG_EX
136 #define PHPC_SIZE_TO_INT     PHPC_LONG_TO_LONG
137 
138 
139 /* STRING */
140 
141 /* accessor and convertor macros */
142 #define PHPC_STR_VAL(_name)                   _name##__val
143 #define PHPC_STR_LEN(_name)                   _name##__len
144 #define PHPC_STR_LEN_FMT                      "d"
145 #define PHPC_STR_LEN_UNUSED(_name)            (void) PHPC_STR_LEN(_name)
146 #define PHPC_STR_LEN_FROM_VAL(_name)          strlen(PHPC_STR_VAL(_name))
147 #define PHPC_STR_LEN_DECLARE(_name)           int PHPC_STR_LEN(_name)
148 #define PHPC_STR_LEN_FETCH(_name)             PHPC_STR_LEN(_name) = PHPC_STR_LEN_FROM_VAL(_name)
149 #define PHPC_STR_LEN_DECLARE_AND_FETCH(_name) int PHPC_STR_LEN_FETCH(_name)
150 #define PHPC_STR_EXISTS(_name)                PHPC_STR_VAL(_name)
151 #define PHPC_STR_DECLARE(_name)               char *PHPC_STR_VAL(_name); int PHPC_STR_LEN(_name)
152 #define PHPC_STR_ARG(_name)                   char *PHPC_STR_VAL(_name), int PHPC_STR_LEN(_name)
153 #define PHPC_STR_ARG_VAL(_name)               char *PHPC_STR_VAL(_name)
154 #define PHPC_STR_ARG_PTR(_name)               char **PHPC_STR_VAL(_name), int *PHPC_STR_LEN(_name)
155 #define PHPC_STR_ARG_PTR_VAL(_name)           char **PHPC_STR_VAL(_name)
156 #define PHPC_STR_PASS(_name)                  PHPC_STR_VAL(_name), PHPC_STR_LEN(_name)
157 #define PHPC_STR_PASS_VAL(_name)              PHPC_STR_VAL(_name)
158 #define PHPC_STR_PASS_PTR(_name)              &PHPC_STR_VAL(_name), &PHPC_STR_LEN(_name)
159 #define PHPC_STR_PASS_PTR_VAL(_name)          &PHPC_STR_VAL(_name)
160 #define PHPC_STR_DEREF_VAL(_name)             *PHPC_STR_VAL(_name)
161 #define PHPC_STR_FROM_PTR_STR(_str, _strp) \
162 	PHPC_STR_VAL(_str) = *PHPC_STR_VAL(_strp); \
163 	PHPC_STR_LEN(_str) = *PHPC_STR_LEN(_strp)
164 #define PHPC_STR_FROM_PTR_VAL(_str, _strpv) \
165 	PHPC_STR_VAL(_str) = *PHPC_STR_VAL(_strpv); \
166 	PHPC_STR_LEN(_str) = strlen(*PHPC_STR_VAL(_strpv))
167 #define PHPC_STR_RETURN(_name) \
168 	RETURN_STRINGL(PHPC_STR_VAL(_name), PHPC_STR_LEN(_name), 0)
169 
170 /* wrapper macros */
171 #define PHPC_STR_INIT(_name, _cstr, _len) do { \
172 		PHPC_STR_VAL(_name) = emalloc(_len + 1); \
173 		memcpy(PHPC_STR_VAL(_name), _cstr, _len); \
174 		PHPC_STR_VAL(_name)[_len] = 0; \
175 		PHPC_STR_LEN(_name) = _len; \
176 	} while (0)
177 #define PHPC_STR_ALLOC(_name, _len) do { \
178 		PHPC_STR_VAL(_name) = emalloc(_len + 1); \
179 		PHPC_STR_LEN(_name) = _len; \
180 	} while (0)
181 #define PHPC_STR_REALLOC(_name, _len) do { \
182 		PHPC_STR_VAL(_name) = erealloc(PHPC_STR_VAL(_name), _len + 1); \
183 		PHPC_STR_LEN(_name) = _len; \
184 	} while (0)
185 #define PHPC_STR_RELEASE(_name) efree(PHPC_STR_VAL(_name))
186 
187 /* C string */
188 #define PHPC_CSTRL_RETURN(_name, _len) RETURN_STRINGL(_name, _len, 1)
189 #define PHPC_CSTR_RETURN(_name)        RETURN_STRING(_name, 1)
190 #define PHPC_CSTRL_RETVAL(_name, _len) RETVAL_STRINGL(_name, _len, 1)
191 #define PHPC_CSTR_RETVAL(_name)        RETVAL_STRING(_name, 1)
192 
193 /* ZPP path flag */
194 #if PHP_VERSION_ID < 50399
195 #define PHPC_PATH_ZPP_FLAG "s"
196 #else
197 #define PHPC_PATH_ZPP_FLAG "p"
198 #endif
199 
200 /* Smart string */
201 #if defined(PHPC_SMART_STR_INCLUDE) || defined(PHPC_SMART_CSTR_INCLUDE)
202 #include "ext/standard/php_smart_str.h"
203 
204 #ifdef PHPC_SMART_CSTR_INCLUDE
205 /* smart_str for C string has been renamed in PHP 7 so we have to wrap it */
206 #define phpc_smart_cstr                 smart_str
207 #define phpc_smart_cstr_alloc           smart_str_alloc
208 #define phpc_smart_cstr_free            smart_str_free
209 #define phpc_smart_cstr_append          smart_str_append
210 #define phpc_smart_cstr_appends         smart_str_appends
211 #define phpc_smart_cstr_appendl         smart_str_appendl
212 #define phpc_smart_cstr_appendc         smart_str_appendc
213 #define phpc_smart_cstr_append_long     smart_str_append_long
214 #define phpc_smart_cstr_append_unsigned smart_str_append_unsigned
215 #define phpc_smart_cstr_0               smart_str_0
216 #endif /* PHPC_SMART_CSTR_INCLUDE */
217 
218 #endif /* PHPC_SMART_STR_INCLUDE || PHPC_SMART_CSTR_INCLUDE */
219 
220 
221 /* OBJECT */
222 #define PHPC_CLASS_REGISTER_EX(_orig_class_entry, _parent_ce, _parent_name) \
223 	zend_register_internal_class_ex(&_orig_class_entry, _parent_ce, _parent_name TSRMLS_CC)
224 #define PHPC_CLASS_REGISTER(_orig_class_entry) \
225 	zend_register_internal_class(&_orig_class_entry TSRMLS_CC)
226 
227 /* struct spec */
228 #define PHPC_OBJ_STRUCT_MEMBER_FIRST zend_object std;
229 #define PHPC_OBJ_STRUCT_MEMBER_LAST
230 #define PHPC_OBJ_STRUCT_BEGIN(_name) \
231 	PHPC_OBJ_STRUCT_NAME(_name) { PHPC_OBJ_STRUCT_MEMBER_FIRST
232 #define PHPC_OBJ_STRUCT_END() \
233 	PHPC_OBJ_STRUCT_MEMBER_LAST };
234 
235 /* object convertors */
236 #define PHPC_OBJ_FROM_ZOBJ(_name, _object) \
237 	(PHPC_OBJ_STRUCT_NAME(_name) *) _object
238 #define PHPC_OBJ_FROM_ZVAL(_name, _zv) \
239 	(PHPC_OBJ_STRUCT_NAME(_name) *) zend_object_store_get_object(_zv TSRMLS_CC)
240 #define PHPC_OBJ_FROM_SELF(_name) \
241 	PHPC_OBJ_FROM_ZVAL(_name, PHPC_SELF)
242 #define PHP_OBJ_GET_HANDLER_OBJ_FROM_ZOBJ(_name) \
243 	PHPC_OBJ_FROM_ZOBJ(_name, _phpc_object)
244 
245 /* create_ex object handler helper */
246 #define PHPC_OBJ_HANDLER_CREATE_EX(_name) \
247 	PHPC_OBJ_GET_HANDLER_FCE_INLINE_DEF(zend_object_value, _name, create_ex) \
248 	(zend_class_entry *PHPC_CLASS_TYPE, PHPC_OBJ_STRUCT_NAME(_name) **_phpc_objptr TSRMLS_DC)
249 #define PHPC_OBJ_HANDLER_CREATE_EX_DECLARE() zend_object_value _phpc_retval
250 #define PHPC_OBJ_HANDLER_CREATE_EX_ALLOC(_name) \
251 	 ecalloc(1, sizeof(PHPC_OBJ_STRUCT_NAME(_name)));
252 #define PHPC_OBJ_HANDLER_INIT_CREATE_EX_PROPS(_intern) \
253 	do { \
254 		if (_phpc_objptr) { \
255 			*_phpc_objptr = _intern; \
256 		} \
257 		zend_object_std_init(&_intern->std, PHPC_CLASS_TYPE TSRMLS_CC); \
258 		PHPC_OBJ_PROPERTIES_INIT(&_intern->std, PHPC_CLASS_TYPE); \
259 	} while(0)
260 #define PHPC_OBJ_HANDLER_CREATE_EX_RETURN_EX(_name, _intern) \
261 	do { \
262 		_phpc_retval.handle = zend_objects_store_put((_intern), \
263 			(zend_objects_store_dtor_t) zend_objects_destroy_object, \
264 			(zend_objects_free_object_storage_t) PHPC_OBJ_GET_HANDLER_FCE(_name, free), \
265 			NULL TSRMLS_CC); \
266 		_phpc_retval.handlers = &PHPC_OBJ_GET_HANDLER_VAR_NAME(_name); \
267 		return _phpc_retval; \
268 	} while(0)
269 
270 /* create object handler */
271 #define PHPC_OBJ_HANDLER_CREATE(_name) \
272 	PHPC_OBJ_DEFINE_HANDLER_FCE(zend_object_value, _name, create) \
273 	(zend_class_entry *PHPC_CLASS_TYPE TSRMLS_DC)
274 #define PHPC_OBJ_HANDLER_CREATE_RETURN(_name) \
275 	return PHPC_OBJ_GET_HANDLER_FCE(_name, create_ex)(PHPC_CLASS_TYPE, NULL TSRMLS_CC)
276 
277 /* clone object handler */
278 #define PHPC_OBJ_HANDLER_CLONE(_name) \
279 	PHPC_OBJ_DEFINE_HANDLER_FCE(zend_object_value, _name, clone)(zval *PHPC_SELF TSRMLS_DC)
280 #define PHPC_OBJ_HANDLER_CLONE_DECLARE() zend_object_value _phpc_retval
281 #define PHPC_OBJ_HANDLER_CLONE_MEMBERS(_name, _new_obj, _old_obj) \
282 	do { \
283 		_phpc_retval = PHPC_OBJ_GET_HANDLER_FCE(_name, create_ex)(_old_obj->std.ce, &_new_obj TSRMLS_CC); \
284 		zend_objects_clone_members(&_new_obj->std, _phpc_retval, &_old_obj->std, Z_OBJ_HANDLE_P(PHPC_SELF) TSRMLS_CC); \
285 	} while(0)
286 #define PHPC_OBJ_HANDLER_CLONE_RETURN_EX(_new_obj) return _phpc_retval
287 
288 /* free object handler */
289 #define PHPC_OBJ_HANDLER_FREE(_name) \
290 	PHPC_OBJ_DEFINE_HANDLER_FCE(void, _name, free)(void *_phpc_object TSRMLS_DC)
291 #define PHPC_OBJ_HANDLER_FREE_DTOR(_intern) \
292 	do { \
293 		zend_object_std_dtor(&(_intern)->std TSRMLS_CC); \
294 		efree(_intern); \
295 	} while(0)
296 
297 /* compare object handler */
298 #define PHPC_OBJ_HANDLER_COMPARE(_name) \
299 	PHPC_OBJ_DEFINE_HANDLER_FCE(int, _name, compare)(zval *_phpc_obj1, zval *_phpc_obj2 TSRMLS_DC)
300 #define PHPC_OBJ_HANDLER_COMPARE_FETCH(_name, _id, _obj) \
301 	PHPC_OBJ_STRUCT_DECLARE(_name, _obj) = PHPC_OBJ_FROM_ZVAL(_name, _phpc_obj ## _id)
302 
303 /* handler setters */
304 #define PHPC_OBJ_SET_HANDLER_OFFSET(_name) PHPC_NOOP
305 #define PHPC_OBJ_SET_HANDLER_FREE(_name) PHPC_NOOP
306 
307 /* read propery */
308 #define PHPC_READ_PROPERTY_RV_NAME
309 #define PHPC_READ_PROPERTY_RV_DECLARE PHPC_NOOP
310 #define PHPC_READ_PROPERTY(_scope, _object, _name, _name_len, _silent) \
311 	zend_read_property(_scope, _object, _name, _name_len, _silent TSRMLS_CC)
312 
313 /* HASH */
314 
315 /* update */
316 #define PHPC_HASH_INDEX_UPDATE(_ht, _idx, _pzv) \
317 	zend_hash_index_update(_ht, _idx, &_pzv, sizeof(_pzv), NULL)
318 #define PHPC_HASH_STR_UPDATE(_ht, _str, _pzv) \
319 	zend_hash_update(_ht, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str) + 1, &_pzv, sizeof(_pzv), NULL)
320 #define PHPC_HASH_CSTRL_UPDATE(_ht, _cstr_value, _cstr_len, _pzv) \
321 	zend_hash_update(_ht, _cstr_value, (_cstr_len) + 1, &_pzv, sizeof(_pzv), NULL)
322 #define PHPC_HASH_CSTR_UPDATE(_ht, _cstr_value, _pzv) \
323 	zend_hash_update(_ht, _cstr_value, strlen(_cstr_value) + 1, &_pzv, sizeof(_pzv), NULL)
324 
325 /* delete */
326 #define PHPC_HASH_INDEX_DELETE(_ht, _idx) \
327 	zend_hash_index_del(_ht, _idx)
328 #define PHPC_HASH_STR_DELETE(_ht, _str) \
329 	 zend_hash_del(_ht, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str) + 1)
330 #define PHPC_HASH_CSTRL_DELETE(_ht, _cstr_value, _cstr_len) \
331 	zend_hash_del(_ht, _cstr_value, (_cstr_len) + 1)
332 #define PHPC_HASH_CSTR_DELETE(_ht, _cstr_value) \
333 	zend_hash_del(_ht, _cstr_value, strlen(_cstr_value) + 1)
334 
335 /* exists */
336 #define PHPC_HASH_INDEX_EXISTS(_ht, _idx) \
337 	zend_hash_index_exists(_ht, _idx)
338 #define PHPC_HASH_STR_EXISTS(_ht, _str) \
339 	 zend_hash_exists(_ht, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str) + 1)
340 #define PHPC_HASH_CSTRL_EXISTS(_ht, _cstr_value, _cstr_len) \
341 	zend_hash_exists(_ht, _cstr_value, (_cstr_len) + 1)
342 #define PHPC_HASH_CSTR_EXISTS(_ht, _cstr_value) \
343 	zend_hash_exists(_ht, _cstr_value, strlen(_cstr_value) + 1)
344 
345 /* find */
346 #define PHPC_HASH_INDEX_FIND(_ht, _idx, _ppv) \
347 	zend_hash_index_find(_ht, _idx, (void **) &_ppv)
348 #define PHPC_HASH_STR_FIND(_ht, _str, _ppv) \
349 	 zend_hash_find(_ht, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str) + 1, (void **) &_ppv)
350 #define PHPC_HASH_CSTRL_FIND(_ht, _cstr_value, _cstr_len, _ppv) \
351 	zend_hash_find(_ht, _cstr_value, (_cstr_len) + 1, (void **) &_ppv)
352 #define PHPC_HASH_CSTR_FIND(_ht, _cstr_value, _ppv) \
353 	zend_hash_find(_ht, _cstr_value, strlen(_cstr_value) + 1, (void **) &_ppv)
354 /* not found value */
355 #define PHPC_HASH_NOT_FOUND FAILURE
356 
357 /* key and data getter */
358 #define PHPC_HASH_GET_CURRENT_KEY_EX(_ht, _str, _num_index, _pos) \
359 	do { \
360 		unsigned int _phpc_current_key_len; \
361 		zend_hash_get_current_key_ex(_ht, &PHPC_STR_VAL(_str), \
362 			&_phpc_current_key_len, &_num_index, 0, _pos); \
363 		PHPC_STR_LEN(_str) = _phpc_current_key_len - 1; \
364 	} while(0)
365 #define PHPC_HASH_GET_CURRENT_DATA_EX(_ht, _val, _pos) \
366 	zend_hash_get_current_data_ex(_ht, (void **) &(_val), _pos)
367 
368 #define PHPC_HASH_GET_CURRENT_KEY(_ht, _str, _num_index) \
369 	zend_hash_get_current_key(_ht, &PHPC_STR_VAL(_str), &_num_index, 0)
370 #define PHPC_HASH_GET_CURRENT_DATA(_ht, _val) \
371 	zend_hash_get_current_data(_ht, (void **) &(_val))
372 
373 /* copy */
374 #define PHPC_HASH_COPY_EX(_target, _source, _copy_ctr) \
375 	zend_hash_copy(_target, _source, NULL, NULL, sizeof(zval *))
376 
377 /* iteration for each element */
378 #define PHPC_HASH_FOREACH_VAL(_ht, _ppv) do { \
379 	HashPosition _pos; \
380 	for (zend_hash_internal_pointer_reset_ex((_ht), &_pos); \
381 			zend_hash_get_current_data_ex((_ht), (void **) &(_ppv), &_pos) == SUCCESS; \
382 			zend_hash_move_forward_ex((_ht), &_pos) ) {
383 
384 #define _PHPC_HASH_FOREACH_KEY_VAL(_ht, _ph, _key, _ppv, _use_h) \
385 	PHPC_HASH_FOREACH_VAL(_ht, _ppv) \
386 		uint _str_length; \
387 		ulong _num_index, *_pnum_index; \
388 		if (_use_h) { \
389 			_pnum_index = _ph; \
390 		} else { \
391 			_pnum_index = &_num_index; \
392 		} \
393 		int _key_type = zend_hash_get_current_key_ex(_ht, &PHPC_STR_VAL(_key), &_str_length, _pnum_index, 0, &_pos); \
394 		if (_key_type == HASH_KEY_IS_STRING) { \
395 			PHPC_STR_LEN(_key) = (int) _str_length; \
396 		} else { \
397 			PHPC_STR_VAL(_key) = NULL; \
398 			PHPC_STR_LEN(_key) = 0; \
399 		}
400 
401 #define PHPC_HASH_FOREACH_KEY_VAL(_ht, _h, _key, _ppv) \
402 	_PHPC_HASH_FOREACH_KEY_VAL(_ht, &_h, _key, _ppv, 1)
403 
404 #define PHPC_HASH_FOREACH_STR_KEY_VAL(_ht, _key, _ppv) \
405 	_PHPC_HASH_FOREACH_KEY_VAL(_ht, NULL, _key, _ppv, 0)
406 
407 #define PHPC_HASH_FOREACH_END() } } while (0)
408 
409 /* hash to zval */
410 #define PHPC_HASH_PZVAL(_ht, _pzv) \
411 	do { \
412 		Z_ARRVAL_P(_pzv) = _ht; \
413 		Z_TYPE_P(_pzv) = IS_ARRAY; \
414 	} while(0)
415 #define PHPC_HASH_RETVAL(_ht) \
416 	PHPC_HASH_PZVAL(_ht, return_value)
417 #define PHPC_HASH_RETURN(_ht) \
418 	do { \
419 		PHPC_HASH_RETVAL(_ht); \
420 		return; \
421 	} while(0)
422 
423 
424 /* ARRAY */
425 #define PHPC_ARRAY_ADD_ASSOC_NULL_EX(_arr, _key, _key_len) \
426     add_assoc_null_ex(_arr, _key, (_key_len) + 1)
427 #define PHPC_ARRAY_ADD_ASSOC_BOOL_EX(_arr, _key, _key_len, _b) \
428     add_assoc_bool_ex(_arr, _key, (_key_len) + 1, _b)
429 #define PHPC_ARRAY_ADD_ASSOC_LONG_EX(_arr, _key, _key_len, _n) \
430     add_assoc_long_ex(_arr, _key, (_key_len) + 1, _n)
431 #define PHPC_ARRAY_ADD_ASSOC_RESOURCE_EX(_arr, _key, _key_len, _r) \
432 add_assoc_resource_ex(_arr, _key, (_key_len) + 1, _r)
433 #define PHPC_ARRAY_ADD_ASSOC_DOUBLE_EX(_arr, _key, _key_len, _d) \
434 	add_assoc_double_ex(_arr, _key, (_key_len) + 1, _d)
435 #define PHPC_ARRAY_ADD_ASSOC_STR_EX(_arr, _key, _key_len, _str) \
436 	add_assoc_stringl_ex(_arr, _key, (_key_len) + 1, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str), 0)
437 #define PHPC_ARRAY_ADD_ASSOC_CSTR_EX(_arr, _key, _key_len, _cstr) \
438 	add_assoc_string_ex(_arr, _key, (_key_len) + 1, _cstr, 1)
439 #define PHPC_ARRAY_ADD_ASSOC_CSTRL_EX(_arr, _key, _key_len, _cstr, _cstr_len) \
440 	add_assoc_stringl_ex(_arr, _key, (_key_len) + 1, _cstr, _cstr_len, 1)
441 #define PHPC_ARRAY_ADD_ASSOC_VAL_EX(_arr, _key, _key_len, _pv) \
442 	add_assoc_zval_ex(_arr, _key, (_key_len) + 1, _pv)
443 
444 #define PHPC_ARRAY_ADD_ASSOC_STR(_arr, _key, _str) \
445 	add_assoc_stringl(_arr, _key, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str), 0)
446 #define PHPC_ARRAY_ADD_ASSOC_CSTR(_arr, _key, _cstr) \
447 	add_assoc_string(_arr, _key, _cstr, 1)
448 #define PHPC_ARRAY_ADD_ASSOC_CSTRL(_arr, _key, _cstr, _cstr_len) \
449 	add_assoc_stringl(_arr, _key, _cstr, _cstr_len, 1)
450 #define PHPC_ARRAY_ADD_ASSOC_VAL      add_assoc_zval
451 
452 #define PHPC_ARRAY_ADD_INDEX_STR(_arr, _idx, _str) \
453 	add_index_stringl(_arr, _idx, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str), 0)
454 #define PHPC_ARRAY_ADD_INDEX_CSTR(_arr, _idx, _cstr) \
455 	add_index_string(_arr, _idx, _cstr, 1)
456 #define PHPC_ARRAY_ADD_INDEX_CSTRL(_arr, _idx, _cstr, _cstr_len) \
457 	add_index_stringl(_arr, _idx, _cstr, _cstr_len, 1)
458 #define PHPC_ARRAY_ADD_INDEX_VAL      add_index_zval
459 
460 #define PHPC_ARRAY_ADD_NEXT_INDEX_STR(_arr, _str) \
461 	add_next_index_stringl(_arr, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str), 0)
462 #define PHPC_ARRAY_ADD_NEXT_INDEX_CSTR(_arr, _cstr) \
463 	add_next_index_string(_arr, _cstr, 1)
464 #define PHPC_ARRAY_ADD_NEXT_INDEX_CSTRL(_arr, _cstr, _cstr_len) \
465 	add_next_index_stringl(_arr, _cstr, _cstr_len, 1)
466 #define PHPC_ARRAY_ADD_NEXT_INDEX_VAL add_next_index_zval
467 
468 
469 /* FCALL */
470 #define _PHPC_FCALL_VARS_NAME(_pname) _phpc_fcall_vars__ ## _pname
471 
472 #define PHPC_FCALL_PARAMS_DECLARE(_pname, _count) \
473 	int _phpc_fcall_params_count = _count; \
474 	zval *_PHPC_FCALL_VARS_NAME(_pname)[_count]; \
475 	zval **PHPC_FCALL_PARAMS_NAME(_pname)[_count]
476 
477 #define PHPC_FCALL_PARAMS_INIT(_pname) \
478 	do { \
479 		int _idx; \
480 		for (_idx = 0; _idx <  _phpc_fcall_params_count; _idx++) \
481 			PHPC_FCALL_PARAMS_NAME(_pname)[_idx] = &_PHPC_FCALL_VARS_NAME(_pname)[_idx]; \
482 	} while(0)
483 
484 #define PHPC_FCALL_PARAM_PZVAL(_pname, _idx) \
485 	_PHPC_FCALL_VARS_NAME(_pname)[_idx]
486 
487 #define PHPC_FCALL_PARAM_VAL(_pname, _idx) \
488 	_PHPC_FCALL_VARS_NAME(_pname)[_idx]
489 
490 #define PHPC_FCALL_PARAM_UNDEF(_pname) \
491 	ZVAL_NULL(PHPC_FCALL_PARAM_PZVAL(_pname))
492 
493 #define PHPC_FCALL_RETVAL(_fci, _pv) \
494 	(_fci).retval_ptr_ptr = &(_pv)
495 
496 /* ZVAL */
497 typedef zval * phpc_val;
498 
499 #define PHPC_TYPE        Z_TYPE_P
500 #define PHPC_TYPE_P      Z_TYPE_PP
501 
502 #define PHPC_LVAL        Z_LVAL_P
503 #define PHPC_LVAL_P      Z_LVAL_PP
504 
505 #define PHPC_DVAL        Z_DVAL_P
506 #define PHPC_DVAL_P      Z_DVAL_PP
507 
508 #define PHPC_STRVAL      Z_STRVAL_P
509 #define PHPC_STRVAL_P    Z_STRVAL_PP
510 
511 #define PHPC_STRLEN      Z_STRLEN_P
512 #define PHPC_STRLEN_P    Z_STRLEN_PP
513 
514 #define PHPC_ARRVAL      Z_ARRVAL_P
515 #define PHPC_ARRVAL_P    Z_ARRVAL_PP
516 
517 #define PHPC_VAL_TO_ZVAL(_pv, _zv) _zv = *(_pv)
518 #define PHPC_VAL_TO_PZVAL(_pv, _zv) _zv = _pv
519 #define PHPC_PVAL_TO_PZVAL(_pv, _zv) _zv = *(_pv)
520 
521 #define PHPC_VAL_MAKE         MAKE_STD_ZVAL
522 #define PHPC_VAL_FREE         FREE_ZVAL
523 #define PHPC_VAL_UNDEF(_pv)   _pv = NULL
524 #define PHPC_VAL_ISUNDEF(_pv) _pv == NULL
525 
526 #define PHPC_VAL_STR(_pv, _str) \
527 	ZVAL_STRINGL(_pv, PHPC_STR_VAL(_str), PHPC_STR_LEN(_str), 0)
528 #define PHPC_VAL_CSTR(_pv, _cstr) \
529     ZVAL_STRING(_pv, _cstr, 1)
530 #define PHPC_VAL_CSTRL(_pv, _cstr, _cstr_len) \
531 	ZVAL_STRINGL(_pv, _cstr, _cstr_len, 1)
532 
533 
534 /* Function end */
535 #if (PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MINOR_VERSION >= 4)
536 #define PHPC_FE_END PHP_FE_END
537 #else
538 #define PHPC_FE_END {NULL,NULL,NULL}
539 #endif
540 
541 
542 /* STREAM */
543 #if PHP_VERSION_ID < 50600
544 typedef char phpc_stream_opener_char_t;
545 #else
546 typedef const char phpc_stream_opener_char_t;
547 #endif
548 #define PHPC_STREAM_WRAPPERDATA_ALLOC(stream) MAKE_STD_ZVAL(stream->wrapperdata)
549 #define PHPC_STREAM_WRAPPERDATA_ISSET(stream) stream->wrapperdata
550 #define PHPC_STREAM_WRAPPERDATA_UNSET(stream) \
551 	do { \
552 		zval_ptr_dtor(&stream->wrapperdata); \
553 		stream->wrapperdata = NULL; \
554 	} while(0)
555 #define PHPC_STREAM_CONTEXT_GET_OPTION(_ctx, _wrappername, _optionname, _ppv) \
556 	php_stream_context_get_option(_ctx, _wrappername, _optionname, &_ppv)
557 #define PHPC_STREAM_CONTEXT_OPTION_NOT_FOUND FAILURE
558 
559 #else /* PHP 7 */
560 
561 
562 /* INTEGER */
563 
564 /* long type */
565 typedef zend_long  phpc_long_t;
566 /* unsigned long type */
567 typedef zend_ulong phpc_ulong_t;
568 /* offset type */
569 typedef zend_off_t phpc_off_t;
570 /* string length type */
571 typedef size_t    phpc_str_size_t;
572 
573 #define PHPC_LONG_TO_LONG_EX2(_plv, _lv, _exc_over, _exc_under) \
574 	PHPC_CONVERT_NUMBER(_plv, _lv, _exc_over, _exc_under, phpc_long_t, long, LONG_MAX, LONG_MIN)
575 #define PHPC_LONG_TO_LONG_EX(_plv, _lv, _exc) \
576 	PHPC_LONG_TO_LONG_EX2(_plv, _lv, _exc, _exc)
577 #define PHPC_LONG_TO_LONG(_plv, _lv) \
578 	PHPC_LONG_TO_LONG_EX2(_plv, _lv, _lv = LONG_MAX, _lv = LONG_MIN)
579 
580 #define PHPC_SIZE_TO_LONG_EX(_plv, _lv, _exc_over) \
581 	PHPC_CONVERT_NUMBER_SIGNED(_plv, _lv, _exc_over, size_t, long, LONG_MAX)
582 #define PHPC_SIZE_TO_LONG(_plv, _lv) \
583 	PHPC_SIZE_TO_LONG_EX(_plv, _lv, _lv = LONG_MAX)
584 
585 #define PHPC_SIZE_TO_INT_EX(_plv, _lv, _exc_over) \
586 	PHPC_CONVERT_NUMBER_SIGNED(_plv, _lv, _exc_over, size_t, int, INT_MAX)
587 #define PHPC_SIZE_TO_INT(_plv, _lv) \
588 	PHPC_SIZE_TO_LONG_EX(_plv, _lv, _lv = INT_MAX)
589 
590 
591 /* STRING */
592 
593 /* accessor and convertor macros */
594 #define PHPC_STR_VAL                          ZSTR_VAL
595 #define PHPC_STR_LEN                          ZSTR_LEN
596 #define PHPC_STR_LEN_FMT                      "zu"
597 #define PHPC_STR_LEN_UNUSED(_name)            PHPC_NOOP
598 #define PHPC_STR_LEN_FROM_VAL                 PHPC_STR_LEN
599 #define PHPC_STR_LEN_DECLARE(_name)           PHPC_NOOP
600 #define PHPC_STR_LEN_FETCH(_name)             PHPC_NOOP
601 #define PHPC_STR_LEN_DECLARE_AND_FETCH(_name) PHPC_NOOP
602 #define PHPC_STR_EXISTS(_name)                (_name)
603 #define PHPC_STR_DECLARE(_name)               zend_string *_name
604 #define PHPC_STR_ARG(_name)                   zend_string *_name
605 #define PHPC_STR_ARG_VAL                      PHPC_STR_ARG
606 #define PHPC_STR_ARG_PTR(_name)               zend_string **_name
607 #define PHPC_STR_ARG_PTR_VAL                  PHPC_STR_ARG_PTR
608 #define PHPC_STR_PASS(_name)                  _name
609 #define PHPC_STR_PASS_VAL                     PHPC_STR_PASS
610 #define PHPC_STR_PASS_PTR(_name)              &_name
611 #define PHPC_STR_PASS_PTR_VAL                 PHPC_STR_PASS_PTR
612 #define PHPC_STR_DEREF_VAL(_name)             *_name
613 #define PHPC_STR_FROM_PTR_STR(_str, _strp)    _str = *_strp
614 #define PHPC_STR_FROM_PTR_VAL(_str, _strpv)   _str = *_strpv
615 #define PHPC_STR_RETURN                       RETURN_STR
616 /* wrapper macros */
617 #define PHPC_STR_INIT(_name, _cstr, _len) \
618 	_name = zend_string_init(_cstr, _len, 0)
619 #define PHPC_STR_ALLOC(_name, _len) \
620 	_name = zend_string_alloc(_len, 0)
621 #define PHPC_STR_REALLOC(_name, _len) \
622 	_name = zend_string_realloc(_name, _len, 0)
623 #define PHPC_STR_RELEASE(_name) \
624 	zend_string_release(_name)
625 
626 /* C string */
627 #define PHPC_CSTRL_RETURN                     RETURN_STRINGL
628 #define PHPC_CSTR_RETURN                      RETURN_STRING
629 #define PHPC_CSTRL_RETVAL                     RETVAL_STRINGL
630 #define PHPC_CSTR_RETVAL                      RETVAL_STRING
631 
632 /* ZPP path flag */
633 #define PHPC_PATH_ZPP_FLAG "p"
634 
635 /* Smart string */
636 #ifdef PHPC_SMART_STR_INCLUDE
637 #include "zend_smart_str.h"
638 #endif /* PHPC_SMART_STR_INCLUDE */
639 
640 #ifdef PHPC_SMART_CSTR_INCLUDE
641 #include "ext/standard/php_smart_string.h"
642 /* smart_str for C string has been renamed in PHP 7 so we have to wrap it */
643 #define phpc_smart_cstr                 smart_string
644 #define phpc_smart_cstr_alloc           smart_string_alloc
645 #define phpc_smart_cstr_free            smart_string_free
646 #define phpc_smart_cstr_append          smart_string_append
647 #define phpc_smart_cstr_appends         smart_string_appends
648 #define phpc_smart_cstr_appendl         smart_string_appendl
649 #define phpc_smart_cstr_appendc         smart_string_appendc
650 #define phpc_smart_cstr_append_long     smart_string_append_long
651 #define phpc_smart_cstr_append_unsigned smart_string_append_unsigned
652 #define phpc_smart_cstr_0               smart_string_0
653 #endif /* PHPC_SMART_CSTR_INCLUDE */
654 
655 
656 /* OBJECT */
657 #define PHPC_CLASS_REGISTER_EX(_orig_class_entry, _parent_ce, _parent_name) \
658 	zend_register_internal_class_ex(&_orig_class_entry, _parent_ce)
659 #define PHPC_CLASS_REGISTER(_orig_class_entry) \
660 	zend_register_internal_class(&_orig_class_entry)
661 
662 /* struct spec */
663 #define PHPC_OBJ_STRUCT_MEMBER_FIRST
664 #define PHPC_OBJ_STRUCT_MEMBER_LAST zend_object std;
665 #define PHPC_OBJ_STRUCT_BEGIN(_name) \
666 	PHPC_OBJ_STRUCT_NAME(_name) { PHPC_OBJ_STRUCT_MEMBER_FIRST
667 #define PHPC_OBJ_STRUCT_END() \
668 	PHPC_OBJ_STRUCT_MEMBER_LAST };
669 
670 #define PHPC_OBJ_FROM_ZOBJ(_name, _object) \
671 	(PHPC_OBJ_STRUCT_NAME(_name) *)((char*)(_object) - XtOffsetOf(PHPC_OBJ_STRUCT_NAME(_name), std))
672 #define PHPC_OBJ_FROM_ZVAL(_name, _zv) \
673 	PHPC_OBJ_FROM_ZOBJ(_name, Z_OBJ_P(_zv))
674 #define PHPC_OBJ_FROM_SELF(_name) \
675 	PHPC_OBJ_FROM_ZVAL(_name, PHPC_SELF)
676 #define PHP_OBJ_GET_HANDLER_OBJ_FROM_ZOBJ(_name) \
677 	PHPC_OBJ_FROM_ZOBJ(_name, _phpc_object)
678 
679 /* create_ex object handler helper */
680 #define PHPC_OBJ_HANDLER_CREATE_EX(_name) \
681 	PHPC_OBJ_GET_HANDLER_FCE_INLINE_DEF(zend_object *, _name, create_ex) \
682 	(zend_class_entry *PHPC_CLASS_TYPE, int _phpc_init_props)
683 #define PHPC_OBJ_HANDLER_CREATE_EX_DECLARE() PHPC_NOOP
684 #define PHPC_OBJ_HANDLER_CREATE_EX_ALLOC(_name) \
685 	 ecalloc(1, sizeof(PHPC_OBJ_STRUCT_NAME(_name)) + sizeof(zval) * (PHPC_CLASS_TYPE->default_properties_count - 1));
686 #define PHPC_OBJ_HANDLER_INIT_CREATE_EX_PROPS(_intern) \
687 	do { \
688 		zend_object_std_init(&_intern->std, PHPC_CLASS_TYPE); \
689 		if (_phpc_init_props) { \
690 			PHPC_OBJ_PROPERTIES_INIT(&_intern->std, PHPC_CLASS_TYPE); \
691 		} \
692 	} while(0)
693 #define PHPC_OBJ_HANDLER_CREATE_EX_RETURN_EX(_name, _intern) \
694 	do { \
695 		_intern->std.handlers = &PHPC_OBJ_GET_HANDLER_VAR_NAME(_name); \
696 		return &_intern->std; \
697 	} while(0)
698 
699 /* create object handler */
700 #define PHPC_OBJ_HANDLER_CREATE(_name) \
701 	PHPC_OBJ_DEFINE_HANDLER_FCE(zend_object *, _name, create) \
702 	(zend_class_entry *PHPC_CLASS_TYPE)
703 #define PHPC_OBJ_HANDLER_CREATE_RETURN(_name) \
704 	return PHPC_OBJ_GET_HANDLER_FCE(_name, create_ex)(PHPC_CLASS_TYPE, 1)
705 
706 /* clone object handler */
707 #define PHPC_OBJ_HANDLER_CLONE(_name) \
708 	PHPC_OBJ_DEFINE_HANDLER_FCE(zend_object *, _name, clone)(zval *PHPC_SELF)
709 #define PHPC_OBJ_HANDLER_CLONE_DECLARE() PHPC_NOOP
710 #define PHPC_OBJ_HANDLER_CLONE_MEMBERS(_name, _new_obj, _old_obj) \
711 	do { \
712 		_new_obj = PHPC_OBJ_FROM_ZOBJ(_name, PHPC_OBJ_GET_HANDLER_FCE(_name, create_ex)(_old_obj->std.ce, 0)); \
713 		zend_objects_clone_members(&_new_obj->std, &_old_obj->std); \
714 	} while(0)
715 #define PHPC_OBJ_HANDLER_CLONE_RETURN_EX(_new_obj) return &_new_obj->std;
716 
717 /* free object handler */
718 #define PHPC_OBJ_HANDLER_FREE(_name) \
719 	PHPC_OBJ_DEFINE_HANDLER_FCE(void, _name, free)(zend_object *_phpc_object)
720 #define PHPC_OBJ_HANDLER_FREE_DTOR(_intern) \
721 	zend_object_std_dtor(&(_intern)->std)
722 
723 /* compare object handler */
724 #define PHPC_OBJ_HANDLER_COMPARE(_name) \
725 	PHPC_OBJ_DEFINE_HANDLER_FCE(int, _name, compare)(zval *_phpc_obj1, zval *_phpc_obj2)
726 #define PHPC_OBJ_HANDLER_COMPARE_FETCH(_name, _id, _obj) \
727 	PHPC_OBJ_STRUCT_DECLARE(_name, _obj) = PHPC_OBJ_FROM_ZVAL(_name, _phpc_obj ## _id)
728 
729 /* handler setters */
730 #define PHPC_OBJ_SET_HANDLER_OFFSET(_name) \
731 	PHPC_OBJ_GET_HANDLER_VAR_NAME(_name).offset = XtOffsetOf(PHPC_OBJ_STRUCT_NAME(_name), std)
732 #define PHPC_OBJ_SET_HANDLER_FREE(_name) \
733 	PHPC_OBJ_GET_HANDLER_VAR_NAME(_name).free_obj = PHPC_OBJ_GET_HANDLER_FCE(_name, free)
734 
735 /* read propery */
736 #define PHPC_READ_PROPERTY_RV_NAME _phpc_read_property_rv
737 #define PHPC_READ_PROPERTY_RV_DECLARE zval PHPC_READ_PROPERTY_RV_NAME
738 #define PHPC_READ_PROPERTY(_scope, _object, _name, _name_len, _silent) \
739 	zend_read_property(_scope, _object, _name, _name_len, _silent, &PHPC_READ_PROPERTY_RV_NAME)
740 
741 
742 /* HASH */
743 
744 /* update */
745 #define PHPC_HASH_INDEX_UPDATE zend_hash_index_update
746 #define PHPC_HASH_STR_UPDATE   zend_hash_update
747 #define PHPC_HASH_CSTRL_UPDATE zend_hash_str_update
748 #define PHPC_HASH_CSTR_UPDATE(_ht, _cstr_value, _pzv) \
749 	zend_hash_str_update(_ht, _cstr_value, strlen(_cstr_value), _pzv)
750 
751 /* delete */
752 #define PHPC_HASH_INDEX_DELETE zend_hash_index_del
753 #define PHPC_HASH_STR_DELETE   zend_hash_del
754 #define PHPC_HASH_CSTRL_DELETE zend_hash_str_del
755 #define PHPC_HASH_CSTR_DELETE(_ht, _cstr_value) \
756 	zend_hash_str_del(_ht, _cstr_value, strlen(_cstr_value))
757 
758 /* exists */
759 #define PHPC_HASH_INDEX_EXISTS zend_hash_index_exists
760 #define PHPC_HASH_STR_EXISTS   zend_hash_exists
761 #define PHPC_HASH_CSTRL_EXISTS zend_hash_str_exists
762 #define PHPC_HASH_CSTR_EXISTS(_ht, _cstr_value) \
763 	zend_hash_str_exists(_ht, _cstr_value, strlen(_cstr_value))
764 
765 /* find */
766 #define PHPC_HASH_STR_FIND(_ht, _str, _ppv) \
767 	_ppv = zend_hash_find(_ht, _str)
768 #define PHPC_HASH_CSTRL_FIND(_ht, _cstr_value, _cstr_len, _ppv) \
769 	_ppv = zend_hash_str_find(_ht, _cstr_value, _cstr_len)
770 #define PHPC_HASH_CSTR_FIND(_ht, _cstr_value, _ppv) \
771 	_ppv = zend_hash_str_find(_ht, _cstr_value, strlen(_cstr_value))
772 #define PHPC_HASH_INDEX_FIND(_ht, _idx, _ppv) \
773 	_ppv = zend_hash_index_find(_ht, _idx)
774 /* not found value */
775 #define PHPC_HASH_NOT_FOUND NULL
776 
777 /* iteration for each element */
778 #define PHPC_HASH_FOREACH_VAL             ZEND_HASH_FOREACH_VAL
779 #define PHPC_HASH_FOREACH_KEY_VAL         ZEND_HASH_FOREACH_KEY_VAL
780 #define PHPC_HASH_FOREACH_STR_KEY_VAL     ZEND_HASH_FOREACH_STR_KEY_VAL
781 #define PHPC_HASH_FOREACH_END             ZEND_HASH_FOREACH_END
782 
783 /* key and data getter */
784 #define PHPC_HASH_GET_CURRENT_KEY_EX(_ht, _str, _num_index, _pos) \
785 	zend_hash_get_current_key_ex(_ht, &_str, &_num_index, _pos)
786 #define PHPC_HASH_GET_CURRENT_DATA_EX(_ht, _val, _pos) \
787 	_val = zend_hash_get_current_data_ex(_ht, _pos)
788 
789 #define PHPC_HASH_GET_CURRENT_KEY(_ht, _str, _num_index) \
790 	zend_hash_get_current_key(_ht, &_str, &_num_index)
791 #define PHPC_HASH_GET_CURRENT_DATA(_ht, _val) \
792 	_val = zend_hash_get_current_data(_ht)
793 
794 /* copy */
795 #define PHPC_HASH_COPY_EX(_target, _source, _copy_ctr) \
796 	zend_hash_copy(_target, _source, NULL)
797 
798 /* hash to zval */
799 #define PHPC_HASH_PZVAL(_ht, _pzv) \
800 	ZVAL_ARR(_pzv, _ht)
801 #define PHPC_HASH_RETVAL RETVAL_ARR
802 #define PHPC_HASH_RETURN RETURN_ARR
803 
804 
805 /* ARRAY */
806 
807 #define PHPC_ARRAY_ADD_ASSOC_NULL_EX     add_assoc_null_ex
808 #define PHPC_ARRAY_ADD_ASSOC_BOOL_EX     add_assoc_bool_ex
809 #define PHPC_ARRAY_ADD_ASSOC_LONG_EX     add_assoc_long_ex
810 #define PHPC_ARRAY_ADD_ASSOC_RESOURCE_EX add_assoc_resource_ex
811 #define PHPC_ARRAY_ADD_ASSOC_DOUBLE_EX   add_assoc_double_ex
812 #define PHPC_ARRAY_ADD_ASSOC_STR_EX      add_assoc_str_ex
813 #define PHPC_ARRAY_ADD_ASSOC_CSTR_EX     add_assoc_string_ex
814 #define PHPC_ARRAY_ADD_ASSOC_CSTRL_EX    add_assoc_stringl_ex
815 #define PHPC_ARRAY_ADD_ASSOC_VAL_EX(_arr, _key, _key_len, _pv) \
816 	add_assoc_zval_ex(_arr, _key, _key_len, &_pv)
817 
818 #define PHPC_ARRAY_ADD_ASSOC_STR         add_assoc_str
819 #define PHPC_ARRAY_ADD_ASSOC_CSTR        add_assoc_string
820 #define PHPC_ARRAY_ADD_ASSOC_CSTRL       add_assoc_stringl
821 #define PHPC_ARRAY_ADD_ASSOC_VAL(_arr, _key, _pv) \
822 	add_assoc_zval(_arr, _key, &_pv)
823 
824 #define PHPC_ARRAY_ADD_INDEX_STR         add_index_str
825 #define PHPC_ARRAY_ADD_INDEX_CSTR        add_index_string
826 #define PHPC_ARRAY_ADD_INDEX_CSTRL       add_index_stringl
827 #define PHPC_ARRAY_ADD_INDEX_VAL(_arr, _idx, _pv) \
828 	add_index_zval(_arr, _idx, &_pv)
829 
830 #define PHPC_ARRAY_ADD_NEXT_INDEX_STR    add_next_index_str
831 #define PHPC_ARRAY_ADD_NEXT_INDEX_CSTR   add_next_index_string
832 #define PHPC_ARRAY_ADD_NEXT_INDEX_CSTRL  add_next_index_stringl
833 #define PHPC_ARRAY_ADD_NEXT_INDEX_VAL(_arr, _pv) \
834 	add_next_index_zval(_arr, &_pv)
835 
836 /* FCALL */
837 #define PHPC_FCALL_PARAMS_DECLARE(_pname, _count) \
838 	zval PHPC_FCALL_PARAMS_NAME(_pname)[_count]
839 
840 #define PHPC_FCALL_PARAMS_INIT(_pname) PHPC_NOOP
841 
842 #define PHPC_FCALL_PARAM_PZVAL(_pname, _idx) \
843 	&PHPC_FCALL_PARAMS_NAME(_pname)[_idx]
844 
845 #define PHPC_FCALL_PARAM_VAL(_pname, _idx) \
846 	PHPC_FCALL_PARAMS_NAME(_pname)[_idx]
847 
848 #define PHPC_FCALL_PARAM_UNDEF(_pname) \
849 	ZVAL_UNDEF(PHPC_FCALL_PARAM_PZVAL(_pname))
850 
851 #define PHPC_FCALL_RETVAL(_fci, _pv) \
852 	(_fci).retval = (&_pv)
853 
854 
855 /* ZVAL */
856 typedef zval  phpc_val;
857 
858 #define PHPC_TYPE        Z_TYPE
859 #define PHPC_TYPE_P      Z_TYPE_P
860 
861 #define PHPC_LVAL        Z_LVAL
862 #define PHPC_LVAL_P      Z_LVAL_P
863 
864 #define PHPC_DVAL        Z_DVAL
865 #define PHPC_DVAL_P      Z_DVAL_P
866 
867 #define PHPC_STRVAL      Z_STRVAL
868 #define PHPC_STRVAL_P    Z_STRVAL_P
869 
870 #define PHPC_STRLEN      Z_STRLEN
871 #define PHPC_STRLEN_P    Z_STRLEN_P
872 
873 #define PHPC_ARRVAL      Z_ARRVAL
874 #define PHPC_ARRVAL_P    Z_ARRVAL_P
875 
876 #define PHPC_VAL_TO_ZVAL(_pv, _zv) _zv = _pv
877 #define PHPC_VAL_TO_PZVAL(_pv, _zv) _zv = &(_pv)
878 #define PHPC_PVAL_TO_PZVAL(_pv, _zv) _zv = _pv
879 
880 #define PHPC_VAL_MAKE(_pv)  PHPC_NOOP
881 #define PHPC_VAL_FREE(_pv)  PHPC_NOOP
882 #define PHPC_VAL_UNDEF(_pv) ZVAL_UNDEF(&(_pv))
883 #define PHPC_VAL_ISUNDEF(_pv) Z_ISUNDEF(_pv)
884 
885 #define PHPC_VAL_STR(_pv, _str) \
886 	ZVAL_STR(&_pv, _str)
887 #define PHPC_VAL_CSTR(_pv, _cstr) \
888     ZVAL_STRING(&_pv, _cstr)
889 #define PHPC_VAL_CSTRL(_pv, _cstr, _cstr_len) \
890 	ZVAL_STRINGL(&_pv, _cstr, _cstr_len)
891 
892 
893 #define PHPC_FE_END PHP_FE_END
894 
895 
896 /* STREAM */
897 typedef const char phpc_stream_opener_char_t;
898 #define PHPC_STREAM_WRAPPERDATA_ALLOC(stream) PHPC_NOOP
899 #define PHPC_STREAM_WRAPPERDATA_ISSET(stream) (Z_TYPE(stream->wrapperdata) != IS_UNDEF)
900 #define PHPC_STREAM_WRAPPERDATA_UNSET(stream) \
901 	do { \
902 		zval_ptr_dtor(&stream->wrapperdata); \
903 		ZVAL_UNDEF(&stream->wrapperdata); \
904 	} while(0)
905 #define PHPC_STREAM_CONTEXT_GET_OPTION(_ctx, _wrappername, _optionname, _ppv) \
906 	_ppv = php_stream_context_get_option(_ctx, _wrappername, _optionname)
907 #define PHPC_STREAM_CONTEXT_OPTION_NOT_FOUND NULL
908 
909 #endif /* PHP_MAJOR_VERSION */
910 
911 
912 /* COMMON (dependent definitions) */
913 
914 /* object structure */
915 #define PHPC_OBJ_STRUCT_DECLARE_AND_FETCH_FROM_ZOBJ(_name, _ptr) \
916 	PHPC_OBJ_STRUCT_DECLARE(_name, _ptr) = PHP_OBJ_GET_HANDLER_OBJ_FROM_ZOBJ(_name)
917 
918 /* this object */
919 #define PHPC_THIS _phpc_this
920 #define PHPC_THIS_DECLARE(_name) PHPC_OBJ_STRUCT_DECLARE(_name, PHPC_THIS)
921 #define PHPC_THIS_FETCH_FROM_ZVAL(_name, _zv) \
922 	PHPC_THIS = PHPC_OBJ_FROM_ZVAL(_name, _zv)
923 #define PHPC_THIS_FETCH(_name) \
924 	PHPC_THIS_FETCH_FROM_ZVAL(_name, getThis())
925 #define PHPC_THIS_DECLARE_AND_FETCH_FROM_ZVAL(_name, _zv) \
926 	PHPC_THIS_DECLARE(_name) = PHPC_THIS_FETCH_FROM_ZVAL(_name, _zv)
927 #define PHPC_THIS_FETCH_FROM_SELF(_name) \
928 	PHPC_THIS = PHPC_OBJ_FROM_ZVAL(_name, PHPC_SELF)
929 #define PHPC_THIS_DECLARE_AND_FETCH_FROM_SELF(_name) \
930 	PHPC_THIS_DECLARE(_name) = PHPC_OBJ_FROM_SELF(_name)
931 #define PHPC_THIS_DECLARE_AND_FETCH(_name) \
932 	PHPC_THIS_DECLARE_AND_FETCH_FROM_ZVAL(_name, getThis())
933 
934 /* that object */
935 #define PHPC_THAT _phpc_that
936 #define PHPC_THAT_DECLARE(_name) PHPC_OBJ_STRUCT_DECLARE(_name, PHPC_THAT)
937 
938 /* object helper create_ex */
939 #define PHPC_OBJ_HANDLER_CREATE_EX_INIT(_name) \
940 	PHPC_OBJ_HANDLER_CREATE_EX_DECLARE(); \
941 	PHPC_THIS_DECLARE(_name); \
942 	PHPC_THIS = PHPC_OBJ_HANDLER_CREATE_EX_ALLOC(_name); \
943 	PHPC_OBJ_HANDLER_INIT_CREATE_EX_PROPS(PHPC_THIS)
944 #define PHPC_OBJ_HANDLER_CREATE_EX_RETURN(_name) \
945 	PHPC_OBJ_HANDLER_CREATE_EX_RETURN_EX(_name, PHPC_THIS)
946 
947 /* object handler clone */
948 #define PHPC_OBJ_HANDLER_CLONE_INIT(_name) \
949 	PHPC_OBJ_HANDLER_CLONE_DECLARE(); \
950 	PHPC_THIS_DECLARE(_name); \
951 	PHPC_THAT_DECLARE(_name); \
952 	PHPC_THIS = PHPC_OBJ_FROM_SELF(_name); \
953 	PHPC_OBJ_HANDLER_CLONE_MEMBERS(_name, PHPC_THAT, PHPC_THIS)
954 #define PHPC_OBJ_HANDLER_CLONE_RETURN() \
955 	PHPC_OBJ_HANDLER_CLONE_RETURN_EX(PHPC_THAT)
956 
957 /* object handler free */
958 #define PHPC_OBJ_HANDLER_FREE_INIT(_name) \
959 	PHPC_OBJ_STRUCT_DECLARE_AND_FETCH_FROM_ZOBJ(_name, PHPC_THIS);
960 #define PHPC_OBJ_HANDLER_FREE_DESTROY() \
961 	PHPC_OBJ_HANDLER_FREE_DTOR(PHPC_THIS);
962 
963 /* object handler compare */
964 #define PHPC_OBJ_HANDLER_COMPARE_INIT(_name) \
965 	PHPC_OBJ_HANDLER_COMPARE_FETCH(_name, 1, PHPC_THIS); \
966 	PHPC_OBJ_HANDLER_COMPARE_FETCH(_name, 2, PHPC_THAT)
967 
968 /* object handler get_gc */
969 #define PHPC_GC_TABLE _phpc_gc_table
970 #define PHPC_GC_N _phpc_gc_n
971 #define PHPC_OBJ_HANDLER_GET_GC(_name) \
972 	PHPC_OBJ_DEFINE_HANDLER_FCE(HashTable *, _name, get_gc)\
973 		(zval *PHPC_SELF, phpc_val **PHPC_GC_TABLE, int *PHPC_GC_N TSRMLS_DC)
974 
975 /* object handler get_debug_info */
976 #define PHPC_DEBUG_INFO_IS_TEMP _phpc_debug_info_is_temp
977 #define PHPC_OBJ_HANDLER_GET_DEBUG_INFO(_name) \
978 	PHPC_OBJ_DEFINE_HANDLER_FCE(HashTable *, _name, get_debug_info)\
979 		(zval *PHPC_SELF, int *PHPC_DEBUG_INFO_IS_TEMP TSRMLS_DC)
980 
981 /* object handler get_properties */
982 #define PHPC_OBJ_HANDLER_GET_PROPERTIES(_name) \
983 	PHPC_OBJ_DEFINE_HANDLER_FCE(HashTable *, _name, get_properties)\
984 		(zval *PHPC_SELF TSRMLS_DC)
985 
986 /* hash */
987 #define PHPC_HASH_ALLOC                     ALLOC_HASHTABLE
988 #define PHPC_HASH_INIT                      zend_hash_init
989 #define PHPC_HASH_NUM_ELEMENTS              zend_hash_num_elements
990 
991 #define PHPC_HASH_HAS_MORE_ELEMENTS_EX      zend_hash_has_more_elements_ex
992 #define PHPC_HASH_MOVE_FORWARD_EX           zend_hash_move_forward_ex
993 #define PHPC_HASH_MOVE_BACKWARDS_EX         zend_hash_move_backwards_ex
994 #define PHPC_HASH_GET_CURRENT_KEY_ZVAL_EX   zend_hash_get_current_key_zval_ex
995 #define PHPC_HASH_GET_CURRENT_KEY_TYPE_EX   zend_hash_get_current_key_type_ex
996 #define PHPC_HASH_INTERNAL_POINTER_RESET_EX zend_hash_internal_pointer_reset_ex
997 #define PHPC_HASH_INTERNAL_POINTER_END_EX   zend_hash_internal_pointer_end_ex
998 
999 #define PHPC_HASH_HAS_MORE_ELEMENTS         zend_hash_has_more_elements
1000 #define PHPC_HASH_MOVE_FORWARD              zend_hash_move_forward
1001 #define PHPC_HASH_MOVE_BACKWARDS            zend_hash_move_backwards
1002 #define PHPC_HASH_GET_CURRENT_KEY_ZVAL      zend_hash_get_current_key_zval
1003 #define PHPC_HASH_GET_CURRENT_KEY_TYPE      zend_hash_get_current_key_type
1004 #define PHPC_HASH_INTERNAL_POINTER_RESET    zend_hash_internal_pointer_reset
1005 #define PHPC_HASH_INTERNAL_POINTER_END      zend_hash_internal_pointer_end
1006 
1007 /* find */
1008 #define PHPC_HASH_IS_FOUND(_found) ((_found) != PHPC_HASH_NOT_FOUND)
1009 
1010 #define PHPC_HASH_STR_FIND_IN_COND(_ht, _str, _ppv) \
1011 	PHPC_HASH_IS_FOUND(PHPC_HASH_STR_FIND(_ht, _str, _ppv))
1012 #define PHPC_HASH_CSTRL_FIND_IN_COND(_ht, _cstr_value, _cstr_len, _ppv) \
1013 	PHPC_HASH_IS_FOUND(PHPC_HASH_CSTRL_FIND(_ht, _cstr_value, _cstr_len, _ppv))
1014 #define PHPC_HASH_CSTR_FIND_IN_COND(_ht, _cstr_value, _ppv) \
1015 	PHPC_HASH_IS_FOUND(PHPC_HASH_CSTR_FIND(_ht, _cstr_value, _ppv))
1016 #define PHPC_HASH_INDEX_FIND_IN_COND(_ht, _idx, _ppv) \
1017 	PHPC_HASH_IS_FOUND(PHPC_HASH_INDEX_FIND(_ht, _idx, _ppv))
1018 
1019 /* copy */
1020 #define PHPC_HASH_COPY(_target, _source) \
1021 	PHPC_HASH_COPY_EX(_target, _source, NULL)
1022 
1023 /* array */
1024 #define PHPC_ARRAY_INIT array_init
1025 #if PHP_VERSION_ID < 50299
1026 #define PHPC_ARRAY_INIT_SIZE(_arr, _size) array_init(_arr)
1027 #else
1028 #define PHPC_ARRAY_INIT_SIZE array_init_size
1029 #endif
1030 
1031 #define PHPC_ARRAY_ADD_ASSOC_NULL          add_assoc_null
1032 #define PHPC_ARRAY_ADD_ASSOC_BOOL          add_assoc_bool
1033 #define PHPC_ARRAY_ADD_ASSOC_LONG          add_assoc_long
1034 #define PHPC_ARRAY_ADD_ASSOC_RESOURCE      add_assoc_resource
1035 #define PHPC_ARRAY_ADD_ASSOC_DOUBLE        add_assoc_double
1036 
1037 #define PHPC_ARRAY_ADD_INDEX_NULL          add_index_null
1038 #define PHPC_ARRAY_ADD_INDEX_BOOL          add_index_bool
1039 #define PHPC_ARRAY_ADD_INDEX_LONG          add_index_long
1040 #define PHPC_ARRAY_ADD_INDEX_RESOURCE      add_index_resource
1041 #define PHPC_ARRAY_ADD_INDEX_DOUBLE        add_index_double
1042 
1043 #define PHPC_ARRAY_ADD_NEXT_INDEX_NULL     add_next_index_null
1044 #define PHPC_ARRAY_ADD_NEXT_INDEX_BOOL     add_next_index_bool
1045 #define PHPC_ARRAY_ADD_NEXT_INDEX_LONG     add_next_index_long
1046 #define PHPC_ARRAY_ADD_NEXT_INDEX_RESOURCE add_next_index_resource
1047 #define PHPC_ARRAY_ADD_NEXT_INDEX_DOUBLE   add_next_index_double
1048 
1049 /* stream */
1050 #define PHPC_STREAM_CONTEXT_GET_OPTION_IN_COND(_ctx, _wrappername, _optionname, _ppv) \
1051 	((PHPC_STREAM_CONTEXT_GET_OPTION(_ctx, _wrappername, _optionname, _ppv)) != \
1052 		PHPC_STREAM_CONTEXT_OPTION_NOT_FOUND)
1053 
1054 
1055 #endif	/* PHPC_H */
1056 
1057