From: Zeev Suraski Date: Fri, 11 Jun 1999 10:44:26 +0000 (+0000) Subject: * Make the output handling of variables much, much cooler. X-Git-Tag: BEFORE_REMOVING_GC_STEP1~154 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=da9faa2c3a7db0f222e751e899c843a1f6561e8b;p=php * Make the output handling of variables much, much cooler. Uses zend_make_printable_zval() instead of convert_to_string() now: $foo = true; print "\$foo is $foo"; will now print $foo is true (instead of "$foo is 1", earlier). Also, with objects, it automatically tries to call __print() and use it as a printing function. For example: class foo { function __print() { return "Foo Object"; } }; $foo = new foo; print $foo; will print "Foo Object". --- diff --git a/Zend/zend.c b/Zend/zend.c index ef9a39451b..fdc6be4a3f 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -22,6 +22,7 @@ #include "modules.h" #include "zend_constants.h" #include "zend_list.h" +#include "zend_API.h" #ifdef ZTS # define GLOBAL_FUNCTION_TABLE global_function_table @@ -97,38 +98,72 @@ static void print_hash(HashTable *ht, int indent) } -ZEND_API int zend_print_zval(zval *expr, int indent) +ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy) { - zval expr_copy; - int destroy=0; - - if (expr->type != IS_STRING) { - if (expr->type == IS_BOOL) { + if (expr->type==IS_STRING) { + *use_copy = 0; + return; + } + switch (expr->type) { + case IS_BOOL: if (expr->value.lval) { - expr_copy.value.str.val = estrndup("true",4); - expr_copy.value.str.len = 4; + expr_copy->value.str.len = sizeof("true")-1; + expr_copy->value.str.val = estrndup("true", expr_copy->value.str.len); } else { - expr_copy.value.str.val = estrndup("false",5); - expr_copy.value.str.len = 5; + expr_copy->value.str.len = sizeof("false")-1; + expr_copy->value.str.val = estrndup("false", expr_copy->value.str.len); } - expr_copy.type = IS_STRING; - } else if (expr->type == IS_RESOURCE) { - expr_copy.value.str.val = (char *) emalloc(sizeof("Resource id #")-1 + MAX_LENGTH_OF_LONG); - expr_copy.value.str.len = sprintf(expr_copy.value.str.val, "Resource id #%ld", expr->value.lval); - expr_copy.type = IS_STRING; - } else { - expr_copy = *expr; - zval_copy_ctor(&expr_copy); - convert_to_string(&expr_copy); - } + break; + case IS_RESOURCE: + expr_copy->value.str.val = (char *) emalloc(sizeof("Resource id #")-1 + MAX_LENGTH_OF_LONG); + expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Resource id #%ld", expr->value.lval); + break; + case IS_ARRAY: + expr_copy->value.str.len = sizeof("Array")-1; + expr_copy->value.str.val = estrndup("Array", expr_copy->value.str.len); + break; + case IS_OBJECT: { + zval function_name; + + function_name.value.str.len = sizeof("__print")-1; + function_name.value.str.val = estrndup("__print", function_name.value.str.len); + function_name.type = IS_STRING; + + if (call_user_function(NULL, expr, &function_name, expr_copy, 0, NULL)==FAILURE) { + expr_copy->value.str.len = sizeof("Object")-1; + expr_copy->value.str.val = estrndup("Object", expr_copy->value.str.len); + } + efree(function_name.value.str.val); + } + break; + default: + *expr_copy = *expr; + zval_copy_ctor(expr_copy); + convert_to_string(expr_copy); + break; + } + expr_copy->type = IS_STRING; + *use_copy = 1; +} + + +ZEND_API int zend_print_zval(zval *expr, int indent) +{ + zval expr_copy; + int use_copy; + + zend_make_printable_zval(expr, &expr_copy, &use_copy); + if (use_copy) { expr = &expr_copy; - destroy=1; } if (expr->value.str.len==0) { /* optimize away empty strings */ + if (use_copy) { + zval_dtor(expr); + } return 0; } ZEND_WRITE(expr->value.str.val,expr->value.str.len); - if (destroy) { + if (use_copy) { zval_dtor(expr); } return expr->value.str.len; diff --git a/Zend/zend.h b/Zend/zend.h index ece884f84a..56fd918bcf 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -180,6 +180,7 @@ ZEND_API void zend_bailout(); END_EXTERN_C() ZEND_API char *get_zend_version(); +ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy); ZEND_API int zend_print_zval(zval *expr, int indent); ZEND_API void zend_print_zval_r(zval *expr, int indent); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index b18a8ef27d..e6e7ac3d8e 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1217,19 +1217,16 @@ binary_assign_op_addr: { case ZEND_ADD_VAR: { zval *var = get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R); zval var_copy; - int destroy=0; + int use_copy; - if (var->type != IS_STRING) { - var_copy = *var; - zval_copy_ctor(&var_copy); + zend_make_printable_zval(var, &var_copy, &use_copy); + if (use_copy) { var = &var_copy; - convert_to_string(var); - destroy=1; } add_string_to_string( &Ts[opline->result.u.var].tmp_var, get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_NA), var); - if (destroy) { + if (use_copy) { zval_dtor(var); } /* original comment, possibly problematic: diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 5440103d7d..bce067597d 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -276,12 +276,10 @@ int call_user_function(HashTable *function_table, zval *object, zval *function_n return FAILURE; } function_table = &object->value.obj.ce->function_table; - /* unimplemented */ } original_function_state_ptr = EG(function_state_ptr); zend_str_tolower(function_name->value.str.val, function_name->value.str.len); if (zend_hash_find(function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function_state.function)==FAILURE) { - zend_error(E_ERROR, "Unknown function: %s()\n", function_name->value.str.val); return FAILURE; }