Line data Source code
1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id$ */
21 :
22 : #ifndef ZEND_OPERATORS_H
23 : #define ZEND_OPERATORS_H
24 :
25 : #include <errno.h>
26 : #include <math.h>
27 : #include <assert.h>
28 :
29 : #ifdef __GNUC__
30 : #include <stddef.h>
31 : #endif
32 :
33 : #ifdef HAVE_IEEEFP_H
34 : #include <ieeefp.h>
35 : #endif
36 :
37 : #include "zend_strtod.h"
38 : #include "zend_multiply.h"
39 :
40 : #if 0&&HAVE_BCMATH
41 : #include "ext/bcmath/libbcmath/src/bcmath.h"
42 : #endif
43 :
44 : #define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
45 :
46 : BEGIN_EXTERN_C()
47 : ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
48 : ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
49 : ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
50 : ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
51 : ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
52 : ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
53 : ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
54 : ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC);
55 : ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC);
56 : ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
57 : ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
58 : ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
59 : ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
60 : ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
61 : ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
62 :
63 : ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
64 : ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
65 : ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
66 : ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
67 : ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
68 : ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
69 :
70 : ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC);
71 : ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC);
72 : END_EXTERN_C()
73 :
74 : #if ZEND_DVAL_TO_LVAL_CAST_OK
75 : # define zend_dval_to_lval(d) ((long) (d))
76 : #elif SIZEOF_LONG == 4
77 : static zend_always_inline long zend_dval_to_lval(double d)
78 : {
79 : if (d > LONG_MAX || d < LONG_MIN) {
80 : double two_pow_32 = pow(2., 32.),
81 : dmod;
82 :
83 : dmod = fmod(d, two_pow_32);
84 : if (dmod < 0) {
85 : /* we're going to make this number positive; call ceil()
86 : * to simulate rounding towards 0 of the negative number */
87 : dmod = ceil(dmod) + two_pow_32;
88 : }
89 : return (long)(unsigned long)dmod;
90 : }
91 : return (long)d;
92 : }
93 : #else
94 : static zend_always_inline long zend_dval_to_lval(double d)
95 : {
96 : /* >= as (double)LONG_MAX is outside signed range */
97 : if (d >= LONG_MAX || d < LONG_MIN) {
98 : double two_pow_64 = pow(2., 64.),
99 : dmod;
100 :
101 : dmod = fmod(d, two_pow_64);
102 : if (dmod < 0) {
103 : /* no need to call ceil; original double must have had no
104 : * fractional part, hence dmod does not have one either */
105 : dmod += two_pow_64;
106 : }
107 : return (long)(unsigned long)dmod;
108 : }
109 : return (long)d;
110 : }
111 : #endif
112 : /* }}} */
113 :
114 : #define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
115 : #define ZEND_IS_XDIGIT(c) (((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))
116 :
117 : /**
118 : * Checks whether the string "str" with length "length" is numeric. The value
119 : * of allow_errors determines whether it's required to be entirely numeric, or
120 : * just its prefix. Leading whitespace is allowed.
121 : *
122 : * The function returns 0 if the string did not contain a valid number; IS_LONG
123 : * if it contained a number that fits within the range of a long; or IS_DOUBLE
124 : * if the number was out of long range or contained a decimal point/exponent.
125 : * The number's value is returned into the respective pointer, *lval or *dval,
126 : * if that pointer is not NULL.
127 : *
128 : * This variant also gives information if a string that represents an integer
129 : * could not be represented as such due to overflow. It writes 1 to oflow_info
130 : * if the integer is larger than LONG_MAX and -1 if it's smaller than LONG_MIN.
131 : */
132 6 : static inline zend_uchar is_numeric_string_ex(const char *str, int length, long *lval, double *dval, int allow_errors, int *oflow_info)
133 : {
134 : const char *ptr;
135 6 : int base = 10, digits = 0, dp_or_e = 0;
136 6 : double local_dval = 0.0;
137 : zend_uchar type;
138 :
139 6 : if (!length) {
140 0 : return 0;
141 : }
142 :
143 6 : if (oflow_info != NULL) {
144 0 : *oflow_info = 0;
145 : }
146 :
147 : /* Skip any whitespace
148 : * This is much faster than the isspace() function */
149 12 : while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
150 0 : str++;
151 0 : length--;
152 : }
153 6 : ptr = str;
154 :
155 6 : if (*ptr == '-' || *ptr == '+') {
156 0 : ptr++;
157 : }
158 :
159 6 : if (ZEND_IS_DIGIT(*ptr)) {
160 : /* Handle hex numbers
161 : * str is used instead of ptr to disallow signs and keep old behavior */
162 4 : if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
163 0 : base = 16;
164 0 : ptr += 2;
165 : }
166 :
167 : /* Skip any leading 0s */
168 8 : while (*ptr == '0') {
169 0 : ptr++;
170 : }
171 :
172 : /* Count the number of digits. If a decimal point/exponent is found,
173 : * it's a double. Otherwise, if there's a dval or no need to check for
174 : * a full match, stop when there are too many digits for a long */
175 48 : for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {
176 : check_digits:
177 24 : if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
178 20 : continue;
179 4 : } else if (base == 10) {
180 4 : if (*ptr == '.' && dp_or_e < 1) {
181 : goto process_double;
182 4 : } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
183 0 : const char *e = ptr + 1;
184 :
185 0 : if (*e == '-' || *e == '+') {
186 0 : ptr = e++;
187 : }
188 0 : if (ZEND_IS_DIGIT(*e)) {
189 0 : goto process_double;
190 : }
191 : }
192 : }
193 :
194 4 : break;
195 : }
196 :
197 8 : if (base == 10) {
198 4 : if (digits >= MAX_LENGTH_OF_LONG) {
199 0 : if (oflow_info != NULL) {
200 0 : *oflow_info = *str == '-' ? -1 : 1;
201 : }
202 0 : dp_or_e = -1;
203 0 : goto process_double;
204 : }
205 0 : } else if (!(digits < SIZEOF_LONG * 2 || (digits == SIZEOF_LONG * 2 && ptr[-digits] <= '7'))) {
206 0 : if (dval) {
207 0 : local_dval = zend_hex_strtod(str, &ptr);
208 : }
209 0 : if (oflow_info != NULL) {
210 0 : *oflow_info = 1;
211 : }
212 0 : type = IS_DOUBLE;
213 : }
214 2 : } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
215 : process_double:
216 0 : type = IS_DOUBLE;
217 :
218 : /* If there's a dval, do the conversion; else continue checking
219 : * the digits if we need to check for a full match */
220 0 : if (dval) {
221 0 : local_dval = zend_strtod(str, &ptr);
222 0 : } else if (allow_errors != 1 && dp_or_e != -1) {
223 0 : dp_or_e = (*ptr++ == '.') ? 1 : 2;
224 0 : goto check_digits;
225 : }
226 : } else {
227 2 : return 0;
228 : }
229 :
230 4 : if (ptr != str + length) {
231 0 : if (!allow_errors) {
232 0 : return 0;
233 : }
234 0 : if (allow_errors == -1) {
235 0 : zend_error(E_NOTICE, "A non well formed numeric value encountered");
236 : }
237 : }
238 :
239 4 : if (type == IS_LONG) {
240 4 : if (digits == MAX_LENGTH_OF_LONG - 1) {
241 0 : int cmp = strcmp(&ptr[-digits], long_min_digits);
242 :
243 0 : if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
244 0 : if (dval) {
245 0 : *dval = zend_strtod(str, NULL);
246 : }
247 0 : if (oflow_info != NULL) {
248 0 : *oflow_info = *str == '-' ? -1 : 1;
249 : }
250 :
251 0 : return IS_DOUBLE;
252 : }
253 : }
254 :
255 4 : if (lval) {
256 4 : *lval = strtol(str, NULL, base);
257 : }
258 :
259 4 : return IS_LONG;
260 : } else {
261 0 : if (dval) {
262 0 : *dval = local_dval;
263 : }
264 :
265 0 : return IS_DOUBLE;
266 : }
267 : }
268 :
269 6 : static inline zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, int allow_errors) {
270 6 : return is_numeric_string_ex(str, length, lval, dval, allow_errors, NULL);
271 : }
272 :
273 : static inline const char *
274 3394 : zend_memnstr(const char *haystack, const char *needle, int needle_len, char *end)
275 : {
276 3394 : const char *p = haystack;
277 3394 : const char ne = needle[needle_len-1];
278 :
279 3394 : if (needle_len == 1) {
280 0 : return (char *)memchr(p, *needle, (end-p));
281 : }
282 :
283 3394 : if (needle_len > end-haystack) {
284 108 : return NULL;
285 : }
286 :
287 3286 : end -= needle_len;
288 :
289 7833 : while (p <= end) {
290 4530 : if ((p = (char *)memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) {
291 281 : if (!memcmp(needle, p, needle_len-1)) {
292 220 : return p;
293 : }
294 : }
295 :
296 4310 : if (p == NULL) {
297 3049 : return NULL;
298 : }
299 :
300 1261 : p++;
301 : }
302 :
303 17 : return NULL;
304 : }
305 :
306 : static inline const void *zend_memrchr(const void *s, int c, size_t n)
307 : {
308 : register const unsigned char *e;
309 :
310 : if (n <= 0) {
311 : return NULL;
312 : }
313 :
314 : for (e = (const unsigned char *)s + n - 1; e >= (const unsigned char *)s; e--) {
315 : if (*e == (const unsigned char)c) {
316 : return (const void *)e;
317 : }
318 : }
319 :
320 : return NULL;
321 : }
322 :
323 : BEGIN_EXTERN_C()
324 : ZEND_API int increment_function(zval *op1);
325 : ZEND_API int decrement_function(zval *op2);
326 :
327 : ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC);
328 : ZEND_API void _convert_to_cstring(zval *op ZEND_FILE_LINE_DC);
329 : ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC);
330 : ZEND_API void convert_to_long(zval *op);
331 : ZEND_API void convert_to_double(zval *op);
332 : ZEND_API void convert_to_long_base(zval *op, int base);
333 : ZEND_API void convert_to_null(zval *op);
334 : ZEND_API void convert_to_boolean(zval *op);
335 : ZEND_API void convert_to_array(zval *op);
336 : ZEND_API void convert_to_object(zval *op);
337 : ZEND_API void multi_convert_to_long_ex(int argc, ...);
338 : ZEND_API void multi_convert_to_double_ex(int argc, ...);
339 : ZEND_API void multi_convert_to_string_ex(int argc, ...);
340 : ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2);
341 : ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2);
342 : #define convert_to_cstring(op) if ((op)->type != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); }
343 : #define convert_to_string(op) if ((op)->type != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }
344 :
345 : ZEND_API double zend_string_to_double(const char *number, zend_uint length);
346 :
347 : ZEND_API int zval_is_true(zval *op);
348 : ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
349 : ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
350 : ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC);
351 : ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
352 : ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
353 : #if HAVE_STRCOLL
354 : ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
355 : #endif
356 :
357 : ZEND_API void zend_str_tolower(char *str, unsigned int length);
358 : ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length);
359 : ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length);
360 :
361 : ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2);
362 : ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3);
363 : ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2);
364 : ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3);
365 : ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2);
366 : ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length);
367 : ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2);
368 : ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length);
369 : ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length);
370 :
371 : ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2);
372 : ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC);
373 : ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC);
374 : ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC);
375 :
376 : ZEND_API int zend_atoi(const char *str, int str_len);
377 : ZEND_API long zend_atol(const char *str, int str_len);
378 :
379 : ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
380 : END_EXTERN_C()
381 :
382 : #define convert_to_ex_master(ppzv, lower_type, upper_type) \
383 : if (Z_TYPE_PP(ppzv)!=IS_##upper_type) { \
384 : SEPARATE_ZVAL_IF_NOT_REF(ppzv); \
385 : convert_to_##lower_type(*ppzv); \
386 : }
387 :
388 : #define convert_to_explicit_type(pzv, type) \
389 : do { \
390 : switch (type) { \
391 : case IS_NULL: \
392 : convert_to_null(pzv); \
393 : break; \
394 : case IS_LONG: \
395 : convert_to_long(pzv); \
396 : break; \
397 : case IS_DOUBLE: \
398 : convert_to_double(pzv); \
399 : break; \
400 : case IS_BOOL: \
401 : convert_to_boolean(pzv); \
402 : break; \
403 : case IS_ARRAY: \
404 : convert_to_array(pzv); \
405 : break; \
406 : case IS_OBJECT: \
407 : convert_to_object(pzv); \
408 : break; \
409 : case IS_STRING: \
410 : convert_to_string(pzv); \
411 : break; \
412 : default: \
413 : assert(0); \
414 : break; \
415 : } \
416 : } while (0);
417 :
418 : #define convert_to_explicit_type_ex(ppzv, str_type) \
419 : if (Z_TYPE_PP(ppzv) != str_type) { \
420 : SEPARATE_ZVAL_IF_NOT_REF(ppzv); \
421 : convert_to_explicit_type(*ppzv, str_type); \
422 : }
423 :
424 : #define convert_to_boolean_ex(ppzv) convert_to_ex_master(ppzv, boolean, BOOL)
425 : #define convert_to_long_ex(ppzv) convert_to_ex_master(ppzv, long, LONG)
426 : #define convert_to_double_ex(ppzv) convert_to_ex_master(ppzv, double, DOUBLE)
427 : #define convert_to_string_ex(ppzv) convert_to_ex_master(ppzv, string, STRING)
428 : #define convert_to_array_ex(ppzv) convert_to_ex_master(ppzv, array, ARRAY)
429 : #define convert_to_object_ex(ppzv) convert_to_ex_master(ppzv, object, OBJECT)
430 : #define convert_to_null_ex(ppzv) convert_to_ex_master(ppzv, null, NULL)
431 :
432 : #define convert_scalar_to_number_ex(ppzv) \
433 : if (Z_TYPE_PP(ppzv)!=IS_LONG && Z_TYPE_PP(ppzv)!=IS_DOUBLE) { \
434 : if (!Z_ISREF_PP(ppzv)) { \
435 : SEPARATE_ZVAL(ppzv); \
436 : } \
437 : convert_scalar_to_number(*ppzv TSRMLS_CC); \
438 : }
439 :
440 :
441 : #define Z_LVAL(zval) (zval).value.lval
442 : #define Z_BVAL(zval) ((zend_bool)(zval).value.lval)
443 : #define Z_DVAL(zval) (zval).value.dval
444 : #define Z_STRVAL(zval) (zval).value.str.val
445 : #define Z_STRLEN(zval) (zval).value.str.len
446 : #define Z_ARRVAL(zval) (zval).value.ht
447 : #define Z_AST(zval) (zval).value.ast
448 : #define Z_OBJVAL(zval) (zval).value.obj
449 : #define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle
450 : #define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers
451 : #define Z_OBJCE(zval) zend_get_class_entry(&(zval) TSRMLS_CC)
452 : #define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC)
453 : #define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
454 : #define Z_RESVAL(zval) (zval).value.lval
455 : #define Z_OBJDEBUG(zval,is_tmp) (Z_OBJ_HANDLER((zval),get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&is_tmp TSRMLS_CC):(is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL))
456 :
457 : #define Z_LVAL_P(zval_p) Z_LVAL(*zval_p)
458 : #define Z_BVAL_P(zval_p) Z_BVAL(*zval_p)
459 : #define Z_DVAL_P(zval_p) Z_DVAL(*zval_p)
460 : #define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p)
461 : #define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)
462 : #define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p)
463 : #define Z_AST_P(zval_p) Z_AST(*zval_p)
464 : #define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p)
465 : #define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p)
466 : #define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p)
467 : #define Z_OBJVAL_P(zval_p) Z_OBJVAL(*zval_p)
468 : #define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p)
469 : #define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p)
470 : #define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h)
471 : #define Z_OBJDEBUG_P(zval_p,is_tmp) Z_OBJDEBUG(*zval_p,is_tmp)
472 :
473 : #define Z_LVAL_PP(zval_pp) Z_LVAL(**zval_pp)
474 : #define Z_BVAL_PP(zval_pp) Z_BVAL(**zval_pp)
475 : #define Z_DVAL_PP(zval_pp) Z_DVAL(**zval_pp)
476 : #define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp)
477 : #define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp)
478 : #define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp)
479 : #define Z_AST_PP(zval_p) Z_AST(**zval_p)
480 : #define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp)
481 : #define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp)
482 : #define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp)
483 : #define Z_OBJVAL_PP(zval_pp) Z_OBJVAL(**zval_pp)
484 : #define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p)
485 : #define Z_OBJ_HT_PP(zval_p) Z_OBJ_HT(**zval_p)
486 : #define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h)
487 : #define Z_OBJDEBUG_PP(zval_pp,is_tmp) Z_OBJDEBUG(**zval_pp,is_tmp)
488 :
489 : #define Z_TYPE(zval) (zval).type
490 : #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p)
491 : #define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp)
492 :
493 : #if HAVE_SETLOCALE && defined(ZEND_WIN32) && !defined(ZTS) && defined(_MSC_VER) && (_MSC_VER >= 1400)
494 : /* This is performance improvement of tolower() on Windows and VC2005
495 : * Gives 10-18% on bench.php
496 : */
497 : #define ZEND_USE_TOLOWER_L 1
498 : #endif
499 :
500 : #ifdef ZEND_USE_TOLOWER_L
501 : ZEND_API void zend_update_current_locale(void);
502 : #else
503 : #define zend_update_current_locale()
504 : #endif
505 :
506 : /* The offset in bytes between the value and type fields of a zval */
507 : #define ZVAL_OFFSETOF_TYPE \
508 : (offsetof(zval,type) - offsetof(zval,value))
509 :
510 : static zend_always_inline int fast_increment_function(zval *op1)
511 : {
512 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
513 : #if defined(__GNUC__) && defined(__i386__)
514 : __asm__(
515 : "incl (%0)\n\t"
516 : "jno 0f\n\t"
517 : "movl $0x0, (%0)\n\t"
518 : "movl $0x41e00000, 0x4(%0)\n\t"
519 : "movb %1, %c2(%0)\n"
520 : "0:"
521 : :
522 : : "r"(&op1->value),
523 : "n"(IS_DOUBLE),
524 : "n"(ZVAL_OFFSETOF_TYPE)
525 : : "cc");
526 : #elif defined(__GNUC__) && defined(__x86_64__)
527 : __asm__(
528 : "incq (%0)\n\t"
529 : "jno 0f\n\t"
530 : "movl $0x0, (%0)\n\t"
531 : "movl $0x43e00000, 0x4(%0)\n\t"
532 : "movb %1, %c2(%0)\n"
533 : "0:"
534 : :
535 : : "r"(&op1->value),
536 : "n"(IS_DOUBLE),
537 : "n"(ZVAL_OFFSETOF_TYPE)
538 : : "cc");
539 : #else
540 : if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) {
541 : /* switch to double */
542 : Z_DVAL_P(op1) = (double)LONG_MAX + 1.0;
543 : Z_TYPE_P(op1) = IS_DOUBLE;
544 : } else {
545 : Z_LVAL_P(op1)++;
546 : }
547 : #endif
548 : return SUCCESS;
549 : }
550 : return increment_function(op1);
551 : }
552 :
553 : static zend_always_inline int fast_decrement_function(zval *op1)
554 : {
555 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
556 : #if defined(__GNUC__) && defined(__i386__)
557 : __asm__(
558 : "decl (%0)\n\t"
559 : "jno 0f\n\t"
560 : "movl $0x00200000, (%0)\n\t"
561 : "movl $0xc1e00000, 0x4(%0)\n\t"
562 : "movb %1,%c2(%0)\n"
563 : "0:"
564 : :
565 : : "r"(&op1->value),
566 : "n"(IS_DOUBLE),
567 : "n"(ZVAL_OFFSETOF_TYPE)
568 : : "cc");
569 : #elif defined(__GNUC__) && defined(__x86_64__)
570 : __asm__(
571 : "decq (%0)\n\t"
572 : "jno 0f\n\t"
573 : "movl $0x00000000, (%0)\n\t"
574 : "movl $0xc3e00000, 0x4(%0)\n\t"
575 : "movb %1,%c2(%0)\n"
576 : "0:"
577 : :
578 : : "r"(&op1->value),
579 : "n"(IS_DOUBLE),
580 : "n"(ZVAL_OFFSETOF_TYPE)
581 : : "cc");
582 : #else
583 : if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) {
584 : /* switch to double */
585 : Z_DVAL_P(op1) = (double)LONG_MIN - 1.0;
586 : Z_TYPE_P(op1) = IS_DOUBLE;
587 : } else {
588 : Z_LVAL_P(op1)--;
589 : }
590 : #endif
591 : return SUCCESS;
592 : }
593 : return decrement_function(op1);
594 : }
595 :
596 : static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
597 : {
598 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
599 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
600 : #if defined(__GNUC__) && defined(__i386__)
601 : __asm__(
602 : "movl (%1), %%eax\n\t"
603 : "addl (%2), %%eax\n\t"
604 : "jo 0f\n\t"
605 : "movl %%eax, (%0)\n\t"
606 : "movb %3, %c5(%0)\n\t"
607 : "jmp 1f\n"
608 : "0:\n\t"
609 : "fildl (%1)\n\t"
610 : "fildl (%2)\n\t"
611 : "faddp %%st, %%st(1)\n\t"
612 : "movb %4, %c5(%0)\n\t"
613 : "fstpl (%0)\n"
614 : "1:"
615 : :
616 : : "r"(&result->value),
617 : "r"(&op1->value),
618 : "r"(&op2->value),
619 : "n"(IS_LONG),
620 : "n"(IS_DOUBLE),
621 : "n"(ZVAL_OFFSETOF_TYPE)
622 : : "eax","cc");
623 : #elif defined(__GNUC__) && defined(__x86_64__)
624 : __asm__(
625 : "movq (%1), %%rax\n\t"
626 : "addq (%2), %%rax\n\t"
627 : "jo 0f\n\t"
628 : "movq %%rax, (%0)\n\t"
629 : "movb %3, %c5(%0)\n\t"
630 : "jmp 1f\n"
631 : "0:\n\t"
632 : "fildq (%1)\n\t"
633 : "fildq (%2)\n\t"
634 : "faddp %%st, %%st(1)\n\t"
635 : "movb %4, %c5(%0)\n\t"
636 : "fstpl (%0)\n"
637 : "1:"
638 : :
639 : : "r"(&result->value),
640 : "r"(&op1->value),
641 : "r"(&op2->value),
642 : "n"(IS_LONG),
643 : "n"(IS_DOUBLE),
644 : "n"(ZVAL_OFFSETOF_TYPE)
645 : : "rax","cc");
646 : #else
647 : /*
648 : * 'result' may alias with op1 or op2, so we need to
649 : * ensure that 'result' is not updated until after we
650 : * have read the values of op1 and op2.
651 : */
652 :
653 : if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
654 : && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != ((Z_LVAL_P(op1) + Z_LVAL_P(op2)) & LONG_SIGN_MASK))) {
655 : Z_DVAL_P(result) = (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2);
656 : Z_TYPE_P(result) = IS_DOUBLE;
657 : } else {
658 : Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
659 : Z_TYPE_P(result) = IS_LONG;
660 : }
661 : #endif
662 : return SUCCESS;
663 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
664 : Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2);
665 : Z_TYPE_P(result) = IS_DOUBLE;
666 : return SUCCESS;
667 : }
668 : } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
669 : if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
670 : Z_DVAL_P(result) = Z_DVAL_P(op1) + Z_DVAL_P(op2);
671 : Z_TYPE_P(result) = IS_DOUBLE;
672 : return SUCCESS;
673 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
674 : Z_DVAL_P(result) = Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2));
675 : Z_TYPE_P(result) = IS_DOUBLE;
676 : return SUCCESS;
677 : }
678 : }
679 : return add_function(result, op1, op2 TSRMLS_CC);
680 : }
681 :
682 : static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
683 : {
684 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
685 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
686 : #if defined(__GNUC__) && defined(__i386__)
687 : __asm__(
688 : "movl (%1), %%eax\n\t"
689 : "subl (%2), %%eax\n\t"
690 : "jo 0f\n\t"
691 : "movl %%eax, (%0)\n\t"
692 : "movb %3, %c5(%0)\n\t"
693 : "jmp 1f\n"
694 : "0:\n\t"
695 : "fildl (%2)\n\t"
696 : "fildl (%1)\n\t"
697 : #if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
698 : "fsubp %%st(1), %%st\n\t" /* LLVM bug #9164 */
699 : #else
700 : "fsubp %%st, %%st(1)\n\t"
701 : #endif
702 : "movb %4, %c5(%0)\n\t"
703 : "fstpl (%0)\n"
704 : "1:"
705 : :
706 : : "r"(&result->value),
707 : "r"(&op1->value),
708 : "r"(&op2->value),
709 : "n"(IS_LONG),
710 : "n"(IS_DOUBLE),
711 : "n"(ZVAL_OFFSETOF_TYPE)
712 : : "eax","cc");
713 : #elif defined(__GNUC__) && defined(__x86_64__)
714 : __asm__(
715 : "movq (%1), %%rax\n\t"
716 : "subq (%2), %%rax\n\t"
717 : "jo 0f\n\t"
718 : "movq %%rax, (%0)\n\t"
719 : "movb %3, %c5(%0)\n\t"
720 : "jmp 1f\n"
721 : "0:\n\t"
722 : "fildq (%2)\n\t"
723 : "fildq (%1)\n\t"
724 : #if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
725 : "fsubp %%st(1), %%st\n\t" /* LLVM bug #9164 */
726 : #else
727 : "fsubp %%st, %%st(1)\n\t"
728 : #endif
729 : "movb %4, %c5(%0)\n\t"
730 : "fstpl (%0)\n"
731 : "1:"
732 : :
733 : : "r"(&result->value),
734 : "r"(&op1->value),
735 : "r"(&op2->value),
736 : "n"(IS_LONG),
737 : "n"(IS_DOUBLE),
738 : "n"(ZVAL_OFFSETOF_TYPE)
739 : : "rax","cc");
740 : #else
741 : Z_LVAL_P(result) = Z_LVAL_P(op1) - Z_LVAL_P(op2);
742 :
743 : if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
744 : && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
745 : Z_DVAL_P(result) = (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2);
746 : Z_TYPE_P(result) = IS_DOUBLE;
747 : } else {
748 : Z_TYPE_P(result) = IS_LONG;
749 : }
750 : #endif
751 : return SUCCESS;
752 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
753 : Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2);
754 : Z_TYPE_P(result) = IS_DOUBLE;
755 : return SUCCESS;
756 : }
757 : } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
758 : if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
759 : Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
760 : Z_TYPE_P(result) = IS_DOUBLE;
761 : return SUCCESS;
762 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
763 : Z_DVAL_P(result) = Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2));
764 : Z_TYPE_P(result) = IS_DOUBLE;
765 : return SUCCESS;
766 : }
767 : }
768 : return sub_function(result, op1, op2 TSRMLS_CC);
769 : }
770 :
771 : static zend_always_inline int fast_mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
772 : {
773 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
774 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
775 : long overflow;
776 :
777 : ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
778 : Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
779 : return SUCCESS;
780 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
781 : Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2);
782 : Z_TYPE_P(result) = IS_DOUBLE;
783 : return SUCCESS;
784 : }
785 : } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
786 : if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
787 : Z_DVAL_P(result) = Z_DVAL_P(op1) * Z_DVAL_P(op2);
788 : Z_TYPE_P(result) = IS_DOUBLE;
789 : return SUCCESS;
790 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
791 : Z_DVAL_P(result) = Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2));
792 : Z_TYPE_P(result) = IS_DOUBLE;
793 : return SUCCESS;
794 : }
795 : }
796 : return mul_function(result, op1, op2 TSRMLS_CC);
797 : }
798 :
799 : static zend_always_inline int fast_div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
800 : {
801 : #if 0
802 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && 0) {
803 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
804 : if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
805 : zend_error(E_WARNING, "Division by zero");
806 : Z_LVAL_P(result) = 0;
807 : Z_TYPE_P(result) = IS_BOOL;
808 : return FAILURE;
809 : } else if (UNEXPECTED(Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN)) {
810 : /* Prevent overflow error/crash */
811 : Z_DVAL_P(result) = (double) LONG_MIN / -1;
812 : Z_TYPE_P(result) = IS_DOUBLE;
813 : } else if (EXPECTED(Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0)) {
814 : /* integer */
815 : Z_LVAL_P(result) = Z_LVAL_P(op1) / Z_LVAL_P(op2);
816 : Z_TYPE_P(result) = IS_LONG;
817 : } else {
818 : Z_DVAL_P(result) = ((double) Z_LVAL_P(op1)) / ((double)Z_LVAL_P(op2));
819 : Z_TYPE_P(result) = IS_DOUBLE;
820 : }
821 : return SUCCESS;
822 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
823 : if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
824 : zend_error(E_WARNING, "Division by zero");
825 : Z_LVAL_P(result) = 0;
826 : Z_TYPE_P(result) = IS_BOOL;
827 : return FAILURE;
828 : }
829 : Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) / Z_DVAL_P(op2);
830 : Z_TYPE_P(result) = IS_DOUBLE;
831 : return SUCCESS;
832 : }
833 : } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE) && 0) {
834 : if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
835 : if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
836 : zend_error(E_WARNING, "Division by zero");
837 : Z_LVAL_P(result) = 0;
838 : Z_TYPE_P(result) = IS_BOOL;
839 : return FAILURE;
840 : }
841 : Z_DVAL_P(result) = Z_DVAL_P(op1) / Z_DVAL_P(op2);
842 : Z_TYPE_P(result) = IS_DOUBLE;
843 : return SUCCESS;
844 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
845 : if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
846 : zend_error(E_WARNING, "Division by zero");
847 : Z_LVAL_P(result) = 0;
848 : Z_TYPE_P(result) = IS_BOOL;
849 : return FAILURE;
850 : }
851 : Z_DVAL_P(result) = Z_DVAL_P(op1) / ((double)Z_LVAL_P(op2));
852 : Z_TYPE_P(result) = IS_DOUBLE;
853 : return SUCCESS;
854 : }
855 : }
856 : #endif
857 : return div_function(result, op1, op2 TSRMLS_CC);
858 : }
859 :
860 : static zend_always_inline int fast_mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
861 : {
862 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
863 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
864 : if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
865 : zend_error(E_WARNING, "Division by zero");
866 : Z_LVAL_P(result) = 0;
867 : Z_TYPE_P(result) = IS_BOOL;
868 : return FAILURE;
869 : } else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
870 : /* Prevent overflow error/crash if op1==LONG_MIN */
871 : Z_LVAL_P(result) = 0;
872 : Z_TYPE_P(result) = IS_LONG;
873 : return SUCCESS;
874 : }
875 : Z_LVAL_P(result) = Z_LVAL_P(op1) % Z_LVAL_P(op2);
876 : Z_TYPE_P(result) = IS_LONG;
877 : return SUCCESS;
878 : }
879 : }
880 : return mod_function(result, op1, op2 TSRMLS_CC);
881 : }
882 :
883 : static zend_always_inline int fast_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
884 : {
885 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
886 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
887 : return Z_LVAL_P(op1) == Z_LVAL_P(op2);
888 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
889 : return ((double)Z_LVAL_P(op1)) == Z_DVAL_P(op2);
890 : }
891 : } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
892 : if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
893 : return Z_DVAL_P(op1) == Z_DVAL_P(op2);
894 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
895 : return Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2));
896 : }
897 : }
898 : compare_function(result, op1, op2 TSRMLS_CC);
899 : return Z_LVAL_P(result) == 0;
900 : }
901 :
902 : static zend_always_inline int fast_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
903 : {
904 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
905 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
906 : return Z_LVAL_P(op1) != Z_LVAL_P(op2);
907 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
908 : return ((double)Z_LVAL_P(op1)) != Z_DVAL_P(op2);
909 : }
910 : } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
911 : if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
912 : return Z_DVAL_P(op1) != Z_DVAL_P(op2);
913 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
914 : return Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2));
915 : }
916 : }
917 : compare_function(result, op1, op2 TSRMLS_CC);
918 : return Z_LVAL_P(result) != 0;
919 : }
920 :
921 : static zend_always_inline int fast_is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
922 : {
923 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
924 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
925 : return Z_LVAL_P(op1) < Z_LVAL_P(op2);
926 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
927 : return ((double)Z_LVAL_P(op1)) < Z_DVAL_P(op2);
928 : }
929 : } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
930 : if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
931 : return Z_DVAL_P(op1) < Z_DVAL_P(op2);
932 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
933 : return Z_DVAL_P(op1) < ((double)Z_LVAL_P(op2));
934 : }
935 : }
936 : compare_function(result, op1, op2 TSRMLS_CC);
937 : return Z_LVAL_P(result) < 0;
938 : }
939 :
940 : static zend_always_inline int fast_is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
941 : {
942 : if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
943 : if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
944 : return Z_LVAL_P(op1) <= Z_LVAL_P(op2);
945 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
946 : return ((double)Z_LVAL_P(op1)) <= Z_DVAL_P(op2);
947 : }
948 : } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
949 : if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
950 : return Z_DVAL_P(op1) <= Z_DVAL_P(op2);
951 : } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
952 : return Z_DVAL_P(op1) <= ((double)Z_LVAL_P(op2));
953 : }
954 : }
955 : compare_function(result, op1, op2 TSRMLS_CC);
956 : return Z_LVAL_P(result) <= 0;
957 : }
958 :
959 : #define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode) \
960 : if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, do_operation)) { \
961 : if (SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, op2 TSRMLS_CC)) { \
962 : return SUCCESS; \
963 : } \
964 : } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, do_operation)) { \
965 : if (SUCCESS == Z_OBJ_HANDLER_P(op2, do_operation)(opcode, result, op1, op2 TSRMLS_CC)) { \
966 : return SUCCESS; \
967 : } \
968 : }
969 :
970 : #define ZEND_TRY_UNARY_OBJECT_OPERATION(opcode) \
971 : if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, do_operation) \
972 : && SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, NULL TSRMLS_CC) \
973 : ) { \
974 : return SUCCESS; \
975 : }
976 :
977 : #endif
978 :
979 : /*
980 : * Local variables:
981 : * tab-width: 4
982 : * c-basic-offset: 4
983 : * indent-tabs-mode: t
984 : * End:
985 : */
|