summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c335
1 files changed, 251 insertions, 84 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 683ab3c5cf..ef21b47a41 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -192,7 +192,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
ZVAL_LONG(op, 0);
}
- STR_FREE(strval);
+ str_efree(strval);
break;
}
case IS_BOOL:
@@ -391,7 +391,7 @@ ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
char *strval = Z_STRVAL_P(op);
Z_LVAL_P(op) = strtol(strval, NULL, base);
- STR_FREE(strval);
+ str_efree(strval);
}
break;
case IS_ARRAY:
@@ -451,7 +451,7 @@ ZEND_API void convert_to_double(zval *op) /* {{{ */
char *strval = Z_STRVAL_P(op);
Z_DVAL_P(op) = zend_strtod(strval, NULL);
- STR_FREE(strval);
+ str_efree(strval);
}
break;
case IS_ARRAY:
@@ -540,7 +540,7 @@ ZEND_API void convert_to_boolean(zval *op) /* {{{ */
} else {
Z_LVAL_P(op) = 1;
}
- STR_FREE(strval);
+ str_efree(strval);
}
break;
case IS_ARRAY:
@@ -857,6 +857,8 @@ ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
default:
if (!converted) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD);
+
zendi_convert_scalar_to_number(op1, op1_copy, result);
zendi_convert_scalar_to_number(op2, op2_copy, result);
converted = 1;
@@ -904,6 +906,8 @@ ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
default:
if (!converted) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB);
+
zendi_convert_scalar_to_number(op1, op1_copy, result);
zendi_convert_scalar_to_number(op2, op2_copy, result);
converted = 1;
@@ -945,6 +949,8 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
default:
if (!converted) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL);
+
zendi_convert_scalar_to_number(op1, op1_copy, result);
zendi_convert_scalar_to_number(op2, op2_copy, result);
converted = 1;
@@ -957,6 +963,90 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
}
/* }}} */
+ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ zval op1_copy, op2_copy;
+ int converted = 0;
+
+ while (1) {
+ switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
+ case TYPE_PAIR(IS_LONG, IS_LONG):
+ if (Z_LVAL_P(op2) >= 0) {
+ long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
+
+ if (i == 0) {
+ ZVAL_LONG(result, 1L);
+ return SUCCESS;
+ } else if (l2 == 0) {
+ ZVAL_LONG(result, 0);
+ return SUCCESS;
+ }
+
+ while (i >= 1) {
+ long overflow;
+ double dval = 0.0;
+
+ if (i % 2) {
+ --i;
+ ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
+ if (overflow) {
+ ZVAL_DOUBLE(result, dval * pow(l2, i));
+ return SUCCESS;
+ }
+ } else {
+ i /= 2;
+ ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
+ if (overflow) {
+ ZVAL_DOUBLE(result, (double)l1 * pow(dval, i));
+ return SUCCESS;
+ }
+ }
+ }
+ /* i == 0 */
+ ZVAL_LONG(result, l1);
+ } else {
+ ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2)));
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_LONG, IS_DOUBLE):
+ ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2)));
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_DOUBLE, IS_LONG):
+ ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2)));
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
+ ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
+ return SUCCESS;
+
+ default:
+ if (!converted) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW);
+
+ if (Z_TYPE_P(op1) == IS_ARRAY) {
+ ZVAL_LONG(result, 0);
+ return SUCCESS;
+ } else {
+ zendi_convert_scalar_to_number(op1, op1_copy, result);
+ }
+ if (Z_TYPE_P(op2) == IS_ARRAY) {
+ ZVAL_LONG(result, 1L);
+ return SUCCESS;
+ } else {
+ zendi_convert_scalar_to_number(op2, op2_copy, result);
+ }
+ converted = 1;
+ } else {
+ zend_error(E_ERROR, "Unsupported operand types");
+ return FAILURE;
+ }
+ }
+ }
+}
+/* }}} */
+
ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
@@ -1010,6 +1100,8 @@ ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
default:
if (!converted) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV);
+
zendi_convert_scalar_to_number(op1, op1_copy, result);
zendi_convert_scalar_to_number(op2, op2_copy, result);
converted = 1;
@@ -1027,9 +1119,15 @@ ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
zval op1_copy, op2_copy;
long op1_lval;
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
+ if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MOD);
+
+ zendi_convert_to_long(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_long(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
if (Z_LVAL_P(op2) == 0) {
zend_error(E_WARNING, "Division by zero");
@@ -1053,9 +1151,16 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
zval op1_copy, op2_copy;
long op1_lval;
- zendi_convert_to_boolean(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_boolean(op2, op2_copy, result);
+ if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_XOR);
+
+ zendi_convert_to_boolean(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_boolean(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
+
ZVAL_BOOL(result, op1_lval ^ Z_LVAL_P(op2));
return SUCCESS;
}
@@ -1065,7 +1170,12 @@ ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
{
zval op1_copy;
- zendi_convert_to_boolean(op1, op1_copy, result);
+ if (Z_TYPE_P(op1) != IS_BOOL) {
+ ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT);
+
+ zendi_convert_to_boolean(op1, op1_copy, result);
+ }
+
ZVAL_BOOL(result, !Z_LVAL_P(op1));
return SUCCESS;
}
@@ -1073,29 +1183,32 @@ ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
{
- zval op1_copy = *op1;
- op1 = &op1_copy;
-
- if (Z_TYPE_P(op1) == IS_LONG) {
- ZVAL_LONG(result, ~Z_LVAL_P(op1));
- return SUCCESS;
- } else if (Z_TYPE_P(op1) == IS_DOUBLE) {
- ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
- return SUCCESS;
- } else if (Z_TYPE_P(op1) == IS_STRING) {
- int i;
-
- Z_TYPE_P(result) = IS_STRING;
- Z_STRVAL_P(result) = estrndup(Z_STRVAL_P(op1), Z_STRLEN_P(op1));
- Z_STRLEN_P(result) = Z_STRLEN_P(op1);
- for (i = 0; i < Z_STRLEN_P(op1); i++) {
- Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
+ switch (Z_TYPE_P(op1)) {
+ case IS_LONG:
+ ZVAL_LONG(result, ~Z_LVAL_P(op1));
+ return SUCCESS;
+ case IS_DOUBLE:
+ ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
+ return SUCCESS;
+ case IS_STRING: {
+ int i;
+ zval op1_copy = *op1;
+
+ Z_TYPE_P(result) = IS_STRING;
+ Z_STRVAL_P(result) = estrndup(Z_STRVAL(op1_copy), Z_STRLEN(op1_copy));
+ Z_STRLEN_P(result) = Z_STRLEN(op1_copy);
+ for (i = 0; i < Z_STRLEN(op1_copy); i++) {
+ Z_STRVAL_P(result)[i] = ~Z_STRVAL(op1_copy)[i];
+ }
+ return SUCCESS;
}
- return SUCCESS;
+ default:
+ ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT);
+
+ zend_error(E_ERROR, "Unsupported operand types");
+ return FAILURE;
}
- zend_error(E_ERROR, "Unsupported operand types");
- return FAILURE; /* unknown datatype */
}
/* }}} */
@@ -1124,15 +1237,22 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /
result_str[i] |= Z_STRVAL_P(shorter)[i];
}
if (result==op1) {
- STR_FREE(Z_STRVAL_P(result));
+ str_efree(Z_STRVAL_P(result));
}
Z_STRVAL_P(result) = result_str;
Z_STRLEN_P(result) = result_len;
return SUCCESS;
}
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
+
+ if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_OR);
+
+ zendi_convert_to_long(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_long(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2));
return SUCCESS;
@@ -1164,17 +1284,22 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
result_str[i] &= Z_STRVAL_P(longer)[i];
}
if (result==op1) {
- STR_FREE(Z_STRVAL_P(result));
+ str_efree(Z_STRVAL_P(result));
}
Z_STRVAL_P(result) = result_str;
Z_STRLEN_P(result) = result_len;
return SUCCESS;
}
+ if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_AND);
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
+ zendi_convert_to_long(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_long(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2));
return SUCCESS;
@@ -1206,16 +1331,22 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
result_str[i] ^= Z_STRVAL_P(longer)[i];
}
if (result==op1) {
- STR_FREE(Z_STRVAL_P(result));
+ str_efree(Z_STRVAL_P(result));
}
Z_STRVAL_P(result) = result_str;
Z_STRLEN_P(result) = result_len;
return SUCCESS;
}
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
+ if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_XOR);
+
+ zendi_convert_to_long(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_long(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2));
return SUCCESS;
@@ -1227,9 +1358,16 @@ ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /
zval op1_copy, op2_copy;
long op1_lval;
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
+ if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SL);
+
+ zendi_convert_to_long(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_long(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
+
ZVAL_LONG(result, op1_lval << Z_LVAL_P(op2));
return SUCCESS;
}
@@ -1240,9 +1378,16 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
zval op1_copy, op2_copy;
long op1_lval;
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
+ if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SR);
+
+ zendi_convert_to_long(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_long(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
+
ZVAL_LONG(result, op1_lval >> Z_LVAL_P(op2));
return SUCCESS;
}
@@ -1252,14 +1397,8 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
int length = Z_STRLEN_P(op1) + 1;
- char *buf;
+ char *buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
- if (IS_INTERNED(Z_STRVAL_P(op1))) {
- buf = (char *) emalloc(length + 1);
- memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
- } else {
- buf = (char *) erealloc(Z_STRVAL_P(op1), length + 1);
- }
buf[length - 1] = (char) Z_LVAL_P(op2);
buf[length] = 0;
ZVAL_STRINGL(result, buf, length, 0);
@@ -1271,14 +1410,8 @@ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2)
ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
- char *buf;
+ char *buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
- if (IS_INTERNED(Z_STRVAL_P(op1))) {
- buf = (char *) emalloc(length+1);
- memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
- } else {
- buf = (char *) erealloc(Z_STRVAL_P(op1), length+1);
- }
memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
buf[length] = 0;
ZVAL_STRINGL(result, buf, length, 0);
@@ -1291,11 +1424,15 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
zval op1_copy, op2_copy;
int use_copy1 = 0, use_copy2 = 0;
- if (Z_TYPE_P(op1) != IS_STRING) {
- zend_make_printable_zval(op1, &op1_copy, &use_copy1);
- }
- if (Z_TYPE_P(op2) != IS_STRING) {
- zend_make_printable_zval(op2, &op2_copy, &use_copy2);
+ if (Z_TYPE_P(op1) != IS_STRING || Z_TYPE_P(op2) != IS_STRING) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT);
+
+ if (Z_TYPE_P(op1) != IS_STRING) {
+ zend_make_printable_zval(op1, &op1_copy, &use_copy1);
+ }
+ if (Z_TYPE_P(op2) != IS_STRING) {
+ zend_make_printable_zval(op2, &op2_copy, &use_copy2);
+ }
}
if (use_copy1) {
@@ -1526,20 +1663,24 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {
ZVAL_LONG(result, -1);
return SUCCESS;
- case TYPE_PAIR(IS_OBJECT, IS_OBJECT):
- /* If both are objects sharing the same comparision handler then use is */
- if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) {
+ default:
+ if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
+ return Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2 TSRMLS_CC);
+ } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
+ return Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2 TSRMLS_CC);
+ }
+
+ if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) {
if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
/* object handles are identical, apparently this is the same object */
ZVAL_LONG(result, 0);
return SUCCESS;
}
- ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));
- return SUCCESS;
+ if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) {
+ ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2 TSRMLS_CC));
+ return SUCCESS;
+ }
}
- /* break missing intentionally */
-
- default:
if (Z_TYPE_P(op1) == IS_OBJECT) {
if (Z_OBJ_HT_P(op1)->get) {
op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
@@ -1773,16 +1914,14 @@ static void increment_string(zval *str) /* {{{ */
int ch;
if (Z_STRLEN_P(str) == 0) {
- STR_FREE(Z_STRVAL_P(str));
+ str_efree(Z_STRVAL_P(str));
Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
Z_STRLEN_P(str) = 1;
return;
}
if (IS_INTERNED(s)) {
- s = (char*) emalloc(Z_STRLEN_P(str) + 1);
- memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1);
- Z_STRVAL_P(str) = s;
+ Z_STRVAL_P(str) = s = estrndup(s, Z_STRLEN_P(str));
}
while (pos >= 0) {
@@ -1840,7 +1979,7 @@ static void increment_string(zval *str) /* {{{ */
t[0] = 'a';
break;
}
- STR_FREE(Z_STRVAL_P(str));
+ str_efree(Z_STRVAL_P(str));
Z_STRVAL_P(str) = t;
}
}
@@ -1890,6 +2029,20 @@ ZEND_API int increment_function(zval *op1) /* {{{ */
}
}
break;
+ case IS_OBJECT:
+ if (Z_OBJ_HANDLER_P(op1, do_operation)) {
+ zval *op2;
+ int res;
+ TSRMLS_FETCH();
+
+ MAKE_STD_ZVAL(op2);
+ ZVAL_LONG(op2, 1);
+ res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_ADD, op1, op1, op2 TSRMLS_CC);
+ zval_ptr_dtor(&op2);
+
+ return res;
+ }
+ return FAILURE;
default:
return FAILURE;
}
@@ -1916,13 +2069,13 @@ ZEND_API int decrement_function(zval *op1) /* {{{ */
break;
case IS_STRING: /* Like perl we only support string increment */
if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
- STR_FREE(Z_STRVAL_P(op1));
+ str_efree(Z_STRVAL_P(op1));
ZVAL_LONG(op1, -1);
break;
}
switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
case IS_LONG:
- STR_FREE(Z_STRVAL_P(op1));
+ str_efree(Z_STRVAL_P(op1));
if (lval == LONG_MIN) {
double d = (double)lval;
ZVAL_DOUBLE(op1, d-1);
@@ -1931,11 +2084,25 @@ ZEND_API int decrement_function(zval *op1) /* {{{ */
}
break;
case IS_DOUBLE:
- STR_FREE(Z_STRVAL_P(op1));
+ str_efree(Z_STRVAL_P(op1));
ZVAL_DOUBLE(op1, dval - 1);
break;
}
break;
+ case IS_OBJECT:
+ if (Z_OBJ_HANDLER_P(op1, do_operation)) {
+ zval *op2;
+ int res;
+ TSRMLS_FETCH();
+
+ MAKE_STD_ZVAL(op2);
+ ZVAL_LONG(op2, 1);
+ res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_SUB, op1, op1, op2 TSRMLS_CC);
+ zval_ptr_dtor(&op2);
+
+ return res;
+ }
+ return FAILURE;
default:
return FAILURE;
}