mirror of
https://github.com/php/php-src.git
synced 2026-04-04 22:52:40 +02:00
* 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".
This commit is contained in:
79
Zend/zend.c
79
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 void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy)
|
||||
{
|
||||
if (expr->type==IS_STRING) {
|
||||
*use_copy = 0;
|
||||
return;
|
||||
}
|
||||
switch (expr->type) {
|
||||
case IS_BOOL:
|
||||
if (expr->value.lval) {
|
||||
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.len = sizeof("false")-1;
|
||||
expr_copy->value.str.val = estrndup("false", expr_copy->value.str.len);
|
||||
}
|
||||
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 destroy=0;
|
||||
int use_copy;
|
||||
|
||||
if (expr->type != IS_STRING) {
|
||||
if (expr->type == IS_BOOL) {
|
||||
if (expr->value.lval) {
|
||||
expr_copy.value.str.val = estrndup("true",4);
|
||||
expr_copy.value.str.len = 4;
|
||||
} else {
|
||||
expr_copy.value.str.val = estrndup("false",5);
|
||||
expr_copy.value.str.len = 5;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user