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