Changed __toString() behavior to call it in all necessary places
authorDmitry Stogov <dmitry@php.net>
Tue, 27 Sep 2005 07:59:18 +0000 (07:59 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 27 Sep 2005 07:59:18 +0000 (07:59 +0000)
12 files changed:
NEWS
Zend/tests/bug26166.phpt
Zend/zend.c
Zend/zend.h
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_object_handlers.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
tests/classes/tostring.phpt

diff --git a/NEWS b/NEWS
index 0fb04e3cac8aa1c3067190eee42e751cc0bbd78c..3e5d89bedd8d8faf9f2a35969d326acbe1b45789 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? ????, PHP 6.0
 - Unicode support. (Andrei, Dmitriy, et al)
+- Changed __toString() behavior to call it in all necessary places
+  (Marcus, Dmitry)
 - Changed "instanceof" and "catch" operators, is_a() and is_subclass_of()
   functions to not call __autoload(). (Dmitry)
 - cURL improvements: (Ilia)
index 1c3934ac9176b0df954bc82fca71c524fdfe4bef..e2800ad8789df515ac14499143b74d8618b34906 100755 (executable)
@@ -64,4 +64,4 @@ Hello World!
 Got the exception
 ===NONE===
 
-Fatal error: Method None::__toString() must return a string value in %sbug26166.php on line %d
+Catchable fatal error: Method None::__toString() must return a string value in %sbug26166.php on line %d
index 8de73997a117eb5390b48f967c28f1819f304c03..37108066ac281a870449d5a7ce2a091c6ffa4676 100644 (file)
@@ -347,39 +347,28 @@ ZEND_API void zend_make_string_zval(zval *expr, zval *expr_copy, int *use_copy)
                case IS_OBJECT:
                        {
                                TSRMLS_FETCH();
-#if 0
-                               /* Standard PHP objects */
-                               if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) {
-                                       if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-                                               break;
-                                       }
-                                       zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
-                               }
-#endif
                                if (Z_OBJ_HANDLER_P(expr, cast_object)) {
                                        if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
                                                break;
                                        }
-                               } else {
-                                       if(Z_OBJ_HANDLER_P(expr, get)) {
-                                               zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
-                                               if(Z_TYPE_P(z) != IS_OBJECT) {
-                                                       zend_make_printable_zval(z, expr_copy, use_copy);
-                                                       FREE_ZVAL(z);
-                                                       return;
-                                               }
+                               }
+                               if (Z_OBJ_HANDLER_P(expr, get)) {
+                                       zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
+                                       if(Z_TYPE_P(z) != IS_OBJECT) {
+                                               zend_make_printable_zval(z, expr_copy, use_copy);
+                                               FREE_ZVAL(z);
+                                               break;
                                        }
                                }
                                if (EG(exception)) {
-                                       zval_dtor(expr_copy);
                                        expr_copy->value.str.len = 0;
                                        expr_copy->value.str.val = STR_EMPTY_ALLOC();
                                        break;
                                }
+
                        }
                        expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG);
                        expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle);
-                       expr_copy->type = IS_STRING;
                        break;
                default:
                        *expr_copy = *expr;
@@ -387,6 +376,7 @@ ZEND_API void zend_make_string_zval(zval *expr, zval *expr_copy, int *use_copy)
                        convert_to_string(expr_copy);
                        break;
        }
+       expr_copy->type = IS_STRING;
        *use_copy = 1;
 }
 
@@ -426,40 +416,26 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
                        expr_copy->value.str.val = estrndup("Array", expr_copy->value.str.len);
                        break;
                case IS_OBJECT:
-                       {
-#if 0
-                               /* Standard PHP objects */
-                               if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) {
-                                       if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-                                               break;
-                                       }
-                                       zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
-                               }
-#endif
-                               if (Z_OBJ_HANDLER_P(expr, cast_object)) {
-                                       if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-                                               break;
-                                       }
-                               } else {
-                                       if(Z_OBJ_HANDLER_P(expr, get)) {
-                                               zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
-                                               if(Z_TYPE_P(z) != IS_OBJECT) {
-                                                       zend_make_printable_zval(z, expr_copy, use_copy);
-                                                       FREE_ZVAL(z);
-                                                       return;
-                                               }
-                                       }
+                       if (Z_OBJ_HANDLER_P(expr, cast_object)) {
+                               if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+                                       break;
                                }
-                               if (EG(exception)) {
-                                       zval_dtor(expr_copy);
-                                       expr_copy->value.str.len = 0;
-                                       expr_copy->value.str.val = STR_EMPTY_ALLOC();
+                       }
+                       if (Z_OBJ_HANDLER_P(expr, get)) {
+                               zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
+                               if(Z_TYPE_P(z) != IS_OBJECT) {
+                                       zend_make_printable_zval(z, expr_copy, use_copy);
+                                       FREE_ZVAL(z);
                                        break;
                                }
                        }
+                       if (EG(exception)) {
+                               expr_copy->value.str.len = 0;
+                               expr_copy->value.str.val = STR_EMPTY_ALLOC();
+                               break;
+                       }
                        expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG);
                        expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle);
-                       expr_copy->type = IS_STRING;
                        break;
                case IS_DOUBLE:
                        *expr_copy = *expr;
@@ -491,40 +467,26 @@ ZEND_API void zend_make_unicode_zval(zval *expr, zval *expr_copy, int *use_copy)
        }
        switch (expr->type) {
                case IS_OBJECT:
-                       {
-#if 0
-                               /* Standard PHP objects */
-                               if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) {
-                                       if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-                                               break;
-                                       }
-                                       zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
-                               }
-#endif
-                               if (Z_OBJ_HANDLER_P(expr, cast_object)) {
-                                       if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) {
-                                               break;
-                                       }
-                               } else {
-                                       if(Z_OBJ_HANDLER_P(expr, get)) {
-                                               zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
-                                               if(Z_TYPE_P(z) != IS_OBJECT) {
-                                                       zend_make_unicode_zval(z, expr_copy, use_copy);
-                                                       FREE_ZVAL(z);
-                                                       return;
-                                               }
-                                       }
+                       if (Z_OBJ_HANDLER_P(expr, cast_object)) {
+                               if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) {
+                                       break;
                                }
-                               if (EG(exception)) {
-                                       zval_dtor(expr_copy);
-                                       expr_copy->value.ustr.len = 0;
-                                       expr_copy->value.ustr.val = USTR_MAKE("");
+                       }
+                       if (Z_OBJ_HANDLER_P(expr, get)) {
+                               zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
+                               if(Z_TYPE_P(z) != IS_OBJECT) {
+                                       zend_make_unicode_zval(z, expr_copy, use_copy);
+                                       FREE_ZVAL(z);
                                        break;
                                }
                        }
-                       expr_copy->value.ustr.val = emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG + 1);
+                       if (EG(exception)) {
+                               expr_copy->value.ustr.len = 0;
+                               expr_copy->value.ustr.val = USTR_MAKE("");
+                               break;
+                       }
+                       expr_copy->value.ustr.val = eumalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG + 1);
                        expr_copy->value.ustr.len = u_sprintf(expr_copy->value.ustr.val, "Object id #%ld", (long)expr->value.obj.handle);
-                       expr_copy->type = IS_UNICODE;
                        break;
                default:
                        *expr_copy = *expr;
@@ -532,6 +494,7 @@ ZEND_API void zend_make_unicode_zval(zval *expr, zval *expr_copy, int *use_copy)
                        convert_to_unicode(expr_copy);
                        break;
        }
+       expr_copy->type = IS_UNICODE;
        *use_copy = 1;
 }
 
@@ -969,6 +932,8 @@ static void fix_classes(HashTable *ht) {
                        ce->__isset = ce->__isset->common.u_twin;
                } else if (ce->__call) {
                        ce->__call = ce->__call->common.u_twin;
+               } else if (ce->__tostring) {
+                       ce->__tostring = ce->__tostring->common.u_twin;
                } else if (ce->serialize_func) {
                        ce->serialize_func = ce->serialize_func->common.u_twin;
                } else if (ce->unserialize_func) {
index 2590398467c2834a88cc12467a527890a3e4acbf..53e3d05705d66a33a89159299f69dfb55eeabc38 100644 (file)
@@ -360,6 +360,7 @@ struct _zend_class_entry {
        union _zend_function *__unset;
        union _zend_function *__isset;
        union _zend_function *__call;
+       union _zend_function *__tostring;
        union _zend_function *serialize_func;
        union _zend_function *unserialize_func;
 
index 7fd4ba8496005aefafb204562242dad4b39f0a3a..22d43f52265459b025d540d1563a69564b18b5f6 100644 (file)
@@ -2022,6 +2022,9 @@ ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_
        } else if (lcname_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 &&
            ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1) && fptr->common.num_args != 2) {
                zend_error(error_type, "Method %v::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
+       } else if (lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
+           ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0) {
+               zend_error(error_type, "Method %v::%s() cannot take arguments", ce->name, ZEND_CALL_FUNC_NAME);
        }
        efree(lcname);
 }
@@ -2035,7 +2038,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
        int count=0, unload=0;
        HashTable *target_function_table = function_table;
        int error_type;
-       zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL;
+       zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__tostring = NULL;
        char *lowercase_name;
        int fname_len;
        char *lc_class_name;
@@ -2139,6 +2142,8 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
                                clone = reg_function;
                        } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
                                __call = reg_function;
+                       } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME))) {
+                               __tostring = reg_function;
                        } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
                                __get = reg_function;
                        } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
@@ -2176,6 +2181,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
                scope->destructor = dtor;
                scope->clone = clone;
                scope->__call = __call;
+               scope->__tostring = __tostring;
                scope->__get = __get;
                scope->__set = __set;
                scope->__unset = __unset;
@@ -2207,6 +2213,12 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
                        }
                        __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
                }
+               if (__tostring) {
+                       if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
+                               zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name);
+                       }
+                       __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
+               }
                if (__get) {
                        if (__get->common.fn_flags & ZEND_ACC_STATIC) {
                                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name);
index 8c21671dc917e93d1db955c92ac565b4de4cd0f2..5720878166be3b772c10bd8f7e21ab3c6f6a0ef3 100644 (file)
@@ -131,6 +131,7 @@ typedef struct _zend_function_entry {
                class_container.create_object = NULL;                                   \
                class_container.interface_gets_implemented = NULL;              \
                class_container.__call = handle_fcall;                                  \
+               class_container.__tostring = NULL;                                              \
                class_container.__get = handle_propget;                                 \
                class_container.__set = handle_propset;                                 \
                class_container.__unset = handle_propunset;                             \
index 1a8c66fb7148f436551828a41f3e45b1a47815e2..2a19b0398f5dfd839365bdc8ef2ba1512e738e59 100644 (file)
@@ -1163,6 +1163,8 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
                                CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
                        } else if ((lcname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
                                CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
+                       } else if ((lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
+                               CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
                        } else if (!(fn_flags & ZEND_ACC_STATIC)) {
                                CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
                        }
@@ -1873,6 +1875,9 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC)
        if (!ce->__call) {
                ce->__call = ce->parent->__call;
        }
+       if (!ce->__tostring) {
+               ce->__tostring = ce->parent->__tostring;
+       }
        if (!ce->clone) {
                ce->clone = ce->parent->clone;
        }
@@ -4152,6 +4157,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
                ce->__unset = NULL;
                ce->__isset = NULL;
                ce->__call = NULL;
+               ce->__tostring = NULL;
                ce->create_object = NULL;
                ce->get_iterator = NULL;
                ce->iterator_funcs.funcs = NULL;
index 6fd22cbd6a349ff12e495957f2a71a987e4d882d..a8d56e917bc10478c7233fcfb12b4ff9dc5f58d9 100644 (file)
@@ -723,6 +723,7 @@ END_EXTERN_C()
 #define ZEND_UNSET_FUNC_NAME        "__unset"
 #define ZEND_ISSET_FUNC_NAME        "__isset"
 #define ZEND_CALL_FUNC_NAME         "__call"
+#define ZEND_TOSTRING_FUNC_NAME     "__tostring"
 #define ZEND_AUTOLOAD_FUNC_NAME     "__autoload"
 
 #endif /* ZEND_COMPILE_H */
index bf8fec3c20cade9040fbc2de977de50784e5afa7..de0d27213dd08470ffbbb675b872601faf6c5af4 100644 (file)
@@ -1008,37 +1008,30 @@ int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *c
 
 ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC)
 {
-       zval fname, *retval;
+       zval *retval;
+       zend_class_entry *ce;
        
        switch (type) {
                case IS_STRING:
                case IS_UNICODE:
-                       if (!zend_hash_exists(&Z_OBJCE_P(readobj)->function_table, "__tostring", sizeof("__tostring"))) {
-                               return FAILURE;
-                       }
-                       ZVAL_ASCII_STRING(&fname, "__tostring", 0);
-                       if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) {
-                               if (UG(unicode)) {
-                                       zval_dtor(&fname);
-                               }
-                               if (retval) {
-                                       if (Z_TYPE_P(retval) != (UG(unicode)?IS_UNICODE:IS_STRING)) {
-                                               zend_error(E_ERROR, "Method %v::__toString() must return a string value", Z_OBJCE_P(readobj)->name);
+                       ce = Z_OBJCE_P(readobj);
+                       if (ce->__tostring &&
+                zend_call_method_with_0_params(&readobj, ce, &ce->__tostring, "__tostring", &retval)) {
+                               if (Z_TYPE_P(retval) == (UG(unicode)?IS_UNICODE:IS_STRING)) {
+                                       *writeobj = *retval;
+                                       zval_copy_ctor(writeobj);
+                                       zval_ptr_dtor(&retval);
+                                       INIT_PZVAL(writeobj);
+                                       if (Z_TYPE_P(writeobj) != type) {
+                                               convert_to_explicit_type(writeobj, type);
                                        }
+                                       return SUCCESS;
                                } else {
-                                       MAKE_STD_ZVAL(retval);
-                                       ZVAL_ASCII_STRINGL(retval, "", 0, 1);
+                                       zval_ptr_dtor(&retval);
+                                       zend_error(E_RECOVERABLE_ERROR, "Method %v::__toString() must return a string value", ce->name);
                                }
-                               *writeobj = *retval;
-                               zval_copy_ctor(writeobj);
-                               INIT_PZVAL(writeobj);
-                               zval_ptr_dtor(&retval);
-                               return SUCCESS;
-                       }
-                       if (UG(unicode)) {
-                               zval_dtor(&fname);
                        }
-                       break;
+                       return FAILURE;
                default:
                        break;
        }
@@ -1069,7 +1062,7 @@ ZEND_API zend_object_handlers std_object_handlers = {
        zend_std_object_get_class,                              /* get_class_entry */
        zend_std_object_get_class_name,                 /* get_class_name */
        zend_std_compare_objects,                               /* compare_objects */
-       NULL,                                                                   /* cast_object */
+       zend_std_cast_object_tostring,                  /* cast_object */
        NULL,                                                                   /* count_elements */
 };
 
index 7b51bf983324222b7f3f76f5fbadcd19b202d16f..fb20ffb8fc879394db1a1e0c06768e3c202cd71d 100644 (file)
@@ -884,34 +884,28 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
        zend_free_op free_op1;
        zval z_copy;
        zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R);
-
-       if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
-               zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-               zend_print_variable(&z_copy);
-               zval_dtor(&z_copy);
-       } else {
-               UErrorCode status = U_ZERO_ERROR;
-               /* Convert inline HTML blocks to the output encoding, but only if necessary. */
-               if (opline->extended_value &&
-                       strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
-                                  EG(active_op_array)->script_encoding)) {
-                       zval z_conv;
-                       UConverter *script_enc_conv = NULL;
-                       if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
-                               zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
-                       }
-                       zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
-                       z_conv.type = IS_BINARY;
-                       if (U_SUCCESS(status)) {
-                               zend_print_variable(&z_conv);
-                       } else {
-                               zend_error(E_WARNING, "Could not convert inline HTML for output");
-                       }
-                       zval_dtor(&z_conv);
-                       ucnv_close(script_enc_conv);
+       UErrorCode status = U_ZERO_ERROR;
+
+       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       if (opline->extended_value &&
+               strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+                          EG(active_op_array)->script_encoding)) {
+               zval z_conv;
+               UConverter *script_enc_conv = NULL;
+               if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
+                       zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
+               }
+               zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+               z_conv.type = IS_BINARY;
+               if (U_SUCCESS(status)) {
+                       zend_print_variable(&z_conv);
                } else {
-                       zend_print_variable(z);
+                       zend_error(E_WARNING, "Could not convert inline HTML for output");
                }
+               zval_dtor(&z_conv);
+               ucnv_close(script_enc_conv);
+       } else {
+               zend_print_variable(z);
        }
 
        FREE_OP1();
index 1e4e82bf77ba6094efb16e5e4f33f9f5f659be9d..89f4402b31804280923daa9a95233bd7887ab21b 100644 (file)
@@ -1367,34 +1367,28 @@ static int ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        
        zval z_copy;
        zval *z = &opline->op1.u.constant;
-
-       if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
-               zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-               zend_print_variable(&z_copy);
-               zval_dtor(&z_copy);
-       } else {
-               UErrorCode status = U_ZERO_ERROR;
-               /* Convert inline HTML blocks to the output encoding, but only if necessary. */
-               if (opline->extended_value &&
-                       strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
-                                  EG(active_op_array)->script_encoding)) {
-                       zval z_conv;
-                       UConverter *script_enc_conv = NULL;
-                       if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
-                               zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
-                       }
-                       zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
-                       z_conv.type = IS_BINARY;
-                       if (U_SUCCESS(status)) {
-                               zend_print_variable(&z_conv);
-                       } else {
-                               zend_error(E_WARNING, "Could not convert inline HTML for output");
-                       }
-                       zval_dtor(&z_conv);
-                       ucnv_close(script_enc_conv);
+       UErrorCode status = U_ZERO_ERROR;
+
+       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       if (opline->extended_value &&
+               strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+                          EG(active_op_array)->script_encoding)) {
+               zval z_conv;
+               UConverter *script_enc_conv = NULL;
+               if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
+                       zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
+               }
+               zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+               z_conv.type = IS_BINARY;
+               if (U_SUCCESS(status)) {
+                       zend_print_variable(&z_conv);
                } else {
-                       zend_print_variable(z);
+                       zend_error(E_WARNING, "Could not convert inline HTML for output");
                }
+               zval_dtor(&z_conv);
+               ucnv_close(script_enc_conv);
+       } else {
+               zend_print_variable(z);
        }
 
        ZEND_VM_NEXT_OPCODE();
@@ -3879,34 +3873,28 @@ static int ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zend_free_op free_op1;
        zval z_copy;
        zval *z = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-
-       if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
-               zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-               zend_print_variable(&z_copy);
-               zval_dtor(&z_copy);
-       } else {
-               UErrorCode status = U_ZERO_ERROR;
-               /* Convert inline HTML blocks to the output encoding, but only if necessary. */
-               if (opline->extended_value &&
-                       strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
-                                  EG(active_op_array)->script_encoding)) {
-                       zval z_conv;
-                       UConverter *script_enc_conv = NULL;
-                       if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
-                               zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
-                       }
-                       zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
-                       z_conv.type = IS_BINARY;
-                       if (U_SUCCESS(status)) {
-                               zend_print_variable(&z_conv);
-                       } else {
-                               zend_error(E_WARNING, "Could not convert inline HTML for output");
-                       }
-                       zval_dtor(&z_conv);
-                       ucnv_close(script_enc_conv);
+       UErrorCode status = U_ZERO_ERROR;
+
+       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       if (opline->extended_value &&
+               strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+                          EG(active_op_array)->script_encoding)) {
+               zval z_conv;
+               UConverter *script_enc_conv = NULL;
+               if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
+                       zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
+               }
+               zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+               z_conv.type = IS_BINARY;
+               if (U_SUCCESS(status)) {
+                       zend_print_variable(&z_conv);
                } else {
-                       zend_print_variable(z);
+                       zend_error(E_WARNING, "Could not convert inline HTML for output");
                }
+               zval_dtor(&z_conv);
+               ucnv_close(script_enc_conv);
+       } else {
+               zend_print_variable(z);
        }
 
        zval_dtor(free_op1.var);
@@ -6930,34 +6918,28 @@ static int ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zend_free_op free_op1;
        zval z_copy;
        zval *z = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-
-       if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
-               zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-               zend_print_variable(&z_copy);
-               zval_dtor(&z_copy);
-       } else {
-               UErrorCode status = U_ZERO_ERROR;
-               /* Convert inline HTML blocks to the output encoding, but only if necessary. */
-               if (opline->extended_value &&
-                       strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
-                                  EG(active_op_array)->script_encoding)) {
-                       zval z_conv;
-                       UConverter *script_enc_conv = NULL;
-                       if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
-                               zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
-                       }
-                       zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
-                       z_conv.type = IS_BINARY;
-                       if (U_SUCCESS(status)) {
-                               zend_print_variable(&z_conv);
-                       } else {
-                               zend_error(E_WARNING, "Could not convert inline HTML for output");
-                       }
-                       zval_dtor(&z_conv);
-                       ucnv_close(script_enc_conv);
+       UErrorCode status = U_ZERO_ERROR;
+
+       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       if (opline->extended_value &&
+               strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+                          EG(active_op_array)->script_encoding)) {
+               zval z_conv;
+               UConverter *script_enc_conv = NULL;
+               if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
+                       zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
+               }
+               zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+               z_conv.type = IS_BINARY;
+               if (U_SUCCESS(status)) {
+                       zend_print_variable(&z_conv);
                } else {
-                       zend_print_variable(z);
+                       zend_error(E_WARNING, "Could not convert inline HTML for output");
                }
+               zval_dtor(&z_conv);
+               ucnv_close(script_enc_conv);
+       } else {
+               zend_print_variable(z);
        }
 
        if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
@@ -19709,34 +19691,28 @@ static int ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        
        zval z_copy;
        zval *z = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
-
-       if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
-               zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
-               zend_print_variable(&z_copy);
-               zval_dtor(&z_copy);
-       } else {
-               UErrorCode status = U_ZERO_ERROR;
-               /* Convert inline HTML blocks to the output encoding, but only if necessary. */
-               if (opline->extended_value &&
-                       strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
-                                  EG(active_op_array)->script_encoding)) {
-                       zval z_conv;
-                       UConverter *script_enc_conv = NULL;
-                       if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
-                               zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
-                       }
-                       zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
-                       z_conv.type = IS_BINARY;
-                       if (U_SUCCESS(status)) {
-                               zend_print_variable(&z_conv);
-                       } else {
-                               zend_error(E_WARNING, "Could not convert inline HTML for output");
-                       }
-                       zval_dtor(&z_conv);
-                       ucnv_close(script_enc_conv);
+       UErrorCode status = U_ZERO_ERROR;
+
+       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       if (opline->extended_value &&
+               strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+                          EG(active_op_array)->script_encoding)) {
+               zval z_conv;
+               UConverter *script_enc_conv = NULL;
+               if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) {
+                       zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding);
+               }
+               zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+               z_conv.type = IS_BINARY;
+               if (U_SUCCESS(status)) {
+                       zend_print_variable(&z_conv);
                } else {
-                       zend_print_variable(z);
+                       zend_error(E_WARNING, "Could not convert inline HTML for output");
                }
+               zval_dtor(&z_conv);
+               ucnv_close(script_enc_conv);
+       } else {
+               zend_print_variable(z);
        }
 
        ZEND_VM_NEXT_OPCODE();
index b639183d2f65e267a2efb7fb92868a51a8e379c8..40876d7292738d80a8b8904a0ee282142cd20b57 100644 (file)
@@ -34,9 +34,11 @@ echo "string:".$o;
 
 echo "====test5====\n";
 echo 1 . $o;
+echo 1 . $o;
 
 echo "====test6====\n";
 echo $o.$o;
+echo $o,$o;
 
 echo "====test7====\n";
 $ar = array();
@@ -56,8 +58,8 @@ echo sprintf("%s", $o);
 test1 Object
 (
 )
-string(1%d) "Object id #%d"
-object(test1)#%d (%d) {
+string(12) "Object id #%d"
+object(test1)#%d (0) {
 }
 ====test2====
 test2 Object
@@ -71,26 +73,42 @@ object(test2)#%d (%d) {
 test2::__toString()
 Converted
 ====test4====
-string:Object id #%d====test5====
-1Object id #%d====test6====
-Object id #%dObject id #2====test7====
+test2::__toString()
+string:Converted
+====test5====
+test2::__toString()
+1Converted
+test2::__toString()
+1Converted
+====test6====
+test2::__toString()
+test2::__toString()
+Converted
+Converted
+test2::__toString()
+Converted
+test2::__toString()
+Converted
+====test7====
 test2::__toString()
 
 Warning: Illegal offset type in %stostring.php on line %d
 ====test8====
-
-Notice: Object of class test2 to string conversion in %stostring.php on line %d
-string(6) "Object"
-string(1%d) "Object id #%d"
+test2::__toString()
+string(9) "Converted"
+test2::__toString()
+string(9) "Converted"
 ====test9====
-Object id #%d====DONE!====
+test2::__toString()
+Converted
+====DONE!====
 --UEXPECTF--
 ====test1====
 test1 Object
 (
 )
-string(1%d) "Object id #%d"
-object(test1)#%d (%d) {
+string(12) "Object id #%d"
+object(test1)#%d (0) {
 }
 ====test2====
 test2 Object
@@ -104,16 +122,32 @@ object(test2)#%d (%d) {
 test2::__toString()
 Converted
 ====test4====
-string:Object id #%d====test5====
-1Object id #%d====test6====
-Object id #%dObject id #2====test7====
+test2::__toString()
+string:Converted
+====test5====
+test2::__toString()
+1Converted
+test2::__toString()
+1Converted
+====test6====
+test2::__toString()
+test2::__toString()
+Converted
+Converted
+test2::__toString()
+Converted
+test2::__toString()
+Converted
+====test7====
 test2::__toString()
 
 Warning: Illegal offset type in %stostring.php on line %d
 ====test8====
-
-Notice: Object of class test2 to string conversion in %stostring.php on line %d
-unicode(6) "Object"
-unicode(1%d) "Object id #%d"
+test2::__toString()
+unicode(9) "Converted"
+test2::__toString()
+unicode(9) "Converted"
 ====test9====
-Object id #%d====DONE!====
+test2::__toString()
+Converted
+====DONE!====