root/Zend/zend_operators.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_atoi
  2. zend_atol
  3. zend_unwrap_reference
  4. convert_scalar_to_number
  5. convert_to_long
  6. convert_to_long_base
  7. convert_to_double
  8. convert_to_null
  9. convert_to_boolean
  10. _convert_to_cstring
  11. _convert_to_string
  12. convert_scalar_to_array
  13. convert_to_array
  14. convert_to_object
  15. multi_convert_to_long_ex
  16. multi_convert_to_double_ex
  17. multi_convert_to_string_ex
  18. _zval_get_long_func
  19. _zval_get_double_func
  20. _zval_get_string_func
  21. add_function
  22. sub_function
  23. mul_function
  24. pow_function
  25. div_function
  26. mod_function
  27. boolean_xor_function
  28. boolean_not_function
  29. bitwise_not_function
  30. bitwise_or_function
  31. bitwise_and_function
  32. bitwise_xor_function
  33. shift_left_function
  34. shift_right_function
  35. concat_function
  36. string_compare_function_ex
  37. string_compare_function
  38. string_case_compare_function
  39. string_locale_compare_function
  40. numeric_compare_function
  41. zend_free_obj_get_result
  42. convert_compare_result_to_long
  43. compare_function
  44. hash_zval_identical_function
  45. zend_is_identical
  46. is_identical_function
  47. is_not_identical_function
  48. is_equal_function
  49. is_not_equal_function
  50. is_smaller_function
  51. is_smaller_or_equal_function
  52. instanceof_interface_only
  53. instanceof_class
  54. instanceof_interface
  55. instanceof_function_ex
  56. instanceof_function
  57. increment_string
  58. increment_function
  59. decrement_function
  60. zend_is_true
  61. zend_object_is_true
  62. zend_update_current_locale
  63. zend_str_tolower_copy
  64. zend_str_tolower_dup
  65. zend_str_tolower
  66. zend_str_tolower_dup_ex
  67. zend_string_tolower
  68. zend_binary_strcmp
  69. zend_binary_strncmp
  70. zend_binary_strcasecmp
  71. zend_binary_strncasecmp
  72. zend_binary_strcasecmp_l
  73. zend_binary_strncasecmp_l
  74. zend_binary_zval_strcmp
  75. zend_binary_zval_strncmp
  76. zend_binary_zval_strcasecmp
  77. zend_binary_zval_strncasecmp
  78. zendi_smart_strcmp
  79. hash_zval_compare_function
  80. zend_compare_symbol_tables
  81. zend_compare_arrays
  82. zend_compare_objects
  83. zend_locale_sprintf_double
  84. zend_long_to_str
  85. is_numeric_str_function
  86. _is_numeric_string_ex
  87. zend_memnstr_ex_pre
  88. zend_memnstr_ex
  89. zend_memnrstr_ex
  90. zend_dval_to_lval_slow
  91. zend_dval_to_lval_slow

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 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    |          Dmitry Stogov <dmitry@zend.com>                             |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 /* $Id$ */
  22 
  23 #include <ctype.h>
  24 
  25 #include "zend.h"
  26 #include "zend_operators.h"
  27 #include "zend_variables.h"
  28 #include "zend_globals.h"
  29 #include "zend_list.h"
  30 #include "zend_API.h"
  31 #include "zend_strtod.h"
  32 #include "zend_exceptions.h"
  33 #include "zend_closures.h"
  34 
  35 #if ZEND_USE_TOLOWER_L
  36 #include <locale.h>
  37 static _locale_t current_locale = NULL;
  38 /* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
  39 #define zend_tolower(c) _tolower_l(c, current_locale)
  40 #else
  41 #define zend_tolower(c) tolower(c)
  42 #endif
  43 
  44 #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
  45 
  46 static const unsigned char tolower_map[256] = {
  47 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
  48 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
  49 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
  50 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
  51 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
  52 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
  53 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
  54 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
  55 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
  56 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
  57 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
  58 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
  59 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
  60 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
  61 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
  62 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
  63 };
  64 
  65 #define zend_tolower_ascii(c) (tolower_map[(unsigned char)(c)])
  66 
  67 /**
  68  * Functions using locale lowercase:
  69                 zend_binary_strncasecmp_l
  70                 zend_binary_strcasecmp_l
  71                 zend_binary_zval_strcasecmp
  72                 zend_binary_zval_strncasecmp
  73                 string_compare_function_ex
  74                 string_case_compare_function
  75  * Functions using ascii lowercase:
  76                 zend_str_tolower_copy
  77                 zend_str_tolower_dup
  78                 zend_str_tolower
  79                 zend_binary_strcasecmp
  80                 zend_binary_strncasecmp
  81  */
  82 
  83 ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, int str_len) /* {{{ */
  84 {
  85         int retval;
  86 
  87         if (!str_len) {
  88                 str_len = (int)strlen(str);
  89         }
  90         retval = ZEND_STRTOL(str, NULL, 0);
  91         if (str_len>0) {
  92                 switch (str[str_len-1]) {
  93                         case 'g':
  94                         case 'G':
  95                                 retval *= 1024;
  96                                 /* break intentionally missing */
  97                         case 'm':
  98                         case 'M':
  99                                 retval *= 1024;
 100                                 /* break intentionally missing */
 101                         case 'k':
 102                         case 'K':
 103                                 retval *= 1024;
 104                                 break;
 105                 }
 106         }
 107         return retval;
 108 }
 109 /* }}} */
 110 
 111 ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, int str_len) /* {{{ */
 112 {
 113         zend_long retval;
 114 
 115         if (!str_len) {
 116                 str_len = (int)strlen(str);
 117         }
 118         retval = ZEND_STRTOL(str, NULL, 0);
 119         if (str_len>0) {
 120                 switch (str[str_len-1]) {
 121                         case 'g':
 122                         case 'G':
 123                                 retval *= 1024;
 124                                 /* break intentionally missing */
 125                         case 'm':
 126                         case 'M':
 127                                 retval *= 1024;
 128                                 /* break intentionally missing */
 129                         case 'k':
 130                         case 'K':
 131                                 retval *= 1024;
 132                                 break;
 133                 }
 134         }
 135         return retval;
 136 }
 137 /* }}} */
 138 
 139 static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */
 140 {
 141         if (Z_REFCOUNT_P(op) == 1) {
 142                 ZVAL_UNREF(op);
 143         } else {
 144                 Z_DELREF_P(op);
 145                 ZVAL_COPY(op, Z_REFVAL_P(op));
 146         }
 147 }
 148 /* }}} */
 149 
 150 ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
 151 {
 152 try_again:
 153         switch (Z_TYPE_P(op)) {
 154                 case IS_REFERENCE:
 155                         zend_unwrap_reference(op);
 156                         goto try_again;
 157                 case IS_STRING:
 158                         {
 159                                 zend_string *str;
 160 
 161                                 str = Z_STR_P(op);
 162                                 if ((Z_TYPE_INFO_P(op)=is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
 163                                         ZVAL_LONG(op, 0);
 164                                 }
 165                                 zend_string_release(str);
 166                                 break;
 167                         }
 168                 case IS_NULL:
 169                 case IS_FALSE:
 170                         ZVAL_LONG(op, 0);
 171                         break;
 172                 case IS_TRUE:
 173                         ZVAL_LONG(op, 1);
 174                         break;
 175                 case IS_RESOURCE:
 176                         {
 177                                 zend_long l = Z_RES_HANDLE_P(op);
 178                                 zval_ptr_dtor(op);
 179                                 ZVAL_LONG(op, l);
 180                         }
 181                         break;
 182                 case IS_OBJECT:
 183                         convert_to_long_base(op, 10);
 184                         break;
 185         }
 186 }
 187 /* }}} */
 188 
 189 /* {{{ zendi_convert_scalar_to_number */
 190 #define zendi_convert_scalar_to_number(op, holder, result)                      \
 191         if (op==result) {                                                                                               \
 192                 if (Z_TYPE_P(op) != IS_LONG) {                                                          \
 193                         convert_scalar_to_number(op);                                   \
 194                 }                                                                                                                       \
 195         } else {                                                                                                                \
 196                 switch (Z_TYPE_P(op)) {                                                                         \
 197                         case IS_STRING:                                                                                 \
 198                                 {                                                                                                       \
 199                                         if ((Z_TYPE_INFO(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) {        \
 200                                                 ZVAL_LONG(&(holder), 0);                                                        \
 201                                         }                                                                                                               \
 202                                         (op) = &(holder);                                                                               \
 203                                         break;                                                                                                  \
 204                                 }                                                                                                                       \
 205                         case IS_NULL:                                                                                                   \
 206                         case IS_FALSE:                                                                                                  \
 207                                 ZVAL_LONG(&(holder), 0);                                                                        \
 208                                 (op) = &(holder);                                                                                       \
 209                                 break;                                                                                                          \
 210                         case IS_TRUE:                                                                                                   \
 211                                 ZVAL_LONG(&(holder), 1);                                                                        \
 212                                 (op) = &(holder);                                                                                       \
 213                                 break;                                                                                                          \
 214                         case IS_RESOURCE:                                                                                               \
 215                                 ZVAL_LONG(&(holder), Z_RES_HANDLE_P(op));                                       \
 216                                 (op) = &(holder);                                                                                       \
 217                                 break;                                                                                                          \
 218                         case IS_OBJECT:                                                                                                 \
 219                                 ZVAL_COPY(&(holder), op);                                                                               \
 220                                 convert_to_long_base(&(holder), 10);                                            \
 221                                 if (Z_TYPE(holder) == IS_LONG) {                                                        \
 222                                         (op) = &(holder);                                                                               \
 223                                 }                                                                                                                       \
 224                                 break;                                                                                                          \
 225                 }                                                                                                                                       \
 226         }
 227 
 228 /* }}} */
 229 
 230 /* {{{ convert_object_to_type: dst will be either ctype or UNDEF */
 231 #define convert_object_to_type(op, dst, ctype, conv_func)                                                                       \
 232         ZVAL_UNDEF(dst);                                                                                                                                                \
 233         if (Z_OBJ_HT_P(op)->cast_object) {                                                                                                              \
 234                 if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) {                           \
 235                         zend_error(E_RECOVERABLE_ERROR,                                                                                                 \
 236                                 "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\
 237                         zend_get_type_by_const(ctype));                                                                                                 \
 238                 }                                                                                                                                                                       \
 239         } else if (Z_OBJ_HT_P(op)->get) {                                                                                                               \
 240                 zval *newop = Z_OBJ_HT_P(op)->get(op, dst);                                                             \
 241                 if (Z_TYPE_P(newop) != IS_OBJECT) {                                                                                                     \
 242                         /* for safety - avoid loop */                                                                                                   \
 243                         ZVAL_COPY_VALUE(dst, newop);                                                                                                    \
 244                         conv_func(dst);                                                                                                                                 \
 245                 }                                                                                                                                                                       \
 246         }
 247 
 248 /* }}} */
 249 
 250 #define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, op, op_func) \
 251         do {                                                                                                                            \
 252                 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {                                             \
 253                         if (Z_ISREF_P(op1)) {                                                                           \
 254                                 op1 = Z_REFVAL_P(op1);                                                                  \
 255                                 if (Z_TYPE_P(op1) == IS_LONG) {                                                 \
 256                                         op1_lval = Z_LVAL_P(op1);                                                       \
 257                                         break;                                                                                          \
 258                                 }                                                                                                               \
 259                         }                                                                                                                       \
 260                         ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(op, op_func);                      \
 261                         op1_lval = _zval_get_long_func(op1);                                            \
 262                 } else {                                                                                                                \
 263                         op1_lval = Z_LVAL_P(op1);                                                                       \
 264                 }                                                                                                                               \
 265         } while (0);                                                                                                            \
 266         do {                                                                                                                            \
 267                 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {                                             \
 268                         if (Z_ISREF_P(op2)) {                                                                           \
 269                                 op2 = Z_REFVAL_P(op2);                                                                  \
 270                                 if (Z_TYPE_P(op2) == IS_LONG) {                                                 \
 271                                         op2_lval = Z_LVAL_P(op2);                                                       \
 272                                         break;                                                                                          \
 273                                 }                                                                                                               \
 274                         }                                                                                                                       \
 275                         ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(op);                                       \
 276                         op2_lval = _zval_get_long_func(op2);                                            \
 277                 } else {                                                                                                                \
 278                         op2_lval = Z_LVAL_P(op2);                                                                       \
 279                 }                                                                                                                               \
 280         } while (0);
 281 
 282 ZEND_API void ZEND_FASTCALL convert_to_long(zval *op) /* {{{ */
 283 {
 284         if (Z_TYPE_P(op) != IS_LONG) {
 285                 convert_to_long_base(op, 10);
 286         }
 287 }
 288 /* }}} */
 289 
 290 ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */
 291 {
 292         zend_long tmp;
 293 
 294 try_again:
 295         switch (Z_TYPE_P(op)) {
 296                 case IS_NULL:
 297                 case IS_FALSE:
 298                         ZVAL_LONG(op, 0);
 299                         break;
 300                 case IS_TRUE:
 301                         ZVAL_LONG(op, 1);
 302                         break;
 303                 case IS_RESOURCE:
 304                         tmp = Z_RES_HANDLE_P(op);
 305                         zval_ptr_dtor(op);
 306                         ZVAL_LONG(op, tmp);
 307                         break;
 308                 case IS_LONG:
 309                         break;
 310                 case IS_DOUBLE:
 311                         ZVAL_LONG(op, zend_dval_to_lval(Z_DVAL_P(op)));
 312                         break;
 313                 case IS_STRING:
 314                         {
 315                                 zend_string *str = Z_STR_P(op);
 316 
 317                                 ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base));
 318                                 zend_string_release(str);
 319                         }
 320                         break;
 321                 case IS_ARRAY:
 322                         tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
 323                         zval_ptr_dtor(op);
 324                         ZVAL_LONG(op, tmp);
 325                         break;
 326                 case IS_OBJECT:
 327                         {
 328                                 zval dst;
 329 
 330                                 convert_object_to_type(op, &dst, IS_LONG, convert_to_long);
 331                                 zval_dtor(op);
 332 
 333                                 if (Z_TYPE(dst) == IS_LONG) {
 334                                         ZVAL_COPY_VALUE(op, &dst);
 335                                 } else {
 336 
 337                                         ZVAL_LONG(op, 1);
 338                                 }
 339                                 return;
 340                         }
 341                 case IS_REFERENCE:
 342                         zend_unwrap_reference(op);
 343                         goto try_again;
 344                 EMPTY_SWITCH_DEFAULT_CASE()
 345         }
 346 }
 347 /* }}} */
 348 
 349 ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */
 350 {
 351         double tmp;
 352 
 353 try_again:
 354         switch (Z_TYPE_P(op)) {
 355                 case IS_NULL:
 356                 case IS_FALSE:
 357                         ZVAL_DOUBLE(op, 0.0);
 358                         break;
 359                 case IS_TRUE:
 360                         ZVAL_DOUBLE(op, 1.0);
 361                         break;
 362                 case IS_RESOURCE: {
 363                                 double d = (double) Z_RES_HANDLE_P(op);
 364                                 zval_ptr_dtor(op);
 365                                 ZVAL_DOUBLE(op, d);
 366                         }
 367                         break;
 368                 case IS_LONG:
 369                         ZVAL_DOUBLE(op, (double) Z_LVAL_P(op));
 370                         break;
 371                 case IS_DOUBLE:
 372                         break;
 373                 case IS_STRING:
 374                         {
 375                                 zend_string *str = Z_STR_P(op);
 376 
 377                                 ZVAL_DOUBLE(op, zend_strtod(ZSTR_VAL(str), NULL));
 378                                 zend_string_release(str);
 379                         }
 380                         break;
 381                 case IS_ARRAY:
 382                         tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
 383                         zval_ptr_dtor(op);
 384                         ZVAL_DOUBLE(op, tmp);
 385                         break;
 386                 case IS_OBJECT:
 387                         {
 388                                 zval dst;
 389 
 390                                 convert_object_to_type(op, &dst, IS_DOUBLE, convert_to_double);
 391                                 zval_dtor(op);
 392 
 393                                 if (Z_TYPE(dst) == IS_DOUBLE) {
 394                                         ZVAL_COPY_VALUE(op, &dst);
 395                                 } else {
 396                                         ZVAL_DOUBLE(op, 1.0);
 397                                 }
 398                                 break;
 399                         }
 400                 case IS_REFERENCE:
 401                         zend_unwrap_reference(op);
 402                         goto try_again;
 403                 EMPTY_SWITCH_DEFAULT_CASE()
 404         }
 405 }
 406 /* }}} */
 407 
 408 ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */
 409 {
 410         if (Z_TYPE_P(op) == IS_OBJECT) {
 411                 if (Z_OBJ_HT_P(op)->cast_object) {
 412                         zval org;
 413 
 414                         ZVAL_COPY_VALUE(&org, op);
 415                         if (Z_OBJ_HT_P(op)->cast_object(&org, op, IS_NULL) == SUCCESS) {
 416                                 zval_dtor(&org);
 417                                 return;
 418                         }
 419                         ZVAL_COPY_VALUE(op, &org);
 420                 }
 421         }
 422 
 423         zval_ptr_dtor(op);
 424         ZVAL_NULL(op);
 425 }
 426 /* }}} */
 427 
 428 ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */
 429 {
 430         int tmp;
 431 
 432 try_again:
 433         switch (Z_TYPE_P(op)) {
 434                 case IS_FALSE:
 435                 case IS_TRUE:
 436                         break;
 437                 case IS_NULL:
 438                         ZVAL_FALSE(op);
 439                         break;
 440                 case IS_RESOURCE: {
 441                                 zend_long l = (Z_RES_HANDLE_P(op) ? 1 : 0);
 442 
 443                                 zval_ptr_dtor(op);
 444                                 ZVAL_BOOL(op, l);
 445                         }
 446                         break;
 447                 case IS_LONG:
 448                         ZVAL_BOOL(op, Z_LVAL_P(op) ? 1 : 0);
 449                         break;
 450                 case IS_DOUBLE:
 451                         ZVAL_BOOL(op, Z_DVAL_P(op) ? 1 : 0);
 452                         break;
 453                 case IS_STRING:
 454                         {
 455                                 zend_string *str = Z_STR_P(op);
 456 
 457                                 if (ZSTR_LEN(str) == 0
 458                                         || (ZSTR_LEN(str) == 1 && ZSTR_VAL(str)[0] == '0')) {
 459                                         ZVAL_FALSE(op);
 460                                 } else {
 461                                         ZVAL_TRUE(op);
 462                                 }
 463                                 zend_string_release(str);
 464                         }
 465                         break;
 466                 case IS_ARRAY:
 467                         tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
 468                         zval_ptr_dtor(op);
 469                         ZVAL_BOOL(op, tmp);
 470                         break;
 471                 case IS_OBJECT:
 472                         {
 473                                 zval dst;
 474 
 475                                 convert_object_to_type(op, &dst, _IS_BOOL, convert_to_boolean);
 476                                 zval_dtor(op);
 477 
 478                                 if (Z_TYPE(dst) == IS_FALSE || Z_TYPE(dst) == IS_TRUE) {
 479                                         ZVAL_COPY_VALUE(op, &dst);
 480                                 } else {
 481                                         ZVAL_TRUE(op);
 482                                 }
 483                                 break;
 484                         }
 485                 case IS_REFERENCE:
 486                         zend_unwrap_reference(op);
 487                         goto try_again;
 488                 EMPTY_SWITCH_DEFAULT_CASE()
 489         }
 490 }
 491 /* }}} */
 492 
 493 ZEND_API void ZEND_FASTCALL _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* {{{ */
 494 {
 495         if (Z_TYPE_P(op) == IS_DOUBLE) {
 496                 zend_string *str;
 497                 double dval = Z_DVAL_P(op);
 498 
 499                 str = zend_strpprintf(0, "%.*H", (int) EG(precision), dval);
 500                 ZVAL_NEW_STR(op, str);
 501         } else {
 502                 _convert_to_string(op ZEND_FILE_LINE_CC);
 503         }
 504 }
 505 /* }}} */
 506 
 507 ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
 508 {
 509 try_again:
 510         switch (Z_TYPE_P(op)) {
 511                 case IS_UNDEF:
 512                 case IS_NULL:
 513                 case IS_FALSE: {
 514                         ZVAL_EMPTY_STRING(op);
 515                         break;
 516                 }
 517                 case IS_TRUE:
 518                         if (CG(one_char_string)['1']) {
 519                                 ZVAL_INTERNED_STR(op, CG(one_char_string)['1']);
 520                         } else {
 521                                 ZVAL_NEW_STR(op, zend_string_init("1", 1, 0));
 522                         }
 523                         break;
 524                 case IS_STRING:
 525                         break;
 526                 case IS_RESOURCE: {
 527                         char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
 528                         int len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
 529                         zval_ptr_dtor(op);
 530                         ZVAL_NEW_STR(op, zend_string_init(buf, len, 0));
 531                         break;
 532                 }
 533                 case IS_LONG: {
 534                         ZVAL_NEW_STR(op, zend_long_to_str(Z_LVAL_P(op)));
 535                         break;
 536                 }
 537                 case IS_DOUBLE: {
 538                         zend_string *str;
 539                         double dval = Z_DVAL_P(op);
 540 
 541                         str = zend_strpprintf(0, "%.*G", (int) EG(precision), dval);
 542                         /* %G already handles removing trailing zeros from the fractional part, yay */
 543                         ZVAL_NEW_STR(op, str);
 544                         break;
 545                 }
 546                 case IS_ARRAY:
 547                         zend_error(E_NOTICE, "Array to string conversion");
 548                         zval_ptr_dtor(op);
 549                         ZVAL_NEW_STR(op, zend_string_init("Array", sizeof("Array")-1, 0));
 550                         break;
 551                 case IS_OBJECT: {
 552                         zval dst;
 553 
 554                         convert_object_to_type(op, &dst, IS_STRING, convert_to_string);
 555                         zval_dtor(op);
 556 
 557                         if (Z_TYPE(dst) == IS_STRING) {
 558                                 ZVAL_COPY_VALUE(op, &dst);
 559                         } else {
 560                                 ZVAL_NEW_STR(op, zend_string_init("Object", sizeof("Object")-1, 0));
 561                         }
 562                         break;
 563                 }
 564                 case IS_REFERENCE:
 565                         zend_unwrap_reference(op);
 566                         goto try_again;
 567                 EMPTY_SWITCH_DEFAULT_CASE()
 568         }
 569 }
 570 /* }}} */
 571 
 572 static void convert_scalar_to_array(zval *op) /* {{{ */
 573 {
 574         zval entry;
 575 
 576         ZVAL_COPY_VALUE(&entry, op);
 577 
 578         ZVAL_NEW_ARR(op);
 579         zend_hash_init(Z_ARRVAL_P(op), 8, NULL, ZVAL_PTR_DTOR, 0);
 580         zend_hash_index_add_new(Z_ARRVAL_P(op), 0, &entry);
 581 }
 582 /* }}} */
 583 
 584 ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */
 585 {
 586 try_again:
 587         switch (Z_TYPE_P(op)) {
 588                 case IS_ARRAY:
 589                         break;
 590 /* OBJECTS_OPTIMIZE */
 591                 case IS_OBJECT:
 592                         if (Z_OBJCE_P(op) == zend_ce_closure) {
 593                                 convert_scalar_to_array(op);
 594                         } else {
 595                                 if (Z_OBJ_HT_P(op)->get_properties) {
 596                                         HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op);
 597                                         if (obj_ht) {
 598                                                 zval arr;
 599 
 600                                                 if (!Z_OBJCE_P(op)->default_properties_count && obj_ht == Z_OBJ_P(op)->properties) {
 601                                                         /* fast copy */
 602                                                         if (EXPECTED(Z_OBJ_P(op)->handlers == &std_object_handlers)) {
 603                                                                 ZVAL_ARR(&arr, obj_ht);
 604                                                                 if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(op)->properties) & IS_ARRAY_IMMUTABLE))) {
 605                                                                         GC_REFCOUNT(Z_OBJ_P(op)->properties)++;
 606                                                                 }
 607                                                         } else {
 608                                                                 ZVAL_ARR(&arr, zend_array_dup(obj_ht));
 609                                                         }
 610                                                         zval_dtor(op);
 611                                                         ZVAL_COPY_VALUE(op, &arr);
 612                                                 } else {
 613                                                         ZVAL_ARR(&arr, zend_array_dup(obj_ht));
 614                                                         zval_dtor(op);
 615                                                         ZVAL_COPY_VALUE(op, &arr);
 616                                                 }
 617                                                 return;
 618                                         }
 619                                 } else {
 620                                         zval dst;
 621                                         convert_object_to_type(op, &dst, IS_ARRAY, convert_to_array);
 622 
 623                                         if (Z_TYPE(dst) == IS_ARRAY) {
 624                                                 zval_dtor(op);
 625                                                 ZVAL_COPY_VALUE(op, &dst);
 626                                                 return;
 627                                         }
 628                                 }
 629 
 630                                 zval_dtor(op);
 631                                 array_init(op);
 632                         }
 633                         break;
 634                 case IS_NULL:
 635                         ZVAL_NEW_ARR(op);
 636                         zend_hash_init(Z_ARRVAL_P(op), 8, NULL, ZVAL_PTR_DTOR, 0);
 637                         break;
 638                 case IS_REFERENCE:
 639                         zend_unwrap_reference(op);
 640                         goto try_again;
 641                 default:
 642                         convert_scalar_to_array(op);
 643                         break;
 644         }
 645 }
 646 /* }}} */
 647 
 648 ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */
 649 {
 650 try_again:
 651         switch (Z_TYPE_P(op)) {
 652                 case IS_ARRAY:
 653                         {
 654                                 HashTable *ht = Z_ARR_P(op);
 655                                 if (Z_IMMUTABLE_P(op)) {
 656                                         /* TODO: try not to duplicate immutable arrays as well ??? */
 657                                         ht = zend_array_dup(ht);
 658                                 }
 659                                 object_and_properties_init(op, zend_standard_class_def, ht);
 660                                 break;
 661                         }
 662                 case IS_OBJECT:
 663                         break;
 664                 case IS_NULL:
 665                         object_init(op);
 666                         break;
 667                 case IS_REFERENCE:
 668                         zend_unwrap_reference(op);
 669                         goto try_again;
 670                 default: {
 671                         zval tmp;
 672                         ZVAL_COPY_VALUE(&tmp, op);
 673                         object_init(op);
 674                         zend_hash_str_add_new(Z_OBJPROP_P(op), "scalar", sizeof("scalar")-1, &tmp);
 675                         break;
 676                 }
 677         }
 678 }
 679 /* }}} */
 680 
 681 ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
 682 {
 683         zval *arg;
 684         va_list ap;
 685 
 686         va_start(ap, argc);
 687 
 688         while (argc--) {
 689                 arg = va_arg(ap, zval *);
 690                 convert_to_long_ex(arg);
 691         }
 692 
 693         va_end(ap);
 694 }
 695 /* }}} */
 696 
 697 ZEND_API void multi_convert_to_double_ex(int argc, ...) /* {{{ */
 698 {
 699         zval *arg;
 700         va_list ap;
 701 
 702         va_start(ap, argc);
 703 
 704         while (argc--) {
 705                 arg = va_arg(ap, zval *);
 706                 convert_to_double_ex(arg);
 707         }
 708 
 709         va_end(ap);
 710 }
 711 /* }}} */
 712 
 713 ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
 714 {
 715         zval *arg;
 716         va_list ap;
 717 
 718         va_start(ap, argc);
 719 
 720         while (argc--) {
 721                 arg = va_arg(ap, zval *);
 722                 convert_to_string_ex(arg);
 723         }
 724 
 725         va_end(ap);
 726 }
 727 /* }}} */
 728 
 729 ZEND_API zend_long ZEND_FASTCALL _zval_get_long_func(zval *op) /* {{{ */
 730 {
 731 try_again:
 732         switch (Z_TYPE_P(op)) {
 733                 case IS_NULL:
 734                 case IS_FALSE:
 735                         return 0;
 736                 case IS_TRUE:
 737                         return 1;
 738                 case IS_RESOURCE:
 739                         return Z_RES_HANDLE_P(op);
 740                 case IS_LONG:
 741                         return Z_LVAL_P(op);
 742                 case IS_DOUBLE:
 743                         return zend_dval_to_lval(Z_DVAL_P(op));
 744                 case IS_STRING:
 745                         return ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10);
 746                 case IS_ARRAY:
 747                         return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0;
 748                 case IS_OBJECT:
 749                         {
 750                                 zval dst;
 751                                 convert_object_to_type(op, &dst, IS_LONG, convert_to_long);
 752                                 if (Z_TYPE(dst) == IS_LONG) {
 753                                         return Z_LVAL(dst);
 754                                 } else {
 755                                         return 1;
 756                                 }
 757                         }
 758                 case IS_REFERENCE:
 759                         op = Z_REFVAL_P(op);
 760                         goto try_again;
 761                 EMPTY_SWITCH_DEFAULT_CASE()
 762         }
 763         return 0;
 764 }
 765 /* }}} */
 766 
 767 ZEND_API double ZEND_FASTCALL _zval_get_double_func(zval *op) /* {{{ */
 768 {
 769 try_again:
 770         switch (Z_TYPE_P(op)) {
 771                 case IS_NULL:
 772                 case IS_FALSE:
 773                         return 0.0;
 774                 case IS_TRUE:
 775                         return 1.0;
 776                 case IS_RESOURCE:
 777                         return (double) Z_RES_HANDLE_P(op);
 778                 case IS_LONG:
 779                         return (double) Z_LVAL_P(op);
 780                 case IS_DOUBLE:
 781                         return Z_DVAL_P(op);
 782                 case IS_STRING:
 783                         return zend_strtod(Z_STRVAL_P(op), NULL);
 784                 case IS_ARRAY:
 785                         return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1.0 : 0.0;
 786                 case IS_OBJECT:
 787                         {
 788                                 zval dst;
 789                                 convert_object_to_type(op, &dst, IS_DOUBLE, convert_to_double);
 790 
 791                                 if (Z_TYPE(dst) == IS_DOUBLE) {
 792                                         return Z_DVAL(dst);
 793                                 } else {
 794                                         return 1.0;
 795                                 }
 796                         }
 797                 case IS_REFERENCE:
 798                         op = Z_REFVAL_P(op);
 799                         goto try_again;
 800                 EMPTY_SWITCH_DEFAULT_CASE()
 801         }
 802         return 0.0;
 803 }
 804 /* }}} */
 805 
 806 ZEND_API zend_string* ZEND_FASTCALL _zval_get_string_func(zval *op) /* {{{ */
 807 {
 808 try_again:
 809         switch (Z_TYPE_P(op)) {
 810                 case IS_UNDEF:
 811                 case IS_NULL:
 812                 case IS_FALSE:
 813                         return ZSTR_EMPTY_ALLOC();
 814                 case IS_TRUE:
 815                         if (CG(one_char_string)['1']) {
 816                                 return CG(one_char_string)['1'];
 817                         } else {
 818                                 return zend_string_init("1", 1, 0);
 819                         }
 820                 case IS_RESOURCE: {
 821                         char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
 822                         int len;
 823 
 824                         len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
 825                         return zend_string_init(buf, len, 0);
 826                 }
 827                 case IS_LONG: {
 828                         return zend_long_to_str(Z_LVAL_P(op));
 829                 }
 830                 case IS_DOUBLE: {
 831                         return zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op));
 832                 }
 833                 case IS_ARRAY:
 834                         zend_error(E_NOTICE, "Array to string conversion");
 835                         return zend_string_init("Array", sizeof("Array")-1, 0);
 836                 case IS_OBJECT: {
 837                         zval tmp;
 838                         if (Z_OBJ_HT_P(op)->cast_object) {
 839                                 if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) == SUCCESS) {
 840                                         return Z_STR(tmp);
 841                                 }
 842                         } else if (Z_OBJ_HT_P(op)->get) {
 843                                 zval *z = Z_OBJ_HT_P(op)->get(op, &tmp);
 844                                 if (Z_TYPE_P(z) != IS_OBJECT) {
 845                                         zend_string *str = zval_get_string(z);
 846                                         zval_ptr_dtor(z);
 847                                         return str;
 848                                 }
 849                                 zval_ptr_dtor(z);
 850                         }
 851                         zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
 852                         return ZSTR_EMPTY_ALLOC();
 853                 }
 854                 case IS_REFERENCE:
 855                         op = Z_REFVAL_P(op);
 856                         goto try_again;
 857                 case IS_STRING:
 858                         return zend_string_copy(Z_STR_P(op));
 859                 EMPTY_SWITCH_DEFAULT_CASE()
 860         }
 861         return NULL;
 862 }
 863 /* }}} */
 864 
 865 ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {{{ */
 866 {
 867         zval op1_copy, op2_copy;
 868         int converted = 0;
 869 
 870         while (1) {
 871                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
 872                         case TYPE_PAIR(IS_LONG, IS_LONG): {
 873                                 zend_long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
 874 
 875                                 /* check for overflow by comparing sign bits */
 876                                 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
 877                                         && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
 878 
 879                                         ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
 880                                 } else {
 881                                         ZVAL_LONG(result, lval);
 882                                 }
 883                                 return SUCCESS;
 884                         }
 885 
 886                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
 887                                 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
 888                                 return SUCCESS;
 889 
 890                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
 891                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
 892                                 return SUCCESS;
 893 
 894                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
 895                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
 896                                 return SUCCESS;
 897 
 898                         case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
 899                                 if ((result == op1) && (result == op2)) {
 900                                         /* $a += $a */
 901                                         return SUCCESS;
 902                                 }
 903                                 if (result != op1) {
 904                                         ZVAL_DUP(result, op1);
 905                                 }
 906                                 zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
 907                                 return SUCCESS;
 908 
 909                         default:
 910                                 if (Z_ISREF_P(op1)) {
 911                                         op1 = Z_REFVAL_P(op1);
 912                                 } else if (Z_ISREF_P(op2)) {
 913                                         op2 = Z_REFVAL_P(op2);
 914                                 } else if (!converted) {
 915                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function);
 916 
 917                                         zendi_convert_scalar_to_number(op1, op1_copy, result);
 918                                         zendi_convert_scalar_to_number(op2, op2_copy, result);
 919                                         converted = 1;
 920                                 } else {
 921                                         zend_throw_error(NULL, "Unsupported operand types");
 922                                         return FAILURE; /* unknown datatype */
 923                                 }
 924                 }
 925         }
 926 }
 927 /* }}} */
 928 
 929 ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {{{ */
 930 {
 931         zval op1_copy, op2_copy;
 932         int converted = 0;
 933 
 934         while (1) {
 935                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
 936                         case TYPE_PAIR(IS_LONG, IS_LONG): {
 937                                 zend_long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
 938 
 939                                 /* check for overflow by comparing sign bits */
 940                                 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
 941                                         && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
 942 
 943                                         ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
 944                                 } else {
 945                                         ZVAL_LONG(result, lval);
 946                                 }
 947                                 return SUCCESS;
 948 
 949                         }
 950                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
 951                                 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
 952                                 return SUCCESS;
 953 
 954                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
 955                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
 956                                 return SUCCESS;
 957 
 958                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
 959                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
 960                                 return SUCCESS;
 961 
 962                         default:
 963                                 if (Z_ISREF_P(op1)) {
 964                                         op1 = Z_REFVAL_P(op1);
 965                                 } else if (Z_ISREF_P(op2)) {
 966                                         op2 = Z_REFVAL_P(op2);
 967                                 } else if (!converted) {
 968                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function);
 969 
 970                                         zendi_convert_scalar_to_number(op1, op1_copy, result);
 971                                         zendi_convert_scalar_to_number(op2, op2_copy, result);
 972                                         converted = 1;
 973                                 } else {
 974                                         zend_throw_error(NULL, "Unsupported operand types");
 975                                         return FAILURE; /* unknown datatype */
 976                                 }
 977                 }
 978         }
 979 }
 980 /* }}} */
 981 
 982 ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* {{{ */
 983 {
 984         zval op1_copy, op2_copy;
 985         int converted = 0;
 986 
 987         while (1) {
 988                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
 989                         case TYPE_PAIR(IS_LONG, IS_LONG): {
 990                                 zend_long overflow;
 991 
 992                                 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
 993                                 Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
 994                                 return SUCCESS;
 995 
 996                         }
 997                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
 998                                 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
 999                                 return SUCCESS;
1000 
1001                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1002                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
1003                                 return SUCCESS;
1004 
1005                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1006                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
1007                                 return SUCCESS;
1008 
1009                         default:
1010                                 if (Z_ISREF_P(op1)) {
1011                                         op1 = Z_REFVAL_P(op1);
1012                                 } else if (Z_ISREF_P(op2)) {
1013                                         op2 = Z_REFVAL_P(op2);
1014                                 } else if (!converted) {
1015                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function);
1016 
1017                                         zendi_convert_scalar_to_number(op1, op1_copy, result);
1018                                         zendi_convert_scalar_to_number(op2, op2_copy, result);
1019                                         converted = 1;
1020                                 } else {
1021                                         zend_throw_error(NULL, "Unsupported operand types");
1022                                         return FAILURE; /* unknown datatype */
1023                                 }
1024                 }
1025         }
1026 }
1027 /* }}} */
1028 
1029 ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* {{{ */
1030 {
1031         zval op1_copy, op2_copy;
1032         int converted = 0;
1033 
1034         while (1) {
1035                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1036                         case TYPE_PAIR(IS_LONG, IS_LONG):
1037                                 if (Z_LVAL_P(op2) >= 0) {
1038                                         zend_long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
1039 
1040                                         if (i == 0) {
1041                                                 ZVAL_LONG(result, 1L);
1042                                                 return SUCCESS;
1043                                         } else if (l2 == 0) {
1044                                                 ZVAL_LONG(result, 0);
1045                                                 return SUCCESS;
1046                                         }
1047 
1048                                         while (i >= 1) {
1049                                                 zend_long overflow;
1050                                                 double dval = 0.0;
1051 
1052                                                 if (i % 2) {
1053                                                         --i;
1054                                                         ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
1055                                                         if (overflow) {
1056                                                                 ZVAL_DOUBLE(result, dval * pow(l2, i));
1057                                                                 return SUCCESS;
1058                                                         }
1059                                                 } else {
1060                                                         i /= 2;
1061                                                         ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
1062                                                         if (overflow) {
1063                                                                 ZVAL_DOUBLE(result, (double)l1 * pow(dval, i));
1064                                                                 return SUCCESS;
1065                                                         }
1066                                                 }
1067                                         }
1068                                         /* i == 0 */
1069                                         ZVAL_LONG(result, l1);
1070                                 } else {
1071                                         ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2)));
1072                                 }
1073                                 return SUCCESS;
1074 
1075                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1076                                 ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2)));
1077                                 return SUCCESS;
1078 
1079                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1080                                 ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2)));
1081                                 return SUCCESS;
1082 
1083                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1084                                 ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
1085                                 return SUCCESS;
1086 
1087                         default:
1088                                 if (Z_ISREF_P(op1)) {
1089                                         op1 = Z_REFVAL_P(op1);
1090                                 } else if (Z_ISREF_P(op2)) {
1091                                         op2 = Z_REFVAL_P(op2);
1092                                 } else if (!converted) {
1093                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW, pow_function);
1094 
1095                                         if (Z_TYPE_P(op1) == IS_ARRAY) {
1096                                                 ZVAL_LONG(result, 0);
1097                                                 return SUCCESS;
1098                                         } else {
1099                                                 zendi_convert_scalar_to_number(op1, op1_copy, result);
1100                                         }
1101                                         if (Z_TYPE_P(op2) == IS_ARRAY) {
1102                                                 ZVAL_LONG(result, 1L);
1103                                                 return SUCCESS;
1104                                         } else {
1105                                                 zendi_convert_scalar_to_number(op2, op2_copy, result);
1106                                         }
1107                                         converted = 1;
1108                                 } else {
1109                                         zend_throw_error(NULL, "Unsupported operand types");
1110                                         return FAILURE;
1111                                 }
1112                 }
1113         }
1114 }
1115 /* }}} */
1116 
1117 ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {{{ */
1118 {
1119         zval op1_copy, op2_copy;
1120         int converted = 0;
1121 
1122         while (1) {
1123                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1124                         case TYPE_PAIR(IS_LONG, IS_LONG):
1125                                 if (Z_LVAL_P(op2) == 0) {
1126                                         zend_error(E_WARNING, "Division by zero");
1127                                         ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1) / (double) Z_LVAL_P(op2)));
1128                                         return SUCCESS;
1129                                 } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
1130                                         /* Prevent overflow error/crash */
1131                                         ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
1132                                         return SUCCESS;
1133                                 }
1134                                 if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
1135                                         ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
1136                                 } else {
1137                                         ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
1138                                 }
1139                                 return SUCCESS;
1140 
1141                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1142                                 if (Z_LVAL_P(op2) == 0) {
1143                                         zend_error(E_WARNING, "Division by zero");
1144                                 }
1145                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
1146                                 return SUCCESS;
1147 
1148                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1149                                 if (Z_DVAL_P(op2) == 0) {
1150                                         zend_error(E_WARNING, "Division by zero");
1151                                 }
1152                                 ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
1153                                 return SUCCESS;
1154 
1155                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1156                                 if (Z_DVAL_P(op2) == 0) {
1157                                         zend_error(E_WARNING, "Division by zero");
1158                                 }
1159                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
1160                                 return SUCCESS;
1161 
1162                         default:
1163                                 if (Z_ISREF_P(op1)) {
1164                                         op1 = Z_REFVAL_P(op1);
1165                                 } else if (Z_ISREF_P(op2)) {
1166                                         op2 = Z_REFVAL_P(op2);
1167                                 } else if (!converted) {
1168                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function);
1169 
1170                                         zendi_convert_scalar_to_number(op1, op1_copy, result);
1171                                         zendi_convert_scalar_to_number(op2, op2_copy, result);
1172                                         converted = 1;
1173                                 } else {
1174                                         zend_throw_error(NULL, "Unsupported operand types");
1175                                         return FAILURE; /* unknown datatype */
1176                                 }
1177                 }
1178         }
1179 }
1180 /* }}} */
1181 
1182 ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {{{ */
1183 {
1184         zend_long op1_lval, op2_lval;
1185 
1186         convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_MOD, mod_function);
1187 
1188         if (op1 == result) {
1189                 zval_dtor(result);
1190         }
1191 
1192         if (op2_lval == 0) {
1193                 /* modulus by zero */
1194                 if (EG(current_execute_data) && !CG(in_compilation)) {
1195                         zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
1196                 } else {
1197                         zend_error_noreturn(E_ERROR, "Modulo by zero");
1198                 }
1199                 ZVAL_UNDEF(result);
1200                 return FAILURE;
1201         }
1202 
1203         if (op2_lval == -1) {
1204                 /* Prevent overflow error/crash if op1==LONG_MIN */
1205                 ZVAL_LONG(result, 0);
1206                 return SUCCESS;
1207         }
1208 
1209         ZVAL_LONG(result, op1_lval % op2_lval);
1210         return SUCCESS;
1211 }
1212 /* }}} */
1213 
1214 ZEND_API int ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, zval *op2) /* {{{ */
1215 {
1216         int op1_val, op2_val;
1217 
1218         do {
1219                 if (Z_TYPE_P(op1) == IS_FALSE) {
1220                         op1_val = 0;
1221                 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1222                         op1_val = 1;
1223                 } else {
1224                         if (Z_ISREF_P(op1)) {
1225                                 op1 = Z_REFVAL_P(op1);
1226                                 if (Z_TYPE_P(op1) == IS_FALSE) {
1227                                         op1_val = 0;
1228                                         break;
1229                                 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1230                                         op1_val = 1;
1231                                         break;
1232                                 }
1233                         }
1234                         ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BOOL_XOR, boolean_xor_function);
1235                         op1_val = zval_is_true(op1);
1236                 }
1237         } while (0);
1238         do {
1239                 if (Z_TYPE_P(op2) == IS_FALSE) {
1240                         op2_val = 0;
1241                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_TRUE)) {
1242                         op2_val = 1;
1243                 } else {
1244                         if (Z_ISREF_P(op2)) {
1245                                 op2 = Z_REFVAL_P(op2);
1246                                 if (Z_TYPE_P(op2) == IS_FALSE) {
1247                                         op2_val = 0;
1248                                         break;
1249                                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_TRUE)) {
1250                                         op2_val = 1;
1251                                         break;
1252                                 }
1253                         }
1254                         ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BOOL_XOR);
1255                         op2_val = zval_is_true(op2);
1256                 }
1257         } while (0);
1258 
1259         ZVAL_BOOL(result, op1_val ^ op2_val);
1260         return SUCCESS;
1261 }
1262 /* }}} */
1263 
1264 ZEND_API int ZEND_FASTCALL boolean_not_function(zval *result, zval *op1) /* {{{ */
1265 {
1266         if (Z_TYPE_P(op1) < IS_TRUE) {
1267                 ZVAL_TRUE(result);
1268         } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1269                 ZVAL_FALSE(result);
1270         } else {
1271                 if (Z_ISREF_P(op1)) {
1272                         op1 = Z_REFVAL_P(op1);
1273                         if (Z_TYPE_P(op1) < IS_TRUE) {
1274                                 ZVAL_TRUE(result);
1275                                 return SUCCESS;
1276                         } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1277                                 ZVAL_FALSE(result);
1278                                 return SUCCESS;
1279                         }
1280                 }
1281                 ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT);
1282 
1283                 ZVAL_BOOL(result, !zval_is_true(op1));
1284         }
1285         return SUCCESS;
1286 }
1287 /* }}} */
1288 
1289 ZEND_API int ZEND_FASTCALL bitwise_not_function(zval *result, zval *op1) /* {{{ */
1290 {
1291 try_again:
1292         switch (Z_TYPE_P(op1)) {
1293                 case IS_LONG:
1294                         ZVAL_LONG(result, ~Z_LVAL_P(op1));
1295                         return SUCCESS;
1296                 case IS_DOUBLE:
1297                         ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
1298                         return SUCCESS;
1299                 case IS_STRING: {
1300                         size_t i;
1301 
1302                         if (Z_STRLEN_P(op1) == 1) {
1303                                 zend_uchar not = (zend_uchar) ~*Z_STRVAL_P(op1);
1304                                 if (CG(one_char_string)[not]) {
1305                                         ZVAL_INTERNED_STR(result, CG(one_char_string)[not]);
1306                                 } else {
1307                                         ZVAL_NEW_STR(result, zend_string_init((char *) &not, 1, 0));
1308                                 }
1309                         } else {
1310                                 ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0));
1311                                 for (i = 0; i < Z_STRLEN_P(op1); i++) {
1312                                         Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
1313                                 }
1314                                 Z_STRVAL_P(result)[i] = 0;
1315                         }
1316                         return SUCCESS;
1317                 }
1318                 case IS_REFERENCE:
1319                         op1 = Z_REFVAL_P(op1);
1320                         goto try_again;
1321                 default:
1322                         ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT);
1323 
1324                         zend_throw_error(NULL, "Unsupported operand types");
1325                         return FAILURE;
1326         }
1327 }
1328 /* }}} */
1329 
1330 ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op2) /* {{{ */
1331 {
1332         zend_long op1_lval, op2_lval;
1333 
1334         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1335                 ZVAL_LONG(result, Z_LVAL_P(op1) | Z_LVAL_P(op2));
1336                 return SUCCESS;
1337         }
1338 
1339         ZVAL_DEREF(op1);
1340         ZVAL_DEREF(op2);
1341 
1342         if (Z_TYPE_P(op1) == IS_STRING && EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1343                 zval *longer, *shorter;
1344                 zend_string *str;
1345                 size_t i;
1346 
1347                 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1348                         if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1349                                 zend_uchar or = (zend_uchar) (*Z_STRVAL_P(op1) | *Z_STRVAL_P(op2));
1350                                 if (CG(one_char_string)[or]) {
1351                                         ZVAL_INTERNED_STR(result, CG(one_char_string)[or]);
1352                                 } else {
1353                                         ZVAL_NEW_STR(result, zend_string_init((char *) &or, 1, 0));
1354                                 }
1355                                 return SUCCESS;
1356                         }
1357                         longer = op1;
1358                         shorter = op2;
1359                 } else {
1360                         longer = op2;
1361                         shorter = op1;
1362                 }
1363 
1364                 str = zend_string_alloc(Z_STRLEN_P(longer), 0);
1365                 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1366                         ZSTR_VAL(str)[i] = Z_STRVAL_P(longer)[i] | Z_STRVAL_P(shorter)[i];
1367                 }
1368                 memcpy(ZSTR_VAL(str) + i, Z_STRVAL_P(longer) + i, Z_STRLEN_P(longer) - i + 1);
1369                 if (result==op1) {
1370                         zend_string_release(Z_STR_P(result));
1371                 }
1372                 ZVAL_NEW_STR(result, str);
1373                 return SUCCESS;
1374         }
1375 
1376         if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1377                 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function);
1378                 op1_lval = _zval_get_long_func(op1);
1379         } else {
1380                 op1_lval = Z_LVAL_P(op1);
1381         }
1382         if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1383                 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR);
1384                 op2_lval = _zval_get_long_func(op2);
1385         } else {
1386                 op2_lval = Z_LVAL_P(op2);
1387         }
1388 
1389         if (op1 == result) {
1390                 zval_dtor(result);
1391         }
1392         ZVAL_LONG(result, op1_lval | op2_lval);
1393         return SUCCESS;
1394 }
1395 /* }}} */
1396 
1397 ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *op2) /* {{{ */
1398 {
1399         zend_long op1_lval, op2_lval;
1400 
1401         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1402                 ZVAL_LONG(result, Z_LVAL_P(op1) & Z_LVAL_P(op2));
1403                 return SUCCESS;
1404         }
1405 
1406         ZVAL_DEREF(op1);
1407         ZVAL_DEREF(op2);
1408 
1409         if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1410                 zval *longer, *shorter;
1411                 zend_string *str;
1412                 size_t i;
1413 
1414                 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1415                         if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1416                                 zend_uchar and = (zend_uchar) (*Z_STRVAL_P(op1) & *Z_STRVAL_P(op2));
1417                                 if (CG(one_char_string)[and]) {
1418                                         ZVAL_INTERNED_STR(result, CG(one_char_string)[and]);
1419                                 } else {
1420                                         ZVAL_NEW_STR(result, zend_string_init((char *) &and, 1, 0));
1421                                 }
1422                                 return SUCCESS;
1423                         }
1424                         longer = op1;
1425                         shorter = op2;
1426                 } else {
1427                         longer = op2;
1428                         shorter = op1;
1429                 }
1430 
1431                 str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
1432                 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1433                         ZSTR_VAL(str)[i] = Z_STRVAL_P(shorter)[i] & Z_STRVAL_P(longer)[i];
1434                 }
1435                 ZSTR_VAL(str)[i] = 0;
1436                 if (result==op1) {
1437                         zend_string_release(Z_STR_P(result));
1438                 }
1439                 ZVAL_NEW_STR(result, str);
1440                 return SUCCESS;
1441         }
1442 
1443         if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1444                 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function);
1445                 op1_lval = _zval_get_long_func(op1);
1446         } else {
1447                 op1_lval = Z_LVAL_P(op1);
1448         }
1449         if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1450                 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND);
1451                 op2_lval = _zval_get_long_func(op2);
1452         } else {
1453                 op2_lval = Z_LVAL_P(op2);
1454         }
1455 
1456         if (op1 == result) {
1457                 zval_dtor(result);
1458         }
1459         ZVAL_LONG(result, op1_lval & op2_lval);
1460         return SUCCESS;
1461 }
1462 /* }}} */
1463 
1464 ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *op2) /* {{{ */
1465 {
1466         zend_long op1_lval, op2_lval;
1467 
1468         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1469                 ZVAL_LONG(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
1470                 return SUCCESS;
1471         }
1472 
1473         ZVAL_DEREF(op1);
1474         ZVAL_DEREF(op2);
1475 
1476         if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1477                 zval *longer, *shorter;
1478                 zend_string *str;
1479                 size_t i;
1480 
1481                 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1482                         if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1483                                 zend_uchar xor = (zend_uchar) (*Z_STRVAL_P(op1) ^ *Z_STRVAL_P(op2));
1484                                 if (CG(one_char_string)[xor]) {
1485                                         ZVAL_INTERNED_STR(result, CG(one_char_string)[xor]);
1486                                 } else {
1487                                         ZVAL_NEW_STR(result, zend_string_init((char *) &xor, 1, 0));
1488                                 }
1489                                 return SUCCESS;
1490                         }
1491                         longer = op1;
1492                         shorter = op2;
1493                 } else {
1494                         longer = op2;
1495                         shorter = op1;
1496                 }
1497 
1498                 str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
1499                 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1500                         ZSTR_VAL(str)[i] = Z_STRVAL_P(shorter)[i] ^ Z_STRVAL_P(longer)[i];
1501                 }
1502                 ZSTR_VAL(str)[i] = 0;
1503                 if (result==op1) {
1504                         zend_string_release(Z_STR_P(result));
1505                 }
1506                 ZVAL_NEW_STR(result, str);
1507                 return SUCCESS;
1508         }
1509 
1510         if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1511                 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function);
1512                 op1_lval = _zval_get_long_func(op1);
1513         } else {
1514                 op1_lval = Z_LVAL_P(op1);
1515         }
1516         if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1517                 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR);
1518                 op2_lval = _zval_get_long_func(op2);
1519         } else {
1520                 op2_lval = Z_LVAL_P(op2);
1521         }
1522 
1523         if (op1 == result) {
1524                 zval_dtor(result);
1525         }
1526         ZVAL_LONG(result, op1_lval ^ op2_lval);
1527         return SUCCESS;
1528 }
1529 /* }}} */
1530 
1531 ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op2) /* {{{ */
1532 {
1533         zend_long op1_lval, op2_lval;
1534 
1535         convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SL, shift_left_function);
1536 
1537         if (op1 == result) {
1538                 zval_dtor(result);
1539         }
1540 
1541         /* prevent wrapping quirkiness on some processors where << 64 + x == << x */
1542         if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
1543                 if (EXPECTED(op2_lval > 0)) {
1544                         ZVAL_LONG(result, 0);
1545                         return SUCCESS;
1546                 } else {
1547                         if (EG(current_execute_data) && !CG(in_compilation)) {
1548                                 zend_throw_exception_ex(zend_ce_arithmetic_error, 0, "Bit shift by negative number");
1549                         } else {
1550                                 zend_error_noreturn(E_ERROR, "Bit shift by negative number");
1551                         }
1552                         ZVAL_UNDEF(result);
1553                         return FAILURE;
1554                 }
1555         }
1556 
1557         ZVAL_LONG(result, op1_lval << op2_lval);
1558         return SUCCESS;
1559 }
1560 /* }}} */
1561 
1562 ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *op2) /* {{{ */
1563 {
1564         zend_long op1_lval, op2_lval;
1565 
1566         convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SR, shift_right_function);
1567 
1568         if (op1 == result) {
1569                 zval_dtor(result);
1570         }
1571 
1572         /* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */
1573         if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
1574                 if (EXPECTED(op2_lval > 0)) {
1575                         ZVAL_LONG(result, (op1_lval < 0) ? -1 : 0);
1576                         return SUCCESS;
1577                 } else {
1578                         if (EG(current_execute_data) && !CG(in_compilation)) {
1579                                 zend_throw_exception_ex(zend_ce_arithmetic_error, 0, "Bit shift by negative number");
1580                         } else {
1581                                 zend_error_noreturn(E_ERROR, "Bit shift by negative number");
1582                         }
1583                         ZVAL_UNDEF(result);
1584                         return FAILURE;
1585                 }
1586         }
1587 
1588         ZVAL_LONG(result, op1_lval >> op2_lval);
1589         return SUCCESS;
1590 }
1591 /* }}} */
1592 
1593 ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /* {{{ */
1594 {
1595         zval op1_copy, op2_copy;
1596         int use_copy1 = 0, use_copy2 = 0;
1597 
1598         do {
1599                 if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) {
1600                         if (Z_ISREF_P(op1)) {
1601                                 op1 = Z_REFVAL_P(op1);
1602                                 if (Z_TYPE_P(op1) == IS_STRING) break;
1603                         }
1604                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT, concat_function);
1605                         use_copy1 = zend_make_printable_zval(op1, &op1_copy);
1606                         if (use_copy1) {
1607                                 /* We have created a converted copy of op1. Therefore, op1 won't become the result so
1608                                  * we have to free it.
1609                                  */
1610                                 if (result == op1) {
1611                                         zval_dtor(op1);
1612                                         if (UNEXPECTED(op1 == op2)) {
1613                                                 op2 = &op1_copy;
1614                                         }
1615                                 }
1616                                 op1 = &op1_copy;
1617                         }
1618                 }
1619         } while (0);
1620         do {
1621                 if (UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) {
1622                         if (Z_ISREF_P(op2)) {
1623                                 op2 = Z_REFVAL_P(op2);
1624                                 if (Z_TYPE_P(op2) == IS_STRING) break;
1625                         }
1626                         ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_CONCAT);
1627                         use_copy2 = zend_make_printable_zval(op2, &op2_copy);
1628                         if (use_copy2) {
1629                                 op2 = &op2_copy;
1630                         }
1631                 }
1632         } while (0);
1633 
1634         {
1635                 size_t op1_len = Z_STRLEN_P(op1);
1636                 size_t op2_len = Z_STRLEN_P(op2);
1637                 size_t result_len = op1_len + op2_len;
1638                 zend_string *result_str;
1639 
1640                 if (UNEXPECTED(op1_len > SIZE_MAX - op2_len)) {
1641                         zend_throw_error(NULL, "String size overflow");
1642                         ZVAL_FALSE(result);
1643                         return FAILURE;
1644                 }
1645 
1646                 if (result == op1 && Z_REFCOUNTED_P(result)) {
1647                         /* special case, perform operations on result */
1648                         result_str = zend_string_extend(Z_STR_P(result), result_len, 0);
1649                 } else {
1650                         result_str = zend_string_alloc(result_len, 0);
1651                         memcpy(ZSTR_VAL(result_str), Z_STRVAL_P(op1), op1_len);
1652                 }
1653 
1654                 /* This has to happen first to account for the cases where result == op1 == op2 and
1655                  * the realloc is done. In this case this line will also update Z_STRVAL_P(op2) to
1656                  * point to the new string. The first op2_len bytes of result will still be the same. */
1657                 ZVAL_NEW_STR(result, result_str);
1658 
1659                 memcpy(ZSTR_VAL(result_str) + op1_len, Z_STRVAL_P(op2), op2_len);
1660                 ZSTR_VAL(result_str)[result_len] = '\0';
1661         }
1662 
1663         if (UNEXPECTED(use_copy1)) {
1664                 zval_dtor(op1);
1665         }
1666         if (UNEXPECTED(use_copy2)) {
1667                 zval_dtor(op2);
1668         }
1669         return SUCCESS;
1670 }
1671 /* }}} */
1672 
1673 ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, zend_bool case_insensitive) /* {{{ */
1674 {
1675         zend_string *str1 = zval_get_string(op1);
1676         zend_string *str2 = zval_get_string(op2);
1677         int ret;
1678 
1679         if (case_insensitive) {
1680                 ret = zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1));
1681         } else {
1682                 ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
1683         }
1684 
1685         zend_string_release(str1);
1686         zend_string_release(str2);
1687         return ret;
1688 }
1689 /* }}} */
1690 
1691 ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2) /* {{{ */
1692 {
1693         if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
1694             EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1695                 if (Z_STR_P(op1) == Z_STR_P(op2)) {
1696                         return 0;
1697                 } else {
1698                         return zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1699                 }
1700         } else {
1701                 zend_string *str1 = zval_get_string(op1);
1702                 zend_string *str2 = zval_get_string(op2);
1703                 int ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
1704 
1705                 zend_string_release(str1);
1706                 zend_string_release(str2);
1707                 return ret;
1708         }
1709 }
1710 /* }}} */
1711 
1712 ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2) /* {{{ */
1713 {
1714         if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
1715             EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1716                 if (Z_STR_P(op1) == Z_STR_P(op2)) {
1717                         return 0;
1718                 } else {
1719                         return zend_binary_strcasecmp_l(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1720                 }
1721         } else {
1722                 zend_string *str1 = zval_get_string(op1);
1723                 zend_string *str2 = zval_get_string(op2);
1724                 int ret = zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1));
1725 
1726                 zend_string_release(str1);
1727                 zend_string_release(str2);
1728                 return ret;
1729         }
1730 }
1731 /* }}} */
1732 
1733 #if HAVE_STRCOLL
1734 ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2) /* {{{ */
1735 {
1736         zend_string *str1 = zval_get_string(op1);
1737         zend_string *str2 = zval_get_string(op2);
1738         int ret = strcoll(ZSTR_VAL(str1), ZSTR_VAL(str2));
1739 
1740         zend_string_release(str1);
1741         zend_string_release(str2);
1742         return ret;
1743 }
1744 /* }}} */
1745 #endif
1746 
1747 ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2) /* {{{ */
1748 {
1749         double d1, d2;
1750 
1751         d1 = zval_get_double(op1);
1752         d2 = zval_get_double(op2);
1753 
1754         return ZEND_NORMALIZE_BOOL(d1 - d2);
1755 }
1756 /* }}} */
1757 
1758 static inline void zend_free_obj_get_result(zval *op) /* {{{ */
1759 {
1760         if (Z_REFCOUNTED_P(op)) {
1761                 if (Z_REFCOUNT_P(op) == 0) {
1762                         zval_dtor(op);
1763                 } else {
1764                         zval_ptr_dtor(op);
1765                 }
1766         }
1767 }
1768 /* }}} */
1769 
1770 static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
1771 {
1772         if (Z_TYPE_P(result) == IS_DOUBLE) {
1773                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1774         } else {
1775                 convert_to_long(result);
1776         }
1777 }
1778 /* }}} */
1779 
1780 ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
1781 {
1782         int ret;
1783         int converted = 0;
1784         zval op1_copy, op2_copy;
1785         zval *op_free, tmp_free;
1786 
1787         while (1) {
1788                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1789                         case TYPE_PAIR(IS_LONG, IS_LONG):
1790                                 ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1791                                 return SUCCESS;
1792 
1793                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1794                                 Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
1795                                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1796                                 return SUCCESS;
1797 
1798                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1799                                 Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
1800                                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1801                                 return SUCCESS;
1802 
1803                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1804                                 if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
1805                                         ZVAL_LONG(result, 0);
1806                                 } else {
1807                                         Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
1808                                         ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1809                                 }
1810                                 return SUCCESS;
1811 
1812                         case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
1813                                 ZVAL_LONG(result, zend_compare_arrays(op1, op2));
1814                                 return SUCCESS;
1815 
1816                         case TYPE_PAIR(IS_NULL, IS_NULL):
1817                         case TYPE_PAIR(IS_NULL, IS_FALSE):
1818                         case TYPE_PAIR(IS_FALSE, IS_NULL):
1819                         case TYPE_PAIR(IS_FALSE, IS_FALSE):
1820                         case TYPE_PAIR(IS_TRUE, IS_TRUE):
1821                                 ZVAL_LONG(result, 0);
1822                                 return SUCCESS;
1823 
1824                         case TYPE_PAIR(IS_NULL, IS_TRUE):
1825                                 ZVAL_LONG(result, -1);
1826                                 return SUCCESS;
1827 
1828                         case TYPE_PAIR(IS_TRUE, IS_NULL):
1829                                 ZVAL_LONG(result, 1);
1830                                 return SUCCESS;
1831 
1832                         case TYPE_PAIR(IS_STRING, IS_STRING):
1833                                 if (Z_STR_P(op1) == Z_STR_P(op2)) {
1834                                         ZVAL_LONG(result, 0);
1835                                         return SUCCESS;
1836                                 }
1837                                 ZVAL_LONG(result, zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)));
1838                                 return SUCCESS;
1839 
1840                         case TYPE_PAIR(IS_NULL, IS_STRING):
1841                                 ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1);
1842                                 return SUCCESS;
1843 
1844                         case TYPE_PAIR(IS_STRING, IS_NULL):
1845                                 ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1);
1846                                 return SUCCESS;
1847 
1848                         case TYPE_PAIR(IS_OBJECT, IS_NULL):
1849                                 ZVAL_LONG(result, 1);
1850                                 return SUCCESS;
1851 
1852                         case TYPE_PAIR(IS_NULL, IS_OBJECT):
1853                                 ZVAL_LONG(result, -1);
1854                                 return SUCCESS;
1855 
1856                         default:
1857                                 if (Z_ISREF_P(op1)) {
1858                                         op1 = Z_REFVAL_P(op1);
1859                                         continue;
1860                                 } else if (Z_ISREF_P(op2)) {
1861                                         op2 = Z_REFVAL_P(op2);
1862                                         continue;
1863                                 }
1864 
1865                                 if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
1866                                         ret = Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2);
1867                                         if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) {
1868                                                 convert_compare_result_to_long(result);
1869                                         }
1870                                         return ret;
1871                                 } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
1872                                         ret = Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2);
1873                                         if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) {
1874                                                 convert_compare_result_to_long(result);
1875                                         }
1876                                         return ret;
1877                                 }
1878 
1879                                 if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) {
1880                                         if (Z_OBJ_P(op1) == Z_OBJ_P(op2)) {
1881                                                 /* object handles are identical, apparently this is the same object */
1882                                                 ZVAL_LONG(result, 0);
1883                                                 return SUCCESS;
1884                                         }
1885                                         if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) {
1886                                                 ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2));
1887                                                 return SUCCESS;
1888                                         }
1889                                 }
1890                                 if (Z_TYPE_P(op1) == IS_OBJECT) {
1891                                         if (Z_OBJ_HT_P(op1)->get) {
1892                                                 zval rv;
1893                                                 op_free = Z_OBJ_HT_P(op1)->get(op1, &rv);
1894                                                 ret = compare_function(result, op_free, op2);
1895                                                 zend_free_obj_get_result(op_free);
1896                                                 return ret;
1897                                         } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
1898                                                 ZVAL_UNDEF(&tmp_free);
1899                                                 if (Z_OBJ_HT_P(op1)->cast_object(op1, &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) {
1900                                                         ZVAL_LONG(result, 1);
1901                                                         zend_free_obj_get_result(&tmp_free);
1902                                                         return SUCCESS;
1903                                                 }
1904                                                 ret = compare_function(result, &tmp_free, op2);
1905                                                 zend_free_obj_get_result(&tmp_free);
1906                                                 return ret;
1907                                         }
1908                                 }
1909                                 if (Z_TYPE_P(op2) == IS_OBJECT) {
1910                                         if (Z_OBJ_HT_P(op2)->get) {
1911                                                 zval rv;
1912                                                 op_free = Z_OBJ_HT_P(op2)->get(op2, &rv);
1913                                                 ret = compare_function(result, op1, op_free);
1914                                                 zend_free_obj_get_result(op_free);
1915                                                 return ret;
1916                                         } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
1917                                                 ZVAL_UNDEF(&tmp_free);
1918                                                 if (Z_OBJ_HT_P(op2)->cast_object(op2, &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) {
1919                                                         ZVAL_LONG(result, -1);
1920                                                         zend_free_obj_get_result(&tmp_free);
1921                                                         return SUCCESS;
1922                                                 }
1923                                                 ret = compare_function(result, op1, &tmp_free);
1924                                                 zend_free_obj_get_result(&tmp_free);
1925                                                 return ret;
1926                                         } else if (Z_TYPE_P(op1) == IS_OBJECT) {
1927                                                 ZVAL_LONG(result, 1);
1928                                                 return SUCCESS;
1929                                         }
1930                                 }
1931                                 if (!converted) {
1932                                         if (Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op1) == IS_FALSE) {
1933                                                 ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0);
1934                                                 return SUCCESS;
1935                                         } else if (Z_TYPE_P(op2) == IS_NULL || Z_TYPE_P(op2) == IS_FALSE) {
1936                                                 ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0);
1937                                                 return SUCCESS;
1938                                         } else if (Z_TYPE_P(op1) == IS_TRUE) {
1939                                                 ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1);
1940                                                 return SUCCESS;
1941                                         } else if (Z_TYPE_P(op2) == IS_TRUE) {
1942                                                 ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1);
1943                                                 return SUCCESS;
1944                                         } else {
1945                                                 zendi_convert_scalar_to_number(op1, op1_copy, result);
1946                                                 zendi_convert_scalar_to_number(op2, op2_copy, result);
1947                                                 converted = 1;
1948                                         }
1949                                 } else if (Z_TYPE_P(op1)==IS_ARRAY) {
1950                                         ZVAL_LONG(result, 1);
1951                                         return SUCCESS;
1952                                 } else if (Z_TYPE_P(op2)==IS_ARRAY) {
1953                                         ZVAL_LONG(result, -1);
1954                                         return SUCCESS;
1955                                 } else if (Z_TYPE_P(op1)==IS_OBJECT) {
1956                                         ZVAL_LONG(result, 1);
1957                                         return SUCCESS;
1958                                 } else if (Z_TYPE_P(op2)==IS_OBJECT) {
1959                                         ZVAL_LONG(result, -1);
1960                                         return SUCCESS;
1961                                 } else {
1962                                         ZVAL_LONG(result, 0);
1963                                         return FAILURE;
1964                                 }
1965                 }
1966         }
1967 }
1968 /* }}} */
1969 
1970 static int hash_zval_identical_function(zval *z1, zval *z2) /* {{{ */
1971 {
1972         zval result;
1973 
1974         /* is_identical_function() returns 1 in case of identity and 0 in case
1975          * of a difference;
1976          * whereas this comparison function is expected to return 0 on identity,
1977          * and non zero otherwise.
1978          */
1979         ZVAL_DEREF(z1);
1980         ZVAL_DEREF(z2);
1981         if (is_identical_function(&result, z1, z2)==FAILURE) {
1982                 return 1;
1983         }
1984         return Z_TYPE(result) != IS_TRUE;
1985 }
1986 /* }}} */
1987 
1988 ZEND_API int ZEND_FASTCALL zend_is_identical(zval *op1, zval *op2) /* {{{ */
1989 {
1990         if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
1991                 return 0;
1992         }
1993         switch (Z_TYPE_P(op1)) {
1994                 case IS_NULL:
1995                 case IS_FALSE:
1996                 case IS_TRUE:
1997                         return 1;
1998                 case IS_LONG:
1999                         return (Z_LVAL_P(op1) == Z_LVAL_P(op2));
2000                 case IS_RESOURCE:
2001                         return (Z_RES_P(op1) == Z_RES_P(op2));
2002                 case IS_DOUBLE:
2003                         return (Z_DVAL_P(op1) == Z_DVAL_P(op2));
2004                 case IS_STRING:
2005                         return (Z_STR_P(op1) == Z_STR_P(op2) ||
2006                                 (Z_STRLEN_P(op1) == Z_STRLEN_P(op2) &&
2007                                  memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0));
2008                 case IS_ARRAY:
2009                         return (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) ||
2010                                 zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1) == 0);
2011                 case IS_OBJECT:
2012                         return (Z_OBJ_P(op1) == Z_OBJ_P(op2) && Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2));
2013                 default:
2014                         return 0;
2015         }
2016 }
2017 /* }}} */
2018 
2019 ZEND_API int ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */
2020 {
2021         ZVAL_BOOL(result, zend_is_identical(op1, op2));
2022         return SUCCESS;
2023 }
2024 /* }}} */
2025 
2026 ZEND_API int ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */
2027 {
2028         ZVAL_BOOL(result, !zend_is_identical(op1, op2));
2029         return SUCCESS;
2030 }
2031 /* }}} */
2032 
2033 ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2034 {
2035         if (compare_function(result, op1, op2) == FAILURE) {
2036                 return FAILURE;
2037         }
2038         ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
2039         return SUCCESS;
2040 }
2041 /* }}} */
2042 
2043 ZEND_API int ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2044 {
2045         if (compare_function(result, op1, op2) == FAILURE) {
2046                 return FAILURE;
2047         }
2048         ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
2049         return SUCCESS;
2050 }
2051 /* }}} */
2052 
2053 ZEND_API int ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2) /* {{{ */
2054 {
2055         if (compare_function(result, op1, op2) == FAILURE) {
2056                 return FAILURE;
2057         }
2058         ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
2059         return SUCCESS;
2060 }
2061 /* }}} */
2062 
2063 ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2064 {
2065         if (compare_function(result, op1, op2) == FAILURE) {
2066                 return FAILURE;
2067         }
2068         ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
2069         return SUCCESS;
2070 }
2071 /* }}} */
2072 
2073 static zend_bool ZEND_FASTCALL instanceof_interface_only(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2074 {
2075         uint32_t i;
2076 
2077         for (i = 0; i < instance_ce->num_interfaces; i++) {
2078                 if (instanceof_interface_only(instance_ce->interfaces[i], ce)) {
2079                         return 1;
2080                 }
2081         }
2082         return 0;
2083 }
2084 /* }}} */
2085 
2086 static zend_always_inline zend_bool instanceof_class(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2087 {
2088         while (instance_ce) {
2089                 if (instance_ce == ce) {
2090                         return 1;
2091                 }
2092                 instance_ce = instance_ce->parent;
2093         }
2094         return 0;
2095 }
2096 /* }}} */
2097 
2098 static zend_bool ZEND_FASTCALL instanceof_interface(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2099 {
2100         uint32_t i;
2101 
2102         for (i = 0; i < instance_ce->num_interfaces; i++) {
2103                 if (instanceof_interface(instance_ce->interfaces[i], ce)) {
2104                         return 1;
2105                 }
2106         }
2107         return instanceof_class(instance_ce, ce);
2108 }
2109 /* }}} */
2110 
2111 ZEND_API zend_bool ZEND_FASTCALL instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only) /* {{{ */
2112 {
2113         if (ce->ce_flags & ZEND_ACC_INTERFACE) {
2114                 if (!interfaces_only) {
2115                         if (instanceof_interface_only(instance_ce, ce)) {
2116                                 return 1;
2117                         }
2118                 } else {
2119                         return instanceof_interface(instance_ce, ce);
2120                 }
2121         }
2122         if (!interfaces_only) {
2123                 return instanceof_class(instance_ce, ce);
2124         }
2125         return 0;
2126 }
2127 /* }}} */
2128 
2129 ZEND_API zend_bool ZEND_FASTCALL instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2130 {
2131         if (ce->ce_flags & ZEND_ACC_INTERFACE) {
2132                 return instanceof_interface(instance_ce, ce);
2133         } else {
2134                 return instanceof_class(instance_ce, ce);
2135         }
2136 }
2137 /* }}} */
2138 
2139 #define LOWER_CASE 1
2140 #define UPPER_CASE 2
2141 #define NUMERIC 3
2142 
2143 static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */
2144 {
2145         int carry=0;
2146         size_t pos=Z_STRLEN_P(str)-1;
2147         char *s;
2148         zend_string *t;
2149         int last=0; /* Shut up the compiler warning */
2150         int ch;
2151 
2152         if (Z_STRLEN_P(str) == 0) {
2153                 zend_string_release(Z_STR_P(str));
2154                 if (CG(one_char_string)['1']) {
2155                         ZVAL_INTERNED_STR(str, CG(one_char_string)['1']);
2156                 } else {
2157                         Z_STR_P(str) = zend_string_init("1", sizeof("1")-1, 0);
2158                         Z_TYPE_INFO_P(str) = IS_STRING_EX;
2159                 }
2160                 return;
2161         }
2162 
2163         if (!Z_REFCOUNTED_P(str)) {
2164                 Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2165                 Z_TYPE_INFO_P(str) = IS_STRING_EX;
2166         } else if (Z_REFCOUNT_P(str) > 1) {
2167                 Z_DELREF_P(str);
2168                 Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2169         } else {
2170                 zend_string_forget_hash_val(Z_STR_P(str));
2171         }
2172         s = Z_STRVAL_P(str);
2173 
2174         do {
2175                 ch = s[pos];
2176                 if (ch >= 'a' && ch <= 'z') {
2177                         if (ch == 'z') {
2178                                 s[pos] = 'a';
2179                                 carry=1;
2180                         } else {
2181                                 s[pos]++;
2182                                 carry=0;
2183                         }
2184                         last=LOWER_CASE;
2185                 } else if (ch >= 'A' && ch <= 'Z') {
2186                         if (ch == 'Z') {
2187                                 s[pos] = 'A';
2188                                 carry=1;
2189                         } else {
2190                                 s[pos]++;
2191                                 carry=0;
2192                         }
2193                         last=UPPER_CASE;
2194                 } else if (ch >= '0' && ch <= '9') {
2195                         if (ch == '9') {
2196                                 s[pos] = '0';
2197                                 carry=1;
2198                         } else {
2199                                 s[pos]++;
2200                                 carry=0;
2201                         }
2202                         last = NUMERIC;
2203                 } else {
2204                         carry=0;
2205                         break;
2206                 }
2207                 if (carry == 0) {
2208                         break;
2209                 }
2210         } while (pos-- > 0);
2211 
2212         if (carry) {
2213                 t = zend_string_alloc(Z_STRLEN_P(str)+1, 0);
2214                 memcpy(ZSTR_VAL(t) + 1, Z_STRVAL_P(str), Z_STRLEN_P(str));
2215                 ZSTR_VAL(t)[Z_STRLEN_P(str) + 1] = '\0';
2216                 switch (last) {
2217                         case NUMERIC:
2218                                 ZSTR_VAL(t)[0] = '1';
2219                                 break;
2220                         case UPPER_CASE:
2221                                 ZSTR_VAL(t)[0] = 'A';
2222                                 break;
2223                         case LOWER_CASE:
2224                                 ZSTR_VAL(t)[0] = 'a';
2225                                 break;
2226                 }
2227                 zend_string_free(Z_STR_P(str));
2228                 ZVAL_NEW_STR(str, t);
2229         }
2230 }
2231 /* }}} */
2232 
2233 ZEND_API int ZEND_FASTCALL increment_function(zval *op1) /* {{{ */
2234 {
2235 try_again:
2236         switch (Z_TYPE_P(op1)) {
2237                 case IS_LONG:
2238                         fast_long_increment_function(op1);
2239                         break;
2240                 case IS_DOUBLE:
2241                         Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
2242                         break;
2243                 case IS_NULL:
2244                         ZVAL_LONG(op1, 1);
2245                         break;
2246                 case IS_STRING: {
2247                                 zend_long lval;
2248                                 double dval;
2249 
2250                                 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2251                                         case IS_LONG:
2252                                                 zend_string_release(Z_STR_P(op1));
2253                                                 if (lval == ZEND_LONG_MAX) {
2254                                                         /* switch to double */
2255                                                         double d = (double)lval;
2256                                                         ZVAL_DOUBLE(op1, d+1);
2257                                                 } else {
2258                                                         ZVAL_LONG(op1, lval+1);
2259                                                 }
2260                                                 break;
2261                                         case IS_DOUBLE:
2262                                                 zend_string_release(Z_STR_P(op1));
2263                                                 ZVAL_DOUBLE(op1, dval+1);
2264                                                 break;
2265                                         default:
2266                                                 /* Perl style string increment */
2267                                                 increment_string(op1);
2268                                                 break;
2269                                 }
2270                         }
2271                         break;
2272                 case IS_OBJECT:
2273                         if (Z_OBJ_HANDLER_P(op1, get)
2274                            && Z_OBJ_HANDLER_P(op1, set)) {
2275                                 /* proxy object */
2276                                 zval rv;
2277                                 zval *val;
2278 
2279                                 val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv);
2280                                 Z_TRY_ADDREF_P(val);
2281                                 increment_function(val);
2282                                 Z_OBJ_HANDLER_P(op1, set)(op1, val);
2283                                 zval_ptr_dtor(val);
2284                         } else if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2285                                 zval op2;
2286                                 int res;
2287 
2288                                 ZVAL_LONG(&op2, 1);
2289                                 res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_ADD, op1, op1, &op2);
2290                                 zval_ptr_dtor(&op2);
2291 
2292                                 return res;
2293                         }
2294                         return FAILURE;
2295                 case IS_REFERENCE:
2296                         op1 = Z_REFVAL_P(op1);
2297                         goto try_again;
2298                 default:
2299                         return FAILURE;
2300         }
2301         return SUCCESS;
2302 }
2303 /* }}} */
2304 
2305 ZEND_API int ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */
2306 {
2307         zend_long lval;
2308         double dval;
2309 
2310 try_again:
2311         switch (Z_TYPE_P(op1)) {
2312                 case IS_LONG:
2313                         fast_long_decrement_function(op1);
2314                         break;
2315                 case IS_DOUBLE:
2316                         Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
2317                         break;
2318                 case IS_STRING:         /* Like perl we only support string increment */
2319                         if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
2320                                 zend_string_release(Z_STR_P(op1));
2321                                 ZVAL_LONG(op1, -1);
2322                                 break;
2323                         }
2324                         switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2325                                 case IS_LONG:
2326                                         zend_string_release(Z_STR_P(op1));
2327                                         if (lval == ZEND_LONG_MIN) {
2328                                                 double d = (double)lval;
2329                                                 ZVAL_DOUBLE(op1, d-1);
2330                                         } else {
2331                                                 ZVAL_LONG(op1, lval-1);
2332                                         }
2333                                         break;
2334                                 case IS_DOUBLE:
2335                                         zend_string_release(Z_STR_P(op1));
2336                                         ZVAL_DOUBLE(op1, dval - 1);
2337                                         break;
2338                         }
2339                         break;
2340                 case IS_OBJECT:
2341                         if (Z_OBJ_HANDLER_P(op1, get)
2342                            && Z_OBJ_HANDLER_P(op1, set)) {
2343                                 /* proxy object */
2344                                 zval rv;
2345                                 zval *val;
2346 
2347                                 val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv);
2348                                 Z_TRY_ADDREF_P(val);
2349                                 decrement_function(val);
2350                                 Z_OBJ_HANDLER_P(op1, set)(op1, val);
2351                                 zval_ptr_dtor(val);
2352                         } else if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2353                                 zval op2;
2354                                 int res;
2355 
2356                                 ZVAL_LONG(&op2, 1);
2357                                 res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_SUB, op1, op1, &op2);
2358                                 zval_ptr_dtor(&op2);
2359 
2360                                 return res;
2361                         }
2362                         return FAILURE;
2363                 case IS_REFERENCE:
2364                         op1 = Z_REFVAL_P(op1);
2365                         goto try_again;
2366                 default:
2367                         return FAILURE;
2368         }
2369 
2370         return SUCCESS;
2371 }
2372 /* }}} */
2373 
2374 ZEND_API int ZEND_FASTCALL zend_is_true(zval *op) /* {{{ */
2375 {
2376         return i_zend_is_true(op);
2377 }
2378 /* }}} */
2379 
2380 ZEND_API int ZEND_FASTCALL zend_object_is_true(zval *op) /* {{{ */
2381 {
2382         if (Z_OBJ_HT_P(op)->cast_object) {
2383                 zval tmp;
2384                 if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL) == SUCCESS) {
2385                         return Z_TYPE(tmp) == IS_TRUE;
2386                 }
2387                 zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", ZSTR_VAL(Z_OBJ_P(op)->ce->name));
2388         } else if (Z_OBJ_HT_P(op)->get) {
2389                 int result;
2390                 zval rv;
2391                 zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv);
2392 
2393                 if (Z_TYPE_P(tmp) != IS_OBJECT) {
2394                         /* for safety - avoid loop */
2395                         result = i_zend_is_true(tmp);
2396                         zval_ptr_dtor(tmp);
2397                         return result;
2398                 }
2399         }
2400         return 1;
2401 }
2402 /* }}} */
2403 
2404 #ifdef ZEND_USE_TOLOWER_L
2405 ZEND_API void zend_update_current_locale(void) /* {{{ */
2406 {
2407         current_locale = _get_current_locale();
2408 }
2409 /* }}} */
2410 #endif
2411 
2412 ZEND_API char* ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length) /* {{{ */
2413 {
2414         register unsigned char *str = (unsigned char*)source;
2415         register unsigned char *result = (unsigned char*)dest;
2416         register unsigned char *end = str + length;
2417 
2418         while (str < end) {
2419                 *result++ = zend_tolower_ascii(*str++);
2420         }
2421         *result = '\0';
2422 
2423         return dest;
2424 }
2425 /* }}} */
2426 
2427 ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length) /* {{{ */
2428 {
2429         return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
2430 }
2431 /* }}} */
2432 
2433 ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length) /* {{{ */
2434 {
2435         register unsigned char *p = (unsigned char*)str;
2436         register unsigned char *end = p + length;
2437 
2438         while (p < end) {
2439                 *p = zend_tolower_ascii(*p);
2440                 p++;
2441         }
2442 }
2443 /* }}} */
2444 
2445 ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length) /* {{{ */
2446 {
2447         register const unsigned char *p = (const unsigned char*)source;
2448         register const unsigned char *end = p + length;
2449 
2450         while (p < end) {
2451                 if (*p != zend_tolower_ascii(*p)) {
2452                         char *res = (char*)emalloc(length + 1);
2453                         register unsigned char *r;
2454 
2455                         if (p != (const unsigned char*)source) {
2456                                 memcpy(res, source, p - (const unsigned char*)source);
2457                         }
2458                         r = (unsigned char*)p + (res - source);
2459                         while (p < end) {
2460                                 *r = zend_tolower_ascii(*p);
2461                                 p++;
2462                                 r++;
2463                         }
2464                         *r = '\0';
2465                         return res;
2466                 }
2467                 p++;
2468         }
2469         return NULL;
2470 }
2471 /* }}} */
2472 
2473 ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower(zend_string *str) /* {{{ */
2474 {
2475         register unsigned char *p = (unsigned char*)ZSTR_VAL(str);
2476         register unsigned char *end = p + ZSTR_LEN(str);
2477 
2478         while (p < end) {
2479                 if (*p != zend_tolower_ascii(*p)) {
2480                         zend_string *res = zend_string_alloc(ZSTR_LEN(str), 0);
2481                         register unsigned char *r;
2482 
2483                         if (p != (unsigned char*)ZSTR_VAL(str)) {
2484                                 memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*)ZSTR_VAL(str));
2485                         }
2486                         r = p + (ZSTR_VAL(res) - ZSTR_VAL(str));
2487                         while (p < end) {
2488                                 *r = zend_tolower_ascii(*p);
2489                                 p++;
2490                                 r++;
2491                         }
2492                         *r = '\0';
2493                         return res;
2494                 }
2495                 p++;
2496         }
2497         return zend_string_copy(str);
2498 }
2499 /* }}} */
2500 
2501 ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2502 {
2503         int retval;
2504 
2505         if (s1 == s2) {
2506                 return 0;
2507         }
2508         retval = memcmp(s1, s2, MIN(len1, len2));
2509         if (!retval) {
2510                 return (int)(len1 - len2);
2511         } else {
2512                 return retval;
2513         }
2514 }
2515 /* }}} */
2516 
2517 ZEND_API int ZEND_FASTCALL zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2518 {
2519         int retval;
2520 
2521         if (s1 == s2) {
2522                 return 0;
2523         }
2524         retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
2525         if (!retval) {
2526                 return (int)(MIN(length, len1) - MIN(length, len2));
2527         } else {
2528                 return retval;
2529         }
2530 }
2531 /* }}} */
2532 
2533 ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2534 {
2535         size_t len;
2536         int c1, c2;
2537 
2538         if (s1 == s2) {
2539                 return 0;
2540         }
2541 
2542         len = MIN(len1, len2);
2543         while (len--) {
2544                 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2545                 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2546                 if (c1 != c2) {
2547                         return c1 - c2;
2548                 }
2549         }
2550 
2551         return (int)(len1 - len2);
2552 }
2553 /* }}} */
2554 
2555 ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2556 {
2557         size_t len;
2558         int c1, c2;
2559 
2560         if (s1 == s2) {
2561                 return 0;
2562         }
2563         len = MIN(length, MIN(len1, len2));
2564         while (len--) {
2565                 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2566                 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2567                 if (c1 != c2) {
2568                         return c1 - c2;
2569                 }
2570         }
2571 
2572         return (int)(MIN(length, len1) - MIN(length, len2));
2573 }
2574 /* }}} */
2575 
2576 ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2577 {
2578         size_t len;
2579         int c1, c2;
2580 
2581         if (s1 == s2) {
2582                 return 0;
2583         }
2584 
2585         len = MIN(len1, len2);
2586         while (len--) {
2587                 c1 = zend_tolower((int)*(unsigned char *)s1++);
2588                 c2 = zend_tolower((int)*(unsigned char *)s2++);
2589                 if (c1 != c2) {
2590                         return c1 - c2;
2591                 }
2592         }
2593 
2594         return (int)(len1 - len2);
2595 }
2596 /* }}} */
2597 
2598 ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2599 {
2600         size_t len;
2601         int c1, c2;
2602 
2603         if (s1 == s2) {
2604                 return 0;
2605         }
2606         len = MIN(length, MIN(len1, len2));
2607         while (len--) {
2608                 c1 = zend_tolower((int)*(unsigned char *)s1++);
2609                 c2 = zend_tolower((int)*(unsigned char *)s2++);
2610                 if (c1 != c2) {
2611                         return c1 - c2;
2612                 }
2613         }
2614 
2615         return (int)(MIN(length, len1) - MIN(length, len2));
2616 }
2617 /* }}} */
2618 
2619 ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
2620 {
2621         return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2622 }
2623 /* }}} */
2624 
2625 ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2626 {
2627         return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2628 }
2629 /* }}} */
2630 
2631 ZEND_API int ZEND_FASTCALL zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */
2632 {
2633         return zend_binary_strcasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2634 }
2635 /* }}} */
2636 
2637 ZEND_API int ZEND_FASTCALL zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2638 {
2639         return zend_binary_strncasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2640 }
2641 /* }}} */
2642 
2643 ZEND_API zend_long ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2) /* {{{ */
2644 {
2645         int ret1, ret2;
2646         int oflow1, oflow2;
2647         zend_long lval1 = 0, lval2 = 0;
2648         double dval1 = 0.0, dval2 = 0.0;
2649 
2650         if ((ret1 = is_numeric_string_ex(s1->val, s1->len, &lval1, &dval1, 0, &oflow1)) &&
2651                 (ret2 = is_numeric_string_ex(s2->val, s2->len, &lval2, &dval2, 0, &oflow2))) {
2652 #if ZEND_ULONG_MAX == 0xFFFFFFFF
2653                 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
2654                         ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
2655                         || (oflow1 == -1 && dval1 < -9007199254740991.))) {
2656 #else
2657                 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
2658 #endif
2659                         /* both values are integers overflown to the same side, and the
2660                          * double comparison may have resulted in crucial accuracy lost */
2661                         goto string_cmp;
2662                 }
2663                 if ((ret1 == IS_DOUBLE) || (ret2 == IS_DOUBLE)) {
2664                         if (ret1 != IS_DOUBLE) {
2665                                 if (oflow2) {
2666                                         /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
2667                                         return -1 * oflow2;
2668                                 }
2669                                 dval1 = (double) lval1;
2670                         } else if (ret2 != IS_DOUBLE) {
2671                                 if (oflow1) {
2672                                         return oflow1;
2673                                 }
2674                                 dval2 = (double) lval2;
2675                         } else if (dval1 == dval2 && !zend_finite(dval1)) {
2676                                 /* Both values overflowed and have the same sign,
2677                                  * so a numeric comparison would be inaccurate */
2678                                 goto string_cmp;
2679                         }
2680                         dval1 = dval1 - dval2;
2681                         return ZEND_NORMALIZE_BOOL(dval1);
2682                 } else { /* they both have to be long's */
2683                         return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0);
2684                 }
2685         } else {
2686                 int strcmp_ret;
2687 string_cmp:
2688                 strcmp_ret = zend_binary_strcmp(s1->val, s1->len, s2->val, s2->len);
2689                 return ZEND_NORMALIZE_BOOL(strcmp_ret);
2690         }
2691 }
2692 /* }}} */
2693 
2694 static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */
2695 {
2696         zval result;
2697 
2698         if (compare_function(&result, z1, z2)==FAILURE) {
2699                 return 1;
2700         }
2701         return Z_LVAL(result);
2702 }
2703 /* }}} */
2704 
2705 ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable *ht2) /* {{{ */
2706 {
2707         return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0);
2708 }
2709 /* }}} */
2710 
2711 ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2) /* {{{ */
2712 {
2713         return zend_compare_symbol_tables(Z_ARRVAL_P(a1), Z_ARRVAL_P(a2));
2714 }
2715 /* }}} */
2716 
2717 ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2) /* {{{ */
2718 {
2719         if (Z_OBJ_P(o1) == Z_OBJ_P(o2)) {
2720                 return 0;
2721         }
2722 
2723         if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2724                 return 1;
2725         } else {
2726                 return Z_OBJ_HT_P(o1)->compare_objects(o1, o2);
2727         }
2728 }
2729 /* }}} */
2730 
2731 ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
2732 {
2733         zend_string *str;
2734 
2735         str = zend_strpprintf(0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
2736         ZVAL_NEW_STR(op, str);
2737 }
2738 /* }}} */
2739 
2740 ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num) /* {{{ */
2741 {
2742         char buf[MAX_LENGTH_OF_LONG + 1];
2743         char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
2744         return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
2745 }
2746 /* }}} */
2747 
2748 ZEND_API zend_uchar ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval) /* {{{ */ {
2749     return is_numeric_string_ex(ZSTR_VAL(str), ZSTR_LEN(str), lval, dval, -1, NULL);
2750 }
2751 /* }}} */
2752 
2753 ZEND_API zend_uchar ZEND_FASTCALL _is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info) /* {{{ */
2754 {
2755         const char *ptr;
2756         int digits = 0, dp_or_e = 0;
2757         double local_dval = 0.0;
2758         zend_uchar type;
2759         zend_long tmp_lval = 0;
2760         int neg = 0;
2761 
2762         if (!length) {
2763                 return 0;
2764         }
2765 
2766         if (oflow_info != NULL) {
2767                 *oflow_info = 0;
2768         }
2769 
2770         /* Skip any whitespace
2771          * This is much faster than the isspace() function */
2772         while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
2773                 str++;
2774                 length--;
2775         }
2776         ptr = str;
2777 
2778         if (*ptr == '-') {
2779                 neg = 1;
2780                 ptr++;
2781         } else if (*ptr == '+') {
2782                 ptr++;
2783         }
2784 
2785         if (ZEND_IS_DIGIT(*ptr)) {
2786                 /* Skip any leading 0s */
2787                 while (*ptr == '0') {
2788                         ptr++;
2789                 }
2790 
2791                 /* Count the number of digits. If a decimal point/exponent is found,
2792                  * it's a double. Otherwise, if there's a dval or no need to check for
2793                  * a full match, stop when there are too many digits for a long */
2794                 for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {
2795 check_digits:
2796                         if (ZEND_IS_DIGIT(*ptr)) {
2797                                 tmp_lval = tmp_lval * 10 + (*ptr) - '0';
2798                                 continue;
2799                         } else if (*ptr == '.' && dp_or_e < 1) {
2800                                 goto process_double;
2801                         } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
2802                                 const char *e = ptr + 1;
2803 
2804                                 if (*e == '-' || *e == '+') {
2805                                         ptr = e++;
2806                                 }
2807                                 if (ZEND_IS_DIGIT(*e)) {
2808                                         goto process_double;
2809                                 }
2810                         }
2811 
2812                         break;
2813                 }
2814 
2815                 if (digits >= MAX_LENGTH_OF_LONG) {
2816                         if (oflow_info != NULL) {
2817                                 *oflow_info = *str == '-' ? -1 : 1;
2818                         }
2819                         dp_or_e = -1;
2820                         goto process_double;
2821                 }
2822         } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
2823 process_double:
2824                 type = IS_DOUBLE;
2825 
2826                 /* If there's a dval, do the conversion; else continue checking
2827                  * the digits if we need to check for a full match */
2828                 if (dval) {
2829                         local_dval = zend_strtod(str, &ptr);
2830                 } else if (allow_errors != 1 && dp_or_e != -1) {
2831                         dp_or_e = (*ptr++ == '.') ? 1 : 2;
2832                         goto check_digits;
2833                 }
2834         } else {
2835                 return 0;
2836         }
2837 
2838         if (ptr != str + length) {
2839                 if (!allow_errors) {
2840                         return 0;
2841                 }
2842                 if (allow_errors == -1) {
2843                         zend_error(E_NOTICE, "A non well formed numeric value encountered");
2844                 }
2845         }
2846 
2847         if (type == IS_LONG) {
2848                 if (digits == MAX_LENGTH_OF_LONG - 1) {
2849                         int cmp = strcmp(&ptr[-digits], long_min_digits);
2850 
2851                         if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
2852                                 if (dval) {
2853                                         *dval = zend_strtod(str, NULL);
2854                                 }
2855                                 if (oflow_info != NULL) {
2856                                         *oflow_info = *str == '-' ? -1 : 1;
2857                                 }
2858 
2859                                 return IS_DOUBLE;
2860                         }
2861                 }
2862 
2863                 if (lval) {
2864                         if (neg) {
2865                                 tmp_lval = -tmp_lval;
2866                         }
2867                         *lval = tmp_lval;
2868                 }
2869 
2870                 return IS_LONG;
2871         } else {
2872                 if (dval) {
2873                         *dval = local_dval;
2874                 }
2875 
2876                 return IS_DOUBLE;
2877         }
2878 }
2879 /* }}} */
2880 
2881 /* 
2882  * String matching - Sunday algorithm
2883  * http://www.iti.fh-flensburg.de/lang/algorithmen/pattern/sundayen.htm
2884  */
2885 static zend_always_inline void zend_memnstr_ex_pre(unsigned int td[], const char *needle, size_t needle_len, int reverse) /* {{{ */ {
2886         int i;
2887 
2888         for (i = 0; i < 256; i++) {
2889                 td[i] = needle_len + 1;
2890         }
2891 
2892         if (reverse) {
2893                 for (i = needle_len - 1; i >= 0; i--) {
2894                         td[(unsigned char)needle[i]] = i + 1;
2895                 }
2896         } else {
2897                 for (i = 0; i < needle_len; i++) {
2898                         td[(unsigned char)needle[i]] = (int)needle_len - i;
2899                 }
2900         }
2901 }
2902 /* }}} */
2903 
2904 ZEND_API const char* ZEND_FASTCALL zend_memnstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
2905 {
2906         unsigned int td[256];
2907         register size_t i;
2908         register const char *p;
2909 
2910         if (needle_len == 0 || (end - haystack) == 0) {
2911                 return NULL;
2912         }
2913 
2914         zend_memnstr_ex_pre(td, needle, needle_len, 0);
2915 
2916         p = haystack;
2917         end -= needle_len;
2918 
2919         while (p <= end) {
2920                 for (i = 0; i < needle_len; i++) {
2921                         if (needle[i] != p[i]) {
2922                                 break;
2923                         }
2924                 }
2925                 if (i == needle_len) {
2926                         return p;
2927                 }
2928                 p += td[(unsigned char)(p[needle_len])];
2929         }
2930 
2931         return NULL;
2932 }
2933 /* }}} */
2934 
2935 ZEND_API const char* ZEND_FASTCALL zend_memnrstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
2936 {
2937         unsigned int td[256];
2938         register size_t i;
2939         register const char *p;
2940 
2941         if (needle_len == 0 || (end - haystack) == 0) {
2942                 return NULL;
2943         }
2944 
2945         zend_memnstr_ex_pre(td, needle, needle_len, 1);
2946 
2947         p = end;
2948         p -= needle_len;
2949 
2950         while (p >= haystack) {
2951                 for (i = 0; i < needle_len; i++) {
2952                         if (needle[i] != p[i]) {
2953                                 break;
2954                         }
2955                 }
2956 
2957                 if (i == needle_len) {
2958                         return (const char *)p;
2959                 }
2960                 
2961                 if (UNEXPECTED(p == haystack)) {
2962                         return NULL;
2963                 }
2964 
2965                 p -= td[(unsigned char)(p[-1])];
2966         }
2967 
2968         return NULL;
2969 }
2970 /* }}} */
2971 
2972 #if !ZEND_DVAL_TO_LVAL_CAST_OK
2973 # if SIZEOF_ZEND_LONG == 4
2974 ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d)
2975 {
2976         double  two_pow_32 = pow(2., 32.),
2977                         dmod;
2978 
2979         dmod = fmod(d, two_pow_32);
2980         if (dmod < 0) {
2981                 /* we're going to make this number positive; call ceil()
2982                  * to simulate rounding towards 0 of the negative number */
2983                 dmod = ceil(dmod);// + two_pow_32;
2984         }
2985         return (zend_long)(zend_ulong)dmod;
2986 }
2987 #else
2988 ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d)
2989 {
2990         double  two_pow_64 = pow(2., 64.),
2991                         dmod;
2992 
2993         dmod = fmod(d, two_pow_64);
2994         if (dmod < 0) {
2995                 /* no need to call ceil; original double must have had no
2996                  * fractional part, hence dmod does not have one either */
2997                 dmod += two_pow_64;
2998         }
2999         return (zend_long)(zend_ulong)dmod;
3000 }
3001 #endif
3002 #endif
3003 
3004 /*
3005  * Local variables:
3006  * tab-width: 4
3007  * c-basic-offset: 4
3008  * indent-tabs-mode: t
3009  * End:
3010  */

/* [<][>][^][v][top][bottom][index][help] */