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_string_to_double
  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. add_function
  19. sub_function
  20. mul_function
  21. pow_function
  22. div_function
  23. mod_function
  24. boolean_xor_function
  25. boolean_not_function
  26. bitwise_not_function
  27. bitwise_or_function
  28. bitwise_and_function
  29. bitwise_xor_function
  30. shift_left_function
  31. shift_right_function
  32. add_char_to_string
  33. add_string_to_string
  34. concat_function
  35. string_compare_function_ex
  36. string_compare_function
  37. string_case_compare_function
  38. string_locale_compare_function
  39. numeric_compare_function
  40. zend_free_obj_get_result
  41. compare_function
  42. hash_zval_identical_function
  43. is_identical_function
  44. is_not_identical_function
  45. is_equal_function
  46. is_not_equal_function
  47. is_smaller_function
  48. is_smaller_or_equal_function
  49. instanceof_function_ex
  50. instanceof_function
  51. increment_string
  52. increment_function
  53. decrement_function
  54. zval_is_true
  55. zend_update_current_locale
  56. zend_str_tolower_copy
  57. zend_str_tolower_dup
  58. zend_str_tolower
  59. zend_binary_strcmp
  60. zend_binary_strncmp
  61. zend_binary_strcasecmp
  62. zend_binary_strncasecmp
  63. zend_binary_strcasecmp_l
  64. zend_binary_strncasecmp_l
  65. zend_binary_zval_strcmp
  66. zend_binary_zval_strncmp
  67. zend_binary_zval_strcasecmp
  68. zend_binary_zval_strncasecmp
  69. zendi_smart_strcmp
  70. hash_zval_compare_function
  71. zend_compare_symbol_tables_i
  72. zend_compare_symbol_tables
  73. zend_compare_arrays
  74. zend_compare_objects
  75. zend_locale_sprintf_double

   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    +----------------------------------------------------------------------+
  18 */
  19 
  20 /* $Id$ */
  21 
  22 #include <ctype.h>
  23 
  24 #include "zend.h"
  25 #include "zend_operators.h"
  26 #include "zend_variables.h"
  27 #include "zend_globals.h"
  28 #include "zend_list.h"
  29 #include "zend_API.h"
  30 #include "zend_strtod.h"
  31 #include "zend_exceptions.h"
  32 #include "zend_closures.h"
  33 
  34 #if ZEND_USE_TOLOWER_L
  35 #include <locale.h>
  36 static _locale_t current_locale = NULL;
  37 /* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
  38 #define zend_tolower(c) _tolower_l(c, current_locale)
  39 #else
  40 #define zend_tolower(c) tolower(c)
  41 #endif
  42 
  43 #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
  44 
  45 static const unsigned char tolower_map[256] = {
  46 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
  47 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
  48 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
  49 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
  50 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
  51 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
  52 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
  53 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
  54 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
  55 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
  56 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
  57 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
  58 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
  59 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
  60 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
  61 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
  62 };
  63 
  64 #define zend_tolower_ascii(c) (tolower_map[(unsigned char)(c)])
  65 
  66 /**
  67  * Functions using locale lowercase:
  68                 zend_binary_strncasecmp_l
  69                 zend_binary_strcasecmp_l
  70                 zend_binary_zval_strcasecmp
  71                 zend_binary_zval_strncasecmp
  72                 string_compare_function_ex
  73                 string_case_compare_function
  74  * Functions using ascii lowercase:
  75                 zend_str_tolower_copy
  76                 zend_str_tolower_dup
  77                 zend_str_tolower
  78                 zend_binary_strcasecmp
  79                 zend_binary_strncasecmp
  80  */
  81 
  82 ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */
  83 {
  84         int retval;
  85 
  86         if (!str_len) {
  87                 str_len = strlen(str);
  88         }
  89         retval = strtol(str, NULL, 0);
  90         if (str_len>0) {
  91                 switch (str[str_len-1]) {
  92                         case 'g':
  93                         case 'G':
  94                                 retval *= 1024;
  95                                 /* break intentionally missing */
  96                         case 'm':
  97                         case 'M':
  98                                 retval *= 1024;
  99                                 /* break intentionally missing */
 100                         case 'k':
 101                         case 'K':
 102                                 retval *= 1024;
 103                                 break;
 104                 }
 105         }
 106         return retval;
 107 }
 108 /* }}} */
 109 
 110 ZEND_API long zend_atol(const char *str, int str_len) /* {{{ */
 111 {
 112         long retval;
 113 
 114         if (!str_len) {
 115                 str_len = strlen(str);
 116         }
 117         retval = strtol(str, NULL, 0);
 118         if (str_len>0) {
 119                 switch (str[str_len-1]) {
 120                         case 'g':
 121                         case 'G':
 122                                 retval *= 1024;
 123                                 /* break intentionally missing */
 124                         case 'm':
 125                         case 'M':
 126                                 retval *= 1024;
 127                                 /* break intentionally missing */
 128                         case 'k':
 129                         case 'K':
 130                                 retval *= 1024;
 131                                 break;
 132                 }
 133         }
 134         return retval;
 135 }
 136 /* }}} */
 137 
 138 ZEND_API double zend_string_to_double(const char *number, zend_uint length) /* {{{ */
 139 {
 140         double divisor = 10.0;
 141         double result = 0.0;
 142         double exponent;
 143         const char *end = number+length;
 144         const char *digit = number;
 145 
 146         if (!length) {
 147                 return result;
 148         }
 149 
 150         while (digit < end) {
 151                 if ((*digit <= '9' && *digit >= '0')) {
 152                         result *= 10;
 153                         result += *digit - '0';
 154                 } else if (*digit == '.') {
 155                         digit++;
 156                         break;
 157                 } else if (toupper(*digit) == 'E') {
 158                         exponent = (double) atoi(digit+1);
 159                         result *= pow(10.0, exponent);
 160                         return result;
 161                 } else {
 162                         return result;
 163                 }
 164                 digit++;
 165         }
 166 
 167         while (digit < end) {
 168                 if ((*digit <= '9' && *digit >= '0')) {
 169                         result += (*digit - '0') / divisor;
 170                         divisor *= 10;
 171                 } else if (toupper(*digit) == 'E') {
 172                         exponent = (double) atoi(digit+1);
 173                         result *= pow(10.0, exponent);
 174                         return result;
 175                 } else {
 176                         return result;
 177                 }
 178                 digit++;
 179         }
 180         return result;
 181 }
 182 /* }}} */
 183 
 184 ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
 185 {
 186         switch (Z_TYPE_P(op)) {
 187                 case IS_STRING:
 188                         {
 189                                 char *strval;
 190 
 191                                 strval = Z_STRVAL_P(op);
 192                                 if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
 193                                         ZVAL_LONG(op, 0);
 194                                 }
 195                                 str_efree(strval);
 196                                 break;
 197                         }
 198                 case IS_BOOL:
 199                         Z_TYPE_P(op) = IS_LONG;
 200                         break;
 201                 case IS_RESOURCE:
 202                         zend_list_delete(Z_LVAL_P(op));
 203                         Z_TYPE_P(op) = IS_LONG;
 204                         break;
 205                 case IS_OBJECT:
 206                         convert_to_long_base(op, 10);
 207                         break;
 208                 case IS_NULL:
 209                         ZVAL_LONG(op, 0);
 210                         break;
 211         }
 212 }
 213 /* }}} */
 214 
 215 /* {{{ zendi_convert_scalar_to_number */
 216 #define zendi_convert_scalar_to_number(op, holder, result)                      \
 217         if (op==result) {                                                                                               \
 218                 if (Z_TYPE_P(op) != IS_LONG) {                                                          \
 219                         convert_scalar_to_number(op TSRMLS_CC);                                 \
 220                 }                                                                                                                       \
 221         } else {                                                                                                                \
 222                 switch (Z_TYPE_P(op)) {                                                                         \
 223                         case IS_STRING:                                                                                 \
 224                                 {                                                                                                       \
 225                                         if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) {     \
 226                                                 ZVAL_LONG(&(holder), 0);                                                        \
 227                                         }                                                                                                               \
 228                                         (op) = &(holder);                                                                               \
 229                                         break;                                                                                                  \
 230                                 }                                                                                                                       \
 231                         case IS_BOOL:                                                                                                   \
 232                         case IS_RESOURCE:                                                                                               \
 233                                 ZVAL_LONG(&(holder), Z_LVAL_P(op));                                                     \
 234                                 (op) = &(holder);                                                                                       \
 235                                 break;                                                                                                          \
 236                         case IS_NULL:                                                                                                   \
 237                                 ZVAL_LONG(&(holder), 0);                                                                        \
 238                                 (op) = &(holder);                                                                                       \
 239                                 break;                                                                                                          \
 240                         case IS_OBJECT:                                                                                                 \
 241                                 (holder) = (*(op));                                                                                     \
 242                                 zval_copy_ctor(&(holder));                                                                      \
 243                                 convert_to_long_base(&(holder), 10);                                            \
 244                                 if (Z_TYPE(holder) == IS_LONG) {                                                        \
 245                                         (op) = &(holder);                                                                               \
 246                                 }                                                                                                                       \
 247                                 break;                                                                                                          \
 248                 }                                                                                                                                       \
 249         }
 250 
 251 /* }}} */
 252 
 253 /* {{{ zendi_convert_to_long */
 254 #define zendi_convert_to_long(op, holder, result)                                       \
 255         if (op == result) {                                                                                             \
 256                 convert_to_long(op);                                                                            \
 257         } else if (Z_TYPE_P(op) != IS_LONG) {                                                   \
 258                 switch (Z_TYPE_P(op)) {                                                                         \
 259                         case IS_NULL:                                                                                   \
 260                                 Z_LVAL(holder) = 0;                                                                     \
 261                                 break;                                                                                          \
 262                         case IS_DOUBLE:                                                                                 \
 263                                 Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op));       \
 264                                 break;                                                                                          \
 265                         case IS_STRING:                                                                                 \
 266                                 Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10);      \
 267                                 break;                                                                                          \
 268                         case IS_ARRAY:                                                                                  \
 269                                 Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);  \
 270                                 break;                                                                                          \
 271                         case IS_OBJECT:                                                                                 \
 272                                 (holder) = (*(op));                                                                     \
 273                                 zval_copy_ctor(&(holder));                                                      \
 274                                 convert_to_long_base(&(holder), 10);                            \
 275                                 break;                                                                                          \
 276                         case IS_BOOL:                                                                                   \
 277                         case IS_RESOURCE:                                                                               \
 278                                 Z_LVAL(holder) = Z_LVAL_P(op);                                          \
 279                                 break;                                                                                          \
 280                         default:                                                                                                \
 281                                 zend_error(E_WARNING, "Cannot convert to ordinal value");       \
 282                                 Z_LVAL(holder) = 0;                                                                     \
 283                                 break;                                                                                          \
 284                 }                                                                                                                       \
 285                 Z_TYPE(holder) = IS_LONG;                                                                       \
 286                 (op) = &(holder);                                                                                       \
 287         }
 288 
 289 /* }}} */
 290 
 291 /* {{{ zendi_convert_to_boolean */
 292 #define zendi_convert_to_boolean(op, holder, result)                            \
 293         if (op==result) {                                                                                               \
 294                 convert_to_boolean(op);                                                                         \
 295         } else if (Z_TYPE_P(op) != IS_BOOL) {                                                   \
 296                 switch (Z_TYPE_P(op)) {                                                                         \
 297                         case IS_NULL:                                                                                   \
 298                                 Z_LVAL(holder) = 0;                                                                     \
 299                                 break;                                                                                          \
 300                         case IS_RESOURCE:                                                                               \
 301                         case IS_LONG:                                                                                   \
 302                                 Z_LVAL(holder) = (Z_LVAL_P(op) ? 1 : 0);                        \
 303                                 break;                                                                                          \
 304                         case IS_DOUBLE:                                                                                 \
 305                                 Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0);                        \
 306                                 break;                                                                                          \
 307                         case IS_STRING:                                                                                 \
 308                                 if (Z_STRLEN_P(op) == 0                                                         \
 309                                         || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {     \
 310                                         Z_LVAL(holder) = 0;                                                             \
 311                                 } else {                                                                                        \
 312                                         Z_LVAL(holder) = 1;                                                             \
 313                                 }                                                                                                       \
 314                                 break;                                                                                          \
 315                         case IS_ARRAY:                                                                                  \
 316                                 Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);  \
 317                                 break;                                                                                          \
 318                         case IS_OBJECT:                                                                                 \
 319                                 (holder) = (*(op));                                                                     \
 320                                 zval_copy_ctor(&(holder));                                                      \
 321                                 convert_to_boolean(&(holder));                                          \
 322                                 break;                                                                                          \
 323                         default:                                                                                                \
 324                                 Z_LVAL(holder) = 0;                                                                     \
 325                                 break;                                                                                          \
 326                 }                                                                                                                       \
 327                 Z_TYPE(holder) = IS_BOOL;                                                                       \
 328                 (op) = &(holder);                                                                                       \
 329         }
 330 
 331 /* }}} */
 332 
 333 /* {{{ convert_object_to_type */
 334 #define convert_object_to_type(op, ctype, conv_func)                                                                            \
 335         if (Z_OBJ_HT_P(op)->cast_object) {                                                                                                              \
 336                 zval dst;                                                                                                                                                       \
 337                 if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype TSRMLS_CC) == FAILURE) {                        \
 338                         zend_error(E_RECOVERABLE_ERROR,                                                                                                 \
 339                                 "Object of class %s could not be converted to %s", Z_OBJCE_P(op)->name,         \
 340                         zend_get_type_by_const(ctype));                                                                                                 \
 341                 } else {                                                                                                                                                        \
 342                         zval_dtor(op);                                                                                                                                  \
 343                         Z_TYPE_P(op) = ctype;                                                                                                                   \
 344                         op->value = dst.value;                                                                                                                  \
 345                 }                                                                                                                                                                       \
 346         } else {                                                                                                                                                                \
 347                 if (Z_OBJ_HT_P(op)->get) {                                                                                                                      \
 348                         zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC);                                                                \
 349                         if (Z_TYPE_P(newop) != IS_OBJECT) {                                                                                             \
 350                                 /* for safety - avoid loop */                                                                                           \
 351                                 zval_dtor(op);                                                                                                                          \
 352                                 *op = *newop;                                                                                                                           \
 353                                 FREE_ZVAL(newop);                                                                                                                       \
 354                                 conv_func(op);                                                                                                                          \
 355                         }                                                                                                                                                               \
 356                 }                                                                                                                                                                       \
 357         }
 358 
 359 /* }}} */
 360 
 361 ZEND_API void convert_to_long(zval *op) /* {{{ */
 362 {
 363         if (Z_TYPE_P(op) != IS_LONG) {
 364                 convert_to_long_base(op, 10);
 365         }
 366 }
 367 /* }}} */
 368 
 369 ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
 370 {
 371         long tmp;
 372 
 373         switch (Z_TYPE_P(op)) {
 374                 case IS_NULL:
 375                         Z_LVAL_P(op) = 0;
 376                         break;
 377                 case IS_RESOURCE: {
 378                                 TSRMLS_FETCH();
 379 
 380                                 zend_list_delete(Z_LVAL_P(op));
 381                         }
 382                         /* break missing intentionally */
 383                 case IS_BOOL:
 384                 case IS_LONG:
 385                         break;
 386                 case IS_DOUBLE:
 387                         Z_LVAL_P(op) = zend_dval_to_lval(Z_DVAL_P(op));
 388                         break;
 389                 case IS_STRING:
 390                         {
 391                                 char *strval = Z_STRVAL_P(op);
 392 
 393                                 Z_LVAL_P(op) = strtol(strval, NULL, base);
 394                                 str_efree(strval);
 395                         }
 396                         break;
 397                 case IS_ARRAY:
 398                         tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
 399                         zval_dtor(op);
 400                         Z_LVAL_P(op) = tmp;
 401                         break;
 402                 case IS_OBJECT:
 403                         {
 404                                 int retval = 1;
 405                                 TSRMLS_FETCH();
 406 
 407                                 convert_object_to_type(op, IS_LONG, convert_to_long);
 408 
 409                                 if (Z_TYPE_P(op) == IS_LONG) {
 410                                         return;
 411                                 }
 412                                 zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name);
 413 
 414                                 zval_dtor(op);
 415                                 ZVAL_LONG(op, retval);
 416                                 return;
 417                         }
 418                 default:
 419                         zend_error(E_WARNING, "Cannot convert to ordinal value");
 420                         zval_dtor(op);
 421                         Z_LVAL_P(op) = 0;
 422                         break;
 423         }
 424 
 425         Z_TYPE_P(op) = IS_LONG;
 426 }
 427 /* }}} */
 428 
 429 ZEND_API void convert_to_double(zval *op) /* {{{ */
 430 {
 431         double tmp;
 432 
 433         switch (Z_TYPE_P(op)) {
 434                 case IS_NULL:
 435                         Z_DVAL_P(op) = 0.0;
 436                         break;
 437                 case IS_RESOURCE: {
 438                                 TSRMLS_FETCH();
 439 
 440                                 zend_list_delete(Z_LVAL_P(op));
 441                         }
 442                         /* break missing intentionally */
 443                 case IS_BOOL:
 444                 case IS_LONG:
 445                         Z_DVAL_P(op) = (double) Z_LVAL_P(op);
 446                         break;
 447                 case IS_DOUBLE:
 448                         break;
 449                 case IS_STRING:
 450                         {
 451                                 char *strval = Z_STRVAL_P(op);
 452 
 453                                 Z_DVAL_P(op) = zend_strtod(strval, NULL);
 454                                 str_efree(strval);
 455                         }
 456                         break;
 457                 case IS_ARRAY:
 458                         tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
 459                         zval_dtor(op);
 460                         Z_DVAL_P(op) = tmp;
 461                         break;
 462                 case IS_OBJECT:
 463                         {
 464                                 double retval = 1.0;
 465                                 TSRMLS_FETCH();
 466 
 467                                 convert_object_to_type(op, IS_DOUBLE, convert_to_double);
 468 
 469                                 if (Z_TYPE_P(op) == IS_DOUBLE) {
 470                                         return;
 471                                 }
 472                                 zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
 473 
 474                                 zval_dtor(op);
 475                                 ZVAL_DOUBLE(op, retval);
 476                                 break;
 477                         }
 478                 default:
 479                         zend_error(E_WARNING, "Cannot convert to real value (type=%d)", Z_TYPE_P(op));
 480                         zval_dtor(op);
 481                         Z_DVAL_P(op) = 0;
 482                         break;
 483         }
 484         Z_TYPE_P(op) = IS_DOUBLE;
 485 }
 486 /* }}} */
 487 
 488 ZEND_API void convert_to_null(zval *op) /* {{{ */
 489 {
 490         if (Z_TYPE_P(op) == IS_OBJECT) {
 491                 if (Z_OBJ_HT_P(op)->cast_object) {
 492                         zval *org;
 493                         TSRMLS_FETCH();
 494 
 495                         ALLOC_ZVAL(org);
 496                         *org = *op;
 497                         if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
 498                                 zval_dtor(org);
 499                                 return;
 500                         }
 501                         *op = *org;
 502                         FREE_ZVAL(org);
 503                 }
 504         }
 505 
 506         zval_dtor(op);
 507         Z_TYPE_P(op) = IS_NULL;
 508 }
 509 /* }}} */
 510 
 511 ZEND_API void convert_to_boolean(zval *op) /* {{{ */
 512 {
 513         int tmp;
 514 
 515         switch (Z_TYPE_P(op)) {
 516                 case IS_BOOL:
 517                         break;
 518                 case IS_NULL:
 519                         Z_LVAL_P(op) = 0;
 520                         break;
 521                 case IS_RESOURCE: {
 522                                 TSRMLS_FETCH();
 523 
 524                                 zend_list_delete(Z_LVAL_P(op));
 525                         }
 526                         /* break missing intentionally */
 527                 case IS_LONG:
 528                         Z_LVAL_P(op) = (Z_LVAL_P(op) ? 1 : 0);
 529                         break;
 530                 case IS_DOUBLE:
 531                         Z_LVAL_P(op) = (Z_DVAL_P(op) ? 1 : 0);
 532                         break;
 533                 case IS_STRING:
 534                         {
 535                                 char *strval = Z_STRVAL_P(op);
 536 
 537                                 if (Z_STRLEN_P(op) == 0
 538                                         || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
 539                                         Z_LVAL_P(op) = 0;
 540                                 } else {
 541                                         Z_LVAL_P(op) = 1;
 542                                 }
 543                                 str_efree(strval);
 544                         }
 545                         break;
 546                 case IS_ARRAY:
 547                         tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
 548                         zval_dtor(op);
 549                         Z_LVAL_P(op) = tmp;
 550                         break;
 551                 case IS_OBJECT:
 552                         {
 553                                 zend_bool retval = 1;
 554                                 TSRMLS_FETCH();
 555 
 556                                 convert_object_to_type(op, IS_BOOL, convert_to_boolean);
 557 
 558                                 if (Z_TYPE_P(op) == IS_BOOL) {
 559                                         return;
 560                                 }
 561 
 562                                 zval_dtor(op);
 563                                 ZVAL_BOOL(op, retval);
 564                                 break;
 565                         }
 566                 default:
 567                         zval_dtor(op);
 568                         Z_LVAL_P(op) = 0;
 569                         break;
 570         }
 571         Z_TYPE_P(op) = IS_BOOL;
 572 }
 573 /* }}} */
 574 
 575 ZEND_API void _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* {{{ */
 576 {
 577         double dval;
 578         switch (Z_TYPE_P(op)) {
 579                 case IS_DOUBLE: {
 580                         TSRMLS_FETCH();
 581                         dval = Z_DVAL_P(op);
 582                         Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*H", (int) EG(precision), dval);
 583                         /* %H already handles removing trailing zeros from the fractional part, yay */
 584                         break;
 585                 }
 586                 default:
 587                         _convert_to_string(op ZEND_FILE_LINE_CC);
 588         }
 589         Z_TYPE_P(op) = IS_STRING;
 590 }
 591 /* }}} */
 592 
 593 ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
 594 {
 595         long lval;
 596         double dval;
 597 
 598         switch (Z_TYPE_P(op)) {
 599                 case IS_NULL:
 600                         Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
 601                         Z_STRLEN_P(op) = 0;
 602                         break;
 603                 case IS_STRING:
 604                         break;
 605                 case IS_BOOL:
 606                         if (Z_LVAL_P(op)) {
 607                                 Z_STRVAL_P(op) = estrndup_rel("1", 1);
 608                                 Z_STRLEN_P(op) = 1;
 609                         } else {
 610                                 Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
 611                                 Z_STRLEN_P(op) = 0;
 612                         }
 613                         break;
 614                 case IS_RESOURCE: {
 615                         long tmp = Z_LVAL_P(op);
 616                         TSRMLS_FETCH();
 617 
 618                         zend_list_delete(Z_LVAL_P(op));
 619                         Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "Resource id #%ld", tmp);
 620                         break;
 621                 }
 622                 case IS_LONG:
 623                         lval = Z_LVAL_P(op);
 624 
 625                         Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%ld", lval);
 626                         break;
 627                 case IS_DOUBLE: {
 628                         TSRMLS_FETCH();
 629                         dval = Z_DVAL_P(op);
 630                         Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), dval);
 631                         /* %G already handles removing trailing zeros from the fractional part, yay */
 632                         break;
 633                 }
 634                 case IS_ARRAY:
 635                         zend_error(E_NOTICE, "Array to string conversion");
 636                         zval_dtor(op);
 637                         Z_STRVAL_P(op) = estrndup_rel("Array", sizeof("Array")-1);
 638                         Z_STRLEN_P(op) = sizeof("Array")-1;
 639                         break;
 640                 case IS_OBJECT: {
 641                         TSRMLS_FETCH();
 642 
 643                         convert_object_to_type(op, IS_STRING, convert_to_string);
 644 
 645                         if (Z_TYPE_P(op) == IS_STRING) {
 646                                 return;
 647                         }
 648 
 649                         zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
 650                         zval_dtor(op);
 651                         Z_STRVAL_P(op) = estrndup_rel("Object", sizeof("Object")-1);
 652                         Z_STRLEN_P(op) = sizeof("Object")-1;
 653                         break;
 654                 }
 655                 default:
 656                         zval_dtor(op);
 657                         ZVAL_BOOL(op, 0);
 658                         break;
 659         }
 660         Z_TYPE_P(op) = IS_STRING;
 661 }
 662 /* }}} */
 663 
 664 static void convert_scalar_to_array(zval *op, int type TSRMLS_DC) /* {{{ */
 665 {
 666         zval *entry;
 667 
 668         ALLOC_ZVAL(entry);
 669         *entry = *op;
 670         INIT_PZVAL(entry);
 671 
 672         switch (type) {
 673                 case IS_ARRAY:
 674                         ALLOC_HASHTABLE(Z_ARRVAL_P(op));
 675                         zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
 676                         zend_hash_index_update(Z_ARRVAL_P(op), 0, (void *) &entry, sizeof(zval *), NULL);
 677                         Z_TYPE_P(op) = IS_ARRAY;
 678                         break;
 679                 case IS_OBJECT:
 680                         object_init(op);
 681                         zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL);
 682                         break;
 683         }
 684 }
 685 /* }}} */
 686 
 687 ZEND_API void convert_to_array(zval *op) /* {{{ */
 688 {
 689         TSRMLS_FETCH();
 690 
 691         switch (Z_TYPE_P(op)) {
 692                 case IS_ARRAY:
 693                         break;
 694 /* OBJECTS_OPTIMIZE */
 695                 case IS_OBJECT:
 696                         {
 697                                 zval *tmp;
 698                                 HashTable *ht;
 699 
 700                                 ALLOC_HASHTABLE(ht);
 701                                 zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
 702                                 if (Z_OBJCE_P(op) == zend_ce_closure) {
 703                                         convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
 704                                         if (Z_TYPE_P(op) == IS_ARRAY) {
 705                                                 zend_hash_destroy(ht);
 706                                                 FREE_HASHTABLE(ht);
 707                                                 return;
 708                                         }
 709                                 } else if (Z_OBJ_HT_P(op)->get_properties) {
 710                                         HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
 711                                         if (obj_ht) {
 712                                                 zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
 713                                         }
 714                                 } else {
 715                                         convert_object_to_type(op, IS_ARRAY, convert_to_array);
 716 
 717                                         if (Z_TYPE_P(op) == IS_ARRAY) {
 718                                                 zend_hash_destroy(ht);
 719                                                 FREE_HASHTABLE(ht);
 720                                                 return;
 721                                         }
 722                                 }
 723                                 zval_dtor(op);
 724                                 Z_TYPE_P(op) = IS_ARRAY;
 725                                 Z_ARRVAL_P(op) = ht;
 726                         }
 727                         break;
 728                 case IS_NULL:
 729                         ALLOC_HASHTABLE(Z_ARRVAL_P(op));
 730                         zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
 731                         Z_TYPE_P(op) = IS_ARRAY;
 732                         break;
 733                 default:
 734                         convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
 735                         break;
 736         }
 737 }
 738 /* }}} */
 739 
 740 ZEND_API void convert_to_object(zval *op) /* {{{ */
 741 {
 742         TSRMLS_FETCH();
 743 
 744         switch (Z_TYPE_P(op)) {
 745                 case IS_ARRAY:
 746                         {
 747                                 object_and_properties_init(op, zend_standard_class_def, Z_ARRVAL_P(op));
 748                                 break;
 749                         }
 750                 case IS_OBJECT:
 751                         break;
 752                 case IS_NULL:
 753                         object_init(op);
 754                         break;
 755                 default:
 756                         convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
 757                         break;
 758         }
 759 }
 760 /* }}} */
 761 
 762 ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
 763 {
 764         zval **arg;
 765         va_list ap;
 766 
 767         va_start(ap, argc);
 768 
 769         while (argc--) {
 770                 arg = va_arg(ap, zval **);
 771                 convert_to_long_ex(arg);
 772         }
 773 
 774         va_end(ap);
 775 }
 776 /* }}} */
 777 
 778 ZEND_API void multi_convert_to_double_ex(int argc, ...) /* {{{ */
 779 {
 780         zval **arg;
 781         va_list ap;
 782 
 783         va_start(ap, argc);
 784 
 785         while (argc--) {
 786                 arg = va_arg(ap, zval **);
 787                 convert_to_double_ex(arg);
 788         }
 789 
 790         va_end(ap);
 791 }
 792 /* }}} */
 793 
 794 ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
 795 {
 796         zval **arg;
 797         va_list ap;
 798 
 799         va_start(ap, argc);
 800 
 801         while (argc--) {
 802                 arg = va_arg(ap, zval **);
 803                 convert_to_string_ex(arg);
 804         }
 805 
 806         va_end(ap);
 807 }
 808 /* }}} */
 809 
 810 ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
 811 {
 812         zval op1_copy, op2_copy;
 813         int converted = 0;
 814 
 815         while (1) {
 816                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
 817                         case TYPE_PAIR(IS_LONG, IS_LONG): {
 818                                 long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
 819 
 820                                 /* check for overflow by comparing sign bits */
 821                                 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
 822                                         && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
 823 
 824                                         ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
 825                                 } else {
 826                                         ZVAL_LONG(result, lval);
 827                                 }
 828                                 return SUCCESS;
 829                         }
 830 
 831                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
 832                                 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
 833                                 return SUCCESS;
 834 
 835                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
 836                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
 837                                 return SUCCESS;
 838 
 839                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
 840                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
 841                                 return SUCCESS;
 842 
 843                         case TYPE_PAIR(IS_ARRAY, IS_ARRAY): {
 844                                 zval *tmp;
 845 
 846                                 if ((result == op1) && (result == op2)) {
 847                                         /* $a += $a */
 848                                         return SUCCESS;
 849                                 }
 850                                 if (result != op1) {
 851                                         *result = *op1;
 852                                         zval_copy_ctor(result);
 853                                 }
 854                                 zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), (void (*)(void *pData)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
 855                                 return SUCCESS;
 856                         }
 857 
 858                         default:
 859                                 if (!converted) {
 860                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD);
 861 
 862                                         zendi_convert_scalar_to_number(op1, op1_copy, result);
 863                                         zendi_convert_scalar_to_number(op2, op2_copy, result);
 864                                         converted = 1;
 865                                 } else {
 866                                         zend_error(E_ERROR, "Unsupported operand types");
 867                                         return FAILURE; /* unknown datatype */
 868                                 }
 869                 }
 870         }
 871 }
 872 /* }}} */
 873 
 874 ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
 875 {
 876         zval op1_copy, op2_copy;
 877         int converted = 0;
 878 
 879         while (1) {
 880                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
 881                         case TYPE_PAIR(IS_LONG, IS_LONG): {
 882                                 long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
 883 
 884                                 /* check for overflow by comparing sign bits */
 885                                 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
 886                                         && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
 887 
 888                                         ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
 889                                 } else {
 890                                         ZVAL_LONG(result, lval);
 891                                 }
 892                                 return SUCCESS;
 893 
 894                         }
 895                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
 896                                 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
 897                                 return SUCCESS;
 898 
 899                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
 900                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
 901                                 return SUCCESS;
 902 
 903                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
 904                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
 905                                 return SUCCESS;
 906 
 907                         default:
 908                                 if (!converted) {
 909                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB);
 910 
 911                                         zendi_convert_scalar_to_number(op1, op1_copy, result);
 912                                         zendi_convert_scalar_to_number(op2, op2_copy, result);
 913                                         converted = 1;
 914                                 } else {
 915                                         zend_error(E_ERROR, "Unsupported operand types");
 916                                         return FAILURE; /* unknown datatype */
 917                                 }
 918                 }
 919         }
 920 }
 921 /* }}} */
 922 
 923 ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
 924 {
 925         zval op1_copy, op2_copy;
 926         int converted = 0;
 927 
 928         while (1) {
 929                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
 930                         case TYPE_PAIR(IS_LONG, IS_LONG): {
 931                                 long overflow;
 932 
 933                                 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
 934                                 Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
 935                                 return SUCCESS;
 936 
 937                         }
 938                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
 939                                 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
 940                                 return SUCCESS;
 941 
 942                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
 943                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
 944                                 return SUCCESS;
 945 
 946                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
 947                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
 948                                 return SUCCESS;
 949 
 950                         default:
 951                                 if (!converted) {
 952                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL);
 953 
 954                                         zendi_convert_scalar_to_number(op1, op1_copy, result);
 955                                         zendi_convert_scalar_to_number(op2, op2_copy, result);
 956                                         converted = 1;
 957                                 } else {
 958                                         zend_error(E_ERROR, "Unsupported operand types");
 959                                         return FAILURE; /* unknown datatype */
 960                                 }
 961                 }
 962         }
 963 }
 964 /* }}} */
 965 
 966 ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
 967 {
 968         zval op1_copy, op2_copy;
 969         int converted = 0;
 970 
 971         while (1) {
 972                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
 973                         case TYPE_PAIR(IS_LONG, IS_LONG):
 974                                 if (Z_LVAL_P(op2) >= 0) {
 975                                         long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
 976 
 977                                         if (i == 0) {
 978                                                 ZVAL_LONG(result, 1L);
 979                                                 return SUCCESS;
 980                                         } else if (l2 == 0) {
 981                                                 ZVAL_LONG(result, 0);
 982                                                 return SUCCESS;
 983                                         }
 984 
 985                                         while (i >= 1) {
 986                                                 long overflow;
 987                                                 double dval = 0.0;
 988 
 989                                                 if (i % 2) {
 990                                                         --i;
 991                                                         ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
 992                                                         if (overflow) {
 993                                                                 ZVAL_DOUBLE(result, dval * pow(l2, i));
 994                                                                 return SUCCESS;
 995                                                         }
 996                                                 } else {
 997                                                         i /= 2;
 998                                                         ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
 999                                                         if (overflow) {
1000                                                                 ZVAL_DOUBLE(result, (double)l1 * pow(dval, i));
1001                                                                 return SUCCESS;
1002                                                         }
1003                                                 }
1004                                         }
1005                                         /* i == 0 */
1006                                         ZVAL_LONG(result, l1);
1007                                 } else {
1008                                         ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2)));
1009                                 }
1010                                 return SUCCESS;
1011 
1012                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1013                                 ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2)));
1014                                 return SUCCESS;
1015 
1016                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1017                                 ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2)));
1018                                 return SUCCESS;
1019 
1020                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1021                                 ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
1022                                 return SUCCESS;
1023 
1024                         default:
1025                                 if (!converted) {
1026                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW);
1027 
1028                                         if (Z_TYPE_P(op1) == IS_ARRAY) {
1029                                                 ZVAL_LONG(result, 0);
1030                                                 return SUCCESS;
1031                                         } else {
1032                                                 zendi_convert_scalar_to_number(op1, op1_copy, result);
1033                                         }
1034                                         if (Z_TYPE_P(op2) == IS_ARRAY) {
1035                                                 ZVAL_LONG(result, 1L);
1036                                                 return SUCCESS;
1037                                         } else {
1038                                                 zendi_convert_scalar_to_number(op2, op2_copy, result);
1039                                         }
1040                                         converted = 1;
1041                                 } else {
1042                                         zend_error(E_ERROR, "Unsupported operand types");
1043                                         return FAILURE;
1044                                 }
1045                 }
1046         }
1047 }
1048 /* }}} */
1049 
1050 ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1051 {
1052         zval op1_copy, op2_copy;
1053         int converted = 0;
1054 
1055         while (1) {
1056                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1057                         case TYPE_PAIR(IS_LONG, IS_LONG):
1058                                 if (Z_LVAL_P(op2) == 0) {
1059                                         zend_error(E_WARNING, "Division by zero");
1060                                         ZVAL_BOOL(result, 0);
1061                                         return FAILURE;                 /* division by zero */
1062                                 } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
1063                                         /* Prevent overflow error/crash */
1064                                         ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
1065                                         return SUCCESS;
1066                                 }
1067                                 if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
1068                                         ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
1069                                 } else {
1070                                         ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
1071                                 }
1072                                 return SUCCESS;
1073 
1074                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1075                                 if (Z_LVAL_P(op2) == 0) {
1076                                         zend_error(E_WARNING, "Division by zero");
1077                                         ZVAL_BOOL(result, 0);
1078                                         return FAILURE;                 /* division by zero */
1079                                 }
1080                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
1081                                 return SUCCESS;
1082 
1083                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1084                                 if (Z_DVAL_P(op2) == 0) {
1085                                         zend_error(E_WARNING, "Division by zero");
1086                                         ZVAL_BOOL(result, 0);
1087                                         return FAILURE;                 /* division by zero */
1088                                 }
1089                                 ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
1090                                 return SUCCESS;
1091 
1092                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1093                                 if (Z_DVAL_P(op2) == 0) {
1094                                         zend_error(E_WARNING, "Division by zero");
1095                                         ZVAL_BOOL(result, 0);
1096                                         return FAILURE;                 /* division by zero */
1097                                 }
1098                                 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
1099                                 return SUCCESS;
1100 
1101                         default:
1102                                 if (!converted) {
1103                                         ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV);
1104 
1105                                         zendi_convert_scalar_to_number(op1, op1_copy, result);
1106                                         zendi_convert_scalar_to_number(op2, op2_copy, result);
1107                                         converted = 1;
1108                                 } else {
1109                                         zend_error(E_ERROR, "Unsupported operand types");
1110                                         return FAILURE; /* unknown datatype */
1111                                 }
1112                 }
1113         }
1114 }
1115 /* }}} */
1116 
1117 ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1118 {
1119         zval op1_copy, op2_copy;
1120         long op1_lval;
1121 
1122         if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1123                 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MOD);
1124 
1125                 zendi_convert_to_long(op1, op1_copy, result);
1126                 op1_lval = Z_LVAL_P(op1);
1127                 zendi_convert_to_long(op2, op2_copy, result);
1128         } else {
1129                 op1_lval = Z_LVAL_P(op1);
1130         }
1131 
1132         if (Z_LVAL_P(op2) == 0) {
1133                 zend_error(E_WARNING, "Division by zero");
1134                 ZVAL_BOOL(result, 0);
1135                 return FAILURE;                 /* modulus by zero */
1136         }
1137 
1138         if (Z_LVAL_P(op2) == -1) {
1139                 /* Prevent overflow error/crash if op1==LONG_MIN */
1140                 ZVAL_LONG(result, 0);
1141                 return SUCCESS;
1142         }
1143 
1144         ZVAL_LONG(result, op1_lval % Z_LVAL_P(op2));
1145         return SUCCESS;
1146 }
1147 /* }}} */
1148 
1149 ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1150 {
1151         zval op1_copy, op2_copy;
1152         long op1_lval;
1153 
1154         if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
1155                 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_XOR);
1156 
1157                 zendi_convert_to_boolean(op1, op1_copy, result);
1158                 op1_lval = Z_LVAL_P(op1);
1159                 zendi_convert_to_boolean(op2, op2_copy, result);
1160         } else {
1161                 op1_lval = Z_LVAL_P(op1);
1162         }
1163 
1164         ZVAL_BOOL(result, op1_lval ^ Z_LVAL_P(op2));
1165         return SUCCESS;
1166 }
1167 /* }}} */
1168 
1169 ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
1170 {
1171         zval op1_copy;
1172 
1173         if (Z_TYPE_P(op1) != IS_BOOL) {
1174                 ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT);
1175 
1176                 zendi_convert_to_boolean(op1, op1_copy, result);
1177         }
1178 
1179         ZVAL_BOOL(result, !Z_LVAL_P(op1));
1180         return SUCCESS;
1181 }
1182 /* }}} */
1183 
1184 ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
1185 {
1186 
1187         switch (Z_TYPE_P(op1)) {
1188                 case IS_LONG:
1189                         ZVAL_LONG(result, ~Z_LVAL_P(op1));
1190                         return SUCCESS;
1191                 case IS_DOUBLE:
1192                         ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
1193                         return SUCCESS;
1194                 case IS_STRING: {
1195                         int i;
1196                         zval op1_copy = *op1;
1197 
1198                         Z_TYPE_P(result) = IS_STRING;
1199                         Z_STRVAL_P(result) = estrndup(Z_STRVAL(op1_copy), Z_STRLEN(op1_copy));
1200                         Z_STRLEN_P(result) = Z_STRLEN(op1_copy);
1201                         for (i = 0; i < Z_STRLEN(op1_copy); i++) {
1202                                 Z_STRVAL_P(result)[i] = ~Z_STRVAL(op1_copy)[i];
1203                         }
1204                         return SUCCESS;
1205                 }
1206                 default:
1207                         ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT);
1208 
1209                         zend_error(E_ERROR, "Unsupported operand types");
1210                         return FAILURE;
1211         }
1212 }
1213 /* }}} */
1214 
1215 ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1216 {
1217         zval op1_copy, op2_copy;
1218         long op1_lval;
1219 
1220         if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1221                 zval *longer, *shorter;
1222                 char *result_str;
1223                 int i, result_len;
1224 
1225                 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1226                         longer = op1;
1227                         shorter = op2;
1228                 } else {
1229                         longer = op2;
1230                         shorter = op1;
1231                 }
1232 
1233                 Z_TYPE_P(result) = IS_STRING;
1234                 result_len = Z_STRLEN_P(longer);
1235                 result_str = estrndup(Z_STRVAL_P(longer), Z_STRLEN_P(longer));
1236                 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1237                         result_str[i] |= Z_STRVAL_P(shorter)[i];
1238                 }
1239                 if (result==op1) {
1240                         str_efree(Z_STRVAL_P(result));
1241                 }
1242                 Z_STRVAL_P(result) = result_str;
1243                 Z_STRLEN_P(result) = result_len;
1244                 return SUCCESS;
1245         }
1246 
1247         if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1248                 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_OR);
1249 
1250                 zendi_convert_to_long(op1, op1_copy, result);
1251                 op1_lval = Z_LVAL_P(op1);
1252                 zendi_convert_to_long(op2, op2_copy, result);
1253         } else {
1254                 op1_lval = Z_LVAL_P(op1);
1255         }
1256 
1257         ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2));
1258         return SUCCESS;
1259 }
1260 /* }}} */
1261 
1262 ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1263 {
1264         zval op1_copy, op2_copy;
1265         long op1_lval;
1266 
1267         if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1268                 zval *longer, *shorter;
1269                 char *result_str;
1270                 int i, result_len;
1271 
1272                 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1273                         longer = op1;
1274                         shorter = op2;
1275                 } else {
1276                         longer = op2;
1277                         shorter = op1;
1278                 }
1279 
1280                 Z_TYPE_P(result) = IS_STRING;
1281                 result_len = Z_STRLEN_P(shorter);
1282                 result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1283                 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1284                         result_str[i] &= Z_STRVAL_P(longer)[i];
1285                 }
1286                 if (result==op1) {
1287                         str_efree(Z_STRVAL_P(result));
1288                 }
1289                 Z_STRVAL_P(result) = result_str;
1290                 Z_STRLEN_P(result) = result_len;
1291                 return SUCCESS;
1292         }
1293 
1294         if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1295                 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_AND);
1296 
1297                 zendi_convert_to_long(op1, op1_copy, result);
1298                 op1_lval = Z_LVAL_P(op1);
1299                 zendi_convert_to_long(op2, op2_copy, result);
1300         } else {
1301                 op1_lval = Z_LVAL_P(op1);
1302         }
1303 
1304         ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2));
1305         return SUCCESS;
1306 }
1307 /* }}} */
1308 
1309 ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1310 {
1311         zval op1_copy, op2_copy;
1312         long op1_lval;
1313 
1314         if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1315                 zval *longer, *shorter;
1316                 char *result_str;
1317                 int i, result_len;
1318 
1319                 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1320                         longer = op1;
1321                         shorter = op2;
1322                 } else {
1323                         longer = op2;
1324                         shorter = op1;
1325                 }
1326 
1327                 Z_TYPE_P(result) = IS_STRING;
1328                 result_len = Z_STRLEN_P(shorter);
1329                 result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1330                 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1331                         result_str[i] ^= Z_STRVAL_P(longer)[i];
1332                 }
1333                 if (result==op1) {
1334                         str_efree(Z_STRVAL_P(result));
1335                 }
1336                 Z_STRVAL_P(result) = result_str;
1337                 Z_STRLEN_P(result) = result_len;
1338                 return SUCCESS;
1339         }
1340 
1341         if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1342                 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_XOR);
1343 
1344                 zendi_convert_to_long(op1, op1_copy, result);
1345                 op1_lval = Z_LVAL_P(op1);
1346                 zendi_convert_to_long(op2, op2_copy, result);
1347         } else {
1348                 op1_lval = Z_LVAL_P(op1);
1349         }
1350 
1351         ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2));
1352         return SUCCESS;
1353 }
1354 /* }}} */
1355 
1356 ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1357 {
1358         zval op1_copy, op2_copy;
1359         long op1_lval;
1360 
1361         if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1362                 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SL);
1363 
1364                 zendi_convert_to_long(op1, op1_copy, result);
1365                 op1_lval = Z_LVAL_P(op1);
1366                 zendi_convert_to_long(op2, op2_copy, result);
1367         } else {
1368                 op1_lval = Z_LVAL_P(op1);
1369         }
1370 
1371         ZVAL_LONG(result, op1_lval << Z_LVAL_P(op2));
1372         return SUCCESS;
1373 }
1374 /* }}} */
1375 
1376 ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1377 {
1378         zval op1_copy, op2_copy;
1379         long op1_lval;
1380 
1381         if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1382                 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SR);
1383 
1384                 zendi_convert_to_long(op1, op1_copy, result);
1385                 op1_lval = Z_LVAL_P(op1);
1386                 zendi_convert_to_long(op2, op2_copy, result);
1387         } else {
1388                 op1_lval = Z_LVAL_P(op1);
1389         }
1390 
1391         ZVAL_LONG(result, op1_lval >> Z_LVAL_P(op2));
1392         return SUCCESS;
1393 }
1394 /* }}} */
1395 
1396 /* must support result==op1 */
1397 ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
1398 {
1399         int length = Z_STRLEN_P(op1) + 1;
1400         char *buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
1401 
1402         buf[length - 1] = (char) Z_LVAL_P(op2);
1403         buf[length] = 0;
1404         ZVAL_STRINGL(result, buf, length, 0);
1405         return SUCCESS;
1406 }
1407 /* }}} */
1408 
1409 /* must support result==op1 */
1410 ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
1411 {
1412         int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1413         char *buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
1414 
1415         memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1416         buf[length] = 0;
1417         ZVAL_STRINGL(result, buf, length, 0);
1418         return SUCCESS;
1419 }
1420 /* }}} */
1421 
1422 ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1423 {
1424         zval op1_copy, op2_copy;
1425         int use_copy1 = 0, use_copy2 = 0;
1426 
1427         if (Z_TYPE_P(op1) != IS_STRING || Z_TYPE_P(op2) != IS_STRING) {
1428                 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT);
1429 
1430                 if (Z_TYPE_P(op1) != IS_STRING) {
1431                         zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1432                 }
1433                 if (Z_TYPE_P(op2) != IS_STRING) {
1434                         zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1435                 }
1436         }
1437 
1438         if (use_copy1) {
1439                 /* We have created a converted copy of op1. Therefore, op1 won't become the result so
1440                  * we have to free it.
1441                  */
1442                 if (result == op1) {
1443                         zval_dtor(op1);
1444                 }
1445                 op1 = &op1_copy;
1446         }
1447         if (use_copy2) {
1448                 op2 = &op2_copy;
1449         }
1450         if (result==op1 && !IS_INTERNED(Z_STRVAL_P(op1))) {     /* special case, perform operations on result */
1451                 uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1452 
1453                 if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
1454                         efree(Z_STRVAL_P(result));
1455                         ZVAL_EMPTY_STRING(result);
1456                         zend_error(E_ERROR, "String size overflow");
1457                 }
1458 
1459                 Z_STRVAL_P(result) = safe_erealloc(Z_STRVAL_P(result), res_len, 1, 1);
1460 
1461                 memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1462                 Z_STRVAL_P(result)[res_len]=0;
1463                 Z_STRLEN_P(result) = res_len;
1464         } else {
1465                 int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1466                 char *buf;
1467 
1468                 if (Z_STRLEN_P(op1) < 0 || Z_STRLEN_P(op2) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
1469                         zend_error(E_ERROR, "String size overflow");
1470                 }
1471                 buf = (char *) safe_emalloc(length, 1, 1);
1472 
1473                 memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1474                 memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1475                 buf[length] = 0;
1476                 ZVAL_STRINGL(result, buf, length, 0);
1477         }
1478         if (use_copy1) {
1479                 zval_dtor(op1);
1480         }
1481         if (use_copy2) {
1482                 zval_dtor(op2);
1483         }
1484         return SUCCESS;
1485 }
1486 /* }}} */
1487 
1488 ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC) /* {{{ */
1489 {
1490         zval op1_copy, op2_copy;
1491         int use_copy1 = 0, use_copy2 = 0;
1492 
1493         if (Z_TYPE_P(op1) != IS_STRING) {
1494                 zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1495         }
1496         if (Z_TYPE_P(op2) != IS_STRING) {
1497                 zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1498         }
1499 
1500         if (use_copy1) {
1501                 op1 = &op1_copy;
1502         }
1503         if (use_copy2) {
1504                 op2 = &op2_copy;
1505         }
1506 
1507         if (case_insensitive) {
1508                 ZVAL_LONG(result, zend_binary_zval_strcasecmp(op1, op2));
1509         } else {
1510                 ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2));
1511         }
1512 
1513         if (use_copy1) {
1514                 zval_dtor(op1);
1515         }
1516         if (use_copy2) {
1517                 zval_dtor(op2);
1518         }
1519         return SUCCESS;
1520 }
1521 /* }}} */
1522 
1523 ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1524 {
1525         return string_compare_function_ex(result, op1, op2, 0 TSRMLS_CC);
1526 }
1527 /* }}} */
1528 
1529 ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1530 {
1531         return string_compare_function_ex(result, op1, op2, 1 TSRMLS_CC);
1532 }
1533 /* }}} */
1534 
1535 #if HAVE_STRCOLL
1536 ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1537 {
1538         zval op1_copy, op2_copy;
1539         int use_copy1 = 0, use_copy2 = 0;
1540 
1541         if (Z_TYPE_P(op1) != IS_STRING) {
1542                 zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1543         }
1544         if (Z_TYPE_P(op2) != IS_STRING) {
1545                 zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1546         }
1547 
1548         if (use_copy1) {
1549                 op1 = &op1_copy;
1550         }
1551         if (use_copy2) {
1552                 op2 = &op2_copy;
1553         }
1554 
1555         ZVAL_LONG(result, strcoll(Z_STRVAL_P(op1), Z_STRVAL_P(op2)));
1556 
1557         if (use_copy1) {
1558                 zval_dtor(op1);
1559         }
1560         if (use_copy2) {
1561                 zval_dtor(op2);
1562         }
1563         return SUCCESS;
1564 }
1565 /* }}} */
1566 #endif
1567 
1568 ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1569 {
1570         zval op1_copy, op2_copy;
1571 
1572         op1_copy = *op1;
1573         zval_copy_ctor(&op1_copy);
1574 
1575         op2_copy = *op2;
1576         zval_copy_ctor(&op2_copy);
1577 
1578         convert_to_double(&op1_copy);
1579         convert_to_double(&op2_copy);
1580 
1581         ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy)));
1582 
1583         return SUCCESS;
1584 }
1585 /* }}} */
1586 
1587 static inline void zend_free_obj_get_result(zval *op TSRMLS_DC) /* {{{ */
1588 {
1589         if (Z_REFCOUNT_P(op) == 0) {
1590                 GC_REMOVE_ZVAL_FROM_BUFFER(op);
1591                 zval_dtor(op);
1592                 FREE_ZVAL(op);
1593         } else {
1594                 zval_ptr_dtor(&op);
1595         }
1596 }
1597 /* }}} */
1598 
1599 ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1600 {
1601         int ret;
1602         int converted = 0;
1603         zval op1_copy, op2_copy;
1604         zval *op_free;
1605 
1606         while (1) {
1607                 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1608                         case TYPE_PAIR(IS_LONG, IS_LONG):
1609                                 ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1610                                 return SUCCESS;
1611 
1612                         case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1613                                 Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
1614                                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1615                                 return SUCCESS;
1616 
1617                         case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1618                                 Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
1619                                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1620                                 return SUCCESS;
1621 
1622                         case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1623                                 if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
1624                                         ZVAL_LONG(result, 0);
1625                                 } else {
1626                                         Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
1627                                         ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1628                                 }
1629                                 return SUCCESS;
1630 
1631                         case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
1632                                 zend_compare_arrays(result, op1, op2 TSRMLS_CC);
1633                                 return SUCCESS;
1634 
1635                         case TYPE_PAIR(IS_NULL, IS_NULL):
1636                                 ZVAL_LONG(result, 0);
1637                                 return SUCCESS;
1638 
1639                         case TYPE_PAIR(IS_NULL, IS_BOOL):
1640                                 ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1641                                 return SUCCESS;
1642 
1643                         case TYPE_PAIR(IS_BOOL, IS_NULL):
1644                                 ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1645                                 return SUCCESS;
1646 
1647                         case TYPE_PAIR(IS_BOOL, IS_BOOL):
1648                                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1649                                 return SUCCESS;
1650 
1651                         case TYPE_PAIR(IS_STRING, IS_STRING):
1652                                 zendi_smart_strcmp(result, op1, op2);
1653                                 return SUCCESS;
1654 
1655                         case TYPE_PAIR(IS_NULL, IS_STRING):
1656                                 ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
1657                                 return SUCCESS;
1658 
1659                         case TYPE_PAIR(IS_STRING, IS_NULL):
1660                                 ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
1661                                 return SUCCESS;
1662 
1663                         case TYPE_PAIR(IS_OBJECT, IS_NULL):
1664                                 ZVAL_LONG(result, 1);
1665                                 return SUCCESS;
1666 
1667                         case TYPE_PAIR(IS_NULL, IS_OBJECT):
1668                                 ZVAL_LONG(result, -1);
1669                                 return SUCCESS;
1670 
1671                         default:
1672                                 if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
1673                                         return Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2 TSRMLS_CC);
1674                                 } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
1675                                         return Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2 TSRMLS_CC);
1676                                 }
1677 
1678                                 if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) {
1679                                         if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
1680                                                 /* object handles are identical, apparently this is the same object */
1681                                                 ZVAL_LONG(result, 0);
1682                                                 return SUCCESS;
1683                                         }
1684                                         if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) {
1685                                                 ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2 TSRMLS_CC));
1686                                                 return SUCCESS;
1687                                         }
1688                                 }
1689                                 if (Z_TYPE_P(op1) == IS_OBJECT) {
1690                                         if (Z_OBJ_HT_P(op1)->get) {
1691                                                 op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
1692                                                 ret = compare_function(result, op_free, op2 TSRMLS_CC);
1693                                                 zend_free_obj_get_result(op_free TSRMLS_CC);
1694                                                 return ret;
1695                                         } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
1696                                                 ALLOC_INIT_ZVAL(op_free);
1697                                                 if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
1698                                                         ZVAL_LONG(result, 1);
1699                                                         zend_free_obj_get_result(op_free TSRMLS_CC);
1700                                                         return SUCCESS;
1701                                                 }
1702                                                 ret = compare_function(result, op_free, op2 TSRMLS_CC);
1703                                                 zend_free_obj_get_result(op_free TSRMLS_CC);
1704                                                 return ret;
1705                                         }
1706                                 }
1707                                 if (Z_TYPE_P(op2) == IS_OBJECT) {
1708                                         if (Z_OBJ_HT_P(op2)->get) {
1709                                                 op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
1710                                                 ret = compare_function(result, op1, op_free TSRMLS_CC);
1711                                                 zend_free_obj_get_result(op_free TSRMLS_CC);
1712                                                 return ret;
1713                                         } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
1714                                                 ALLOC_INIT_ZVAL(op_free);
1715                                                 if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
1716                                                         ZVAL_LONG(result, -1);
1717                                                         zend_free_obj_get_result(op_free TSRMLS_CC);
1718                                                         return SUCCESS;
1719                                                 }
1720                                                 ret = compare_function(result, op1, op_free TSRMLS_CC);
1721                                                 zend_free_obj_get_result(op_free TSRMLS_CC);
1722                                                 return ret;
1723                                         } else if (Z_TYPE_P(op1) == IS_OBJECT) {
1724                                                 ZVAL_LONG(result, 1);
1725                                                 return SUCCESS;
1726                                         }
1727                                 }
1728                                 if (!converted) {
1729                                         if (Z_TYPE_P(op1) == IS_NULL) {
1730                                                 zendi_convert_to_boolean(op2, op2_copy, result);
1731                                                 ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1732                                                 return SUCCESS;
1733                                         } else if (Z_TYPE_P(op2) == IS_NULL) {
1734                                                 zendi_convert_to_boolean(op1, op1_copy, result);
1735                                                 ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1736                                                 return SUCCESS;
1737                                         } else if (Z_TYPE_P(op1) == IS_BOOL) {
1738                                                 zendi_convert_to_boolean(op2, op2_copy, result);
1739                                                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1740                                                 return SUCCESS;
1741                                         } else if (Z_TYPE_P(op2) == IS_BOOL) {
1742                                                 zendi_convert_to_boolean(op1, op1_copy, result);
1743                                                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1744                                                 return SUCCESS;
1745                                         } else {
1746                                                 zendi_convert_scalar_to_number(op1, op1_copy, result);
1747                                                 zendi_convert_scalar_to_number(op2, op2_copy, result);
1748                                                 converted = 1;
1749                                         }
1750                                 } else if (Z_TYPE_P(op1)==IS_ARRAY) {
1751                                         ZVAL_LONG(result, 1);
1752                                         return SUCCESS;
1753                                 } else if (Z_TYPE_P(op2)==IS_ARRAY) {
1754                                         ZVAL_LONG(result, -1);
1755                                         return SUCCESS;
1756                                 } else if (Z_TYPE_P(op1)==IS_OBJECT) {
1757                                         ZVAL_LONG(result, 1);
1758                                         return SUCCESS;
1759                                 } else if (Z_TYPE_P(op2)==IS_OBJECT) {
1760                                         ZVAL_LONG(result, -1);
1761                                         return SUCCESS;
1762                                 } else {
1763                                         ZVAL_LONG(result, 0);
1764                                         return FAILURE;
1765                                 }
1766                 }
1767         }
1768 }
1769 /* }}} */
1770 
1771 static int hash_zval_identical_function(const zval **z1, const zval **z2) /* {{{ */
1772 {
1773         zval result;
1774         TSRMLS_FETCH();
1775 
1776         /* is_identical_function() returns 1 in case of identity and 0 in case
1777          * of a difference;
1778          * whereas this comparison function is expected to return 0 on identity,
1779          * and non zero otherwise.
1780          */
1781         if (is_identical_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
1782                 return 1;
1783         }
1784         return !Z_LVAL(result);
1785 }
1786 /* }}} */
1787 
1788 ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1789 {
1790         Z_TYPE_P(result) = IS_BOOL;
1791         if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
1792                 Z_LVAL_P(result) = 0;
1793                 return SUCCESS;
1794         }
1795         switch (Z_TYPE_P(op1)) {
1796                 case IS_NULL:
1797                         Z_LVAL_P(result) = 1;
1798                         break;
1799                 case IS_BOOL:
1800                 case IS_LONG:
1801                 case IS_RESOURCE:
1802                         Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
1803                         break;
1804                 case IS_DOUBLE:
1805                         Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
1806                         break;
1807                 case IS_STRING:
1808                         Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2))
1809                                 && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));
1810                         break;
1811                 case IS_ARRAY:
1812                         Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) ||
1813                                 zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0);
1814                         break;
1815                 case IS_OBJECT:
1816                         if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {
1817                                 Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));
1818                         } else {
1819                                 Z_LVAL_P(result) = 0;
1820                         }
1821                         break;
1822                 default:
1823                         Z_LVAL_P(result) = 0;
1824                         return FAILURE;
1825         }
1826         return SUCCESS;
1827 }
1828 /* }}} */
1829 
1830 ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1831 {
1832         if (is_identical_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1833                 return FAILURE;
1834         }
1835         Z_LVAL_P(result) = !Z_LVAL_P(result);
1836         return SUCCESS;
1837 }
1838 /* }}} */
1839 
1840 ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1841 {
1842         if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1843                 return FAILURE;
1844         }
1845         ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
1846         return SUCCESS;
1847 }
1848 /* }}} */
1849 
1850 ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1851 {
1852         if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1853                 return FAILURE;
1854         }
1855         ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
1856         return SUCCESS;
1857 }
1858 /* }}} */
1859 
1860 ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1861 {
1862         if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1863                 return FAILURE;
1864         }
1865         ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
1866         return SUCCESS;
1867 }
1868 /* }}} */
1869 
1870 ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1871 {
1872         if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1873                 return FAILURE;
1874         }
1875         ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
1876         return SUCCESS;
1877 }
1878 /* }}} */
1879 
1880 ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC) /* {{{ */
1881 {
1882         zend_uint i;
1883 
1884         for (i=0; i<instance_ce->num_interfaces; i++) {
1885                 if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) {
1886                         return 1;
1887                 }
1888         }
1889         if (!interfaces_only) {
1890                 while (instance_ce) {
1891                         if (instance_ce == ce) {
1892                                 return 1;
1893                         }
1894                         instance_ce = instance_ce->parent;
1895                 }
1896         }
1897 
1898         return 0;
1899 }
1900 /* }}} */
1901 
1902 ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC) /* {{{ */
1903 {
1904         return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC);
1905 }
1906 /* }}} */
1907 
1908 #define LOWER_CASE 1
1909 #define UPPER_CASE 2
1910 #define NUMERIC 3
1911 
1912 static void increment_string(zval *str) /* {{{ */
1913 {
1914         int carry=0;
1915         int pos=Z_STRLEN_P(str)-1;
1916         char *s=Z_STRVAL_P(str);
1917         char *t;
1918         int last=0; /* Shut up the compiler warning */
1919         int ch;
1920 
1921         if (Z_STRLEN_P(str) == 0) {
1922                 str_efree(Z_STRVAL_P(str));
1923                 Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
1924                 Z_STRLEN_P(str) = 1;
1925                 return;
1926         }
1927 
1928         if (IS_INTERNED(s)) {
1929                 Z_STRVAL_P(str) = s = estrndup(s, Z_STRLEN_P(str));
1930         }
1931 
1932         while (pos >= 0) {
1933                 ch = s[pos];
1934                 if (ch >= 'a' && ch <= 'z') {
1935                         if (ch == 'z') {
1936                                 s[pos] = 'a';
1937                                 carry=1;
1938                         } else {
1939                                 s[pos]++;
1940                                 carry=0;
1941                         }
1942                         last=LOWER_CASE;
1943                 } else if (ch >= 'A' && ch <= 'Z') {
1944                         if (ch == 'Z') {
1945                                 s[pos] = 'A';
1946                                 carry=1;
1947                         } else {
1948                                 s[pos]++;
1949                                 carry=0;
1950                         }
1951                         last=UPPER_CASE;
1952                 } else if (ch >= '0' && ch <= '9') {
1953                         if (ch == '9') {
1954                                 s[pos] = '0';
1955                                 carry=1;
1956                         } else {
1957                                 s[pos]++;
1958                                 carry=0;
1959                         }
1960                         last = NUMERIC;
1961                 } else {
1962                         carry=0;
1963                         break;
1964                 }
1965                 if (carry == 0) {
1966                         break;
1967                 }
1968                 pos--;
1969         }
1970 
1971         if (carry) {
1972                 t = (char *) emalloc(Z_STRLEN_P(str)+1+1);
1973                 memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str));
1974                 Z_STRLEN_P(str)++;
1975                 t[Z_STRLEN_P(str)] = '\0';
1976                 switch (last) {
1977                         case NUMERIC:
1978                                 t[0] = '1';
1979                                 break;
1980                         case UPPER_CASE:
1981                                 t[0] = 'A';
1982                                 break;
1983                         case LOWER_CASE:
1984                                 t[0] = 'a';
1985                                 break;
1986                 }
1987                 str_efree(Z_STRVAL_P(str));
1988                 Z_STRVAL_P(str) = t;
1989         }
1990 }
1991 /* }}} */
1992 
1993 ZEND_API int increment_function(zval *op1) /* {{{ */
1994 {
1995         switch (Z_TYPE_P(op1)) {
1996                 case IS_LONG:
1997                         if (Z_LVAL_P(op1) == LONG_MAX) {
1998                                 /* switch to double */
1999                                 double d = (double)Z_LVAL_P(op1);
2000                                 ZVAL_DOUBLE(op1, d+1);
2001                         } else {
2002                         Z_LVAL_P(op1)++;
2003                         }
2004                         break;
2005                 case IS_DOUBLE:
2006                         Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
2007                         break;
2008                 case IS_NULL:
2009                         ZVAL_LONG(op1, 1);
2010                         break;
2011                 case IS_STRING: {
2012                                 long lval;
2013                                 double dval;
2014 
2015                                 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2016                                         case IS_LONG:
2017                                                 str_efree(Z_STRVAL_P(op1));
2018                                                 if (lval == LONG_MAX) {
2019                                                         /* switch to double */
2020                                                         double d = (double)lval;
2021                                                         ZVAL_DOUBLE(op1, d+1);
2022                                                 } else {
2023                                                         ZVAL_LONG(op1, lval+1);
2024                                                 }
2025                                                 break;
2026                                         case IS_DOUBLE:
2027                                                 str_efree(Z_STRVAL_P(op1));
2028                                                 ZVAL_DOUBLE(op1, dval+1);
2029                                                 break;
2030                                         default:
2031                                                 /* Perl style string increment */
2032                                                 increment_string(op1);
2033                                                 break;
2034                                 }
2035                         }
2036                         break;
2037                 case IS_OBJECT:
2038                         if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2039                                 zval *op2;
2040                                 int res;
2041                                 TSRMLS_FETCH();
2042 
2043                                 MAKE_STD_ZVAL(op2);
2044                                 ZVAL_LONG(op2, 1);
2045                                 res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_ADD, op1, op1, op2 TSRMLS_CC);
2046                                 zval_ptr_dtor(&op2);
2047 
2048                                 return res;
2049                         }
2050                         return FAILURE;
2051                 default:
2052                         return FAILURE;
2053         }
2054         return SUCCESS;
2055 }
2056 /* }}} */
2057 
2058 ZEND_API int decrement_function(zval *op1) /* {{{ */
2059 {
2060         long lval;
2061         double dval;
2062 
2063         switch (Z_TYPE_P(op1)) {
2064                 case IS_LONG:
2065                         if (Z_LVAL_P(op1) == LONG_MIN) {
2066                                 double d = (double)Z_LVAL_P(op1);
2067                                 ZVAL_DOUBLE(op1, d-1);
2068                         } else {
2069                         Z_LVAL_P(op1)--;
2070                         }
2071                         break;
2072                 case IS_DOUBLE:
2073                         Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
2074                         break;
2075                 case IS_STRING:         /* Like perl we only support string increment */
2076                         if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
2077                                 str_efree(Z_STRVAL_P(op1));
2078                                 ZVAL_LONG(op1, -1);
2079                                 break;
2080                         }
2081                         switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2082                                 case IS_LONG:
2083                                         str_efree(Z_STRVAL_P(op1));
2084                                         if (lval == LONG_MIN) {
2085                                                 double d = (double)lval;
2086                                                 ZVAL_DOUBLE(op1, d-1);
2087                                         } else {
2088                                                 ZVAL_LONG(op1, lval-1);
2089                                         }
2090                                         break;
2091                                 case IS_DOUBLE:
2092                                         str_efree(Z_STRVAL_P(op1));
2093                                         ZVAL_DOUBLE(op1, dval - 1);
2094                                         break;
2095                         }
2096                         break;
2097                 case IS_OBJECT:
2098                         if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2099                                 zval *op2;
2100                                 int res;
2101                                 TSRMLS_FETCH();
2102 
2103                                 MAKE_STD_ZVAL(op2);
2104                                 ZVAL_LONG(op2, 1);
2105                                 res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_SUB, op1, op1, op2 TSRMLS_CC);
2106                                 zval_ptr_dtor(&op2);
2107 
2108                                 return res;
2109                         }
2110                         return FAILURE;
2111                 default:
2112                         return FAILURE;
2113         }
2114 
2115         return SUCCESS;
2116 }
2117 /* }}} */
2118 
2119 ZEND_API int zval_is_true(zval *op) /* {{{ */
2120 {
2121         convert_to_boolean(op);
2122         return (Z_LVAL_P(op) ? 1 : 0);
2123 }
2124 /* }}} */
2125 
2126 #ifdef ZEND_USE_TOLOWER_L
2127 ZEND_API void zend_update_current_locale(void) /* {{{ */
2128 {
2129         current_locale = _get_current_locale();
2130 }
2131 /* }}} */
2132 #endif
2133 
2134 ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length) /* {{{ */
2135 {
2136         register unsigned char *str = (unsigned char*)source;
2137         register unsigned char *result = (unsigned char*)dest;
2138         register unsigned char *end = str + length;
2139 
2140         while (str < end) {
2141                 *result++ = zend_tolower_ascii(*str++);
2142         }
2143         *result = '\0';
2144 
2145         return dest;
2146 }
2147 /* }}} */
2148 
2149 ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length) /* {{{ */
2150 {
2151         return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
2152 }
2153 /* }}} */
2154 
2155 ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */
2156 {
2157         register unsigned char *p = (unsigned char*)str;
2158         register unsigned char *end = p + length;
2159 
2160         while (p < end) {
2161                 *p = zend_tolower_ascii(*p);
2162                 p++;
2163         }
2164 }
2165 /* }}} */
2166 
2167 ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
2168 {
2169         int retval;
2170 
2171         if (s1 == s2) {
2172                 return 0;
2173         }
2174         retval = memcmp(s1, s2, MIN(len1, len2));
2175         if (!retval) {
2176                 return (len1 - len2);
2177         } else {
2178                 return retval;
2179         }
2180 }
2181 /* }}} */
2182 
2183 ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
2184 {
2185         int retval;
2186 
2187         if (s1 == s2) {
2188                 return 0;
2189         }
2190         retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
2191         if (!retval) {
2192                 return (MIN(length, len1) - MIN(length, len2));
2193         } else {
2194                 return retval;
2195         }
2196 }
2197 /* }}} */
2198 
2199 ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
2200 {
2201         int len;
2202         int c1, c2;
2203 
2204         if (s1 == s2) {
2205                 return 0;
2206         }
2207 
2208         len = MIN(len1, len2);
2209         while (len--) {
2210                 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2211                 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2212                 if (c1 != c2) {
2213                         return c1 - c2;
2214                 }
2215         }
2216 
2217         return len1 - len2;
2218 }
2219 /* }}} */
2220 
2221 ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
2222 {
2223         int len;
2224         int c1, c2;
2225 
2226         if (s1 == s2) {
2227                 return 0;
2228         }
2229         len = MIN(length, MIN(len1, len2));
2230         while (len--) {
2231                 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2232                 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2233                 if (c1 != c2) {
2234                         return c1 - c2;
2235                 }
2236         }
2237 
2238         return MIN(length, len1) - MIN(length, len2);
2239 }
2240 /* }}} */
2241 
2242 ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
2243 {
2244         int len;
2245         int c1, c2;
2246 
2247         if (s1 == s2) {
2248                 return 0;
2249         }
2250 
2251         len = MIN(len1, len2);
2252         while (len--) {
2253                 c1 = zend_tolower((int)*(unsigned char *)s1++);
2254                 c2 = zend_tolower((int)*(unsigned char *)s2++);
2255                 if (c1 != c2) {
2256                         return c1 - c2;
2257                 }
2258         }
2259 
2260         return len1 - len2;
2261 }
2262 /* }}} */
2263 
2264 ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
2265 {
2266         int len;
2267         int c1, c2;
2268 
2269         if (s1 == s2) {
2270                 return 0;
2271         }
2272         len = MIN(length, MIN(len1, len2));
2273         while (len--) {
2274                 c1 = zend_tolower((int)*(unsigned char *)s1++);
2275                 c2 = zend_tolower((int)*(unsigned char *)s2++);
2276                 if (c1 != c2) {
2277                         return c1 - c2;
2278                 }
2279         }
2280 
2281         return MIN(length, len1) - MIN(length, len2);
2282 }
2283 /* }}} */
2284 
2285 ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
2286 {
2287         return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2288 }
2289 /* }}} */
2290 
2291 ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2292 {
2293         return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2294 }
2295 /* }}} */
2296 
2297 ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */
2298 {
2299         return zend_binary_strcasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2300 }
2301 /* }}} */
2302 
2303 ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2304 {
2305         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));
2306 }
2307 /* }}} */
2308 
2309 ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
2310 {
2311         int ret1, ret2;
2312         int oflow1, oflow2;
2313         long lval1 = 0, lval2 = 0;
2314         double dval1 = 0.0, dval2 = 0.0;
2315 
2316         if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) &&
2317                 (ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) {
2318 #if ULONG_MAX == 0xFFFFFFFF
2319                 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
2320                         ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
2321                         || (oflow1 == -1 && dval1 < -9007199254740991.))) {
2322 #else
2323                 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
2324 #endif
2325                         /* both values are integers overflown to the same side, and the
2326                          * double comparison may have resulted in crucial accuracy lost */
2327                         goto string_cmp;
2328                 }
2329                 if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
2330                         if (ret1!=IS_DOUBLE) {
2331                                 if (oflow2) {
2332                                         /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
2333                                         ZVAL_LONG(result, -1 * oflow2);
2334                                         return;
2335                                 }
2336                                 dval1 = (double) lval1;
2337                         } else if (ret2!=IS_DOUBLE) {
2338                                 if (oflow1) {
2339                                         ZVAL_LONG(result, oflow1);
2340                                         return;
2341                                 }
2342                                 dval2 = (double) lval2;
2343                         } else if (dval1 == dval2 && !zend_finite(dval1)) {
2344                                 /* Both values overflowed and have the same sign,
2345                                  * so a numeric comparison would be inaccurate */
2346                                 goto string_cmp;
2347                         }
2348                         Z_DVAL_P(result) = dval1 - dval2;
2349                         ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
2350                 } else { /* they both have to be long's */
2351                         ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0));
2352                 }
2353         } else {
2354 string_cmp:
2355                 Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
2356                 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
2357         }
2358 }
2359 /* }}} */
2360 
2361 static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC) /* {{{ */
2362 {
2363         zval result;
2364 
2365         if (compare_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
2366                 return 1;
2367         }
2368         return Z_LVAL(result);
2369 }
2370 /* }}} */
2371 
2372 ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
2373 {
2374         return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
2375 }
2376 /* }}} */
2377 
2378 ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
2379 {
2380         ZVAL_LONG(result, ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC));
2381 }
2382 /* }}} */
2383 
2384 ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC) /* {{{ */
2385 {
2386         zend_compare_symbol_tables(result, Z_ARRVAL_P(a1), Z_ARRVAL_P(a2) TSRMLS_CC);
2387 }
2388 /* }}} */
2389 
2390 ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
2391 {
2392         Z_TYPE_P(result) = IS_LONG;
2393 
2394         if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) {
2395                 Z_LVAL_P(result) = 0;
2396                 return;
2397         }
2398 
2399         if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2400                 Z_LVAL_P(result) = 1;
2401         } else {
2402                 Z_LVAL_P(result) = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC);
2403         }
2404 }
2405 /* }}} */
2406 
2407 ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
2408 {
2409         TSRMLS_FETCH();
2410 
2411         Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
2412 }
2413 /* }}} */
2414 
2415 /*
2416  * Local variables:
2417  * tab-width: 4
2418  * c-basic-offset: 4
2419  * indent-tabs-mode: t
2420  * End:
2421  */

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