Annotation of embedaddon/php/Zend/zend_operators.c, revision 1.1.1.4

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>