1/* 2 +----------------------------------------------------------------------+ 3 | Zend Engine | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 2.00 of the Zend license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available through the world-wide-web at the following url: | 10 | http://www.zend.com/license/2_00.txt. | 11 | If you did not receive a copy of the Zend license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@zend.com so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Authors: Andi Gutmans <andi@zend.com> | 16 | Zeev Suraski <zeev@zend.com> | 17 +----------------------------------------------------------------------+ 18*/ 19 20/* $Id$ */ 21 22#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> 36static _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 45static const unsigned char tolower_map[256] = { 460x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 470x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 480x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 490x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 500x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 510x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f, 520x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 530x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 540x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 550x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 560xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 570xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, 580xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, 590xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 600xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, 610xf0,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 82ZEND_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 110ZEND_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 138ZEND_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 184ZEND_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_FREE(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 361ZEND_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 369ZEND_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_FREE(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 429ZEND_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_FREE(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 488ZEND_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 511ZEND_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_FREE(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 575ZEND_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 593ZEND_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 664static 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 687ZEND_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 740ZEND_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 762ZEND_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 778ZEND_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 794ZEND_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 810ZEND_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 zendi_convert_scalar_to_number(op1, op1_copy, result); 861 zendi_convert_scalar_to_number(op2, op2_copy, result); 862 converted = 1; 863 } else { 864 zend_error(E_ERROR, "Unsupported operand types"); 865 return FAILURE; /* unknown datatype */ 866 } 867 } 868 } 869} 870/* }}} */ 871 872ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 873{ 874 zval op1_copy, op2_copy; 875 int converted = 0; 876 877 while (1) { 878 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { 879 case TYPE_PAIR(IS_LONG, IS_LONG): { 880 long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2); 881 882 /* check for overflow by comparing sign bits */ 883 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK) 884 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) { 885 886 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2)); 887 } else { 888 ZVAL_LONG(result, lval); 889 } 890 return SUCCESS; 891 892 } 893 case TYPE_PAIR(IS_LONG, IS_DOUBLE): 894 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2)); 895 return SUCCESS; 896 897 case TYPE_PAIR(IS_DOUBLE, IS_LONG): 898 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2))); 899 return SUCCESS; 900 901 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): 902 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2)); 903 return SUCCESS; 904 905 default: 906 if (!converted) { 907 zendi_convert_scalar_to_number(op1, op1_copy, result); 908 zendi_convert_scalar_to_number(op2, op2_copy, result); 909 converted = 1; 910 } else { 911 zend_error(E_ERROR, "Unsupported operand types"); 912 return FAILURE; /* unknown datatype */ 913 } 914 } 915 } 916} 917/* }}} */ 918 919ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 920{ 921 zval op1_copy, op2_copy; 922 int converted = 0; 923 924 while (1) { 925 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { 926 case TYPE_PAIR(IS_LONG, IS_LONG): { 927 long overflow; 928 929 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow); 930 Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG; 931 return SUCCESS; 932 933 } 934 case TYPE_PAIR(IS_LONG, IS_DOUBLE): 935 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2)); 936 return SUCCESS; 937 938 case TYPE_PAIR(IS_DOUBLE, IS_LONG): 939 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2))); 940 return SUCCESS; 941 942 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): 943 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2)); 944 return SUCCESS; 945 946 default: 947 if (!converted) { 948 zendi_convert_scalar_to_number(op1, op1_copy, result); 949 zendi_convert_scalar_to_number(op2, op2_copy, result); 950 converted = 1; 951 } else { 952 zend_error(E_ERROR, "Unsupported operand types"); 953 return FAILURE; /* unknown datatype */ 954 } 955 } 956 } 957} 958/* }}} */ 959 960ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 961{ 962 zval op1_copy, op2_copy; 963 int converted = 0; 964 965 while (1) { 966 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { 967 case TYPE_PAIR(IS_LONG, IS_LONG): 968 if (Z_LVAL_P(op2) == 0) { 969 zend_error(E_WARNING, "Division by zero"); 970 ZVAL_BOOL(result, 0); 971 return FAILURE; /* division by zero */ 972 } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) { 973 /* Prevent overflow error/crash */ 974 ZVAL_DOUBLE(result, (double) LONG_MIN / -1); 975 return SUCCESS; 976 } 977 if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */ 978 ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2)); 979 } else { 980 ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2)); 981 } 982 return SUCCESS; 983 984 case TYPE_PAIR(IS_DOUBLE, IS_LONG): 985 if (Z_LVAL_P(op2) == 0) { 986 zend_error(E_WARNING, "Division by zero"); 987 ZVAL_BOOL(result, 0); 988 return FAILURE; /* division by zero */ 989 } 990 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2)); 991 return SUCCESS; 992 993 case TYPE_PAIR(IS_LONG, IS_DOUBLE): 994 if (Z_DVAL_P(op2) == 0) { 995 zend_error(E_WARNING, "Division by zero"); 996 ZVAL_BOOL(result, 0); 997 return FAILURE; /* division by zero */ 998 } 999 ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2)); 1000 return SUCCESS; 1001 1002 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): 1003 if (Z_DVAL_P(op2) == 0) { 1004 zend_error(E_WARNING, "Division by zero"); 1005 ZVAL_BOOL(result, 0); 1006 return FAILURE; /* division by zero */ 1007 } 1008 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2)); 1009 return SUCCESS; 1010 1011 default: 1012 if (!converted) { 1013 zendi_convert_scalar_to_number(op1, op1_copy, result); 1014 zendi_convert_scalar_to_number(op2, op2_copy, result); 1015 converted = 1; 1016 } else { 1017 zend_error(E_ERROR, "Unsupported operand types"); 1018 return FAILURE; /* unknown datatype */ 1019 } 1020 } 1021 } 1022} 1023/* }}} */ 1024 1025ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1026{ 1027 zval op1_copy, op2_copy; 1028 long op1_lval; 1029 1030 zendi_convert_to_long(op1, op1_copy, result); 1031 op1_lval = Z_LVAL_P(op1); 1032 zendi_convert_to_long(op2, op2_copy, result); 1033 1034 if (Z_LVAL_P(op2) == 0) { 1035 zend_error(E_WARNING, "Division by zero"); 1036 ZVAL_BOOL(result, 0); 1037 return FAILURE; /* modulus by zero */ 1038 } 1039 1040 if (Z_LVAL_P(op2) == -1) { 1041 /* Prevent overflow error/crash if op1==LONG_MIN */ 1042 ZVAL_LONG(result, 0); 1043 return SUCCESS; 1044 } 1045 1046 ZVAL_LONG(result, op1_lval % Z_LVAL_P(op2)); 1047 return SUCCESS; 1048} 1049/* }}} */ 1050 1051ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1052{ 1053 zval op1_copy, op2_copy; 1054 long op1_lval; 1055 1056 zendi_convert_to_boolean(op1, op1_copy, result); 1057 op1_lval = Z_LVAL_P(op1); 1058 zendi_convert_to_boolean(op2, op2_copy, result); 1059 ZVAL_BOOL(result, op1_lval ^ Z_LVAL_P(op2)); 1060 return SUCCESS; 1061} 1062/* }}} */ 1063 1064ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */ 1065{ 1066 zval op1_copy; 1067 1068 zendi_convert_to_boolean(op1, op1_copy, result); 1069 ZVAL_BOOL(result, !Z_LVAL_P(op1)); 1070 return SUCCESS; 1071} 1072/* }}} */ 1073 1074ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */ 1075{ 1076 zval op1_copy = *op1; 1077 1078 op1 = &op1_copy; 1079 1080 if (Z_TYPE_P(op1) == IS_LONG) { 1081 ZVAL_LONG(result, ~Z_LVAL_P(op1)); 1082 return SUCCESS; 1083 } else if (Z_TYPE_P(op1) == IS_DOUBLE) { 1084 ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1))); 1085 return SUCCESS; 1086 } else if (Z_TYPE_P(op1) == IS_STRING) { 1087 int i; 1088 1089 Z_TYPE_P(result) = IS_STRING; 1090 Z_STRVAL_P(result) = estrndup(Z_STRVAL_P(op1), Z_STRLEN_P(op1)); 1091 Z_STRLEN_P(result) = Z_STRLEN_P(op1); 1092 for (i = 0; i < Z_STRLEN_P(op1); i++) { 1093 Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i]; 1094 } 1095 return SUCCESS; 1096 } 1097 zend_error(E_ERROR, "Unsupported operand types"); 1098 return FAILURE; /* unknown datatype */ 1099} 1100/* }}} */ 1101 1102ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1103{ 1104 zval op1_copy, op2_copy; 1105 long op1_lval; 1106 1107 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) { 1108 zval *longer, *shorter; 1109 char *result_str; 1110 int i, result_len; 1111 1112 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) { 1113 longer = op1; 1114 shorter = op2; 1115 } else { 1116 longer = op2; 1117 shorter = op1; 1118 } 1119 1120 Z_TYPE_P(result) = IS_STRING; 1121 result_len = Z_STRLEN_P(longer); 1122 result_str = estrndup(Z_STRVAL_P(longer), Z_STRLEN_P(longer)); 1123 for (i = 0; i < Z_STRLEN_P(shorter); i++) { 1124 result_str[i] |= Z_STRVAL_P(shorter)[i]; 1125 } 1126 if (result==op1) { 1127 STR_FREE(Z_STRVAL_P(result)); 1128 } 1129 Z_STRVAL_P(result) = result_str; 1130 Z_STRLEN_P(result) = result_len; 1131 return SUCCESS; 1132 } 1133 zendi_convert_to_long(op1, op1_copy, result); 1134 op1_lval = Z_LVAL_P(op1); 1135 zendi_convert_to_long(op2, op2_copy, result); 1136 1137 ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2)); 1138 return SUCCESS; 1139} 1140/* }}} */ 1141 1142ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1143{ 1144 zval op1_copy, op2_copy; 1145 long op1_lval; 1146 1147 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) { 1148 zval *longer, *shorter; 1149 char *result_str; 1150 int i, result_len; 1151 1152 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) { 1153 longer = op1; 1154 shorter = op2; 1155 } else { 1156 longer = op2; 1157 shorter = op1; 1158 } 1159 1160 Z_TYPE_P(result) = IS_STRING; 1161 result_len = Z_STRLEN_P(shorter); 1162 result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter)); 1163 for (i = 0; i < Z_STRLEN_P(shorter); i++) { 1164 result_str[i] &= Z_STRVAL_P(longer)[i]; 1165 } 1166 if (result==op1) { 1167 STR_FREE(Z_STRVAL_P(result)); 1168 } 1169 Z_STRVAL_P(result) = result_str; 1170 Z_STRLEN_P(result) = result_len; 1171 return SUCCESS; 1172 } 1173 1174 1175 zendi_convert_to_long(op1, op1_copy, result); 1176 op1_lval = Z_LVAL_P(op1); 1177 zendi_convert_to_long(op2, op2_copy, result); 1178 1179 ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2)); 1180 return SUCCESS; 1181} 1182/* }}} */ 1183 1184ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1185{ 1186 zval op1_copy, op2_copy; 1187 long op1_lval; 1188 1189 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) { 1190 zval *longer, *shorter; 1191 char *result_str; 1192 int i, result_len; 1193 1194 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) { 1195 longer = op1; 1196 shorter = op2; 1197 } else { 1198 longer = op2; 1199 shorter = op1; 1200 } 1201 1202 Z_TYPE_P(result) = IS_STRING; 1203 result_len = Z_STRLEN_P(shorter); 1204 result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter)); 1205 for (i = 0; i < Z_STRLEN_P(shorter); i++) { 1206 result_str[i] ^= Z_STRVAL_P(longer)[i]; 1207 } 1208 if (result==op1) { 1209 STR_FREE(Z_STRVAL_P(result)); 1210 } 1211 Z_STRVAL_P(result) = result_str; 1212 Z_STRLEN_P(result) = result_len; 1213 return SUCCESS; 1214 } 1215 1216 zendi_convert_to_long(op1, op1_copy, result); 1217 op1_lval = Z_LVAL_P(op1); 1218 zendi_convert_to_long(op2, op2_copy, result); 1219 1220 ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2)); 1221 return SUCCESS; 1222} 1223/* }}} */ 1224 1225ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1226{ 1227 zval op1_copy, op2_copy; 1228 long op1_lval; 1229 1230 zendi_convert_to_long(op1, op1_copy, result); 1231 op1_lval = Z_LVAL_P(op1); 1232 zendi_convert_to_long(op2, op2_copy, result); 1233 ZVAL_LONG(result, op1_lval << Z_LVAL_P(op2)); 1234 return SUCCESS; 1235} 1236/* }}} */ 1237 1238ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1239{ 1240 zval op1_copy, op2_copy; 1241 long op1_lval; 1242 1243 zendi_convert_to_long(op1, op1_copy, result); 1244 op1_lval = Z_LVAL_P(op1); 1245 zendi_convert_to_long(op2, op2_copy, result); 1246 ZVAL_LONG(result, op1_lval >> Z_LVAL_P(op2)); 1247 return SUCCESS; 1248} 1249/* }}} */ 1250 1251/* must support result==op1 */ 1252ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */ 1253{ 1254 int length = Z_STRLEN_P(op1) + 1; 1255 char *buf; 1256 1257 if (IS_INTERNED(Z_STRVAL_P(op1))) { 1258 buf = (char *) emalloc(length + 1); 1259 memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); 1260 } else { 1261 buf = (char *) erealloc(Z_STRVAL_P(op1), length + 1); 1262 } 1263 buf[length - 1] = (char) Z_LVAL_P(op2); 1264 buf[length] = 0; 1265 ZVAL_STRINGL(result, buf, length, 0); 1266 return SUCCESS; 1267} 1268/* }}} */ 1269 1270/* must support result==op1 */ 1271ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */ 1272{ 1273 int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); 1274 char *buf; 1275 1276 if (IS_INTERNED(Z_STRVAL_P(op1))) { 1277 buf = (char *) emalloc(length+1); 1278 memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); 1279 } else { 1280 buf = (char *) erealloc(Z_STRVAL_P(op1), length+1); 1281 } 1282 memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); 1283 buf[length] = 0; 1284 ZVAL_STRINGL(result, buf, length, 0); 1285 return SUCCESS; 1286} 1287/* }}} */ 1288 1289ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1290{ 1291 zval op1_copy, op2_copy; 1292 int use_copy1 = 0, use_copy2 = 0; 1293 1294 if (Z_TYPE_P(op1) != IS_STRING) { 1295 zend_make_printable_zval(op1, &op1_copy, &use_copy1); 1296 } 1297 if (Z_TYPE_P(op2) != IS_STRING) { 1298 zend_make_printable_zval(op2, &op2_copy, &use_copy2); 1299 } 1300 1301 if (use_copy1) { 1302 /* We have created a converted copy of op1. Therefore, op1 won't become the result so 1303 * we have to free it. 1304 */ 1305 if (result == op1) { 1306 zval_dtor(op1); 1307 } 1308 op1 = &op1_copy; 1309 } 1310 if (use_copy2) { 1311 op2 = &op2_copy; 1312 } 1313 if (result==op1 && !IS_INTERNED(Z_STRVAL_P(op1))) { /* special case, perform operations on result */ 1314 uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); 1315 1316 if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) { 1317 efree(Z_STRVAL_P(result)); 1318 ZVAL_EMPTY_STRING(result); 1319 zend_error(E_ERROR, "String size overflow"); 1320 } 1321 1322 Z_STRVAL_P(result) = erealloc(Z_STRVAL_P(result), res_len+1); 1323 1324 memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); 1325 Z_STRVAL_P(result)[res_len]=0; 1326 Z_STRLEN_P(result) = res_len; 1327 } else { 1328 int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); 1329 char *buf = (char *) emalloc(length + 1); 1330 1331 memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); 1332 memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); 1333 buf[length] = 0; 1334 ZVAL_STRINGL(result, buf, length, 0); 1335 } 1336 if (use_copy1) { 1337 zval_dtor(op1); 1338 } 1339 if (use_copy2) { 1340 zval_dtor(op2); 1341 } 1342 return SUCCESS; 1343} 1344/* }}} */ 1345 1346ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC) /* {{{ */ 1347{ 1348 zval op1_copy, op2_copy; 1349 int use_copy1 = 0, use_copy2 = 0; 1350 1351 if (Z_TYPE_P(op1) != IS_STRING) { 1352 zend_make_printable_zval(op1, &op1_copy, &use_copy1); 1353 } 1354 if (Z_TYPE_P(op2) != IS_STRING) { 1355 zend_make_printable_zval(op2, &op2_copy, &use_copy2); 1356 } 1357 1358 if (use_copy1) { 1359 op1 = &op1_copy; 1360 } 1361 if (use_copy2) { 1362 op2 = &op2_copy; 1363 } 1364 1365 if (case_insensitive) { 1366 ZVAL_LONG(result, zend_binary_zval_strcasecmp(op1, op2)); 1367 } else { 1368 ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2)); 1369 } 1370 1371 if (use_copy1) { 1372 zval_dtor(op1); 1373 } 1374 if (use_copy2) { 1375 zval_dtor(op2); 1376 } 1377 return SUCCESS; 1378} 1379/* }}} */ 1380 1381ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1382{ 1383 return string_compare_function_ex(result, op1, op2, 0 TSRMLS_CC); 1384} 1385/* }}} */ 1386 1387ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1388{ 1389 return string_compare_function_ex(result, op1, op2, 1 TSRMLS_CC); 1390} 1391/* }}} */ 1392 1393#if HAVE_STRCOLL 1394ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1395{ 1396 zval op1_copy, op2_copy; 1397 int use_copy1 = 0, use_copy2 = 0; 1398 1399 if (Z_TYPE_P(op1) != IS_STRING) { 1400 zend_make_printable_zval(op1, &op1_copy, &use_copy1); 1401 } 1402 if (Z_TYPE_P(op2) != IS_STRING) { 1403 zend_make_printable_zval(op2, &op2_copy, &use_copy2); 1404 } 1405 1406 if (use_copy1) { 1407 op1 = &op1_copy; 1408 } 1409 if (use_copy2) { 1410 op2 = &op2_copy; 1411 } 1412 1413 ZVAL_LONG(result, strcoll(Z_STRVAL_P(op1), Z_STRVAL_P(op2))); 1414 1415 if (use_copy1) { 1416 zval_dtor(op1); 1417 } 1418 if (use_copy2) { 1419 zval_dtor(op2); 1420 } 1421 return SUCCESS; 1422} 1423/* }}} */ 1424#endif 1425 1426ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1427{ 1428 zval op1_copy, op2_copy; 1429 1430 op1_copy = *op1; 1431 zval_copy_ctor(&op1_copy); 1432 1433 op2_copy = *op2; 1434 zval_copy_ctor(&op2_copy); 1435 1436 convert_to_double(&op1_copy); 1437 convert_to_double(&op2_copy); 1438 1439 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy))); 1440 1441 return SUCCESS; 1442} 1443/* }}} */ 1444 1445static inline void zend_free_obj_get_result(zval *op TSRMLS_DC) /* {{{ */ 1446{ 1447 if (Z_REFCOUNT_P(op) == 0) { 1448 GC_REMOVE_ZVAL_FROM_BUFFER(op); 1449 zval_dtor(op); 1450 FREE_ZVAL(op); 1451 } else { 1452 zval_ptr_dtor(&op); 1453 } 1454} 1455/* }}} */ 1456 1457ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1458{ 1459 int ret; 1460 int converted = 0; 1461 zval op1_copy, op2_copy; 1462 zval *op_free; 1463 1464 while (1) { 1465 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { 1466 case TYPE_PAIR(IS_LONG, IS_LONG): 1467 ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0)); 1468 return SUCCESS; 1469 1470 case TYPE_PAIR(IS_DOUBLE, IS_LONG): 1471 Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2); 1472 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); 1473 return SUCCESS; 1474 1475 case TYPE_PAIR(IS_LONG, IS_DOUBLE): 1476 Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2); 1477 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); 1478 return SUCCESS; 1479 1480 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): 1481 if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) { 1482 ZVAL_LONG(result, 0); 1483 } else { 1484 Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2); 1485 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); 1486 } 1487 return SUCCESS; 1488 1489 case TYPE_PAIR(IS_ARRAY, IS_ARRAY): 1490 zend_compare_arrays(result, op1, op2 TSRMLS_CC); 1491 return SUCCESS; 1492 1493 case TYPE_PAIR(IS_NULL, IS_NULL): 1494 ZVAL_LONG(result, 0); 1495 return SUCCESS; 1496 1497 case TYPE_PAIR(IS_NULL, IS_BOOL): 1498 ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0); 1499 return SUCCESS; 1500 1501 case TYPE_PAIR(IS_BOOL, IS_NULL): 1502 ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0); 1503 return SUCCESS; 1504 1505 case TYPE_PAIR(IS_BOOL, IS_BOOL): 1506 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2))); 1507 return SUCCESS; 1508 1509 case TYPE_PAIR(IS_STRING, IS_STRING): 1510 zendi_smart_strcmp(result, op1, op2); 1511 return SUCCESS; 1512 1513 case TYPE_PAIR(IS_NULL, IS_STRING): 1514 ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2))); 1515 return SUCCESS; 1516 1517 case TYPE_PAIR(IS_STRING, IS_NULL): 1518 ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0)); 1519 return SUCCESS; 1520 1521 case TYPE_PAIR(IS_OBJECT, IS_NULL): 1522 ZVAL_LONG(result, 1); 1523 return SUCCESS; 1524 1525 case TYPE_PAIR(IS_NULL, IS_OBJECT): 1526 ZVAL_LONG(result, -1); 1527 return SUCCESS; 1528 1529 case TYPE_PAIR(IS_OBJECT, IS_OBJECT): 1530 /* If both are objects sharing the same comparision handler then use is */ 1531 if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) { 1532 if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) { 1533 /* object handles are identical, apprently this is the same object */ 1534 ZVAL_LONG(result, 0); 1535 return SUCCESS; 1536 } 1537 ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC)); 1538 return SUCCESS; 1539 } 1540 /* break missing intentionally */ 1541 1542 default: 1543 if (Z_TYPE_P(op1) == IS_OBJECT) { 1544 if (Z_OBJ_HT_P(op1)->get) { 1545 op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC); 1546 ret = compare_function(result, op_free, op2 TSRMLS_CC); 1547 zend_free_obj_get_result(op_free TSRMLS_CC); 1548 return ret; 1549 } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) { 1550 ALLOC_INIT_ZVAL(op_free); 1551 if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) { 1552 ZVAL_LONG(result, 1); 1553 zend_free_obj_get_result(op_free TSRMLS_CC); 1554 return SUCCESS; 1555 } 1556 ret = compare_function(result, op_free, op2 TSRMLS_CC); 1557 zend_free_obj_get_result(op_free TSRMLS_CC); 1558 return ret; 1559 } 1560 } 1561 if (Z_TYPE_P(op2) == IS_OBJECT) { 1562 if (Z_OBJ_HT_P(op2)->get) { 1563 op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC); 1564 ret = compare_function(result, op1, op_free TSRMLS_CC); 1565 zend_free_obj_get_result(op_free TSRMLS_CC); 1566 return ret; 1567 } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) { 1568 ALLOC_INIT_ZVAL(op_free); 1569 if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) { 1570 ZVAL_LONG(result, -1); 1571 zend_free_obj_get_result(op_free TSRMLS_CC); 1572 return SUCCESS; 1573 } 1574 ret = compare_function(result, op1, op_free TSRMLS_CC); 1575 zend_free_obj_get_result(op_free TSRMLS_CC); 1576 return ret; 1577 } else if (Z_TYPE_P(op1) == IS_OBJECT) { 1578 ZVAL_LONG(result, 1); 1579 return SUCCESS; 1580 } 1581 } 1582 if (!converted) { 1583 if (Z_TYPE_P(op1) == IS_NULL) { 1584 zendi_convert_to_boolean(op2, op2_copy, result); 1585 ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0); 1586 return SUCCESS; 1587 } else if (Z_TYPE_P(op2) == IS_NULL) { 1588 zendi_convert_to_boolean(op1, op1_copy, result); 1589 ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0); 1590 return SUCCESS; 1591 } else if (Z_TYPE_P(op1) == IS_BOOL) { 1592 zendi_convert_to_boolean(op2, op2_copy, result); 1593 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2))); 1594 return SUCCESS; 1595 } else if (Z_TYPE_P(op2) == IS_BOOL) { 1596 zendi_convert_to_boolean(op1, op1_copy, result); 1597 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2))); 1598 return SUCCESS; 1599 } else { 1600 zendi_convert_scalar_to_number(op1, op1_copy, result); 1601 zendi_convert_scalar_to_number(op2, op2_copy, result); 1602 converted = 1; 1603 } 1604 } else if (Z_TYPE_P(op1)==IS_ARRAY) { 1605 ZVAL_LONG(result, 1); 1606 return SUCCESS; 1607 } else if (Z_TYPE_P(op2)==IS_ARRAY) { 1608 ZVAL_LONG(result, -1); 1609 return SUCCESS; 1610 } else if (Z_TYPE_P(op1)==IS_OBJECT) { 1611 ZVAL_LONG(result, 1); 1612 return SUCCESS; 1613 } else if (Z_TYPE_P(op2)==IS_OBJECT) { 1614 ZVAL_LONG(result, -1); 1615 return SUCCESS; 1616 } else { 1617 ZVAL_LONG(result, 0); 1618 return FAILURE; 1619 } 1620 } 1621 } 1622} 1623/* }}} */ 1624 1625static int hash_zval_identical_function(const zval **z1, const zval **z2) /* {{{ */ 1626{ 1627 zval result; 1628 TSRMLS_FETCH(); 1629 1630 /* is_identical_function() returns 1 in case of identity and 0 in case 1631 * of a difference; 1632 * whereas this comparison function is expected to return 0 on identity, 1633 * and non zero otherwise. 1634 */ 1635 if (is_identical_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) { 1636 return 1; 1637 } 1638 return !Z_LVAL(result); 1639} 1640/* }}} */ 1641 1642ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1643{ 1644 Z_TYPE_P(result) = IS_BOOL; 1645 if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { 1646 Z_LVAL_P(result) = 0; 1647 return SUCCESS; 1648 } 1649 switch (Z_TYPE_P(op1)) { 1650 case IS_NULL: 1651 Z_LVAL_P(result) = 1; 1652 break; 1653 case IS_BOOL: 1654 case IS_LONG: 1655 case IS_RESOURCE: 1656 Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); 1657 break; 1658 case IS_DOUBLE: 1659 Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); 1660 break; 1661 case IS_STRING: 1662 Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) 1663 && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)))); 1664 break; 1665 case IS_ARRAY: 1666 Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) || 1667 zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0); 1668 break; 1669 case IS_OBJECT: 1670 if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) { 1671 Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)); 1672 } else { 1673 Z_LVAL_P(result) = 0; 1674 } 1675 break; 1676 default: 1677 Z_LVAL_P(result) = 0; 1678 return FAILURE; 1679 } 1680 return SUCCESS; 1681} 1682/* }}} */ 1683 1684ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1685{ 1686 if (is_identical_function(result, op1, op2 TSRMLS_CC) == FAILURE) { 1687 return FAILURE; 1688 } 1689 Z_LVAL_P(result) = !Z_LVAL_P(result); 1690 return SUCCESS; 1691} 1692/* }}} */ 1693 1694ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1695{ 1696 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) { 1697 return FAILURE; 1698 } 1699 ZVAL_BOOL(result, (Z_LVAL_P(result) == 0)); 1700 return SUCCESS; 1701} 1702/* }}} */ 1703 1704ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1705{ 1706 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) { 1707 return FAILURE; 1708 } 1709 ZVAL_BOOL(result, (Z_LVAL_P(result) != 0)); 1710 return SUCCESS; 1711} 1712/* }}} */ 1713 1714ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1715{ 1716 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) { 1717 return FAILURE; 1718 } 1719 ZVAL_BOOL(result, (Z_LVAL_P(result) < 0)); 1720 return SUCCESS; 1721} 1722/* }}} */ 1723 1724ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 1725{ 1726 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) { 1727 return FAILURE; 1728 } 1729 ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0)); 1730 return SUCCESS; 1731} 1732/* }}} */ 1733 1734ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC) /* {{{ */ 1735{ 1736 zend_uint i; 1737 1738 for (i=0; i<instance_ce->num_interfaces; i++) { 1739 if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) { 1740 return 1; 1741 } 1742 } 1743 if (!interfaces_only) { 1744 while (instance_ce) { 1745 if (instance_ce == ce) { 1746 return 1; 1747 } 1748 instance_ce = instance_ce->parent; 1749 } 1750 } 1751 1752 return 0; 1753} 1754/* }}} */ 1755 1756ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC) /* {{{ */ 1757{ 1758 return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC); 1759} 1760/* }}} */ 1761 1762#define LOWER_CASE 1 1763#define UPPER_CASE 2 1764#define NUMERIC 3 1765 1766static void increment_string(zval *str) /* {{{ */ 1767{ 1768 int carry=0; 1769 int pos=Z_STRLEN_P(str)-1; 1770 char *s=Z_STRVAL_P(str); 1771 char *t; 1772 int last=0; /* Shut up the compiler warning */ 1773 int ch; 1774 1775 if (Z_STRLEN_P(str) == 0) { 1776 STR_FREE(Z_STRVAL_P(str)); 1777 Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1); 1778 Z_STRLEN_P(str) = 1; 1779 return; 1780 } 1781 1782 if (IS_INTERNED(s)) { 1783 s = (char*) emalloc(Z_STRLEN_P(str) + 1); 1784 memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1); 1785 Z_STRVAL_P(str) = s; 1786 } 1787 1788 while (pos >= 0) { 1789 ch = s[pos]; 1790 if (ch >= 'a' && ch <= 'z') { 1791 if (ch == 'z') { 1792 s[pos] = 'a'; 1793 carry=1; 1794 } else { 1795 s[pos]++; 1796 carry=0; 1797 } 1798 last=LOWER_CASE; 1799 } else if (ch >= 'A' && ch <= 'Z') { 1800 if (ch == 'Z') { 1801 s[pos] = 'A'; 1802 carry=1; 1803 } else { 1804 s[pos]++; 1805 carry=0; 1806 } 1807 last=UPPER_CASE; 1808 } else if (ch >= '0' && ch <= '9') { 1809 if (ch == '9') { 1810 s[pos] = '0'; 1811 carry=1; 1812 } else { 1813 s[pos]++; 1814 carry=0; 1815 } 1816 last = NUMERIC; 1817 } else { 1818 carry=0; 1819 break; 1820 } 1821 if (carry == 0) { 1822 break; 1823 } 1824 pos--; 1825 } 1826 1827 if (carry) { 1828 t = (char *) emalloc(Z_STRLEN_P(str)+1+1); 1829 memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str)); 1830 Z_STRLEN_P(str)++; 1831 t[Z_STRLEN_P(str)] = '\0'; 1832 switch (last) { 1833 case NUMERIC: 1834 t[0] = '1'; 1835 break; 1836 case UPPER_CASE: 1837 t[0] = 'A'; 1838 break; 1839 case LOWER_CASE: 1840 t[0] = 'a'; 1841 break; 1842 } 1843 STR_FREE(Z_STRVAL_P(str)); 1844 Z_STRVAL_P(str) = t; 1845 } 1846} 1847/* }}} */ 1848 1849ZEND_API int increment_function(zval *op1) /* {{{ */ 1850{ 1851 switch (Z_TYPE_P(op1)) { 1852 case IS_LONG: 1853 if (Z_LVAL_P(op1) == LONG_MAX) { 1854 /* switch to double */ 1855 double d = (double)Z_LVAL_P(op1); 1856 ZVAL_DOUBLE(op1, d+1); 1857 } else { 1858 Z_LVAL_P(op1)++; 1859 } 1860 break; 1861 case IS_DOUBLE: 1862 Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1; 1863 break; 1864 case IS_NULL: 1865 ZVAL_LONG(op1, 1); 1866 break; 1867 case IS_STRING: { 1868 long lval; 1869 double dval; 1870 1871 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) { 1872 case IS_LONG: 1873 str_efree(Z_STRVAL_P(op1)); 1874 if (lval == LONG_MAX) { 1875 /* switch to double */ 1876 double d = (double)lval; 1877 ZVAL_DOUBLE(op1, d+1); 1878 } else { 1879 ZVAL_LONG(op1, lval+1); 1880 } 1881 break; 1882 case IS_DOUBLE: 1883 str_efree(Z_STRVAL_P(op1)); 1884 ZVAL_DOUBLE(op1, dval+1); 1885 break; 1886 default: 1887 /* Perl style string increment */ 1888 increment_string(op1); 1889 break; 1890 } 1891 } 1892 break; 1893 default: 1894 return FAILURE; 1895 } 1896 return SUCCESS; 1897} 1898/* }}} */ 1899 1900ZEND_API int decrement_function(zval *op1) /* {{{ */ 1901{ 1902 long lval; 1903 double dval; 1904 1905 switch (Z_TYPE_P(op1)) { 1906 case IS_LONG: 1907 if (Z_LVAL_P(op1) == LONG_MIN) { 1908 double d = (double)Z_LVAL_P(op1); 1909 ZVAL_DOUBLE(op1, d-1); 1910 } else { 1911 Z_LVAL_P(op1)--; 1912 } 1913 break; 1914 case IS_DOUBLE: 1915 Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1; 1916 break; 1917 case IS_STRING: /* Like perl we only support string increment */ 1918 if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */ 1919 STR_FREE(Z_STRVAL_P(op1)); 1920 ZVAL_LONG(op1, -1); 1921 break; 1922 } 1923 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) { 1924 case IS_LONG: 1925 STR_FREE(Z_STRVAL_P(op1)); 1926 if (lval == LONG_MIN) { 1927 double d = (double)lval; 1928 ZVAL_DOUBLE(op1, d-1); 1929 } else { 1930 ZVAL_LONG(op1, lval-1); 1931 } 1932 break; 1933 case IS_DOUBLE: 1934 STR_FREE(Z_STRVAL_P(op1)); 1935 ZVAL_DOUBLE(op1, dval - 1); 1936 break; 1937 } 1938 break; 1939 default: 1940 return FAILURE; 1941 } 1942 1943 return SUCCESS; 1944} 1945/* }}} */ 1946 1947ZEND_API int zval_is_true(zval *op) /* {{{ */ 1948{ 1949 convert_to_boolean(op); 1950 return (Z_LVAL_P(op) ? 1 : 0); 1951} 1952/* }}} */ 1953 1954#ifdef ZEND_USE_TOLOWER_L 1955ZEND_API void zend_update_current_locale(void) /* {{{ */ 1956{ 1957 current_locale = _get_current_locale(); 1958} 1959/* }}} */ 1960#endif 1961 1962ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length) /* {{{ */ 1963{ 1964 register unsigned char *str = (unsigned char*)source; 1965 register unsigned char *result = (unsigned char*)dest; 1966 register unsigned char *end = str + length; 1967 1968 while (str < end) { 1969 *result++ = zend_tolower_ascii(*str++); 1970 } 1971 *result = '\0'; 1972 1973 return dest; 1974} 1975/* }}} */ 1976 1977ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length) /* {{{ */ 1978{ 1979 return zend_str_tolower_copy((char *)emalloc(length+1), source, length); 1980} 1981/* }}} */ 1982 1983ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */ 1984{ 1985 register unsigned char *p = (unsigned char*)str; 1986 register unsigned char *end = p + length; 1987 1988 while (p < end) { 1989 *p = zend_tolower_ascii(*p); 1990 p++; 1991 } 1992} 1993/* }}} */ 1994 1995ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */ 1996{ 1997 int retval; 1998 1999 if (s1 == s2) { 2000 return 0; 2001 } 2002 retval = memcmp(s1, s2, MIN(len1, len2)); 2003 if (!retval) { 2004 return (len1 - len2); 2005 } else { 2006 return retval; 2007 } 2008} 2009/* }}} */ 2010 2011ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */ 2012{ 2013 int retval; 2014 2015 if (s1 == s2) { 2016 return 0; 2017 } 2018 retval = memcmp(s1, s2, MIN(length, MIN(len1, len2))); 2019 if (!retval) { 2020 return (MIN(length, len1) - MIN(length, len2)); 2021 } else { 2022 return retval; 2023 } 2024} 2025/* }}} */ 2026 2027ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */ 2028{ 2029 int len; 2030 int c1, c2; 2031 2032 if (s1 == s2) { 2033 return 0; 2034 } 2035 2036 len = MIN(len1, len2); 2037 while (len--) { 2038 c1 = zend_tolower_ascii(*(unsigned char *)s1++); 2039 c2 = zend_tolower_ascii(*(unsigned char *)s2++); 2040 if (c1 != c2) { 2041 return c1 - c2; 2042 } 2043 } 2044 2045 return len1 - len2; 2046} 2047/* }}} */ 2048 2049ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */ 2050{ 2051 int len; 2052 int c1, c2; 2053 2054 if (s1 == s2) { 2055 return 0; 2056 } 2057 len = MIN(length, MIN(len1, len2)); 2058 while (len--) { 2059 c1 = zend_tolower_ascii(*(unsigned char *)s1++); 2060 c2 = zend_tolower_ascii(*(unsigned char *)s2++); 2061 if (c1 != c2) { 2062 return c1 - c2; 2063 } 2064 } 2065 2066 return MIN(length, len1) - MIN(length, len2); 2067} 2068/* }}} */ 2069 2070ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */ 2071{ 2072 int len; 2073 int c1, c2; 2074 2075 if (s1 == s2) { 2076 return 0; 2077 } 2078 2079 len = MIN(len1, len2); 2080 while (len--) { 2081 c1 = zend_tolower((int)*(unsigned char *)s1++); 2082 c2 = zend_tolower((int)*(unsigned char *)s2++); 2083 if (c1 != c2) { 2084 return c1 - c2; 2085 } 2086 } 2087 2088 return len1 - len2; 2089} 2090/* }}} */ 2091 2092ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */ 2093{ 2094 int len; 2095 int c1, c2; 2096 2097 if (s1 == s2) { 2098 return 0; 2099 } 2100 len = MIN(length, MIN(len1, len2)); 2101 while (len--) { 2102 c1 = zend_tolower((int)*(unsigned char *)s1++); 2103 c2 = zend_tolower((int)*(unsigned char *)s2++); 2104 if (c1 != c2) { 2105 return c1 - c2; 2106 } 2107 } 2108 2109 return MIN(length, len1) - MIN(length, len2); 2110} 2111/* }}} */ 2112 2113ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */ 2114{ 2115 return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2)); 2116} 2117/* }}} */ 2118 2119ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */ 2120{ 2121 return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3)); 2122} 2123/* }}} */ 2124 2125ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */ 2126{ 2127 return zend_binary_strcasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2)); 2128} 2129/* }}} */ 2130 2131ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */ 2132{ 2133 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)); 2134} 2135/* }}} */ 2136 2137ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */ 2138{ 2139 int ret1, ret2; 2140 int oflow1, oflow2; 2141 long lval1, lval2; 2142 double dval1, dval2; 2143 2144 if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) && 2145 (ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) { 2146#if ULONG_MAX == 0xFFFFFFFF 2147 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. && 2148 ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/) 2149 || (oflow1 == -1 && dval1 < -9007199254740991.))) { 2150#else 2151 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) { 2152#endif 2153 /* both values are integers overflown to the same side, and the 2154 * double comparison may have resulted in crucial accuracy lost */ 2155 goto string_cmp; 2156 } 2157 if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) { 2158 if (ret1!=IS_DOUBLE) { 2159 if (oflow2) { 2160 /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */ 2161 ZVAL_LONG(result, -1 * oflow2); 2162 return; 2163 } 2164 dval1 = (double) lval1; 2165 } else if (ret2!=IS_DOUBLE) { 2166 if (oflow1) { 2167 ZVAL_LONG(result, oflow1); 2168 return; 2169 } 2170 dval2 = (double) lval2; 2171 } else if (dval1 == dval2 && !zend_finite(dval1)) { 2172 /* Both values overflowed and have the same sign, 2173 * so a numeric comparison would be inaccurate */ 2174 goto string_cmp; 2175 } 2176 Z_DVAL_P(result) = dval1 - dval2; 2177 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); 2178 } else { /* they both have to be long's */ 2179 ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0)); 2180 } 2181 } else { 2182string_cmp: 2183 Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2); 2184 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result))); 2185 } 2186} 2187/* }}} */ 2188 2189static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC) /* {{{ */ 2190{ 2191 zval result; 2192 2193 if (compare_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) { 2194 return 1; 2195 } 2196 return Z_LVAL(result); 2197} 2198/* }}} */ 2199 2200ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */ 2201{ 2202 return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC); 2203} 2204/* }}} */ 2205 2206ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */ 2207{ 2208 ZVAL_LONG(result, ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC)); 2209} 2210/* }}} */ 2211 2212ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC) /* {{{ */ 2213{ 2214 zend_compare_symbol_tables(result, Z_ARRVAL_P(a1), Z_ARRVAL_P(a2) TSRMLS_CC); 2215} 2216/* }}} */ 2217 2218ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC) /* {{{ */ 2219{ 2220 Z_TYPE_P(result) = IS_LONG; 2221 2222 if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) { 2223 Z_LVAL_P(result) = 0; 2224 return; 2225 } 2226 2227 if (Z_OBJ_HT_P(o1)->compare_objects == NULL) { 2228 Z_LVAL_P(result) = 1; 2229 } else { 2230 Z_LVAL_P(result) = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC); 2231 } 2232} 2233/* }}} */ 2234 2235ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */ 2236{ 2237 TSRMLS_FETCH(); 2238 2239 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op)); 2240} 2241/* }}} */ 2242 2243/* 2244 * Local variables: 2245 * tab-width: 4 2246 * c-basic-offset: 4 2247 * indent-tabs-mode: t 2248 * End: 2249 */ 2250