Back to index

php5  5.3.10
zend_operators.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | Zend Engine                                                          |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 2.00 of the Zend license,     |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.zend.com/license/2_00.txt.                                |
00011    | If you did not receive a copy of the Zend license and are unable to  |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@zend.com so we can mail you a copy immediately.              |
00014    +----------------------------------------------------------------------+
00015    | Authors: Andi Gutmans <andi@zend.com>                                |
00016    |          Zeev Suraski <zeev@zend.com>                                |
00017    +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: zend_operators.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include <ctype.h>
00023 
00024 #include "zend.h"
00025 #include "zend_operators.h"
00026 #include "zend_variables.h"
00027 #include "zend_globals.h"
00028 #include "zend_list.h"
00029 #include "zend_API.h"
00030 #include "zend_multiply.h"
00031 #include "zend_strtod.h"
00032 #include "zend_exceptions.h"
00033 #include "zend_closures.h"
00034 
00035 #define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
00036 
00037 #if ZEND_USE_TOLOWER_L
00038 #include <locale.h>
00039 static _locale_t current_locale = NULL;
00040 /* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
00041 #define zend_tolower(c) _tolower_l(c, current_locale)
00042 #else
00043 #define zend_tolower(c) tolower(c)
00044 #endif
00045 
00046 #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
00047 
00048 ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */
00049 {
00050        int retval;
00051 
00052        if (!str_len) {
00053               str_len = strlen(str);
00054        }
00055        retval = strtol(str, NULL, 0);
00056        if (str_len>0) {
00057               switch (str[str_len-1]) {
00058                      case 'g':
00059                      case 'G':
00060                             retval *= 1024;
00061                             /* break intentionally missing */
00062                      case 'm':
00063                      case 'M':
00064                             retval *= 1024;
00065                             /* break intentionally missing */
00066                      case 'k':
00067                      case 'K':
00068                             retval *= 1024;
00069                             break;
00070               }
00071        }
00072        return retval;
00073 }
00074 /* }}} */
00075 
00076 ZEND_API long zend_atol(const char *str, int str_len) /* {{{ */
00077 {
00078        long retval;
00079 
00080        if (!str_len) {
00081               str_len = strlen(str);
00082        }
00083        retval = strtol(str, NULL, 0);
00084        if (str_len>0) {
00085               switch (str[str_len-1]) {
00086                      case 'g':
00087                      case 'G':
00088                             retval *= 1024;
00089                             /* break intentionally missing */
00090                      case 'm':
00091                      case 'M':
00092                             retval *= 1024;
00093                             /* break intentionally missing */
00094                      case 'k':
00095                      case 'K':
00096                             retval *= 1024;
00097                             break;
00098               }
00099        }
00100        return retval;
00101 }
00102 /* }}} */
00103 
00104 ZEND_API double zend_string_to_double(const char *number, zend_uint length) /* {{{ */
00105 {
00106        double divisor = 10.0;
00107        double result = 0.0;
00108        double exponent;
00109        const char *end = number+length;
00110        const char *digit = number;
00111 
00112        if (!length) {
00113               return result;
00114        }
00115 
00116        while (digit < end) {
00117               if ((*digit <= '9' && *digit >= '0')) {
00118                      result *= 10;
00119                      result += *digit - '0';
00120               } else if (*digit == '.') {
00121                      digit++;
00122                      break;
00123               } else if (toupper(*digit) == 'E') {
00124                      exponent = (double) atoi(digit+1);
00125                      result *= pow(10.0, exponent);
00126                      return result;
00127               } else {
00128                      return result;
00129               }
00130               digit++;
00131        }
00132 
00133        while (digit < end) {
00134               if ((*digit <= '9' && *digit >= '0')) {
00135                      result += (*digit - '0') / divisor;
00136                      divisor *= 10;
00137               } else if (toupper(*digit) == 'E') {
00138                      exponent = (double) atoi(digit+1);
00139                      result *= pow(10.0, exponent);
00140                      return result;
00141               } else {
00142                      return result;
00143               }
00144               digit++;
00145        }
00146        return result;
00147 }
00148 /* }}} */
00149 
00150 ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
00151 {
00152        switch (Z_TYPE_P(op)) {
00153               case IS_STRING:
00154                      {
00155                             char *strval;
00156 
00157                             strval = Z_STRVAL_P(op);
00158                             if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
00159                                    ZVAL_LONG(op, 0);
00160                             }
00161                             STR_FREE(strval);
00162                             break;
00163                      }
00164               case IS_BOOL:
00165                      Z_TYPE_P(op) = IS_LONG;
00166                      break;
00167               case IS_RESOURCE:
00168                      zend_list_delete(Z_LVAL_P(op));
00169                      Z_TYPE_P(op) = IS_LONG;
00170                      break;
00171               case IS_OBJECT:
00172                      convert_to_long_base(op, 10);
00173                      break;
00174               case IS_NULL:
00175                      ZVAL_LONG(op, 0);
00176                      break;
00177        }
00178 }
00179 /* }}} */
00180 
00181 /* {{{ zendi_convert_scalar_to_number */
00182 #define zendi_convert_scalar_to_number(op, holder, result)                   \
00183        if (op==result) {                                                                                 \
00184               if (Z_TYPE_P(op) != IS_LONG) {                                                      \
00185                      convert_scalar_to_number(op TSRMLS_CC);                               \
00186               }                                                                                                        \
00187        } else {                                                                                                 \
00188               switch (Z_TYPE_P(op)) {                                                                    \
00189                      case IS_STRING:                                                                            \
00190                             {                                                                                          \
00191                                    if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) {    \
00192                                           ZVAL_LONG(&(holder), 0);                                              \
00193                                    }                                                                                                 \
00194                                    (op) = &(holder);                                                                   \
00195                                    break;                                                                                     \
00196                             }                                                                                                        \
00197                      case IS_BOOL:                                                                                     \
00198                      case IS_RESOURCE:                                                                                 \
00199                             ZVAL_LONG(&(holder), Z_LVAL_P(op));                                                 \
00200                             (op) = &(holder);                                                                          \
00201                             break;                                                                                            \
00202                      case IS_NULL:                                                                                     \
00203                             ZVAL_LONG(&(holder), 0);                                                            \
00204                             (op) = &(holder);                                                                          \
00205                             break;                                                                                            \
00206                      case IS_OBJECT:                                                                                          \
00207                             (holder) = (*(op));                                                                        \
00208                             zval_copy_ctor(&(holder));                                                          \
00209                             convert_to_long_base(&(holder), 10);                                         \
00210                             if (Z_TYPE(holder) == IS_LONG) {                                             \
00211                                    (op) = &(holder);                                                                   \
00212                             }                                                                                                        \
00213                             break;                                                                                            \
00214               }                                                                                                                      \
00215        }
00216 
00217 /* }}} */
00218 
00219 /* {{{ zendi_convert_to_long */
00220 #define zendi_convert_to_long(op, holder, result)                                   \
00221        if (op == result) {                                                                               \
00222               convert_to_long(op);                                                                \
00223        } else if (Z_TYPE_P(op) != IS_LONG) {                                               \
00224               switch (Z_TYPE_P(op)) {                                                                    \
00225                      case IS_NULL:                                                                       \
00226                             Z_LVAL(holder) = 0;                                                          \
00227                             break;                                                                              \
00228                      case IS_DOUBLE:                                                                            \
00229                             Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op));       \
00230                             break;                                                                              \
00231                      case IS_STRING:                                                                            \
00232                             Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10);      \
00233                             break;                                                                              \
00234                      case IS_ARRAY:                                                                             \
00235                             Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
00236                             break;                                                                              \
00237                      case IS_OBJECT:                                                                            \
00238                             (holder) = (*(op));                                                          \
00239                             zval_copy_ctor(&(holder));                                            \
00240                             convert_to_long_base(&(holder), 10);                           \
00241                             break;                                                                              \
00242                      case IS_BOOL:                                                                       \
00243                      case IS_RESOURCE:                                                                   \
00244                             Z_LVAL(holder) = Z_LVAL_P(op);                                        \
00245                             break;                                                                              \
00246                      default:                                                                                   \
00247                             zend_error(E_WARNING, "Cannot convert to ordinal value");      \
00248                             Z_LVAL(holder) = 0;                                                          \
00249                             break;                                                                              \
00250               }                                                                                                        \
00251               Z_TYPE(holder) = IS_LONG;                                                           \
00252               (op) = &(holder);                                                                          \
00253        }
00254 
00255 /* }}} */
00256 
00257 /* {{{ zendi_convert_to_boolean */
00258 #define zendi_convert_to_boolean(op, holder, result)                         \
00259        if (op==result) {                                                                                 \
00260               convert_to_boolean(op);                                                                    \
00261        } else if (Z_TYPE_P(op) != IS_BOOL) {                                               \
00262               switch (Z_TYPE_P(op)) {                                                                    \
00263                      case IS_NULL:                                                                       \
00264                             Z_LVAL(holder) = 0;                                                          \
00265                             break;                                                                              \
00266                      case IS_RESOURCE:                                                                   \
00267                      case IS_LONG:                                                                       \
00268                             Z_LVAL(holder) = (Z_LVAL_P(op) ? 1 : 0);                \
00269                             break;                                                                              \
00270                      case IS_DOUBLE:                                                                            \
00271                             Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0);                \
00272                             break;                                                                              \
00273                      case IS_STRING:                                                                            \
00274                             if (Z_STRLEN_P(op) == 0                                                      \
00275                                    || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {     \
00276                                    Z_LVAL(holder) = 0;                                                   \
00277                             } else {                                                                            \
00278                                    Z_LVAL(holder) = 1;                                                   \
00279                             }                                                                                          \
00280                             break;                                                                              \
00281                      case IS_ARRAY:                                                                             \
00282                             Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
00283                             break;                                                                              \
00284                      case IS_OBJECT:                                                                            \
00285                             (holder) = (*(op));                                                          \
00286                             zval_copy_ctor(&(holder));                                            \
00287                             convert_to_boolean(&(holder));                                        \
00288                             break;                                                                              \
00289                      default:                                                                                   \
00290                             Z_LVAL(holder) = 0;                                                          \
00291                             break;                                                                              \
00292               }                                                                                                        \
00293               Z_TYPE(holder) = IS_BOOL;                                                           \
00294               (op) = &(holder);                                                                          \
00295        }
00296 
00297 /* }}} */
00298 
00299 /* {{{ convert_object_to_type */
00300 #define convert_object_to_type(op, ctype, conv_func)                                                                   \
00301        if (Z_OBJ_HT_P(op)->cast_object) {                                                                                            \
00302               zval dst;                                                                                                                                   \
00303               if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype TSRMLS_CC) == FAILURE) {                   \
00304                      zend_error(E_RECOVERABLE_ERROR,                                                                                        \
00305                             "Object of class %s could not be converted to %s", Z_OBJCE_P(op)->name,             \
00306                      zend_get_type_by_const(ctype));                                                                                        \
00307               } else {                                                                                                                                    \
00308                      zval_dtor(op);                                                                                                                       \
00309                      Z_TYPE_P(op) = ctype;                                                                                                         \
00310                      op->value = dst.value;                                                                                                        \
00311               }                                                                                                                                                  \
00312        } else {                                                                                                                                           \
00313               if (Z_OBJ_HT_P(op)->get) {                                                                                                    \
00314                      zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC);                                                  \
00315                      if (Z_TYPE_P(newop) != IS_OBJECT) {                                                                                    \
00316                             /* for safety - avoid loop */                                                                                   \
00317                             zval_dtor(op);                                                                                                                \
00318                             *op = *newop;                                                                                                          \
00319                             FREE_ZVAL(newop);                                                                                                      \
00320                             conv_func(op);                                                                                                                \
00321                      }                                                                                                                                           \
00322               }                                                                                                                                                  \
00323        }
00324 
00325 /* }}} */
00326 
00327 ZEND_API void convert_to_long(zval *op) /* {{{ */
00328 {
00329        if (Z_TYPE_P(op) != IS_LONG) {
00330               convert_to_long_base(op, 10);
00331        }
00332 }
00333 /* }}} */
00334 
00335 ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
00336 {
00337        long tmp;
00338 
00339        switch (Z_TYPE_P(op)) {
00340               case IS_NULL:
00341                      Z_LVAL_P(op) = 0;
00342                      break;
00343               case IS_RESOURCE: {
00344                             TSRMLS_FETCH();
00345 
00346                             zend_list_delete(Z_LVAL_P(op));
00347                      }
00348                      /* break missing intentionally */
00349               case IS_BOOL:
00350               case IS_LONG:
00351                      break;
00352               case IS_DOUBLE:
00353                      Z_LVAL_P(op) = zend_dval_to_lval(Z_DVAL_P(op));
00354                      break;
00355               case IS_STRING:
00356                      {
00357                             char *strval = Z_STRVAL_P(op);
00358 
00359                             Z_LVAL_P(op) = strtol(strval, NULL, base);
00360                             STR_FREE(strval);
00361                      }
00362                      break;
00363               case IS_ARRAY:
00364                      tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
00365                      zval_dtor(op);
00366                      Z_LVAL_P(op) = tmp;
00367                      break;
00368               case IS_OBJECT:
00369                      {
00370                             int retval = 1;
00371                             TSRMLS_FETCH();
00372 
00373                             convert_object_to_type(op, IS_LONG, convert_to_long);
00374 
00375                             if (Z_TYPE_P(op) == IS_LONG) {
00376                                    return;
00377                             }
00378                             zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name);
00379 
00380                             zval_dtor(op);
00381                             ZVAL_LONG(op, retval);
00382                             return;
00383                      }
00384               default:
00385                      zend_error(E_WARNING, "Cannot convert to ordinal value");
00386                      zval_dtor(op);
00387                      Z_LVAL_P(op) = 0;
00388                      break;
00389        }
00390 
00391        Z_TYPE_P(op) = IS_LONG;
00392 }
00393 /* }}} */
00394 
00395 ZEND_API void convert_to_double(zval *op) /* {{{ */
00396 {
00397        double tmp;
00398 
00399        switch (Z_TYPE_P(op)) {
00400               case IS_NULL:
00401                      Z_DVAL_P(op) = 0.0;
00402                      break;
00403               case IS_RESOURCE: {
00404                             TSRMLS_FETCH();
00405 
00406                             zend_list_delete(Z_LVAL_P(op));
00407                      }
00408                      /* break missing intentionally */
00409               case IS_BOOL:
00410               case IS_LONG:
00411                      Z_DVAL_P(op) = (double) Z_LVAL_P(op);
00412                      break;
00413               case IS_DOUBLE:
00414                      break;
00415               case IS_STRING:
00416                      {
00417                             char *strval = Z_STRVAL_P(op);
00418 
00419                             Z_DVAL_P(op) = zend_strtod(strval, NULL);
00420                             STR_FREE(strval);
00421                      }
00422                      break;
00423               case IS_ARRAY:
00424                      tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
00425                      zval_dtor(op);
00426                      Z_DVAL_P(op) = tmp;
00427                      break;
00428               case IS_OBJECT:
00429                      {
00430                             double retval = 1.0;
00431                             TSRMLS_FETCH();
00432 
00433                             convert_object_to_type(op, IS_DOUBLE, convert_to_double);
00434 
00435                             if (Z_TYPE_P(op) == IS_DOUBLE) {
00436                                    return;
00437                             }
00438                             zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
00439 
00440                             zval_dtor(op);
00441                             ZVAL_DOUBLE(op, retval);
00442                             break;
00443                      }
00444               default:
00445                      zend_error(E_WARNING, "Cannot convert to real value (type=%d)", Z_TYPE_P(op));
00446                      zval_dtor(op);
00447                      Z_DVAL_P(op) = 0;
00448                      break;
00449        }
00450        Z_TYPE_P(op) = IS_DOUBLE;
00451 }
00452 /* }}} */
00453 
00454 ZEND_API void convert_to_null(zval *op) /* {{{ */
00455 {
00456        if (Z_TYPE_P(op) == IS_OBJECT) {
00457               if (Z_OBJ_HT_P(op)->cast_object) {
00458                      zval *org;
00459                      TSRMLS_FETCH();
00460 
00461                      ALLOC_ZVAL(org);
00462                      *org = *op;
00463                      if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
00464                             zval_dtor(org);
00465                             return;
00466                      }
00467                      *op = *org;
00468                      FREE_ZVAL(org);
00469               }
00470        }
00471 
00472        zval_dtor(op);
00473        Z_TYPE_P(op) = IS_NULL;
00474 }
00475 /* }}} */
00476 
00477 ZEND_API void convert_to_boolean(zval *op) /* {{{ */
00478 {
00479        int tmp;
00480 
00481        switch (Z_TYPE_P(op)) {
00482               case IS_BOOL:
00483                      break;
00484               case IS_NULL:
00485                      Z_LVAL_P(op) = 0;
00486                      break;
00487               case IS_RESOURCE: {
00488                             TSRMLS_FETCH();
00489 
00490                             zend_list_delete(Z_LVAL_P(op));
00491                      }
00492                      /* break missing intentionally */
00493               case IS_LONG:
00494                      Z_LVAL_P(op) = (Z_LVAL_P(op) ? 1 : 0);
00495                      break;
00496               case IS_DOUBLE:
00497                      Z_LVAL_P(op) = (Z_DVAL_P(op) ? 1 : 0);
00498                      break;
00499               case IS_STRING:
00500                      {
00501                             char *strval = Z_STRVAL_P(op);
00502 
00503                             if (Z_STRLEN_P(op) == 0
00504                                    || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
00505                                    Z_LVAL_P(op) = 0;
00506                             } else {
00507                                    Z_LVAL_P(op) = 1;
00508                             }
00509                             STR_FREE(strval);
00510                      }
00511                      break;
00512               case IS_ARRAY:
00513                      tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
00514                      zval_dtor(op);
00515                      Z_LVAL_P(op) = tmp;
00516                      break;
00517               case IS_OBJECT:
00518                      {
00519                             zend_bool retval = 1;
00520                             TSRMLS_FETCH();
00521 
00522                             convert_object_to_type(op, IS_BOOL, convert_to_boolean);
00523 
00524                             if (Z_TYPE_P(op) == IS_BOOL) {
00525                                    return;
00526                             }
00527 
00528                             zval_dtor(op);
00529                             ZVAL_BOOL(op, retval);
00530                             break;
00531                      }
00532               default:
00533                      zval_dtor(op);
00534                      Z_LVAL_P(op) = 0;
00535                      break;
00536        }
00537        Z_TYPE_P(op) = IS_BOOL;
00538 }
00539 /* }}} */
00540 
00541 ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
00542 {
00543        long lval;
00544        double dval;
00545 
00546        switch (Z_TYPE_P(op)) {
00547               case IS_NULL:
00548                      Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
00549                      Z_STRLEN_P(op) = 0;
00550                      break;
00551               case IS_STRING:
00552                      break;
00553               case IS_BOOL:
00554                      if (Z_LVAL_P(op)) {
00555                             Z_STRVAL_P(op) = estrndup_rel("1", 1);
00556                             Z_STRLEN_P(op) = 1;
00557                      } else {
00558                             Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
00559                             Z_STRLEN_P(op) = 0;
00560                      }
00561                      break;
00562               case IS_RESOURCE: {
00563                      long tmp = Z_LVAL_P(op);
00564                      TSRMLS_FETCH();
00565 
00566                      zend_list_delete(Z_LVAL_P(op));
00567                      Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "Resource id #%ld", tmp);
00568                      break;
00569               }
00570               case IS_LONG:
00571                      lval = Z_LVAL_P(op);
00572 
00573                      Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%ld", lval);
00574                      break;
00575               case IS_DOUBLE: {
00576                      TSRMLS_FETCH();
00577                      dval = Z_DVAL_P(op);
00578                      Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), dval);
00579                      /* %G already handles removing trailing zeros from the fractional part, yay */
00580                      break;
00581               }
00582               case IS_ARRAY:
00583                      zend_error(E_NOTICE, "Array to string conversion");
00584                      zval_dtor(op);
00585                      Z_STRVAL_P(op) = estrndup_rel("Array", sizeof("Array")-1);
00586                      Z_STRLEN_P(op) = sizeof("Array")-1;
00587                      break;
00588               case IS_OBJECT: {
00589                      TSRMLS_FETCH();
00590 
00591                      convert_object_to_type(op, IS_STRING, convert_to_string);
00592 
00593                      if (Z_TYPE_P(op) == IS_STRING) {
00594                             return;
00595                      }
00596 
00597                      zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
00598                      zval_dtor(op);
00599                      Z_STRVAL_P(op) = estrndup_rel("Object", sizeof("Object")-1);
00600                      Z_STRLEN_P(op) = sizeof("Object")-1;
00601                      break;
00602               }
00603               default:
00604                      zval_dtor(op);
00605                      ZVAL_BOOL(op, 0);
00606                      break;
00607        }
00608        Z_TYPE_P(op) = IS_STRING;
00609 }
00610 /* }}} */
00611 
00612 static void convert_scalar_to_array(zval *op, int type TSRMLS_DC) /* {{{ */
00613 {
00614        zval *entry;
00615 
00616        ALLOC_ZVAL(entry);
00617        *entry = *op;
00618        INIT_PZVAL(entry);
00619 
00620        switch (type) {
00621               case IS_ARRAY:
00622                      ALLOC_HASHTABLE(Z_ARRVAL_P(op));
00623                      zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
00624                      zend_hash_index_update(Z_ARRVAL_P(op), 0, (void *) &entry, sizeof(zval *), NULL);
00625                      Z_TYPE_P(op) = IS_ARRAY;
00626                      break;
00627               case IS_OBJECT:
00628                      object_init(op);
00629                      zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL);
00630                      break;
00631        }
00632 }
00633 /* }}} */
00634 
00635 ZEND_API void convert_to_array(zval *op) /* {{{ */
00636 {
00637        TSRMLS_FETCH();
00638 
00639        switch (Z_TYPE_P(op)) {
00640               case IS_ARRAY:
00641                      break;
00642 /* OBJECTS_OPTIMIZE */
00643               case IS_OBJECT:
00644                      {
00645                             zval *tmp;
00646                             HashTable *ht;
00647 
00648                             ALLOC_HASHTABLE(ht);
00649                             zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
00650                             if (Z_OBJCE_P(op) == zend_ce_closure) {
00651                                    convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
00652                                    if (Z_TYPE_P(op) == IS_ARRAY) {
00653                                           zend_hash_destroy(ht);
00654                                           FREE_HASHTABLE(ht);
00655                                           return;
00656                                    }
00657                             } else if (Z_OBJ_HT_P(op)->get_properties) {
00658                                    HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
00659                                    if (obj_ht) {
00660                                           zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
00661                                    }
00662                             } else {
00663                                    convert_object_to_type(op, IS_ARRAY, convert_to_array);
00664 
00665                                    if (Z_TYPE_P(op) == IS_ARRAY) {
00666                                           zend_hash_destroy(ht);
00667                                           FREE_HASHTABLE(ht);
00668                                           return;
00669                                    }
00670                             }
00671                             zval_dtor(op);
00672                             Z_TYPE_P(op) = IS_ARRAY;
00673                             Z_ARRVAL_P(op) = ht;
00674                      }
00675                      break;
00676               case IS_NULL:
00677                      ALLOC_HASHTABLE(Z_ARRVAL_P(op));
00678                      zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
00679                      Z_TYPE_P(op) = IS_ARRAY;
00680                      break;
00681               default:
00682                      convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
00683                      break;
00684        }
00685 }
00686 /* }}} */
00687 
00688 ZEND_API void convert_to_object(zval *op) /* {{{ */
00689 {
00690        TSRMLS_FETCH();
00691 
00692        switch (Z_TYPE_P(op)) {
00693               case IS_ARRAY:
00694                      {
00695                             object_and_properties_init(op, zend_standard_class_def, Z_ARRVAL_P(op));
00696                             break;
00697                      }
00698               case IS_OBJECT:
00699                      break;
00700               case IS_NULL:
00701                      object_init(op);
00702                      break;
00703               default:
00704                      convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
00705                      break;
00706        }
00707 }
00708 /* }}} */
00709 
00710 ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
00711 {
00712        zval **arg;
00713        va_list ap;
00714 
00715        va_start(ap, argc);
00716 
00717        while (argc--) {
00718               arg = va_arg(ap, zval **);
00719               convert_to_long_ex(arg);
00720        }
00721 
00722        va_end(ap);
00723 }
00724 /* }}} */
00725 
00726 ZEND_API void multi_convert_to_double_ex(int argc, ...) /* {{{ */
00727 {
00728        zval **arg;
00729        va_list ap;
00730 
00731        va_start(ap, argc);
00732 
00733        while (argc--) {
00734               arg = va_arg(ap, zval **);
00735               convert_to_double_ex(arg);
00736        }
00737 
00738        va_end(ap);
00739 }
00740 /* }}} */
00741 
00742 ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
00743 {
00744        zval **arg;
00745        va_list ap;
00746 
00747        va_start(ap, argc);
00748 
00749        while (argc--) {
00750               arg = va_arg(ap, zval **);
00751               convert_to_string_ex(arg);
00752        }
00753 
00754        va_end(ap);
00755 }
00756 /* }}} */
00757 
00758 ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
00759 {
00760        zval op1_copy, op2_copy;
00761        int converted = 0;
00762 
00763        while (1) {
00764               switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
00765                      case TYPE_PAIR(IS_LONG, IS_LONG): {
00766                             long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
00767 
00768                             /* check for overflow by comparing sign bits */
00769                             if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
00770                                    && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
00771 
00772                                    ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
00773                             } else {
00774                                    ZVAL_LONG(result, lval);
00775                             }
00776                             return SUCCESS;
00777                      }
00778 
00779                      case TYPE_PAIR(IS_LONG, IS_DOUBLE):
00780                             ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
00781                             return SUCCESS;
00782 
00783                      case TYPE_PAIR(IS_DOUBLE, IS_LONG):
00784                             ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
00785                             return SUCCESS;
00786 
00787                      case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
00788                             ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
00789                             return SUCCESS;
00790 
00791                      case TYPE_PAIR(IS_ARRAY, IS_ARRAY): {
00792                             zval *tmp;
00793 
00794                             if ((result == op1) && (result == op2)) {
00795                                    /* $a += $a */
00796                                    return SUCCESS;
00797                             }
00798                             if (result != op1) {
00799                                    *result = *op1;
00800                                    zval_copy_ctor(result);
00801                             }
00802                             zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), (void (*)(void *pData)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
00803                             return SUCCESS;
00804                      }
00805 
00806                      default:
00807                             if (!converted) {
00808                                    zendi_convert_scalar_to_number(op1, op1_copy, result);
00809                                    zendi_convert_scalar_to_number(op2, op2_copy, result);
00810                                    converted = 1;
00811                             } else {
00812                                    zend_error(E_ERROR, "Unsupported operand types");
00813                                    return FAILURE; /* unknown datatype */
00814                             }
00815               }
00816        }
00817 }
00818 /* }}} */
00819 
00820 ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
00821 {
00822        zval op1_copy, op2_copy;
00823        int converted = 0;
00824 
00825        while (1) {
00826               switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
00827                      case TYPE_PAIR(IS_LONG, IS_LONG): {
00828                             long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
00829 
00830                             /* check for overflow by comparing sign bits */
00831                             if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
00832                                    && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
00833 
00834                                    ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
00835                             } else {
00836                                    ZVAL_LONG(result, lval);
00837                             }
00838                             return SUCCESS;
00839 
00840                      }
00841                      case TYPE_PAIR(IS_LONG, IS_DOUBLE):
00842                             ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
00843                             return SUCCESS;
00844 
00845                      case TYPE_PAIR(IS_DOUBLE, IS_LONG):
00846                             ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
00847                             return SUCCESS;
00848 
00849                      case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
00850                             ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
00851                             return SUCCESS;
00852 
00853                      default:
00854                             if (!converted) {
00855                                    zendi_convert_scalar_to_number(op1, op1_copy, result);
00856                                    zendi_convert_scalar_to_number(op2, op2_copy, result);
00857                                    converted = 1;
00858                             } else {
00859                                    zend_error(E_ERROR, "Unsupported operand types");
00860                                    return FAILURE; /* unknown datatype */
00861                             }
00862               }
00863        }
00864 }
00865 /* }}} */
00866 
00867 ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
00868 {
00869        zval op1_copy, op2_copy;
00870        int converted = 0;
00871 
00872        while (1) {
00873               switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
00874                      case TYPE_PAIR(IS_LONG, IS_LONG): {
00875                             long overflow;
00876 
00877                             ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
00878                             Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
00879                             return SUCCESS;
00880 
00881                      }
00882                      case TYPE_PAIR(IS_LONG, IS_DOUBLE):
00883                             ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
00884                             return SUCCESS;
00885 
00886                      case TYPE_PAIR(IS_DOUBLE, IS_LONG):
00887                             ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
00888                             return SUCCESS;
00889 
00890                      case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
00891                             ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
00892                             return SUCCESS;
00893 
00894                      default:
00895                             if (!converted) {
00896                                    zendi_convert_scalar_to_number(op1, op1_copy, result);
00897                                    zendi_convert_scalar_to_number(op2, op2_copy, result);
00898                                    converted = 1;
00899                             } else {
00900                                    zend_error(E_ERROR, "Unsupported operand types");
00901                                    return FAILURE; /* unknown datatype */
00902                             }
00903               }
00904        }
00905 }
00906 /* }}} */
00907 
00908 ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
00909 {
00910        zval op1_copy, op2_copy;
00911        int converted = 0;
00912 
00913        while (1) {
00914               switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
00915                      case TYPE_PAIR(IS_LONG, IS_LONG):
00916                             if (Z_LVAL_P(op2) == 0) {
00917                                    zend_error(E_WARNING, "Division by zero");
00918                                    ZVAL_BOOL(result, 0);
00919                                    return FAILURE;                    /* division by zero */
00920                             } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
00921                                    /* Prevent overflow error/crash */
00922                                    ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
00923                                    return SUCCESS;
00924                             }
00925                             if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
00926                                    ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
00927                             } else {
00928                                    ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
00929                             }
00930                             return SUCCESS;
00931 
00932                      case TYPE_PAIR(IS_DOUBLE, IS_LONG):
00933                             if (Z_LVAL_P(op2) == 0) {
00934                                    zend_error(E_WARNING, "Division by zero");
00935                                    ZVAL_BOOL(result, 0);
00936                                    return FAILURE;                    /* division by zero */
00937                             }
00938                             ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
00939                             return SUCCESS;
00940 
00941                      case TYPE_PAIR(IS_LONG, IS_DOUBLE):
00942                             if (Z_DVAL_P(op2) == 0) {
00943                                    zend_error(E_WARNING, "Division by zero");
00944                                    ZVAL_BOOL(result, 0);
00945                                    return FAILURE;                    /* division by zero */
00946                             }
00947                             ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
00948                             return SUCCESS;
00949 
00950                      case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
00951                             if (Z_DVAL_P(op2) == 0) {
00952                                    zend_error(E_WARNING, "Division by zero");
00953                                    ZVAL_BOOL(result, 0);
00954                                    return FAILURE;                    /* division by zero */
00955                             }
00956                             ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
00957                             return SUCCESS;
00958 
00959                      default:
00960                             if (!converted) {
00961                                    zendi_convert_scalar_to_number(op1, op1_copy, result);
00962                                    zendi_convert_scalar_to_number(op2, op2_copy, result);
00963                                    converted = 1;
00964                             } else {
00965                                    zend_error(E_ERROR, "Unsupported operand types");
00966                                    return FAILURE; /* unknown datatype */
00967                             }
00968               }
00969        }
00970 }
00971 /* }}} */
00972 
00973 ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
00974 {
00975        zval op1_copy, op2_copy;
00976        long op1_lval;
00977 
00978        zendi_convert_to_long(op1, op1_copy, result);
00979        op1_lval = Z_LVAL_P(op1);
00980        zendi_convert_to_long(op2, op2_copy, result);
00981 
00982        if (Z_LVAL_P(op2) == 0) {
00983               zend_error(E_WARNING, "Division by zero");
00984               ZVAL_BOOL(result, 0);
00985               return FAILURE;                    /* modulus by zero */
00986        }
00987 
00988        if (Z_LVAL_P(op2) == -1) {
00989               /* Prevent overflow error/crash if op1==LONG_MIN */
00990               ZVAL_LONG(result, 0);
00991               return SUCCESS;
00992        }
00993 
00994        ZVAL_LONG(result, op1_lval % Z_LVAL_P(op2));
00995        return SUCCESS;
00996 }
00997 /* }}} */
00998 
00999 ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01000 {
01001        zval op1_copy, op2_copy;
01002        long op1_lval;
01003 
01004        zendi_convert_to_boolean(op1, op1_copy, result);
01005        op1_lval = Z_LVAL_P(op1);
01006        zendi_convert_to_boolean(op2, op2_copy, result);
01007        ZVAL_BOOL(result, op1_lval ^ Z_LVAL_P(op2));
01008        return SUCCESS;
01009 }
01010 /* }}} */
01011 
01012 ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
01013 {
01014        zval op1_copy;
01015 
01016        zendi_convert_to_boolean(op1, op1_copy, result);
01017        ZVAL_BOOL(result, !Z_LVAL_P(op1));
01018        return SUCCESS;
01019 }
01020 /* }}} */
01021 
01022 ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
01023 {
01024        zval op1_copy = *op1;
01025 
01026        op1 = &op1_copy;
01027 
01028        if (Z_TYPE_P(op1) == IS_LONG) {
01029               ZVAL_LONG(result, ~Z_LVAL_P(op1));
01030               return SUCCESS;
01031        } else if (Z_TYPE_P(op1) == IS_DOUBLE) {
01032               ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
01033               return SUCCESS;
01034        } else if (Z_TYPE_P(op1) == IS_STRING) {
01035               int i;
01036 
01037               Z_TYPE_P(result) = IS_STRING;
01038               Z_STRVAL_P(result) = estrndup(Z_STRVAL_P(op1), Z_STRLEN_P(op1));
01039               Z_STRLEN_P(result) = Z_STRLEN_P(op1);
01040               for (i = 0; i < Z_STRLEN_P(op1); i++) {
01041                      Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
01042               }
01043               return SUCCESS;
01044        }
01045        zend_error(E_ERROR, "Unsupported operand types");
01046        return FAILURE;                           /* unknown datatype */
01047 }
01048 /* }}} */
01049 
01050 ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01051 {
01052        zval op1_copy, op2_copy;
01053        long op1_lval;
01054 
01055        if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
01056               zval *longer, *shorter;
01057               char *result_str;
01058               int i, result_len;
01059 
01060               if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
01061                      longer = op1;
01062                      shorter = op2;
01063               } else {
01064                      longer = op2;
01065                      shorter = op1;
01066               }
01067 
01068               Z_TYPE_P(result) = IS_STRING;
01069               result_len = Z_STRLEN_P(longer);
01070               result_str = estrndup(Z_STRVAL_P(longer), Z_STRLEN_P(longer));
01071               for (i = 0; i < Z_STRLEN_P(shorter); i++) {
01072                      result_str[i] |= Z_STRVAL_P(shorter)[i];
01073               }
01074               if (result==op1) {
01075                      STR_FREE(Z_STRVAL_P(result));
01076               }
01077               Z_STRVAL_P(result) = result_str;
01078               Z_STRLEN_P(result) = result_len;
01079               return SUCCESS;
01080        }
01081        zendi_convert_to_long(op1, op1_copy, result);
01082        op1_lval = Z_LVAL_P(op1);
01083        zendi_convert_to_long(op2, op2_copy, result);
01084 
01085        ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2));
01086        return SUCCESS;
01087 }
01088 /* }}} */
01089 
01090 ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01091 {
01092        zval op1_copy, op2_copy;
01093        long op1_lval;
01094 
01095        if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
01096               zval *longer, *shorter;
01097               char *result_str;
01098               int i, result_len;
01099 
01100               if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
01101                      longer = op1;
01102                      shorter = op2;
01103               } else {
01104                      longer = op2;
01105                      shorter = op1;
01106               }
01107 
01108               Z_TYPE_P(result) = IS_STRING;
01109               result_len = Z_STRLEN_P(shorter);
01110               result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
01111               for (i = 0; i < Z_STRLEN_P(shorter); i++) {
01112                      result_str[i] &= Z_STRVAL_P(longer)[i];
01113               }
01114               if (result==op1) {
01115                      STR_FREE(Z_STRVAL_P(result));
01116               }
01117               Z_STRVAL_P(result) = result_str;
01118               Z_STRLEN_P(result) = result_len;
01119               return SUCCESS;
01120        }
01121 
01122 
01123        zendi_convert_to_long(op1, op1_copy, result);
01124        op1_lval = Z_LVAL_P(op1);
01125        zendi_convert_to_long(op2, op2_copy, result);
01126 
01127        ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2));
01128        return SUCCESS;
01129 }
01130 /* }}} */
01131 
01132 ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01133 {
01134        zval op1_copy, op2_copy;
01135        long op1_lval;
01136 
01137        if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
01138               zval *longer, *shorter;
01139               char *result_str;
01140               int i, result_len;
01141 
01142               if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
01143                      longer = op1;
01144                      shorter = op2;
01145               } else {
01146                      longer = op2;
01147                      shorter = op1;
01148               }
01149 
01150               Z_TYPE_P(result) = IS_STRING;
01151               result_len = Z_STRLEN_P(shorter);
01152               result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
01153               for (i = 0; i < Z_STRLEN_P(shorter); i++) {
01154                      result_str[i] ^= Z_STRVAL_P(longer)[i];
01155               }
01156               if (result==op1) {
01157                      STR_FREE(Z_STRVAL_P(result));
01158               }
01159               Z_STRVAL_P(result) = result_str;
01160               Z_STRLEN_P(result) = result_len;
01161               return SUCCESS;
01162        }
01163 
01164        zendi_convert_to_long(op1, op1_copy, result);
01165        op1_lval = Z_LVAL_P(op1);
01166        zendi_convert_to_long(op2, op2_copy, result);
01167 
01168        ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2));
01169        return SUCCESS;
01170 }
01171 /* }}} */
01172 
01173 ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01174 {
01175        zval op1_copy, op2_copy;
01176        long op1_lval;
01177 
01178        zendi_convert_to_long(op1, op1_copy, result);
01179        op1_lval = Z_LVAL_P(op1);
01180        zendi_convert_to_long(op2, op2_copy, result);
01181        ZVAL_LONG(result, op1_lval << Z_LVAL_P(op2));
01182        return SUCCESS;
01183 }
01184 /* }}} */
01185 
01186 ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01187 {
01188        zval op1_copy, op2_copy;
01189        long op1_lval;
01190 
01191        zendi_convert_to_long(op1, op1_copy, result);
01192        op1_lval = Z_LVAL_P(op1);
01193        zendi_convert_to_long(op2, op2_copy, result);
01194        ZVAL_LONG(result, op1_lval >> Z_LVAL_P(op2));
01195        return SUCCESS;
01196 }
01197 /* }}} */
01198 
01199 /* must support result==op1 */
01200 ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
01201 {
01202        Z_STRLEN_P(result) = Z_STRLEN_P(op1) + 1;
01203        Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), Z_STRLEN_P(result)+1);
01204        Z_STRVAL_P(result)[Z_STRLEN_P(result) - 1] = (char) Z_LVAL_P(op2);
01205        Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
01206        Z_TYPE_P(result) = IS_STRING;
01207        return SUCCESS;
01208 }
01209 /* }}} */
01210 
01211 /* must support result==op1 */
01212 ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
01213 {
01214        int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
01215 
01216        Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), length+1);
01217        memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
01218        Z_STRVAL_P(result)[length] = 0;
01219        Z_STRLEN_P(result) = length;
01220        Z_TYPE_P(result) = IS_STRING;
01221        return SUCCESS;
01222 }
01223 /* }}} */
01224 
01225 ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01226 {
01227        zval op1_copy, op2_copy;
01228        int use_copy1 = 0, use_copy2 = 0;
01229 
01230        if (Z_TYPE_P(op1) != IS_STRING) {
01231               zend_make_printable_zval(op1, &op1_copy, &use_copy1);
01232        }
01233        if (Z_TYPE_P(op2) != IS_STRING) {
01234               zend_make_printable_zval(op2, &op2_copy, &use_copy2);
01235        }
01236 
01237        if (use_copy1) {
01238               /* We have created a converted copy of op1. Therefore, op1 won't become the result so
01239                * we have to free it.
01240                */
01241               if (result == op1) {
01242                      zval_dtor(op1);
01243               }
01244               op1 = &op1_copy;
01245        }
01246        if (use_copy2) {
01247               op2 = &op2_copy;
01248        }
01249        if (result==op1) {   /* special case, perform operations on result */
01250               uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
01251 
01252               if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
01253                      efree(Z_STRVAL_P(result));
01254                      ZVAL_EMPTY_STRING(result);
01255                      zend_error(E_ERROR, "String size overflow");
01256               }
01257 
01258               Z_STRVAL_P(result) = erealloc(Z_STRVAL_P(result), res_len+1);
01259 
01260               memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
01261               Z_STRVAL_P(result)[res_len]=0;
01262               Z_STRLEN_P(result) = res_len;
01263        } else {
01264               Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
01265               Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1);
01266               memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1));
01267               memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
01268               Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
01269               Z_TYPE_P(result) = IS_STRING;
01270        }
01271        if (use_copy1) {
01272               zval_dtor(op1);
01273        }
01274        if (use_copy2) {
01275               zval_dtor(op2);
01276        }
01277        return SUCCESS;
01278 }
01279 /* }}} */
01280 
01281 ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01282 {
01283        zval op1_copy, op2_copy;
01284        int use_copy1 = 0, use_copy2 = 0;
01285 
01286        if (Z_TYPE_P(op1) != IS_STRING) {
01287               zend_make_printable_zval(op1, &op1_copy, &use_copy1);
01288        }
01289        if (Z_TYPE_P(op2) != IS_STRING) {
01290               zend_make_printable_zval(op2, &op2_copy, &use_copy2);
01291        }
01292 
01293        if (use_copy1) {
01294               op1 = &op1_copy;
01295        }
01296        if (use_copy2) {
01297               op2 = &op2_copy;
01298        }
01299 
01300        ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2));
01301 
01302        if (use_copy1) {
01303               zval_dtor(op1);
01304        }
01305        if (use_copy2) {
01306               zval_dtor(op2);
01307        }
01308        return SUCCESS;
01309 }
01310 /* }}} */
01311 
01312 #if HAVE_STRCOLL
01313 ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01314 {
01315        zval op1_copy, op2_copy;
01316        int use_copy1 = 0, use_copy2 = 0;
01317 
01318        if (Z_TYPE_P(op1) != IS_STRING) {
01319               zend_make_printable_zval(op1, &op1_copy, &use_copy1);
01320        }
01321        if (Z_TYPE_P(op2) != IS_STRING) {
01322               zend_make_printable_zval(op2, &op2_copy, &use_copy2);
01323        }
01324 
01325        if (use_copy1) {
01326               op1 = &op1_copy;
01327        }
01328        if (use_copy2) {
01329               op2 = &op2_copy;
01330        }
01331 
01332        ZVAL_LONG(result, strcoll(Z_STRVAL_P(op1), Z_STRVAL_P(op2)));
01333 
01334        if (use_copy1) {
01335               zval_dtor(op1);
01336        }
01337        if (use_copy2) {
01338               zval_dtor(op2);
01339        }
01340        return SUCCESS;
01341 }
01342 /* }}} */
01343 #endif
01344 
01345 ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01346 {
01347        zval op1_copy, op2_copy;
01348 
01349        op1_copy = *op1;
01350        zval_copy_ctor(&op1_copy);
01351 
01352        op2_copy = *op2;
01353        zval_copy_ctor(&op2_copy);
01354 
01355        convert_to_double(&op1_copy);
01356        convert_to_double(&op2_copy);
01357 
01358        ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy)));
01359 
01360        return SUCCESS;
01361 }
01362 /* }}} */
01363 
01364 static inline void zend_free_obj_get_result(zval *op TSRMLS_DC) /* {{{ */
01365 {
01366        if (Z_REFCOUNT_P(op) == 0) {
01367               GC_REMOVE_ZVAL_FROM_BUFFER(op);
01368               zval_dtor(op);
01369               FREE_ZVAL(op);
01370        } else {
01371               zval_ptr_dtor(&op);
01372        }
01373 }
01374 /* }}} */
01375 
01376 ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01377 {
01378        int ret;
01379        int converted = 0;
01380        zval op1_copy, op2_copy;
01381        zval *op_free;
01382 
01383        while (1) {
01384               switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
01385                      case TYPE_PAIR(IS_LONG, IS_LONG):
01386                             ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
01387                             return SUCCESS;
01388 
01389                      case TYPE_PAIR(IS_DOUBLE, IS_LONG):
01390                             Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
01391                             ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
01392                             return SUCCESS;
01393 
01394                      case TYPE_PAIR(IS_LONG, IS_DOUBLE):
01395                             Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
01396                             ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
01397                             return SUCCESS;
01398 
01399                      case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
01400                             Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
01401                             ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
01402                             return SUCCESS;
01403 
01404                      case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
01405                             zend_compare_arrays(result, op1, op2 TSRMLS_CC);
01406                             return SUCCESS;
01407 
01408                      case TYPE_PAIR(IS_NULL, IS_NULL):
01409                             ZVAL_LONG(result, 0);
01410                             return SUCCESS;
01411 
01412                      case TYPE_PAIR(IS_NULL, IS_BOOL):
01413                             ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
01414                             return SUCCESS;
01415 
01416                      case TYPE_PAIR(IS_BOOL, IS_NULL):
01417                             ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
01418                             return SUCCESS;
01419 
01420                      case TYPE_PAIR(IS_BOOL, IS_BOOL):
01421                             ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
01422                             return SUCCESS;
01423 
01424                      case TYPE_PAIR(IS_STRING, IS_STRING):
01425                             zendi_smart_strcmp(result, op1, op2);
01426                             return SUCCESS;
01427 
01428                      case TYPE_PAIR(IS_NULL, IS_STRING):
01429                             ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
01430                             return SUCCESS;
01431 
01432                      case TYPE_PAIR(IS_STRING, IS_NULL):
01433                             ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
01434                             return SUCCESS;
01435 
01436                      case TYPE_PAIR(IS_OBJECT, IS_NULL):
01437                             ZVAL_LONG(result, 1);
01438                             return SUCCESS;
01439 
01440                      case TYPE_PAIR(IS_NULL, IS_OBJECT):
01441                             ZVAL_LONG(result, -1);
01442                             return SUCCESS;
01443 
01444                      case TYPE_PAIR(IS_OBJECT, IS_OBJECT):
01445                             /* If both are objects sharing the same comparision handler then use is */
01446                             if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) {
01447                                    if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
01448                                           /* object handles are identical, apprently this is the same object */
01449                                           ZVAL_LONG(result, 0);
01450                                           return SUCCESS;
01451                                    }
01452                                    ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));
01453                                    return SUCCESS;
01454                             }
01455                             /* break missing intentionally */
01456 
01457                      default:
01458                             if (Z_TYPE_P(op1) == IS_OBJECT) {
01459                                    if (Z_OBJ_HT_P(op1)->get) {
01460                                           op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
01461                                           ret = compare_function(result, op_free, op2 TSRMLS_CC);
01462                                           zend_free_obj_get_result(op_free TSRMLS_CC);
01463                                           return ret;
01464                                    } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
01465                                           ALLOC_INIT_ZVAL(op_free);
01466                                           if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
01467                                                  ZVAL_LONG(result, 1);
01468                                                  zend_free_obj_get_result(op_free TSRMLS_CC);
01469                                                  return SUCCESS;
01470                                           }
01471                                           ret = compare_function(result, op_free, op2 TSRMLS_CC);
01472                                           zend_free_obj_get_result(op_free TSRMLS_CC);
01473                                           return ret;
01474                                    }
01475                             }
01476                             if (Z_TYPE_P(op2) == IS_OBJECT) {
01477                                    if (Z_OBJ_HT_P(op2)->get) {
01478                                           op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
01479                                           ret = compare_function(result, op1, op_free TSRMLS_CC);
01480                                           zend_free_obj_get_result(op_free TSRMLS_CC);
01481                                           return ret;
01482                                    } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
01483                                           ALLOC_INIT_ZVAL(op_free);
01484                                           if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
01485                                                  ZVAL_LONG(result, -1);
01486                                                  zend_free_obj_get_result(op_free TSRMLS_CC);
01487                                                  return SUCCESS;
01488                                           }
01489                                           ret = compare_function(result, op1, op_free TSRMLS_CC);
01490                                           zend_free_obj_get_result(op_free TSRMLS_CC);
01491                                           return ret;
01492                                    }
01493                             }
01494                             if (!converted) {
01495                                    if (Z_TYPE_P(op1) == IS_NULL) {
01496                                           zendi_convert_to_boolean(op2, op2_copy, result);
01497                                           ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
01498                                           return SUCCESS;
01499                                    } else if (Z_TYPE_P(op2) == IS_NULL) {
01500                                           zendi_convert_to_boolean(op1, op1_copy, result);
01501                                           ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
01502                                           return SUCCESS;
01503                                    } else if (Z_TYPE_P(op1) == IS_BOOL) {
01504                                           zendi_convert_to_boolean(op2, op2_copy, result);
01505                                           ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
01506                                           return SUCCESS;
01507                                    } else if (Z_TYPE_P(op2) == IS_BOOL) {
01508                                           zendi_convert_to_boolean(op1, op1_copy, result);
01509                                           ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
01510                                           return SUCCESS;
01511                                    } else {
01512                                           zendi_convert_scalar_to_number(op1, op1_copy, result);
01513                                           zendi_convert_scalar_to_number(op2, op2_copy, result);
01514                                           converted = 1;
01515                                    }
01516                             } else if (Z_TYPE_P(op1)==IS_ARRAY) {
01517                                    ZVAL_LONG(result, 1);
01518                                    return SUCCESS;
01519                             } else if (Z_TYPE_P(op2)==IS_ARRAY) {
01520                                    ZVAL_LONG(result, -1);
01521                                    return SUCCESS;
01522                             } else if (Z_TYPE_P(op1)==IS_OBJECT) {
01523                                    ZVAL_LONG(result, 1);
01524                                    return SUCCESS;
01525                             } else if (Z_TYPE_P(op2)==IS_OBJECT) {
01526                                    ZVAL_LONG(result, -1);
01527                                    return SUCCESS;
01528                             } else {
01529                                    ZVAL_LONG(result, 0);
01530                                    return FAILURE;
01531                             }
01532               }
01533        }
01534 }
01535 /* }}} */
01536 
01537 static int hash_zval_identical_function(const zval **z1, const zval **z2) /* {{{ */
01538 {
01539        zval result;
01540        TSRMLS_FETCH();
01541 
01542        /* is_identical_function() returns 1 in case of identity and 0 in case
01543         * of a difference;
01544         * whereas this comparison function is expected to return 0 on identity,
01545         * and non zero otherwise.
01546         */
01547        if (is_identical_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
01548               return 1;
01549        }
01550        return !Z_LVAL(result);
01551 }
01552 /* }}} */
01553 
01554 ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01555 {
01556        Z_TYPE_P(result) = IS_BOOL;
01557        if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
01558               Z_LVAL_P(result) = 0;
01559               return SUCCESS;
01560        }
01561        switch (Z_TYPE_P(op1)) {
01562               case IS_NULL:
01563                      Z_LVAL_P(result) = 1;
01564                      break;
01565               case IS_BOOL:
01566               case IS_LONG:
01567               case IS_RESOURCE:
01568                      Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
01569                      break;
01570               case IS_DOUBLE:
01571                      Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
01572                      break;
01573               case IS_STRING:
01574                      Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2))
01575                             && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));
01576                      break;
01577               case IS_ARRAY:
01578                      Z_LVAL_P(result) = zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0;
01579                      break;
01580               case IS_OBJECT:
01581                      if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {
01582                             Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));
01583                      } else {
01584                             Z_LVAL_P(result) = 0;
01585                      }
01586                      break;
01587               default:
01588                      Z_LVAL_P(result) = 0;
01589                      return FAILURE;
01590        }
01591        return SUCCESS;
01592 }
01593 /* }}} */
01594 
01595 ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01596 {
01597        if (is_identical_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
01598               return FAILURE;
01599        }
01600        Z_LVAL_P(result) = !Z_LVAL_P(result);
01601        return SUCCESS;
01602 }
01603 /* }}} */
01604 
01605 ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01606 {
01607        if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
01608               return FAILURE;
01609        }
01610        ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
01611        return SUCCESS;
01612 }
01613 /* }}} */
01614 
01615 ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01616 {
01617        if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
01618               return FAILURE;
01619        }
01620        ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
01621        return SUCCESS;
01622 }
01623 /* }}} */
01624 
01625 ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01626 {
01627        if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
01628               return FAILURE;
01629        }
01630        ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
01631        return SUCCESS;
01632 }
01633 /* }}} */
01634 
01635 ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
01636 {
01637        if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
01638               return FAILURE;
01639        }
01640        ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
01641        return SUCCESS;
01642 }
01643 /* }}} */
01644 
01645 ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC) /* {{{ */
01646 {
01647        zend_uint i;
01648 
01649        for (i=0; i<instance_ce->num_interfaces; i++) {
01650               if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) {
01651                      return 1;
01652               }
01653        }
01654        if (!interfaces_only) {
01655               while (instance_ce) {
01656                      if (instance_ce == ce) {
01657                             return 1;
01658                      }
01659                      instance_ce = instance_ce->parent;
01660               }
01661        }
01662 
01663        return 0;
01664 }
01665 /* }}} */
01666 
01667 ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC) /* {{{ */
01668 {
01669        return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC);
01670 }
01671 /* }}} */
01672 
01673 #define LOWER_CASE 1
01674 #define UPPER_CASE 2
01675 #define NUMERIC 3
01676 
01677 static void increment_string(zval *str) /* {{{ */
01678 {
01679        int carry=0;
01680        int pos=Z_STRLEN_P(str)-1;
01681        char *s=Z_STRVAL_P(str);
01682        char *t;
01683        int last=0; /* Shut up the compiler warning */
01684        int ch;
01685 
01686        if (Z_STRLEN_P(str) == 0) {
01687               STR_FREE(Z_STRVAL_P(str));
01688               Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
01689               Z_STRLEN_P(str) = 1;
01690               return;
01691        }
01692 
01693        while (pos >= 0) {
01694               ch = s[pos];
01695               if (ch >= 'a' && ch <= 'z') {
01696                      if (ch == 'z') {
01697                             s[pos] = 'a';
01698                             carry=1;
01699                      } else {
01700                             s[pos]++;
01701                             carry=0;
01702                      }
01703                      last=LOWER_CASE;
01704               } else if (ch >= 'A' && ch <= 'Z') {
01705                      if (ch == 'Z') {
01706                             s[pos] = 'A';
01707                             carry=1;
01708                      } else {
01709                             s[pos]++;
01710                             carry=0;
01711                      }
01712                      last=UPPER_CASE;
01713               } else if (ch >= '0' && ch <= '9') {
01714                      if (ch == '9') {
01715                             s[pos] = '0';
01716                             carry=1;
01717                      } else {
01718                             s[pos]++;
01719                             carry=0;
01720                      }
01721                      last = NUMERIC;
01722               } else {
01723                      carry=0;
01724                      break;
01725               }
01726               if (carry == 0) {
01727                      break;
01728               }
01729               pos--;
01730        }
01731 
01732        if (carry) {
01733               t = (char *) emalloc(Z_STRLEN_P(str)+1+1);
01734               memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str));
01735               Z_STRLEN_P(str)++;
01736               t[Z_STRLEN_P(str)] = '\0';
01737               switch (last) {
01738                      case NUMERIC:
01739                             t[0] = '1';
01740                             break;
01741                      case UPPER_CASE:
01742                             t[0] = 'A';
01743                             break;
01744                      case LOWER_CASE:
01745                             t[0] = 'a';
01746                             break;
01747               }
01748               STR_FREE(Z_STRVAL_P(str));
01749               Z_STRVAL_P(str) = t;
01750        }
01751 }
01752 /* }}} */
01753 
01754 ZEND_API int increment_function(zval *op1) /* {{{ */
01755 {
01756        switch (Z_TYPE_P(op1)) {
01757               case IS_LONG:
01758                      if (Z_LVAL_P(op1) == LONG_MAX) {
01759                             /* switch to double */
01760                             double d = (double)Z_LVAL_P(op1);
01761                             ZVAL_DOUBLE(op1, d+1);
01762                      } else {
01763                      Z_LVAL_P(op1)++;
01764                      }
01765                      break;
01766               case IS_DOUBLE:
01767                      Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
01768                      break;
01769               case IS_NULL:
01770                      ZVAL_LONG(op1, 1);
01771                      break;
01772               case IS_STRING: {
01773                             long lval;
01774                             double dval;
01775 
01776                             switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
01777                                    case IS_LONG:
01778                                           efree(Z_STRVAL_P(op1));
01779                                           if (lval == LONG_MAX) {
01780                                                  /* switch to double */
01781                                                  double d = (double)lval;
01782                                                  ZVAL_DOUBLE(op1, d+1);
01783                                           } else {
01784                                                  ZVAL_LONG(op1, lval+1);
01785                                           }
01786                                           break;
01787                                    case IS_DOUBLE:
01788                                           efree(Z_STRVAL_P(op1));
01789                                           ZVAL_DOUBLE(op1, dval+1);
01790                                           break;
01791                                    default:
01792                                           /* Perl style string increment */
01793                                           increment_string(op1);
01794                                           break;
01795                             }
01796                      }
01797                      break;
01798               default:
01799                      return FAILURE;
01800        }
01801        return SUCCESS;
01802 }
01803 /* }}} */
01804 
01805 ZEND_API int decrement_function(zval *op1) /* {{{ */
01806 {
01807        long lval;
01808        double dval;
01809 
01810        switch (Z_TYPE_P(op1)) {
01811               case IS_LONG:
01812                      if (Z_LVAL_P(op1) == LONG_MIN) {
01813                             double d = (double)Z_LVAL_P(op1);
01814                             ZVAL_DOUBLE(op1, d-1);
01815                      } else {
01816                      Z_LVAL_P(op1)--;
01817                      }
01818                      break;
01819               case IS_DOUBLE:
01820                      Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
01821                      break;
01822               case IS_STRING:             /* Like perl we only support string increment */
01823                      if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
01824                             STR_FREE(Z_STRVAL_P(op1));
01825                             ZVAL_LONG(op1, -1);
01826                             break;
01827                      }
01828                      switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
01829                             case IS_LONG:
01830                                    STR_FREE(Z_STRVAL_P(op1));
01831                                    if (lval == LONG_MIN) {
01832                                           double d = (double)lval;
01833                                           ZVAL_DOUBLE(op1, d-1);
01834                                    } else {
01835                                           ZVAL_LONG(op1, lval-1);
01836                                    }
01837                                    break;
01838                             case IS_DOUBLE:
01839                                    STR_FREE(Z_STRVAL_P(op1));
01840                                    ZVAL_DOUBLE(op1, dval - 1);
01841                                    break;
01842                      }
01843                      break;
01844               default:
01845                      return FAILURE;
01846        }
01847 
01848        return SUCCESS;
01849 }
01850 /* }}} */
01851 
01852 ZEND_API int zval_is_true(zval *op) /* {{{ */
01853 {
01854        convert_to_boolean(op);
01855        return (Z_LVAL_P(op) ? 1 : 0);
01856 }
01857 /* }}} */
01858 
01859 #ifdef ZEND_USE_TOLOWER_L
01860 ZEND_API void zend_update_current_locale(void) /* {{{ */
01861 {
01862        current_locale = _get_current_locale();
01863 }
01864 /* }}} */
01865 #endif
01866 
01867 ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length) /* {{{ */
01868 {
01869        register unsigned char *str = (unsigned char*)source;
01870        register unsigned char *result = (unsigned char*)dest;
01871        register unsigned char *end = str + length;
01872 
01873        while (str < end) {
01874               *result++ = zend_tolower((int)*str++);
01875        }
01876        *result = '\0';
01877 
01878        return dest;
01879 }
01880 /* }}} */
01881 
01882 ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length) /* {{{ */
01883 {
01884        return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
01885 }
01886 /* }}} */
01887 
01888 ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */
01889 {
01890        register unsigned char *p = (unsigned char*)str;
01891        register unsigned char *end = p + length;
01892 
01893        while (p < end) {
01894               *p = zend_tolower((int)*p);
01895               p++;
01896        }
01897 }
01898 /* }}} */
01899 
01900 ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
01901 {
01902        int retval;
01903 
01904        retval = memcmp(s1, s2, MIN(len1, len2));
01905        if (!retval) {
01906               return (len1 - len2);
01907        } else {
01908               return retval;
01909        }
01910 }
01911 /* }}} */
01912 
01913 ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
01914 {
01915        int retval;
01916 
01917        retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
01918        if (!retval) {
01919               return (MIN(length, len1) - MIN(length, len2));
01920        } else {
01921               return retval;
01922        }
01923 }
01924 /* }}} */
01925 
01926 ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
01927 {
01928        int len;
01929        int c1, c2;
01930 
01931        len = MIN(len1, len2);
01932 
01933        while (len--) {
01934               c1 = zend_tolower((int)*(unsigned char *)s1++);
01935               c2 = zend_tolower((int)*(unsigned char *)s2++);
01936               if (c1 != c2) {
01937                      return c1 - c2;
01938               }
01939        }
01940 
01941        return len1 - len2;
01942 }
01943 /* }}} */
01944 
01945 ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
01946 {
01947        int len;
01948        int c1, c2;
01949 
01950        len = MIN(length, MIN(len1, len2));
01951 
01952        while (len--) {
01953               c1 = zend_tolower((int)*(unsigned char *)s1++);
01954               c2 = zend_tolower((int)*(unsigned char *)s2++);
01955               if (c1 != c2) {
01956                      return c1 - c2;
01957               }
01958        }
01959 
01960        return MIN(length, len1) - MIN(length, len2);
01961 }
01962 /* }}} */
01963 
01964 ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
01965 {
01966        return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
01967 }
01968 /* }}} */
01969 
01970 ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
01971 {
01972        return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
01973 }
01974 /* }}} */
01975 
01976 ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */
01977 {
01978        return zend_binary_strcasecmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
01979 }
01980 /* }}} */
01981 
01982 ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */
01983 {
01984        return zend_binary_strncasecmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
01985 }
01986 /* }}} */
01987 
01988 ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
01989 {
01990        int ret1, ret2;
01991        long lval1, lval2;
01992        double dval1, dval2;
01993 
01994        if ((ret1=is_numeric_string(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0)) &&
01995               (ret2=is_numeric_string(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0))) {
01996               if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
01997                      if (ret1!=IS_DOUBLE) {
01998                             dval1 = (double) lval1;
01999                      } else if (ret2!=IS_DOUBLE) {
02000                             dval2 = (double) lval2;
02001                      } else if (dval1 == dval2 && !zend_finite(dval1)) {
02002                             /* Both values overflowed and have the same sign,
02003                              * so a numeric comparison would be inaccurate */
02004                             goto string_cmp;
02005                      }
02006                      Z_DVAL_P(result) = dval1 - dval2;
02007                      ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
02008               } else { /* they both have to be long's */
02009                      ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0));
02010               }
02011        } else {
02012 string_cmp:
02013               Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
02014               ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
02015        }
02016 }
02017 /* }}} */
02018 
02019 static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC) /* {{{ */
02020 {
02021        zval result;
02022 
02023        if (compare_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
02024               return 1;
02025        }
02026        return Z_LVAL(result);
02027 }
02028 /* }}} */
02029 
02030 ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
02031 {
02032        return zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
02033 }
02034 /* }}} */
02035 
02036 ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
02037 {
02038        ZVAL_LONG(result, zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC));
02039 }
02040 /* }}} */
02041 
02042 ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC) /* {{{ */
02043 {
02044        zend_compare_symbol_tables(result, Z_ARRVAL_P(a1), Z_ARRVAL_P(a2) TSRMLS_CC);
02045 }
02046 /* }}} */
02047 
02048 ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
02049 {
02050        Z_TYPE_P(result) = IS_LONG;
02051 
02052        if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) {
02053               Z_LVAL_P(result) = 0;
02054               return;
02055        }
02056 
02057        if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
02058               Z_LVAL_P(result) = 1;
02059        } else {
02060               Z_LVAL_P(result) = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC);
02061        }
02062 }
02063 /* }}} */
02064 
02065 ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
02066 {
02067        TSRMLS_FETCH();
02068 
02069        Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
02070 }
02071 /* }}} */
02072 
02073 /*
02074  * Local variables:
02075  * tab-width: 4
02076  * c-basic-offset: 4
02077  * indent-tabs-mode: t
02078  * End:
02079  */