1/* 2 +----------------------------------------------------------------------+ 3 | Zend Engine | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1998-2013 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 HAVE_IEEEFP_H 30#include <ieeefp.h> 31#endif 32 33#include "zend_strtod.h" 34 35#if 0&&HAVE_BCMATH 36#include "ext/bcmath/libbcmath/src/bcmath.h" 37#endif 38 39BEGIN_EXTERN_C() 40ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 41ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 42ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 43ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 44ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 45ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 46ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC); 47ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC); 48ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 49ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 50ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 51ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 52ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 53ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 54 55ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 56ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 57ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 58ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 59ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 60ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 61 62ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC); 63ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC); 64END_EXTERN_C() 65 66#if ZEND_DVAL_TO_LVAL_CAST_OK 67# define zend_dval_to_lval(d) ((long) (d)) 68#elif SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) 69static zend_always_inline long zend_dval_to_lval(double d) 70{ 71 if (d > LONG_MAX || d < LONG_MIN) { 72 return (long)(unsigned long)(zend_long64) d; 73 } 74 return (long) d; 75} 76#else 77static zend_always_inline long zend_dval_to_lval(double d) 78{ 79 if (d > LONG_MAX) { 80 return (long)(unsigned long) d; 81 } 82 return (long) d; 83} 84#endif 85/* }}} */ 86 87#define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9') 88#define ZEND_IS_XDIGIT(c) (((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f')) 89 90/** 91 * Checks whether the string "str" with length "length" is numeric. The value 92 * of allow_errors determines whether it's required to be entirely numeric, or 93 * just its prefix. Leading whitespace is allowed. 94 * 95 * The function returns 0 if the string did not contain a valid number; IS_LONG 96 * if it contained a number that fits within the range of a long; or IS_DOUBLE 97 * if the number was out of long range or contained a decimal point/exponent. 98 * The number's value is returned into the respective pointer, *lval or *dval, 99 * if that pointer is not NULL. 100 */ 101 102static inline zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, int allow_errors) 103{ 104 const char *ptr; 105 int base = 10, digits = 0, dp_or_e = 0; 106 double local_dval; 107 zend_uchar type; 108 109 if (!length) { 110 return 0; 111 } 112 113 /* Skip any whitespace 114 * This is much faster than the isspace() function */ 115 while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') { 116 str++; 117 length--; 118 } 119 ptr = str; 120 121 if (*ptr == '-' || *ptr == '+') { 122 ptr++; 123 } 124 125 if (ZEND_IS_DIGIT(*ptr)) { 126 /* Handle hex numbers 127 * str is used instead of ptr to disallow signs and keep old behavior */ 128 if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) { 129 base = 16; 130 ptr += 2; 131 } 132 133 /* Skip any leading 0s */ 134 while (*ptr == '0') { 135 ptr++; 136 } 137 138 /* Count the number of digits. If a decimal point/exponent is found, 139 * it's a double. Otherwise, if there's a dval or no need to check for 140 * a full match, stop when there are too many digits for a long */ 141 for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) { 142check_digits: 143 if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) { 144 continue; 145 } else if (base == 10) { 146 if (*ptr == '.' && dp_or_e < 1) { 147 goto process_double; 148 } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) { 149 const char *e = ptr + 1; 150 151 if (*e == '-' || *e == '+') { 152 ptr = e++; 153 } 154 if (ZEND_IS_DIGIT(*e)) { 155 goto process_double; 156 } 157 } 158 } 159 160 break; 161 } 162 163 if (base == 10) { 164 if (digits >= MAX_LENGTH_OF_LONG) { 165 dp_or_e = -1; 166 goto process_double; 167 } 168 } else if (!(digits < SIZEOF_LONG * 2 || (digits == SIZEOF_LONG * 2 && ptr[-digits] <= '7'))) { 169 if (dval) { 170 local_dval = zend_hex_strtod(str, (char **)&ptr); 171 } 172 type = IS_DOUBLE; 173 } 174 } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) { 175process_double: 176 type = IS_DOUBLE; 177 178 /* If there's a dval, do the conversion; else continue checking 179 * the digits if we need to check for a full match */ 180 if (dval) { 181 local_dval = zend_strtod(str, (char **)&ptr); 182 } else if (allow_errors != 1 && dp_or_e != -1) { 183 dp_or_e = (*ptr++ == '.') ? 1 : 2; 184 goto check_digits; 185 } 186 } else { 187 return 0; 188 } 189 190 if (ptr != str + length) { 191 if (!allow_errors) { 192 return 0; 193 } 194 if (allow_errors == -1) { 195 zend_error(E_NOTICE, "A non well formed numeric value encountered"); 196 } 197 } 198 199 if (type == IS_LONG) { 200 if (digits == MAX_LENGTH_OF_LONG - 1) { 201 int cmp = strcmp(&ptr[-digits], long_min_digits); 202 203 if (!(cmp < 0 || (cmp == 0 && *str == '-'))) { 204 if (dval) { 205 *dval = zend_strtod(str, NULL); 206 } 207 208 return IS_DOUBLE; 209 } 210 } 211 212 if (lval) { 213 *lval = strtol(str, NULL, base); 214 } 215 216 return IS_LONG; 217 } else { 218 if (dval) { 219 *dval = local_dval; 220 } 221 222 return IS_DOUBLE; 223 } 224} 225 226static inline char * 227zend_memnstr(char *haystack, char *needle, int needle_len, char *end) 228{ 229 char *p = haystack; 230 char ne = needle[needle_len-1]; 231 232 if (needle_len == 1) { 233 return (char *)memchr(p, *needle, (end-p)); 234 } 235 236 if (needle_len > end-haystack) { 237 return NULL; 238 } 239 240 end -= needle_len; 241 242 while (p <= end) { 243 if ((p = (char *)memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) { 244 if (!memcmp(needle, p, needle_len-1)) { 245 return p; 246 } 247 } 248 249 if (p == NULL) { 250 return NULL; 251 } 252 253 p++; 254 } 255 256 return NULL; 257} 258 259static inline void *zend_memrchr(const void *s, int c, size_t n) 260{ 261 register unsigned char *e; 262 263 if (n <= 0) { 264 return NULL; 265 } 266 267 for (e = (unsigned char *)s + n - 1; e >= (unsigned char *)s; e--) { 268 if (*e == (unsigned char)c) { 269 return (void *)e; 270 } 271 } 272 273 return NULL; 274} 275 276BEGIN_EXTERN_C() 277ZEND_API int increment_function(zval *op1); 278ZEND_API int decrement_function(zval *op2); 279 280ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC); 281ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC); 282ZEND_API void convert_to_long(zval *op); 283ZEND_API void convert_to_double(zval *op); 284ZEND_API void convert_to_long_base(zval *op, int base); 285ZEND_API void convert_to_null(zval *op); 286ZEND_API void convert_to_boolean(zval *op); 287ZEND_API void convert_to_array(zval *op); 288ZEND_API void convert_to_object(zval *op); 289ZEND_API void multi_convert_to_long_ex(int argc, ...); 290ZEND_API void multi_convert_to_double_ex(int argc, ...); 291ZEND_API void multi_convert_to_string_ex(int argc, ...); 292ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2); 293ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2); 294#define convert_to_string(op) if ((op)->type != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); } 295 296ZEND_API double zend_string_to_double(const char *number, zend_uint length); 297 298ZEND_API int zval_is_true(zval *op); 299ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 300ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 301ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 302#if HAVE_STRCOLL 303ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); 304#endif 305 306ZEND_API void zend_str_tolower(char *str, unsigned int length); 307ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length); 308ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length); 309 310ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2); 311ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3); 312ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2); 313ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3); 314ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2); 315ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length); 316ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2); 317ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length); 318 319ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2); 320ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC); 321ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC); 322ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC); 323 324ZEND_API int zend_atoi(const char *str, int str_len); 325ZEND_API long zend_atol(const char *str, int str_len); 326 327ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC); 328END_EXTERN_C() 329 330#define convert_to_ex_master(ppzv, lower_type, upper_type) \ 331 if (Z_TYPE_PP(ppzv)!=IS_##upper_type) { \ 332 SEPARATE_ZVAL_IF_NOT_REF(ppzv); \ 333 convert_to_##lower_type(*ppzv); \ 334 } 335 336#define convert_to_explicit_type(pzv, type) \ 337 do { \ 338 switch (type) { \ 339 case IS_NULL: \ 340 convert_to_null(pzv); \ 341 break; \ 342 case IS_LONG: \ 343 convert_to_long(pzv); \ 344 break; \ 345 case IS_DOUBLE: \ 346 convert_to_double(pzv); \ 347 break; \ 348 case IS_BOOL: \ 349 convert_to_boolean(pzv); \ 350 break; \ 351 case IS_ARRAY: \ 352 convert_to_array(pzv); \ 353 break; \ 354 case IS_OBJECT: \ 355 convert_to_object(pzv); \ 356 break; \ 357 case IS_STRING: \ 358 convert_to_string(pzv); \ 359 break; \ 360 default: \ 361 assert(0); \ 362 break; \ 363 } \ 364 } while (0); 365 366#define convert_to_explicit_type_ex(ppzv, str_type) \ 367 if (Z_TYPE_PP(ppzv) != str_type) { \ 368 SEPARATE_ZVAL_IF_NOT_REF(ppzv); \ 369 convert_to_explicit_type(*ppzv, str_type); \ 370 } 371 372#define convert_to_boolean_ex(ppzv) convert_to_ex_master(ppzv, boolean, BOOL) 373#define convert_to_long_ex(ppzv) convert_to_ex_master(ppzv, long, LONG) 374#define convert_to_double_ex(ppzv) convert_to_ex_master(ppzv, double, DOUBLE) 375#define convert_to_string_ex(ppzv) convert_to_ex_master(ppzv, string, STRING) 376#define convert_to_array_ex(ppzv) convert_to_ex_master(ppzv, array, ARRAY) 377#define convert_to_object_ex(ppzv) convert_to_ex_master(ppzv, object, OBJECT) 378#define convert_to_null_ex(ppzv) convert_to_ex_master(ppzv, null, NULL) 379 380#define convert_scalar_to_number_ex(ppzv) \ 381 if (Z_TYPE_PP(ppzv)!=IS_LONG && Z_TYPE_PP(ppzv)!=IS_DOUBLE) { \ 382 if (!Z_ISREF_PP(ppzv)) { \ 383 SEPARATE_ZVAL(ppzv); \ 384 } \ 385 convert_scalar_to_number(*ppzv TSRMLS_CC); \ 386 } 387 388 389#define Z_LVAL(zval) (zval).value.lval 390#define Z_BVAL(zval) ((zend_bool)(zval).value.lval) 391#define Z_DVAL(zval) (zval).value.dval 392#define Z_STRVAL(zval) (zval).value.str.val 393#define Z_STRLEN(zval) (zval).value.str.len 394#define Z_ARRVAL(zval) (zval).value.ht 395#define Z_OBJVAL(zval) (zval).value.obj 396#define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle 397#define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers 398#define Z_OBJCE(zval) zend_get_class_entry(&(zval) TSRMLS_CC) 399#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC) 400#define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf 401#define Z_RESVAL(zval) (zval).value.lval 402#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)) 403 404#define Z_LVAL_P(zval_p) Z_LVAL(*zval_p) 405#define Z_BVAL_P(zval_p) Z_BVAL(*zval_p) 406#define Z_DVAL_P(zval_p) Z_DVAL(*zval_p) 407#define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p) 408#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p) 409#define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p) 410#define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p) 411#define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p) 412#define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p) 413#define Z_OBJVAL_P(zval_p) Z_OBJVAL(*zval_p) 414#define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p) 415#define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p) 416#define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h) 417#define Z_OBJDEBUG_P(zval_p,is_tmp) Z_OBJDEBUG(*zval_p,is_tmp) 418 419#define Z_LVAL_PP(zval_pp) Z_LVAL(**zval_pp) 420#define Z_BVAL_PP(zval_pp) Z_BVAL(**zval_pp) 421#define Z_DVAL_PP(zval_pp) Z_DVAL(**zval_pp) 422#define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp) 423#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp) 424#define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp) 425#define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp) 426#define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp) 427#define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp) 428#define Z_OBJVAL_PP(zval_pp) Z_OBJVAL(**zval_pp) 429#define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p) 430#define Z_OBJ_HT_PP(zval_p) Z_OBJ_HT(**zval_p) 431#define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h) 432#define Z_OBJDEBUG_PP(zval_pp,is_tmp) Z_OBJDEBUG(**zval_pp,is_tmp) 433 434#define Z_TYPE(zval) (zval).type 435#define Z_TYPE_P(zval_p) Z_TYPE(*zval_p) 436#define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp) 437 438#if HAVE_SETLOCALE && defined(ZEND_WIN32) && !defined(ZTS) && defined(_MSC_VER) && (_MSC_VER >= 1400) 439/* This is performance improvement of tolower() on Windows and VC2005 440 * Gives 10-18% on bench.php 441 */ 442#define ZEND_USE_TOLOWER_L 1 443#endif 444 445#ifdef ZEND_USE_TOLOWER_L 446ZEND_API void zend_update_current_locale(void); 447#else 448#define zend_update_current_locale() 449#endif 450 451#endif 452 453/* 454 * Local variables: 455 * tab-width: 4 456 * c-basic-offset: 4 457 * indent-tabs-mode: t 458 * End: 459 */ 460