1999-04-08 02:10:10 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2001-02-26 13:43:27 +08:00
| Copyright ( c ) 1998 - 2001 Zend Technologies Ltd . ( http : //www.zend.com) |
1999-04-08 02:10:10 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2000-03-06 13:26:39 +08:00
| This source file is subject to version 0.92 of the Zend license , |
1999-07-16 22:58:16 +08:00
| that is bundled with this package in the file LICENSE , and is |
| available at through the world - wide - web at |
2000-03-06 13:26:39 +08:00
| http : //www.zend.com/license/0_92.txt. |
1999-07-16 22:58:16 +08:00
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ zend . com so we can mail you a copy immediately . |
1999-04-08 02:10:10 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Andi Gutmans < andi @ zend . com > |
| Zeev Suraski < zeev @ zend . com > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2000-02-10 05:48:16 +08:00
# define ZEND_INTENSIVE_DEBUGGING 0
1999-07-16 22:58:16 +08:00
1999-04-08 02:10:10 +08:00
# include <stdio.h>
# include <signal.h>
# include "zend.h"
# include "zend_compile.h"
# include "zend_execute.h"
# include "zend_API.h"
# include "zend_ptr_stack.h"
# include "zend_constants.h"
# include "zend_extensions.h"
1999-12-28 03:07:33 +08:00
# include "zend_fast_cache.h"
2000-02-02 06:04:52 +08:00
# include "zend_execute_locks.h"
1999-04-08 02:10:10 +08:00
2001-07-27 18:10:39 +08:00
# define get_zval_ptr(node, Ts, should_free, type) _get_zval_ptr(node, Ts, should_free TSRMLS_CC)
# define get_zval_ptr_ptr(node, Ts, type) _get_zval_ptr_ptr(node, Ts TSRMLS_CC)
1999-04-08 02:10:10 +08:00
# define get_incdec_op(op, opcode) \
switch ( opcode ) { \
case ZEND_PRE_INC : \
case ZEND_POST_INC : \
( op ) = increment_function ; \
break ; \
case ZEND_PRE_DEC : \
case ZEND_POST_DEC : \
( op ) = decrement_function ; \
break ; \
default : \
( op ) = NULL ; \
break ; \
} \
/* These globals don't have to be thread safe since they're never modified */
/* Prototypes */
2001-07-27 18:10:39 +08:00
static zval get_overloaded_property ( temp_variable * T TSRMLS_DC ) ;
static void set_overloaded_property ( temp_variable * T , zval * value TSRMLS_DC ) ;
static void call_overloaded_function ( temp_variable * T , int arg_count , zval * return_value TSRMLS_DC ) ;
static void zend_fetch_var_address ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts , int type TSRMLS_DC ) ;
static void zend_fetch_dimension_address ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts , int type TSRMLS_DC ) ;
static void zend_fetch_property_address ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts , int type TSRMLS_DC ) ;
static void zend_fetch_dimension_address_from_tmp_var ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts TSRMLS_DC ) ;
2001-07-31 12:53:54 +08:00
static void zend_extension_statement_handler ( zend_extension * extension , zend_op_array * op_array TSRMLS_DC ) ;
static void zend_extension_fcall_begin_handler ( zend_extension * extension , zend_op_array * op_array TSRMLS_DC ) ;
static void zend_extension_fcall_end_handler ( zend_extension * extension , zend_op_array * op_array TSRMLS_DC ) ;
1999-04-08 02:10:10 +08:00
1999-12-21 23:55:46 +08:00
# define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED))
2001-07-27 18:10:39 +08:00
static inline zval * _get_zval_ptr ( znode * node , temp_variable * Ts , int * should_free TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
switch ( node - > op_type ) {
case IS_CONST :
* should_free = 0 ;
return & node - > u . constant ;
break ;
case IS_TMP_VAR :
* should_free = 1 ;
return & Ts [ node - > u . var ] . tmp_var ;
break ;
case IS_VAR :
1999-09-29 00:03:09 +08:00
if ( Ts [ node - > u . var ] . var . ptr ) {
PZVAL_UNLOCK ( Ts [ node - > u . var ] . var . ptr ) ;
1999-04-08 02:10:10 +08:00
* should_free = 0 ;
1999-09-29 00:03:09 +08:00
return Ts [ node - > u . var ] . var . ptr ;
1999-04-08 02:10:10 +08:00
} else {
* should_free = 1 ;
switch ( Ts [ node - > u . var ] . EA . type ) {
case IS_OVERLOADED_OBJECT :
2001-07-27 18:10:39 +08:00
Ts [ node - > u . var ] . tmp_var = get_overloaded_property ( & Ts [ node - > u . var ] TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
Ts [ node - > u . var ] . tmp_var . refcount = 1 ;
1999-10-02 07:31:39 +08:00
Ts [ node - > u . var ] . tmp_var . is_ref = 1 ;
1999-04-08 02:10:10 +08:00
return & Ts [ node - > u . var ] . tmp_var ;
break ;
case IS_STRING_OFFSET : {
temp_variable * T = & Ts [ node - > u . var ] ;
2000-04-07 00:34:55 +08:00
zval * str = T - > EA . data . str_offset . str ;
1999-04-08 02:10:10 +08:00
2000-04-07 00:34:55 +08:00
if ( T - > EA . data . str_offset . str - > type ! = IS_STRING
2001-02-06 06:27:47 +08:00
| | ( T - > EA . data . str_offset . offset < 0 )
2000-04-07 00:34:55 +08:00
| | ( T - > EA . data . str_offset . str - > value . str . len < = T - > EA . data . str_offset . offset ) ) {
2001-06-27 23:40:49 +08:00
zend_error ( E_NOTICE , " Uninitialized string offset: %d " , T - > EA . data . str_offset . offset ) ;
1999-04-08 02:10:10 +08:00
T - > tmp_var . value . str . val = empty_string ;
T - > tmp_var . value . str . len = 0 ;
} else {
2000-04-07 00:34:55 +08:00
char c = str - > value . str . val [ T - > EA . data . str_offset . offset ] ;
1999-04-08 02:10:10 +08:00
T - > tmp_var . value . str . val = estrndup ( & c , 1 ) ;
T - > tmp_var . value . str . len = 1 ;
}
1999-10-28 23:53:31 +08:00
PZVAL_UNLOCK ( str ) ;
1999-04-08 02:10:10 +08:00
T - > tmp_var . refcount = 1 ;
1999-10-02 07:31:39 +08:00
T - > tmp_var . is_ref = 1 ;
1999-04-08 02:10:10 +08:00
T - > tmp_var . type = IS_STRING ;
return & T - > tmp_var ;
}
break ;
}
}
break ;
case IS_UNUSED :
1999-09-17 10:06:12 +08:00
* should_free = 0 ;
1999-04-08 02:10:10 +08:00
return NULL ;
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
return NULL ;
}
2001-07-27 18:10:39 +08:00
static inline zval * _get_object_zval_ptr ( znode * node , temp_variable * Ts , int * should_free TSRMLS_DC )
1999-10-10 04:29:36 +08:00
{
1999-10-28 23:53:31 +08:00
switch ( node - > op_type ) {
case IS_TMP_VAR :
* should_free = 1 ;
return & Ts [ node - > u . var ] . tmp_var ;
break ;
case IS_VAR :
2000-07-07 06:38:01 +08:00
if ( Ts [ node - > u . var ] . var . ptr_ptr ) {
PZVAL_UNLOCK ( * Ts [ node - > u . var ] . var . ptr_ptr ) ;
1999-10-28 23:53:31 +08:00
* should_free = 0 ;
2000-07-07 07:00:46 +08:00
SEPARATE_ZVAL_IF_NOT_REF ( Ts [ node - > u . var ] . var . ptr_ptr ) ;
2000-07-07 06:38:01 +08:00
return * Ts [ node - > u . var ] . var . ptr_ptr ;
1999-10-28 23:53:31 +08:00
} else {
if ( Ts [ node - > u . var ] . EA . type = = IS_STRING_OFFSET ) {
2000-04-07 00:34:55 +08:00
PZVAL_UNLOCK ( Ts [ node - > u . var ] . EA . data . str_offset . str ) ;
1999-10-28 23:53:31 +08:00
}
* should_free = 1 ;
return NULL ;
}
break ;
case IS_UNUSED :
return NULL ;
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-10-28 23:53:31 +08:00
}
return NULL ;
1999-10-10 04:29:36 +08:00
}
1999-04-08 02:10:10 +08:00
2001-07-27 18:10:39 +08:00
static inline zval * * _get_zval_ptr_ptr ( znode * node , temp_variable * Ts TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2000-02-02 02:54:01 +08:00
if ( node - > op_type = = IS_VAR ) {
if ( Ts [ node - > u . var ] . var . ptr_ptr ) {
PZVAL_UNLOCK ( * Ts [ node - > u . var ] . var . ptr_ptr ) ;
} else if ( Ts [ node - > u . var ] . EA . type = = IS_STRING_OFFSET ) {
2000-04-07 00:34:55 +08:00
PZVAL_UNLOCK ( Ts [ node - > u . var ] . EA . data . str_offset . str ) ;
2000-02-02 02:54:01 +08:00
}
return Ts [ node - > u . var ] . var . ptr_ptr ;
} else {
return NULL ;
1999-04-08 02:10:10 +08:00
}
}
1999-12-23 02:10:38 +08:00
2001-07-27 18:10:39 +08:00
static inline zval * * zend_fetch_property_address_inner ( HashTable * ht , znode * op2 , temp_variable * Ts , int type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-01-18 01:34:16 +08:00
zval * prop_ptr = get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
zval * * retval ;
zval tmp ;
switch ( op2 - > op_type ) {
case IS_CONST :
/* already a constant string */
break ;
case IS_VAR :
tmp = * prop_ptr ;
zval_copy_ctor ( & tmp ) ;
convert_to_string ( & tmp ) ;
prop_ptr = & tmp ;
break ;
case IS_TMP_VAR :
convert_to_string ( prop_ptr ) ;
break ;
}
if ( zend_hash_find ( ht , prop_ptr - > value . str . val , prop_ptr - > value . str . len + 1 , ( void * * ) & retval ) = = FAILURE ) {
switch ( type ) {
case BP_VAR_R :
zend_error ( E_NOTICE , " Undefined property: %s " , prop_ptr - > value . str . val ) ;
/* break missing intentionally */
case BP_VAR_IS :
retval = & EG ( uninitialized_zval_ptr ) ;
break ;
case BP_VAR_RW :
zend_error ( E_NOTICE , " Undefined property: %s " , prop_ptr - > value . str . val ) ;
/* break missing intentionally */
case BP_VAR_W : {
1999-05-21 04:00:59 +08:00
zval * new_zval = & EG ( uninitialized_zval ) ;
1999-04-08 02:10:10 +08:00
1999-05-21 04:00:59 +08:00
new_zval - > refcount + + ;
2000-03-24 19:12:30 +08:00
zend_hash_update ( ht , prop_ptr - > value . str . val , prop_ptr - > value . str . len + 1 , & new_zval , sizeof ( zval * ) , ( void * * ) & retval ) ;
1999-04-08 02:10:10 +08:00
}
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
}
if ( prop_ptr = = & tmp ) {
zval_dtor ( prop_ptr ) ;
}
2001-01-18 01:34:16 +08:00
FREE_OP ( op2 , EG ( free_op2 ) ) ;
1999-04-08 02:10:10 +08:00
return retval ;
}
1999-12-23 02:10:38 +08:00
2001-07-27 18:10:39 +08:00
static inline void zend_switch_free ( zend_op * opline , temp_variable * Ts TSRMLS_DC )
1999-12-23 02:10:38 +08:00
{
switch ( opline - > op1 . op_type ) {
case IS_VAR :
if ( ! Ts [ opline - > op1 . u . var ] . var . ptr_ptr ) {
get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
} else {
zval_ptr_dtor ( & Ts [ opline - > op1 . u . var ] . var . ptr ) ;
2000-01-25 03:04:07 +08:00
if ( opline - > extended_value ) { /* foreach() free */
zval_ptr_dtor ( & Ts [ opline - > op1 . u . var ] . var . ptr ) ;
}
1999-12-23 02:10:38 +08:00
}
break ;
case IS_TMP_VAR :
zendi_zval_dtor ( Ts [ opline - > op1 . u . var ] . tmp_var ) ;
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-12-23 02:10:38 +08:00
}
}
2001-07-27 18:10:39 +08:00
void zend_assign_to_variable_reference ( znode * result , zval * * variable_ptr_ptr , zval * * value_ptr_ptr , temp_variable * Ts TSRMLS_DC )
2001-06-22 05:17:10 +08:00
{
zval * variable_ptr ;
zval * value_ptr ;
if ( ! value_ptr_ptr | | ! variable_ptr_ptr ) {
zend_error ( E_ERROR , " Cannot create references to/from string offsets nor overloaded objects " ) ;
return ;
}
variable_ptr = * variable_ptr_ptr ;
value_ptr = * value_ptr_ptr ;
if ( variable_ptr = = EG ( error_zval_ptr ) | | value_ptr = = EG ( error_zval_ptr ) ) {
variable_ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
/* } else if (variable_ptr==&EG(uninitialized_zval) || variable_ptr!=value_ptr) { */
} else if ( variable_ptr_ptr ! = value_ptr_ptr ) {
variable_ptr - > refcount - - ;
if ( variable_ptr - > refcount = = 0 ) {
zendi_zval_dtor ( * variable_ptr ) ;
FREE_ZVAL ( variable_ptr ) ;
}
if ( ! PZVAL_IS_REF ( value_ptr ) ) {
/* break it away */
value_ptr - > refcount - - ;
if ( value_ptr - > refcount > 0 ) {
ALLOC_ZVAL ( * value_ptr_ptr ) ;
* * value_ptr_ptr = * value_ptr ;
value_ptr = * value_ptr_ptr ;
zendi_zval_copy_ctor ( * value_ptr ) ;
}
value_ptr - > refcount = 1 ;
value_ptr - > is_ref = 1 ;
}
* variable_ptr_ptr = value_ptr ;
value_ptr - > refcount + + ;
} else {
if ( variable_ptr - > refcount > 1 ) { /* we need to break away */
SEPARATE_ZVAL ( variable_ptr_ptr ) ;
}
( * variable_ptr_ptr ) - > is_ref = 1 ;
}
if ( result & & ! ( result - > u . EA . type & EXT_TYPE_UNUSED ) ) {
Ts [ result - > u . var ] . var . ptr_ptr = variable_ptr_ptr ;
SELECTIVE_PZVAL_LOCK ( * variable_ptr_ptr , result ) ;
AI_USE_PTR ( Ts [ result - > u . var ] . var ) ;
}
}
1999-12-23 02:10:38 +08:00
2001-07-27 18:10:39 +08:00
static inline void zend_assign_to_variable ( znode * result , znode * op1 , znode * op2 , zval * value , int type , temp_variable * Ts TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zval * * variable_ptr_ptr = get_zval_ptr_ptr ( op1 , Ts , BP_VAR_W ) ;
zval * variable_ptr ;
1999-10-02 07:26:00 +08:00
1999-04-08 02:10:10 +08:00
if ( ! variable_ptr_ptr ) {
switch ( Ts [ op1 - > u . var ] . EA . type ) {
case IS_OVERLOADED_OBJECT :
2001-07-27 18:10:39 +08:00
set_overloaded_property ( & Ts [ op1 - > u . var ] , value TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
if ( type = = IS_TMP_VAR ) {
zval_dtor ( value ) ;
}
break ;
case IS_STRING_OFFSET : {
temp_variable * T = & Ts [ op1 - > u . var ] ;
2001-06-27 23:40:49 +08:00
if ( T - > EA . data . str_offset . str - > type = = IS_STRING ) do {
1999-04-08 02:10:10 +08:00
zval tmp ;
1999-09-19 06:07:12 +08:00
zval * final_value = value ;
1999-04-08 02:10:10 +08:00
2001-06-27 23:40:49 +08:00
if ( ( T - > EA . data . str_offset . offset < 0 ) ) {
zend_error ( E_WARNING , " Illegal string offset: %d " , T - > EA . data . str_offset . offset ) ;
break ;
}
if ( T - > EA . data . str_offset . offset > = T - > EA . data . str_offset . str - > value . str . len ) {
int i ;
if ( T - > EA . data . str_offset . str - > value . str . len = = 0 ) {
2001-06-27 23:47:31 +08:00
STR_FREE ( T - > EA . data . str_offset . str - > value . str . val ) ;
2001-06-27 23:40:49 +08:00
T - > EA . data . str_offset . str - > value . str . val = ( char * ) emalloc ( T - > EA . data . str_offset . offset + 1 + 1 ) ;
} else {
T - > EA . data . str_offset . str - > value . str . val = ( char * ) erealloc ( T - > EA . data . str_offset . str - > value . str . val , T - > EA . data . str_offset . offset + 1 + 1 ) ;
}
for ( i = T - > EA . data . str_offset . str - > value . str . len ; i < T - > EA . data . str_offset . offset ; i + + ) {
T - > EA . data . str_offset . str - > value . str . val [ i ] = ' ' ;
}
T - > EA . data . str_offset . str - > value . str . val [ T - > EA . data . str_offset . offset + 1 ] = 0 ;
T - > EA . data . str_offset . str - > value . str . len = T - > EA . data . str_offset . offset + 1 ;
}
1999-04-08 02:10:10 +08:00
if ( value - > type ! = IS_STRING ) {
tmp = * value ;
1999-09-19 06:07:12 +08:00
if ( op2 & & op2 - > op_type = = IS_VAR ) {
zval_copy_ctor ( & tmp ) ;
}
1999-04-08 02:10:10 +08:00
convert_to_string ( & tmp ) ;
1999-09-19 06:07:12 +08:00
final_value = & tmp ;
1999-04-08 02:10:10 +08:00
}
2000-04-07 00:34:55 +08:00
T - > EA . data . str_offset . str - > value . str . val [ T - > EA . data . str_offset . offset ] = final_value - > value . str . val [ 0 ] ;
1999-06-01 02:33:12 +08:00
if ( op2
& & op2 - > op_type = = IS_VAR
& & value = = & Ts [ op2 - > u . var ] . tmp_var ) {
2001-06-21 01:14:58 +08:00
STR_FREE ( value - > value . str . val ) ;
1999-06-01 02:33:12 +08:00
}
1999-09-19 06:07:12 +08:00
if ( final_value = = & tmp ) {
zval_dtor ( final_value ) ;
1999-04-08 02:10:10 +08:00
}
/*
* the value of an assignment to a string offset is undefined
2000-04-07 00:34:55 +08:00
Ts [ result - > u . var ] . var = & T - > EA . data . str_offset . str ;
1999-04-08 02:10:10 +08:00
*/
2001-06-27 23:40:49 +08:00
} while ( 0 ) ;
2000-04-07 00:34:55 +08:00
/* zval_ptr_dtor(&T->EA.data.str_offset.str); Nuke this line if it doesn't cause a leak */
1999-04-08 02:10:10 +08:00
T - > tmp_var . type = IS_STRING ;
}
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
1999-09-26 13:45:18 +08:00
Ts [ result - > u . var ] . var . ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
SELECTIVE_PZVAL_LOCK ( * Ts [ result - > u . var ] . var . ptr_ptr , result ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ result - > u . var ] . var ) ;
1999-04-08 02:10:10 +08:00
return ;
}
variable_ptr = * variable_ptr_ptr ;
if ( variable_ptr = = EG ( error_zval_ptr ) ) {
if ( result ) {
1999-09-26 13:45:18 +08:00
Ts [ result - > u . var ] . var . ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
SELECTIVE_PZVAL_LOCK ( * Ts [ result - > u . var ] . var . ptr_ptr , result ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ result - > u . var ] . var ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-19 06:18:17 +08:00
if ( type = = IS_TMP_VAR ) {
zval_dtor ( value ) ;
}
1999-04-08 02:10:10 +08:00
return ;
}
1999-07-10 02:19:48 +08:00
if ( PZVAL_IS_REF ( variable_ptr ) ) {
1999-04-08 02:10:10 +08:00
if ( variable_ptr ! = value ) {
short refcount = variable_ptr - > refcount ;
2000-02-09 04:10:47 +08:00
zval garbage ;
1999-04-08 02:10:10 +08:00
1999-07-13 02:07:01 +08:00
if ( type ! = IS_TMP_VAR ) {
value - > refcount + + ;
}
2000-02-09 04:10:47 +08:00
garbage = * variable_ptr ;
1999-04-08 02:10:10 +08:00
* variable_ptr = * value ;
variable_ptr - > refcount = refcount ;
1999-10-02 07:31:39 +08:00
variable_ptr - > is_ref = 1 ;
1999-04-08 02:10:10 +08:00
if ( type ! = IS_TMP_VAR ) {
zendi_zval_copy_ctor ( * variable_ptr ) ;
2000-01-25 01:29:15 +08:00
value - > refcount - - ;
1999-04-08 02:10:10 +08:00
}
2000-02-09 04:10:47 +08:00
zendi_zval_dtor ( garbage ) ;
1999-04-08 02:10:10 +08:00
}
} else {
1999-05-29 20:00:32 +08:00
variable_ptr - > refcount - - ;
1999-04-08 02:10:10 +08:00
if ( variable_ptr - > refcount = = 0 ) {
switch ( type ) {
case IS_VAR :
1999-08-24 03:02:28 +08:00
/* break missing intentionally */
1999-04-08 02:10:10 +08:00
case IS_CONST :
if ( variable_ptr = = value ) {
variable_ptr - > refcount + + ;
1999-07-10 02:19:48 +08:00
} else if ( PZVAL_IS_REF ( value ) ) {
2001-01-27 20:29:02 +08:00
zval tmp ;
1999-06-10 05:39:12 +08:00
tmp = * value ;
zval_copy_ctor ( & tmp ) ;
tmp . refcount = 1 ;
1999-05-29 20:00:32 +08:00
zendi_zval_dtor ( * variable_ptr ) ;
1999-06-10 05:39:12 +08:00
* variable_ptr = tmp ;
1999-04-08 02:10:10 +08:00
} else {
1999-06-10 05:39:12 +08:00
value - > refcount + + ;
1999-04-08 02:10:10 +08:00
zendi_zval_dtor ( * variable_ptr ) ;
safe_free_zval_ptr ( variable_ptr ) ;
* variable_ptr_ptr = value ;
}
break ;
case IS_TMP_VAR :
zendi_zval_dtor ( * variable_ptr ) ;
value - > refcount = 1 ;
* variable_ptr = * value ;
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
} else { /* we need to split */
switch ( type ) {
case IS_VAR :
1999-08-24 03:02:28 +08:00
/* break missing intentionally */
1999-04-08 02:10:10 +08:00
case IS_CONST :
1999-12-16 04:15:32 +08:00
if ( PZVAL_IS_REF ( value ) & & value - > refcount > 0 ) {
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( variable_ptr ) ;
* variable_ptr_ptr = variable_ptr ;
1999-04-08 02:10:10 +08:00
* variable_ptr = * value ;
zval_copy_ctor ( variable_ptr ) ;
variable_ptr - > refcount = 1 ;
break ;
}
* variable_ptr_ptr = value ;
value - > refcount + + ;
break ;
case IS_TMP_VAR :
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( * variable_ptr_ptr ) ;
1999-04-08 02:10:10 +08:00
value - > refcount = 1 ;
* * variable_ptr_ptr = * value ;
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
}
1999-10-02 07:31:39 +08:00
( * variable_ptr_ptr ) - > is_ref = 0 ;
1999-04-08 02:10:10 +08:00
}
if ( result ) {
1999-09-26 13:45:18 +08:00
Ts [ result - > u . var ] . var . ptr_ptr = variable_ptr_ptr ;
1999-07-10 17:29:02 +08:00
SELECTIVE_PZVAL_LOCK ( * variable_ptr_ptr , result ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ result - > u . var ] . var ) ;
1999-07-10 04:43:59 +08:00
}
1999-04-08 02:10:10 +08:00
}
/* Utility Functions for Extensions */
2001-07-31 12:53:54 +08:00
static void zend_extension_statement_handler ( zend_extension * extension , zend_op_array * op_array TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
if ( extension - > statement_handler ) {
extension - > statement_handler ( op_array ) ;
}
}
2001-07-31 12:53:54 +08:00
static void zend_extension_fcall_begin_handler ( zend_extension * extension , zend_op_array * op_array TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
if ( extension - > fcall_begin_handler ) {
extension - > fcall_begin_handler ( op_array ) ;
}
}
2001-07-31 12:53:54 +08:00
static void zend_extension_fcall_end_handler ( zend_extension * extension , zend_op_array * op_array TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
if ( extension - > fcall_end_handler ) {
extension - > fcall_end_handler ( op_array ) ;
}
}
static void print_refcount ( zval * p , char * str )
{
print_refcount ( NULL , NULL ) ;
}
2001-07-27 18:10:39 +08:00
static void zend_fetch_var_address ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts , int type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int free_op1 ;
zval * varname = get_zval_ptr ( op1 , Ts , & free_op1 , BP_VAR_R ) ;
zval * * retval ;
zval tmp_varname ;
2000-01-29 05:43:46 +08:00
HashTable * target_symbol_table = 0 ;
1999-04-08 02:10:10 +08:00
1999-08-04 02:54:49 +08:00
switch ( op2 - > u . fetch_type ) {
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_LOCAL :
target_symbol_table = EG ( active_symbol_table ) ;
break ;
case ZEND_FETCH_GLOBAL :
1999-06-06 02:47:36 +08:00
if ( op1 - > op_type = = IS_VAR ) {
1999-07-10 18:55:55 +08:00
PZVAL_LOCK ( varname ) ;
1999-06-06 02:47:36 +08:00
}
1999-04-08 02:10:10 +08:00
target_symbol_table = & EG ( symbol_table ) ;
break ;
case ZEND_FETCH_STATIC :
1999-04-08 08:18:29 +08:00
if ( ! EG ( active_op_array ) - > static_variables ) {
1999-12-28 03:07:33 +08:00
ALLOC_HASHTABLE ( EG ( active_op_array ) - > static_variables ) ;
1999-12-22 01:14:31 +08:00
zend_hash_init ( EG ( active_op_array ) - > static_variables , 2 , NULL , ZVAL_PTR_DTOR , 0 ) ;
1999-04-08 08:18:29 +08:00
}
1999-04-08 02:10:10 +08:00
target_symbol_table = EG ( active_op_array ) - > static_variables ;
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
if ( varname - > type ! = IS_STRING ) {
tmp_varname = * varname ;
zval_copy_ctor ( & tmp_varname ) ;
convert_to_string ( & tmp_varname ) ;
varname = & tmp_varname ;
}
if ( zend_hash_find ( target_symbol_table , varname - > value . str . val , varname - > value . str . len + 1 , ( void * * ) & retval ) = = FAILURE ) {
switch ( type ) {
case BP_VAR_R :
zend_error ( E_NOTICE , " Undefined variable: %s " , varname - > value . str . val ) ;
/* break missing intentionally */
case BP_VAR_IS :
retval = & EG ( uninitialized_zval_ptr ) ;
break ;
case BP_VAR_RW :
zend_error ( E_NOTICE , " Undefined variable: %s " , varname - > value . str . val ) ;
/* break missing intentionally */
case BP_VAR_W : {
1999-05-21 04:00:59 +08:00
zval * new_zval = & EG ( uninitialized_zval ) ;
1999-04-08 02:10:10 +08:00
1999-05-21 04:00:59 +08:00
new_zval - > refcount + + ;
2000-03-24 19:12:30 +08:00
zend_hash_update ( target_symbol_table , varname - > value . str . val , varname - > value . str . len + 1 , & new_zval , sizeof ( zval * ) , ( void * * ) & retval ) ;
1999-04-08 02:10:10 +08:00
}
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
}
1999-08-04 02:54:49 +08:00
if ( op2 - > u . fetch_type = = ZEND_FETCH_LOCAL ) {
1999-04-08 02:10:10 +08:00
FREE_OP ( op1 , free_op1 ) ;
1999-08-04 02:54:49 +08:00
} else if ( op2 - > u . fetch_type = = ZEND_FETCH_STATIC ) {
2001-07-31 12:53:54 +08:00
zval_update_constant ( retval , ( void * ) 1 TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
if ( varname = = & tmp_varname ) {
zval_dtor ( varname ) ;
}
1999-10-10 12:38:51 +08:00
Ts [ result - > u . var ] . var . ptr_ptr = retval ;
1999-07-10 17:29:02 +08:00
SELECTIVE_PZVAL_LOCK ( * retval , result ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-27 18:10:39 +08:00
static inline zval * * zend_fetch_dimension_address_inner ( HashTable * ht , znode * op2 , temp_variable * Ts , int type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-01-18 01:34:16 +08:00
zval * dim = get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
zval * * retval ;
2000-01-04 01:26:24 +08:00
char * offset_key ;
int offset_key_length ;
1999-04-08 02:10:10 +08:00
switch ( dim - > type ) {
2000-01-04 21:22:58 +08:00
case IS_NULL :
2000-01-04 01:26:24 +08:00
offset_key = " " ;
offset_key_length = 0 ;
goto fetch_string_dim ;
case IS_STRING :
offset_key = dim - > value . str . val ;
offset_key_length = dim - > value . str . len ;
fetch_string_dim :
if ( zend_hash_find ( ht , offset_key , offset_key_length + 1 , ( void * * ) & retval ) = = FAILURE ) {
switch ( type ) {
case BP_VAR_R :
zend_error ( E_NOTICE , " Undefined index: %s " , offset_key ) ;
/* break missing intentionally */
case BP_VAR_IS :
retval = & EG ( uninitialized_zval_ptr ) ;
break ;
case BP_VAR_RW :
zend_error ( E_NOTICE , " Undefined index: %s " , offset_key ) ;
/* break missing intentionally */
case BP_VAR_W : {
zval * new_zval = & EG ( uninitialized_zval ) ;
new_zval - > refcount + + ;
2000-03-24 19:12:30 +08:00
zend_hash_update ( ht , offset_key , offset_key_length + 1 , & new_zval , sizeof ( zval * ) , ( void * * ) & retval ) ;
2000-01-04 01:26:24 +08:00
}
break ;
1999-04-08 02:10:10 +08:00
}
}
break ;
1999-09-09 04:38:08 +08:00
case IS_DOUBLE :
1999-10-06 23:09:26 +08:00
case IS_RESOURCE :
2000-01-19 06:18:17 +08:00
case IS_BOOL :
1999-04-08 02:10:10 +08:00
case IS_LONG : {
1999-09-09 04:38:08 +08:00
long index ;
2000-01-19 06:18:17 +08:00
if ( dim - > type = = IS_DOUBLE ) {
1999-09-09 04:38:08 +08:00
index = ( long ) dim - > value . dval ;
2000-01-19 06:18:17 +08:00
} else {
index = dim - > value . lval ;
1999-09-09 04:38:08 +08:00
}
if ( zend_hash_index_find ( ht , index , ( void * * ) & retval ) = = FAILURE ) {
1999-04-08 02:10:10 +08:00
switch ( type ) {
case BP_VAR_R :
1999-09-09 04:38:08 +08:00
zend_error ( E_NOTICE , " Undefined offset: %d " , index ) ;
1999-04-08 02:10:10 +08:00
/* break missing intentionally */
case BP_VAR_IS :
retval = & EG ( uninitialized_zval_ptr ) ;
break ;
case BP_VAR_RW :
1999-09-09 04:38:08 +08:00
zend_error ( E_NOTICE , " Undefined offset: %d " , index ) ;
1999-04-08 02:10:10 +08:00
/* break missing intentionally */
case BP_VAR_W : {
1999-05-21 04:00:59 +08:00
zval * new_zval = & EG ( uninitialized_zval ) ;
1999-04-08 02:10:10 +08:00
1999-05-21 04:00:59 +08:00
new_zval - > refcount + + ;
1999-09-09 04:38:08 +08:00
zend_hash_index_update ( ht , index , & new_zval , sizeof ( zval * ) , ( void * * ) & retval ) ;
1999-04-08 02:10:10 +08:00
}
break ;
}
}
}
break ;
default :
zend_error ( E_WARNING , " Illegal offset type " ) ;
if ( type = = BP_VAR_R | | type = = BP_VAR_IS ) {
retval = & EG ( uninitialized_zval_ptr ) ;
} else {
retval = & EG ( error_zval_ptr ) ;
}
break ;
}
2001-01-18 01:34:16 +08:00
FREE_OP ( op2 , EG ( free_op2 ) ) ;
1999-04-08 02:10:10 +08:00
return retval ;
}
2001-07-27 18:10:39 +08:00
static void fetch_overloaded_element ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts , int type , zval * * * retval , int overloaded_element_type TSRMLS_DC )
2001-01-18 01:34:16 +08:00
{
zend_overloaded_element overloaded_element ;
if ( Ts [ op1 - > u . var ] . EA . type = = IS_STRING_OFFSET ) {
2001-06-21 23:33:55 +08:00
get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
2001-01-18 01:34:16 +08:00
switch ( type ) {
case BP_VAR_R :
case BP_VAR_IS :
* retval = & EG ( uninitialized_zval_ptr ) ;
break ;
case BP_VAR_W :
case BP_VAR_RW :
* retval = & EG ( error_zval_ptr ) ;
break ;
EMPTY_SWITCH_DEFAULT_CASE ( )
}
SELECTIVE_PZVAL_LOCK ( * * retval , result ) ;
return ;
}
overloaded_element . element = * get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , type ) ;
overloaded_element . type = overloaded_element_type ;
if ( ! EG ( free_op2 ) ) {
zval_copy_ctor ( & overloaded_element . element ) ;
}
Ts [ result - > u . var ] . EA = Ts [ op1 - > u . var ] . EA ;
zend_llist_add_element ( Ts [ result - > u . var ] . EA . data . overloaded_element . elements_list , & overloaded_element ) ;
Ts [ result - > u . var ] . EA . type = IS_OVERLOADED_OBJECT ;
* retval = NULL ;
return ;
}
1999-04-08 02:10:10 +08:00
2001-07-27 18:10:39 +08:00
static void zend_fetch_dimension_address ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts , int type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zval * * container_ptr = get_zval_ptr_ptr ( op1 , Ts , type ) ;
zval * container ;
1999-09-26 13:45:18 +08:00
zval * * * retval = & Ts [ result - > u . var ] . var . ptr_ptr ;
1999-04-08 02:10:10 +08:00
if ( container_ptr = = NULL ) {
2001-07-27 18:10:39 +08:00
fetch_overloaded_element ( result , op1 , op2 , Ts , type , retval , OE_IS_ARRAY TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
return ;
}
2001-01-18 01:34:16 +08:00
1999-04-08 02:10:10 +08:00
container = * container_ptr ;
if ( container = = EG ( error_zval_ptr ) ) {
* retval = & EG ( error_zval_ptr ) ;
1999-07-11 02:46:20 +08:00
SELECTIVE_PZVAL_LOCK ( * * retval , result ) ;
1999-04-08 02:10:10 +08:00
return ;
}
2000-01-10 03:16:34 +08:00
if ( container - > type = = IS_NULL
2000-03-18 22:28:03 +08:00
| | ( container - > type = = IS_BOOL & & container - > value . lval = = 0 )
2000-01-10 03:16:34 +08:00
| | ( container - > type = = IS_STRING & & container - > value . str . len = = 0 ) ) {
1999-04-08 02:10:10 +08:00
switch ( type ) {
case BP_VAR_RW :
case BP_VAR_W :
1999-07-10 02:19:48 +08:00
if ( ! PZVAL_IS_REF ( container ) ) {
2000-08-05 21:54:07 +08:00
SEPARATE_ZVAL ( container_ptr ) ;
container = * container_ptr ;
1999-04-08 02:10:10 +08:00
}
array_init ( container ) ;
break ;
}
}
switch ( container - > type ) {
case IS_ARRAY :
1999-07-10 02:19:48 +08:00
if ( ( type = = BP_VAR_W | | type = = BP_VAR_RW ) & & container - > refcount > 1 & & ! PZVAL_IS_REF ( container ) ) {
2000-08-05 21:54:07 +08:00
SEPARATE_ZVAL ( container_ptr ) ;
1999-04-08 02:10:10 +08:00
container = * container_ptr ;
}
if ( op2 - > op_type = = IS_UNUSED ) {
1999-05-21 04:00:59 +08:00
zval * new_zval = & EG ( uninitialized_zval ) ;
1999-04-08 02:10:10 +08:00
1999-05-21 04:00:59 +08:00
new_zval - > refcount + + ;
2000-03-24 19:12:30 +08:00
zend_hash_next_index_insert ( container - > value . ht , & new_zval , sizeof ( zval * ) , ( void * * ) retval ) ;
1999-04-08 02:10:10 +08:00
} else {
2001-07-27 18:10:39 +08:00
* retval = zend_fetch_dimension_address_inner ( container - > value . ht , op2 , Ts , type TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
1999-07-10 17:29:02 +08:00
SELECTIVE_PZVAL_LOCK ( * * retval , result ) ;
1999-04-08 02:10:10 +08:00
break ;
2000-01-04 21:22:58 +08:00
case IS_NULL :
1999-12-31 21:56:59 +08:00
/* for read-mode only */
2001-01-18 01:34:16 +08:00
get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-12-31 21:56:59 +08:00
* retval = & EG ( uninitialized_zval_ptr ) ;
SELECTIVE_PZVAL_LOCK ( * * retval , result ) ;
2001-01-18 01:34:16 +08:00
FREE_OP ( op2 , EG ( free_op2 ) ) ;
2000-04-12 01:38:19 +08:00
if ( type = = BP_VAR_W | | type = = BP_VAR_RW ) {
zend_error ( E_WARNING , " Cannot use a NULL value as an array " ) ;
}
1999-12-31 21:56:59 +08:00
break ;
1999-04-08 02:10:10 +08:00
case IS_STRING : {
zval * offset ;
1999-12-31 21:56:59 +08:00
zval tmp ;
1999-04-08 02:10:10 +08:00
2000-01-04 04:01:54 +08:00
if ( op2 - > op_type = = IS_UNUSED ) {
zend_error ( E_ERROR , " [] operator not supported for strings " ) ;
}
2001-01-18 01:34:16 +08:00
offset = get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
1999-12-31 21:56:59 +08:00
if ( offset - > type ! = IS_LONG ) {
tmp = * offset ;
zval_copy_ctor ( & tmp ) ;
convert_to_long ( & tmp ) ;
offset = & tmp ;
}
2000-02-17 00:00:02 +08:00
if ( type ! = BP_VAR_R & & type ! = BP_VAR_IS ) {
SEPARATE_ZVAL_IF_NOT_REF ( container_ptr ) ;
1999-04-08 02:10:10 +08:00
}
1999-12-31 21:56:59 +08:00
container = * container_ptr ;
2000-04-07 00:34:55 +08:00
Ts [ result - > u . var ] . EA . data . str_offset . str = container ;
1999-12-31 21:56:59 +08:00
PZVAL_LOCK ( container ) ;
2000-04-07 00:34:55 +08:00
Ts [ result - > u . var ] . EA . data . str_offset . offset = offset - > value . lval ;
1999-12-31 21:56:59 +08:00
Ts [ result - > u . var ] . EA . type = IS_STRING_OFFSET ;
2001-01-18 01:34:16 +08:00
FREE_OP ( op2 , EG ( free_op2 ) ) ;
1999-12-31 21:56:59 +08:00
* retval = NULL ;
return ;
1999-04-08 02:10:10 +08:00
}
break ;
default : {
zval * offset ;
2001-01-18 01:34:16 +08:00
offset = get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
if ( type = = BP_VAR_R | | type = = BP_VAR_IS ) {
* retval = & EG ( uninitialized_zval_ptr ) ;
} else {
* retval = & EG ( error_zval_ptr ) ;
}
2001-01-18 01:34:16 +08:00
FREE_OP ( op2 , EG ( free_op2 ) ) ;
1999-07-11 02:46:20 +08:00
SELECTIVE_PZVAL_LOCK ( * * retval , result ) ;
2000-04-12 01:38:19 +08:00
if ( type = = BP_VAR_W | | type = = BP_VAR_RW ) {
zend_error ( E_WARNING , " Cannot use a scalar value as an array " ) ;
}
1999-04-08 02:10:10 +08:00
}
break ;
}
}
2001-07-27 18:10:39 +08:00
static void zend_fetch_dimension_address_from_tmp_var ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int free_op1 ;
zval * container = get_zval_ptr ( op1 , Ts , & free_op1 , BP_VAR_R ) ;
if ( container - > type ! = IS_ARRAY ) {
1999-09-26 13:45:18 +08:00
Ts [ result - > u . var ] . var . ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
SELECTIVE_PZVAL_LOCK ( * Ts [ result - > u . var ] . var . ptr_ptr , result ) ;
1999-04-08 02:10:10 +08:00
return ;
}
2001-07-27 18:10:39 +08:00
Ts [ result - > u . var ] . var . ptr_ptr = zend_fetch_dimension_address_inner ( container - > value . ht , op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
1999-09-26 13:45:18 +08:00
SELECTIVE_PZVAL_LOCK ( * Ts [ result - > u . var ] . var . ptr_ptr , result ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-27 18:10:39 +08:00
static void zend_fetch_property_address ( znode * result , znode * op1 , znode * op2 , temp_variable * Ts , int type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zval * * container_ptr = get_zval_ptr_ptr ( op1 , Ts , type ) ;
zval * container ;
1999-09-26 13:45:18 +08:00
zval * * * retval = & Ts [ result - > u . var ] . var . ptr_ptr ;
1999-04-08 02:10:10 +08:00
if ( container_ptr = = NULL ) {
2001-07-27 18:10:39 +08:00
fetch_overloaded_element ( result , op1 , op2 , Ts , type , retval , OE_IS_OBJECT TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
return ;
}
container = * container_ptr ;
if ( container = = EG ( error_zval_ptr ) ) {
* retval = & EG ( error_zval_ptr ) ;
1999-07-11 02:46:20 +08:00
SELECTIVE_PZVAL_LOCK ( * * retval , result ) ;
1999-04-08 02:10:10 +08:00
return ;
}
if ( container - > type = = IS_OBJECT
2001-08-06 10:52:03 +08:00
& & Z_OBJCE_P ( container ) - > handle_property_get ) {
1999-04-08 02:10:10 +08:00
zend_overloaded_element overloaded_element ;
2000-04-11 04:21:13 +08:00
Ts [ result - > u . var ] . EA . data . overloaded_element . object = container ;
Ts [ result - > u . var ] . EA . data . overloaded_element . type = type ;
Ts [ result - > u . var ] . EA . data . overloaded_element . elements_list = ( zend_llist * ) emalloc ( sizeof ( zend_llist ) ) ;
zend_llist_init ( Ts [ result - > u . var ] . EA . data . overloaded_element . elements_list , sizeof ( zend_overloaded_element ) , NULL , 0 ) ;
2001-01-18 01:34:16 +08:00
overloaded_element . element = * get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , type ) ;
2000-01-04 21:52:52 +08:00
overloaded_element . type = OE_IS_OBJECT ;
2001-01-18 01:34:16 +08:00
if ( ! EG ( free_op2 ) ) {
1999-04-08 02:10:10 +08:00
zval_copy_ctor ( & overloaded_element . element ) ;
}
2000-04-11 04:21:13 +08:00
zend_llist_add_element ( Ts [ result - > u . var ] . EA . data . overloaded_element . elements_list , & overloaded_element ) ;
1999-04-08 02:10:10 +08:00
Ts [ result - > u . var ] . EA . type = IS_OVERLOADED_OBJECT ;
* retval = NULL ;
return ;
}
2000-05-07 02:40:48 +08:00
if ( container - > type = = IS_NULL
| | ( container - > type = = IS_BOOL & & container - > value . lval = = 0 )
| | ( container - > type = = IS_STRING & & container - > value . str . len = = 0 ) ) {
1999-04-08 02:10:10 +08:00
switch ( type ) {
case BP_VAR_RW :
case BP_VAR_W :
1999-07-10 02:19:48 +08:00
if ( ! PZVAL_IS_REF ( container ) ) {
2000-08-05 21:54:07 +08:00
SEPARATE_ZVAL ( container_ptr ) ;
container = * container_ptr ;
1999-04-08 02:10:10 +08:00
}
object_init ( container ) ;
break ;
}
}
if ( container - > type ! = IS_OBJECT ) {
zval * offset ;
2001-01-18 01:34:16 +08:00
offset = get_zval_ptr ( op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
FREE_OP ( op2 , EG ( free_op2 ) ) ;
1999-04-08 02:10:10 +08:00
if ( type = = BP_VAR_R | | type = = BP_VAR_IS ) {
* retval = & EG ( uninitialized_zval_ptr ) ;
} else {
* retval = & EG ( error_zval_ptr ) ;
}
1999-10-03 02:02:10 +08:00
SELECTIVE_PZVAL_LOCK ( * * retval , result ) ;
return ;
1999-04-08 02:10:10 +08:00
}
1999-07-10 02:19:48 +08:00
if ( ( type = = BP_VAR_W | | type = = BP_VAR_RW ) & & container - > refcount > 1 & & ! PZVAL_IS_REF ( container ) ) {
2000-08-05 21:54:07 +08:00
SEPARATE_ZVAL ( container_ptr ) ;
1999-04-08 02:10:10 +08:00
container = * container_ptr ;
}
2001-08-06 10:52:03 +08:00
* retval = zend_fetch_property_address_inner ( Z_OBJPROP_P ( container ) , op2 , Ts , type TSRMLS_CC ) ;
1999-07-10 17:29:02 +08:00
SELECTIVE_PZVAL_LOCK ( * * retval , result ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-27 18:10:39 +08:00
static zval get_overloaded_property ( temp_variable * T TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zval result ;
2001-08-06 10:52:03 +08:00
result = Z_OBJCE_P ( T - > EA . data . overloaded_element . object ) - > handle_property_get ( & T - > EA . data . overloaded_element ) ;
1999-04-08 02:10:10 +08:00
2000-04-11 04:21:13 +08:00
zend_llist_destroy ( T - > EA . data . overloaded_element . elements_list ) ;
efree ( T - > EA . data . overloaded_element . elements_list ) ;
1999-04-08 02:10:10 +08:00
return result ;
}
2001-07-27 18:10:39 +08:00
static void set_overloaded_property ( temp_variable * T , zval * value TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-08-06 10:52:03 +08:00
zend_class_entry * ce ;
ce = Z_OBJCE_P ( T - > EA . data . overloaded_element . object ) ;
if ( ce - > handle_property_set ) {
ce - > handle_property_set ( & T - > EA . data . overloaded_element , value ) ;
2001-05-03 03:51:33 +08:00
} else {
2001-08-06 10:52:03 +08:00
zend_error ( E_ERROR , " Class '%s' does not support setting overloaded properties " , ce - > name ) ;
2001-05-03 03:51:33 +08:00
}
2000-04-11 04:21:13 +08:00
zend_llist_destroy ( T - > EA . data . overloaded_element . elements_list ) ;
efree ( T - > EA . data . overloaded_element . elements_list ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-27 18:10:39 +08:00
static void call_overloaded_function ( temp_variable * T , int arg_count , zval * return_value TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-08-06 10:52:03 +08:00
zend_class_entry * ce ;
ce = Z_OBJCE_P ( T - > EA . data . overloaded_element . object ) ;
if ( ce - > handle_function_call ) {
ce - > handle_function_call ( arg_count , return_value , T - > EA . data . overloaded_element . object , 1 TSRMLS_CC , & T - > EA . data . overloaded_element ) ;
2001-05-03 03:51:33 +08:00
} else {
2001-08-06 10:52:03 +08:00
zend_error ( E_ERROR , " Class '%s' does not support overloaded method calls " , ce - > name ) ;
2001-05-03 03:51:33 +08:00
}
2000-04-11 04:21:13 +08:00
zend_llist_destroy ( T - > EA . data . overloaded_element . elements_list ) ;
efree ( T - > EA . data . overloaded_element . elements_list ) ;
1999-04-08 02:10:10 +08:00
}
2000-02-10 05:48:16 +08:00
# if ZEND_INTENSIVE_DEBUGGING
# define CHECK_SYMBOL_TABLES() \
2001-07-31 12:53:54 +08:00
zend_hash_apply ( & EG ( symbol_table ) , ( apply_func_t ) zend_check_symbol TSRMLS_CC ) ; \
2000-02-10 05:48:16 +08:00
if ( & EG ( symbol_table ) ! = EG ( active_symbol_table ) ) { \
2001-07-31 12:53:54 +08:00
zend_hash_apply ( EG ( active_symbol_table ) , ( apply_func_t ) zend_check_symbol TSRMLS_CC ) ; \
2000-02-10 05:48:16 +08:00
}
2001-07-31 12:53:54 +08:00
static int zend_check_symbol ( zval * * pz TSRMLS_DC )
2000-02-10 05:48:16 +08:00
{
2001-08-06 10:52:03 +08:00
if ( Z_TYPE_PP ( pz ) > 9 ) {
2000-02-10 05:48:16 +08:00
fprintf ( stderr , " Warning! %x has invalid type! \n " , * pz ) ;
2001-08-06 10:52:03 +08:00
} else if ( Z_TYPE_PP ( pz ) = = IS_ARRAY ) {
zend_hash_apply ( Z_ARRVAL_PP ( pz ) , ( apply_func_t ) zend_check_symbol TSRMLS_CC ) ;
} else if ( Z_TYPE_PP ( pz ) = = IS_OBJECT ) {
zend_hash_apply ( Z_OBJPROP_PP ( pz ) , ( apply_func_t ) zend_check_symbol TSRMLS_CC ) ;
2000-02-10 05:48:16 +08:00
}
return 0 ;
}
# else
# define CHECK_SYMBOL_TABLES()
# endif
# define NEXT_OPCODE() \
CHECK_SYMBOL_TABLES ( ) \
opline + + ; \
2000-01-29 08:33:07 +08:00
continue ;
1999-07-28 01:30:16 +08:00
typedef struct _object_info {
zval * ptr ;
} object_info ;
1999-04-08 02:10:10 +08:00
2001-07-27 18:10:39 +08:00
ZEND_API void execute ( zend_op_array * op_array TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-15 22:08:58 +08:00
zend_op * opline ;
1999-04-08 02:10:10 +08:00
zend_function_state function_state ;
1999-11-04 03:21:56 +08:00
zend_function * fbc = NULL ; /* Function Being Called */
1999-10-10 04:29:36 +08:00
object_info object = { NULL } ;
2000-02-02 03:22:59 +08:00
# if ZEND_DEBUG || (!defined (__GNUC__) || __GNUC__ < 2)
1999-06-04 05:06:03 +08:00
temp_variable * Ts = ( temp_variable * ) do_alloca ( sizeof ( temp_variable ) * op_array - > T ) ;
1999-04-08 02:10:10 +08:00
# else
temp_variable Ts [ op_array - > T ] ;
# endif
2000-02-04 22:45:58 +08:00
zend_bool original_in_execution = EG ( in_execution ) ;
1999-04-08 02:10:10 +08:00
2000-02-04 22:45:58 +08:00
EG ( in_execution ) = 1 ;
2001-07-15 22:08:58 +08:00
if ( op_array - > start_op ) {
opline = op_array - > start_op ;
} else {
opline = op_array - > opcodes ;
1999-04-08 02:10:10 +08:00
}
EG ( opline_ptr ) = & opline ;
function_state . function = ( zend_function * ) op_array ;
EG ( function_state_ptr ) = & function_state ;
# if ZEND_DEBUG
/* function_state.function_symbol_table is saved as-is to a stack,
* which is an intentional UMR . Shut it up if we ' re in DEBUG .
*/
function_state . function_symbol_table = NULL ;
# endif
1999-06-04 21:09:24 +08:00
if ( op_array - > uses_globals ) {
1999-12-27 05:21:33 +08:00
zval * globals ;
1999-06-04 21:09:24 +08:00
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( globals ) ;
1999-06-04 21:09:24 +08:00
globals - > refcount = 1 ;
1999-10-02 07:31:39 +08:00
globals - > is_ref = 1 ;
1999-06-04 21:09:24 +08:00
globals - > type = IS_ARRAY ;
globals - > value . ht = & EG ( symbol_table ) ;
if ( zend_hash_add ( EG ( active_symbol_table ) , " GLOBALS " , sizeof ( " GLOBALS " ) , & globals , sizeof ( zval * ) , NULL ) = = FAILURE ) {
1999-12-24 23:22:11 +08:00
FREE_ZVAL ( globals ) ;
1999-06-04 21:09:24 +08:00
}
}
1999-04-08 02:10:10 +08:00
2000-01-29 06:23:28 +08:00
while ( 1 ) {
2000-06-16 22:27:28 +08:00
# ifdef ZEND_WIN32
if ( EG ( timed_out ) ) {
zend_timeout ( 0 ) ;
}
# endif
2001-06-22 06:30:23 +08:00
2001-07-27 18:10:39 +08:00
zend_clean_garbage ( TSRMLS_C ) ;
2001-06-22 06:30:23 +08:00
1999-04-08 02:10:10 +08:00
switch ( opline - > opcode ) {
case ZEND_ADD :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = add_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_SUB :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = sub_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_MUL :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = mul_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_DIV :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = div_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_MOD :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = mod_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_SL :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = shift_left_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_SR :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = shift_right_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_CONCAT :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = concat_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
1999-10-19 21:33:17 +08:00
case ZEND_IS_IDENTICAL :
EG ( binary_op ) = is_identical_function ;
goto binary_op_addr ;
2000-03-30 06:05:19 +08:00
case ZEND_IS_NOT_IDENTICAL :
EG ( binary_op ) = is_not_identical_function ;
goto binary_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_IS_EQUAL :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = is_equal_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_IS_NOT_EQUAL :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = is_not_equal_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_IS_SMALLER :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = is_smaller_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_IS_SMALLER_OR_EQUAL :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = is_smaller_or_equal_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_BW_OR :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = bitwise_or_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_BW_AND :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = bitwise_and_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_BW_XOR :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = bitwise_xor_function ;
1999-04-08 02:10:10 +08:00
goto binary_op_addr ;
case ZEND_BOOL_XOR :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = boolean_xor_function ;
1999-04-08 02:10:10 +08:00
/* Fall through */
binary_op_addr :
2001-06-27 23:47:31 +08:00
EG ( binary_op ) ( & Ts [ opline - > result . u . var ] . tmp_var ,
get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ,
2001-07-30 12:54:16 +08:00
get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) TSRMLS_CC ) ;
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
FREE_OP ( & opline - > op2 , EG ( free_op2 ) ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_BW_NOT :
case ZEND_BOOL_NOT :
1999-08-16 03:29:39 +08:00
EG ( unary_op ) = get_unary_op ( opline - > opcode ) ;
EG ( unary_op ) ( & Ts [ opline - > result . u . var ] . tmp_var ,
get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ;
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_ADD :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = add_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_SUB :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = sub_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_MUL :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = mul_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_DIV :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = div_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_MOD :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = mod_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_SL :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = shift_left_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_SR :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = shift_right_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_CONCAT :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = concat_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_BW_OR :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = bitwise_or_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_BW_AND :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = bitwise_and_function ;
1999-04-08 02:10:10 +08:00
goto binary_assign_op_addr ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_BW_XOR :
1999-08-16 03:29:39 +08:00
EG ( binary_op ) = bitwise_xor_function ;
1999-04-08 02:10:10 +08:00
/* Fall through */
binary_assign_op_addr : {
zval * * var_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_RW ) ;
if ( ! var_ptr ) {
zend_error ( E_ERROR , " Cannot use assign-op operators with overloaded objects nor string offsets " ) ;
}
if ( * var_ptr = = EG ( error_zval_ptr ) ) {
1999-09-26 13:45:18 +08:00
Ts [ opline - > result . u . var ] . var . ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
SELECTIVE_PZVAL_LOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr , & opline - > result ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
1999-04-08 02:10:10 +08:00
opline + + ;
continue ;
}
2000-08-04 16:11:54 +08:00
SEPARATE_ZVAL_IF_NOT_REF ( var_ptr ) ;
2001-07-30 12:54:16 +08:00
EG ( binary_op ) ( * var_ptr , * var_ptr , get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) TSRMLS_CC ) ;
1999-09-26 13:45:18 +08:00
Ts [ opline - > result . u . var ] . var . ptr_ptr = var_ptr ;
1999-07-10 17:29:02 +08:00
SELECTIVE_PZVAL_LOCK ( * var_ptr , & opline - > result ) ;
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op2 , EG ( free_op2 ) ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_PRE_INC :
case ZEND_PRE_DEC :
case ZEND_POST_INC :
case ZEND_POST_DEC : {
int ( * incdec_op ) ( zval * op ) ;
zval * * var_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_RW ) ;
if ( ! var_ptr ) {
zend_error ( E_ERROR , " Cannot increment/decrement overloaded objects nor string offsets " ) ;
}
if ( * var_ptr = = EG ( error_zval_ptr ) ) {
1999-09-26 13:45:18 +08:00
Ts [ opline - > result . u . var ] . var . ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
SELECTIVE_PZVAL_LOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr , & opline - > result ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
1999-04-08 02:10:10 +08:00
opline + + ;
continue ;
}
get_incdec_op ( incdec_op , opline - > opcode ) ;
switch ( opline - > opcode ) {
case ZEND_POST_INC :
case ZEND_POST_DEC :
Ts [ opline - > result . u . var ] . tmp_var = * * var_ptr ;
zendi_zval_copy_ctor ( Ts [ opline - > result . u . var ] . tmp_var ) ;
break ;
}
2000-08-04 16:11:54 +08:00
SEPARATE_ZVAL_IF_NOT_REF ( var_ptr ) ;
1999-04-08 02:10:10 +08:00
incdec_op ( * var_ptr ) ;
switch ( opline - > opcode ) {
case ZEND_PRE_INC :
case ZEND_PRE_DEC :
1999-09-26 13:45:18 +08:00
Ts [ opline - > result . u . var ] . var . ptr_ptr = var_ptr ;
1999-07-10 17:29:02 +08:00
SELECTIVE_PZVAL_LOCK ( * var_ptr , & opline - > result ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
1999-04-08 02:10:10 +08:00
break ;
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-24 08:12:55 +08:00
case ZEND_PRINT :
1999-08-16 03:29:39 +08:00
zend_print_variable ( get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ;
1999-04-08 02:10:10 +08:00
Ts [ opline - > result . u . var ] . tmp_var . value . lval = 1 ;
Ts [ opline - > result . u . var ] . tmp_var . type = IS_LONG ;
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-24 08:12:55 +08:00
case ZEND_ECHO :
1999-08-16 03:29:39 +08:00
zend_print_variable ( get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ;
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_R :
2001-07-27 18:10:39 +08:00
zend_fetch_var_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_W :
2001-07-27 18:10:39 +08:00
zend_fetch_var_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_W TSRMLS_CC ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_RW :
2001-07-27 18:10:39 +08:00
zend_fetch_var_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_RW TSRMLS_CC ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-09-30 01:18:36 +08:00
case ZEND_FETCH_FUNC_ARG :
1999-11-04 03:21:56 +08:00
if ( ARG_SHOULD_BE_SENT_BY_REF ( opline - > extended_value , fbc , fbc - > common . arg_types ) ) {
1999-09-30 01:18:36 +08:00
/* Behave like FETCH_W */
2001-07-27 18:10:39 +08:00
zend_fetch_var_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_W TSRMLS_CC ) ;
1999-09-30 01:18:36 +08:00
} else {
/* Behave like FETCH_R */
2001-07-27 18:10:39 +08:00
zend_fetch_var_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
1999-09-30 01:18:36 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
2000-02-15 04:31:01 +08:00
case ZEND_FETCH_UNSET :
2001-07-27 18:10:39 +08:00
zend_fetch_var_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
2000-02-17 00:49:44 +08:00
PZVAL_UNLOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-16 17:20:10 +08:00
if ( Ts [ opline - > result . u . var ] . var . ptr_ptr ! = & EG ( uninitialized_zval_ptr ) ) {
2000-02-17 00:00:02 +08:00
SEPARATE_ZVAL_IF_NOT_REF ( Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-16 17:20:10 +08:00
}
2000-02-17 00:49:44 +08:00
PZVAL_LOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-15 04:31:01 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_IS :
2001-07-27 18:10:39 +08:00
zend_fetch_var_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_IS TSRMLS_CC ) ;
1999-10-03 00:40:25 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_DIM_R :
1999-07-10 19:45:23 +08:00
if ( opline - > extended_value = = ZEND_FETCH_ADD_LOCK ) {
1999-09-26 13:45:18 +08:00
PZVAL_LOCK ( * Ts [ opline - > op1 . u . var ] . var . ptr_ptr ) ;
1999-05-23 00:10:51 +08:00
}
2001-07-27 18:10:39 +08:00
zend_fetch_dimension_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_DIM_W :
2001-07-27 18:10:39 +08:00
zend_fetch_dimension_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_W TSRMLS_CC ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_DIM_RW :
2001-07-27 18:10:39 +08:00
zend_fetch_dimension_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_RW TSRMLS_CC ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_DIM_IS :
2001-07-27 18:10:39 +08:00
zend_fetch_dimension_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_IS TSRMLS_CC ) ;
1999-10-03 00:40:25 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-09-30 01:18:36 +08:00
case ZEND_FETCH_DIM_FUNC_ARG :
1999-11-04 03:21:56 +08:00
if ( ARG_SHOULD_BE_SENT_BY_REF ( opline - > extended_value , fbc , fbc - > common . arg_types ) ) {
1999-09-30 01:18:36 +08:00
/* Behave like FETCH_DIM_W */
2001-07-27 18:10:39 +08:00
zend_fetch_dimension_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_W TSRMLS_CC ) ;
1999-09-30 01:18:36 +08:00
} else {
/* Behave like FETCH_DIM_R, except for locking used for list() */
2001-07-27 18:10:39 +08:00
zend_fetch_dimension_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
1999-09-30 01:18:36 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
2000-02-15 04:31:01 +08:00
case ZEND_FETCH_DIM_UNSET :
2000-02-16 17:20:10 +08:00
/* Not needed in DIM_UNSET
2000-02-15 04:31:01 +08:00
if ( opline - > extended_value = = ZEND_FETCH_ADD_LOCK ) {
PZVAL_LOCK ( * Ts [ opline - > op1 . u . var ] . var . ptr_ptr ) ;
}
2000-02-16 17:20:10 +08:00
*/
2001-07-27 18:10:39 +08:00
zend_fetch_dimension_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
2000-02-17 00:49:44 +08:00
PZVAL_UNLOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-16 17:20:10 +08:00
if ( Ts [ opline - > result . u . var ] . var . ptr_ptr ! = & EG ( uninitialized_zval_ptr ) ) {
2000-02-17 00:00:02 +08:00
SEPARATE_ZVAL_IF_NOT_REF ( Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-16 17:20:10 +08:00
}
2000-02-17 00:49:44 +08:00
PZVAL_LOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-15 04:31:01 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_OBJ_R :
2001-07-27 18:10:39 +08:00
zend_fetch_property_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_OBJ_W :
2001-07-27 18:10:39 +08:00
zend_fetch_property_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_W TSRMLS_CC ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_OBJ_RW :
2001-07-27 18:10:39 +08:00
zend_fetch_property_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_RW TSRMLS_CC ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_OBJ_IS :
2001-07-27 18:10:39 +08:00
zend_fetch_property_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_IS TSRMLS_CC ) ;
1999-10-03 00:40:25 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-09-30 01:18:36 +08:00
case ZEND_FETCH_OBJ_FUNC_ARG :
1999-11-04 03:21:56 +08:00
if ( ARG_SHOULD_BE_SENT_BY_REF ( opline - > extended_value , fbc , fbc - > common . arg_types ) ) {
1999-09-30 01:18:36 +08:00
/* Behave like FETCH_OBJ_W */
2001-07-27 18:10:39 +08:00
zend_fetch_property_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_W TSRMLS_CC ) ;
1999-09-30 01:18:36 +08:00
} else {
2001-07-27 18:10:39 +08:00
zend_fetch_property_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
1999-09-30 01:18:36 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
2000-02-15 04:31:01 +08:00
case ZEND_FETCH_OBJ_UNSET :
2001-07-27 18:10:39 +08:00
zend_fetch_property_address ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts , BP_VAR_R TSRMLS_CC ) ;
2000-02-17 00:49:44 +08:00
PZVAL_UNLOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-16 17:20:10 +08:00
if ( Ts [ opline - > result . u . var ] . var . ptr_ptr ! = & EG ( uninitialized_zval_ptr ) ) {
2000-02-17 00:00:02 +08:00
SEPARATE_ZVAL_IF_NOT_REF ( Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-16 17:20:10 +08:00
}
2000-02-17 00:49:44 +08:00
PZVAL_LOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
2000-02-15 04:31:01 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_DIM_TMP_VAR :
2001-07-27 18:10:39 +08:00
zend_fetch_dimension_address_from_tmp_var ( & opline - > result , & opline - > op1 , & opline - > op2 , Ts TSRMLS_CC ) ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN : {
1999-12-16 04:15:32 +08:00
zval * value ;
value = get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
2001-07-27 18:10:39 +08:00
zend_assign_to_variable ( & opline - > result , & opline - > op1 , & opline - > op2 , value , ( EG ( free_op2 ) ? IS_TMP_VAR : opline - > op2 . op_type ) , Ts TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
/* zend_assign_to_variable() always takes care of op2, never free it! */
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-24 08:12:55 +08:00
case ZEND_ASSIGN_REF :
2001-07-27 18:10:39 +08:00
zend_assign_to_variable_reference ( & opline - > result , get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_W ) , get_zval_ptr_ptr ( & opline - > op2 , Ts , BP_VAR_W ) , Ts TSRMLS_CC ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_JMP :
# if DEBUG_ZEND>=2
printf ( " Jumping to %d \n " , opline - > op1 . u . opline_num ) ;
# endif
opline = & op_array - > opcodes [ opline - > op1 . u . opline_num ] ;
continue ;
break ;
case ZEND_JMPZ : {
znode * op1 = & opline - > op1 ;
1999-08-16 03:29:39 +08:00
if ( ! i_zend_is_true ( get_zval_ptr ( op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ) {
1999-04-08 02:10:10 +08:00
# if DEBUG_ZEND>=2
printf ( " Conditional jmp to %d \n " , opline - > op2 . u . opline_num ) ;
# endif
opline = & op_array - > opcodes [ opline - > op2 . u . opline_num ] ;
1999-08-16 03:29:39 +08:00
FREE_OP ( op1 , EG ( free_op1 ) ) ;
1999-04-08 02:10:10 +08:00
continue ;
}
1999-08-16 03:29:39 +08:00
FREE_OP ( op1 , EG ( free_op1 ) ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_JMPNZ : {
znode * op1 = & opline - > op1 ;
1999-08-16 03:29:39 +08:00
if ( zend_is_true ( get_zval_ptr ( op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ) {
1999-04-08 02:10:10 +08:00
# if DEBUG_ZEND>=2
printf ( " Conditional jmp to %d \n " , opline - > op2 . u . opline_num ) ;
# endif
opline = & op_array - > opcodes [ opline - > op2 . u . opline_num ] ;
1999-08-16 03:29:39 +08:00
FREE_OP ( op1 , EG ( free_op1 ) ) ;
1999-04-08 02:10:10 +08:00
continue ;
}
1999-08-16 03:29:39 +08:00
FREE_OP ( op1 , EG ( free_op1 ) ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_JMPZNZ : {
2000-04-06 04:55:51 +08:00
znode * res = & opline - > op1 ;
1999-04-08 02:10:10 +08:00
2000-04-18 01:16:47 +08:00
if ( zend_is_true ( get_zval_ptr ( res , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ) {
1999-04-08 02:10:10 +08:00
# if DEBUG_ZEND>=2
2000-04-18 01:16:47 +08:00
printf ( " Conditional jmp on true to %d \n " , opline - > extended_value ) ;
1999-04-08 02:10:10 +08:00
# endif
2000-04-06 04:55:51 +08:00
opline = & op_array - > opcodes [ opline - > extended_value ] ;
1999-04-08 02:10:10 +08:00
} else {
# if DEBUG_ZEND>=2
2000-04-18 01:16:47 +08:00
printf ( " Conditional jmp on false to %d \n " , opline - > op2 . u . opline_num ) ;
1999-04-08 02:10:10 +08:00
# endif
2000-04-06 04:55:51 +08:00
opline = & op_array - > opcodes [ opline - > op2 . u . opline_num ] ;
1999-04-08 02:10:10 +08:00
}
1999-08-16 03:29:39 +08:00
FREE_OP ( res , EG ( free_op1 ) ) ;
1999-04-08 02:10:10 +08:00
}
continue ;
break ;
case ZEND_JMPZ_EX : {
zend_op * original_opline = opline ;
1999-08-16 03:29:39 +08:00
int retval = zend_is_true ( get_zval_ptr ( & original_opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ;
1999-04-08 02:10:10 +08:00
2001-02-09 20:47:57 +08:00
FREE_OP ( & original_opline - > op1 , EG ( free_op1 ) ) ;
Ts [ original_opline - > result . u . var ] . tmp_var . value . lval = retval ;
Ts [ original_opline - > result . u . var ] . tmp_var . type = IS_LONG ;
1999-04-08 02:10:10 +08:00
if ( ! retval ) {
# if DEBUG_ZEND>=2
printf ( " Conditional jmp to %d \n " , opline - > op2 . u . opline_num ) ;
# endif
opline = & op_array - > opcodes [ opline - > op2 . u . opline_num ] ;
continue ;
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_JMPNZ_EX : {
zend_op * original_opline = opline ;
1999-08-16 03:29:39 +08:00
int retval = zend_is_true ( get_zval_ptr ( & original_opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ;
1999-04-08 02:10:10 +08:00
2001-02-09 20:47:57 +08:00
FREE_OP ( & original_opline - > op1 , EG ( free_op1 ) ) ;
Ts [ original_opline - > result . u . var ] . tmp_var . value . lval = retval ;
Ts [ original_opline - > result . u . var ] . tmp_var . type = IS_LONG ;
1999-04-08 02:10:10 +08:00
if ( retval ) {
# if DEBUG_ZEND>=2
printf ( " Conditional jmp to %d \n " , opline - > op2 . u . opline_num ) ;
# endif
opline = & op_array - > opcodes [ opline - > op2 . u . opline_num ] ;
continue ;
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FREE :
zendi_zval_dtor ( Ts [ opline - > op1 . u . var ] . tmp_var ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_INIT_STRING :
Ts [ opline - > result . u . var ] . tmp_var . value . str . val = emalloc ( 1 ) ;
Ts [ opline - > result . u . var ] . tmp_var . value . str . val [ 0 ] = 0 ;
Ts [ opline - > result . u . var ] . tmp_var . value . str . len = 0 ;
Ts [ opline - > result . u . var ] . tmp_var . refcount = 1 ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_ADD_CHAR :
add_char_to_string ( & Ts [ opline - > result . u . var ] . tmp_var ,
1999-08-16 03:29:39 +08:00
get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_NA ) ,
1999-04-08 02:10:10 +08:00
& opline - > op2 . u . constant ) ;
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_ADD_STRING :
add_string_to_string ( & Ts [ opline - > result . u . var ] . tmp_var ,
1999-08-16 03:29:39 +08:00
get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_NA ) ,
1999-04-08 02:10:10 +08:00
& opline - > op2 . u . constant ) ;
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_ADD_VAR : {
1999-08-16 03:29:39 +08:00
zval * var = get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
zval var_copy ;
1999-06-11 18:44:26 +08:00
int use_copy ;
1999-04-08 02:10:10 +08:00
1999-06-11 18:44:26 +08:00
zend_make_printable_zval ( var , & var_copy , & use_copy ) ;
if ( use_copy ) {
1999-04-08 02:10:10 +08:00
var = & var_copy ;
}
add_string_to_string ( & Ts [ opline - > result . u . var ] . tmp_var ,
1999-08-16 03:29:39 +08:00
get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_NA ) ,
1999-04-08 02:10:10 +08:00
var ) ;
1999-06-11 18:44:26 +08:00
if ( use_copy ) {
1999-04-08 02:10:10 +08:00
zval_dtor ( var ) ;
}
/* original comment, possibly problematic:
* FREE_OP is missing intentionally here - we ' re always working on the same temporary variable
* ( Zeev ) : I don ' t think it ' s problematic , we only use variables
* which aren ' t affected by FREE_OP ( ) ' s anyway , unless they ' re
* string offsets or overloaded objects
*/
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op2 , EG ( free_op2 ) ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_INIT_FCALL_BY_NAME : {
1999-04-14 04:50:31 +08:00
zval * function_name ;
1999-04-08 02:10:10 +08:00
zend_function * function ;
HashTable * active_function_table ;
zval tmp ;
1999-11-04 03:21:56 +08:00
zend_ptr_stack_n_push ( & EG ( arg_types_stack ) , 2 , fbc , object . ptr ) ;
1999-05-28 20:06:59 +08:00
if ( opline - > extended_value & ZEND_CTOR_CALL ) {
1999-04-14 04:50:31 +08:00
/* constructor call */
1999-07-27 00:57:06 +08:00
2000-08-19 23:16:53 +08:00
if ( opline - > op1 . op_type = = IS_VAR ) {
SELECTIVE_PZVAL_LOCK ( * Ts [ opline - > op1 . u . var ] . var . ptr_ptr , & opline - > op1 ) ;
1999-07-27 00:57:06 +08:00
}
2001-03-10 17:21:48 +08:00
if ( opline - > op2 . op_type = = IS_VAR ) {
1999-09-26 13:45:18 +08:00
PZVAL_LOCK ( * Ts [ opline - > op2 . u . var ] . var . ptr_ptr ) ;
1999-04-14 04:50:31 +08:00
}
}
1999-08-16 03:29:39 +08:00
function_name = get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-14 04:50:31 +08:00
1999-04-08 02:10:10 +08:00
tmp = * function_name ;
zval_copy_ctor ( & tmp ) ;
convert_to_string ( & tmp ) ;
function_name = & tmp ;
zend_str_tolower ( tmp . value . str . val , tmp . value . str . len ) ;
if ( opline - > op1 . op_type ! = IS_UNUSED ) {
if ( opline - > op1 . op_type = = IS_CONST ) { /* used for class_name::function() */
zend_class_entry * ce ;
1999-07-27 00:57:06 +08:00
zval * * object_ptr_ptr ;
1999-04-08 02:10:10 +08:00
1999-07-27 00:57:06 +08:00
if ( zend_hash_find ( EG ( active_symbol_table ) , " this " , sizeof ( " this " ) , ( void * * ) & object_ptr_ptr ) = = FAILURE ) {
1999-07-28 01:30:16 +08:00
object . ptr = NULL ;
1999-07-27 00:57:06 +08:00
} else {
1999-10-10 04:29:36 +08:00
/* We assume that "this" is already is_ref and pointing to the object.
If it isn ' t then tough */
1999-07-28 01:30:16 +08:00
object . ptr = * object_ptr_ptr ;
1999-10-10 04:29:36 +08:00
object . ptr - > refcount + + ; /* For this pointer */
1999-04-08 02:10:10 +08:00
}
2001-03-07 18:07:25 +08:00
if ( zend_hash_find ( EG ( class_table ) , opline - > op1 . u . constant . value . str . val , opline - > op1 . u . constant . value . str . len + 1 , ( void * * ) & ce ) = = FAILURE ) { /* class doesn't exist */
2001-06-21 22:53:05 +08:00
zend_error ( E_ERROR , " Undefined class name '%s' " , opline - > op1 . u . constant . value . str . val ) ;
2001-03-07 18:07:25 +08:00
}
active_function_table = & ce - > function_table ;
1999-04-08 02:10:10 +08:00
} else { /* used for member function calls */
2001-07-27 18:10:39 +08:00
object . ptr = _get_object_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) TSRMLS_CC ) ;
1999-10-10 04:29:36 +08:00
1999-10-28 23:53:31 +08:00
if ( ( ! object . ptr & & Ts [ opline - > op1 . u . var ] . EA . type = = IS_OVERLOADED_OBJECT )
| | ( ( object . ptr & & object . ptr - > type = = IS_OBJECT ) & & ( object . ptr - > value . obj . ce - > handle_function_call ) ) ) { /* overloaded function call */
1999-04-08 02:10:10 +08:00
zend_overloaded_element overloaded_element ;
overloaded_element . element = * function_name ;
2000-01-04 21:52:52 +08:00
overloaded_element . type = OE_IS_METHOD ;
1999-04-08 02:10:10 +08:00
1999-07-28 01:30:16 +08:00
if ( object . ptr ) {
2000-04-11 04:21:13 +08:00
Ts [ opline - > op1 . u . var ] . EA . data . overloaded_element . object = object . ptr ;
Ts [ opline - > op1 . u . var ] . EA . data . overloaded_element . type = BP_VAR_NA ;
Ts [ opline - > op1 . u . var ] . EA . data . overloaded_element . elements_list = ( zend_llist * ) emalloc ( sizeof ( zend_llist ) ) ;
zend_llist_init ( Ts [ opline - > op1 . u . var ] . EA . data . overloaded_element . elements_list , sizeof ( zend_overloaded_element ) , NULL , 0 ) ;
1999-04-08 02:10:10 +08:00
}
2000-04-11 04:21:13 +08:00
zend_llist_add_element ( Ts [ opline - > op1 . u . var ] . EA . data . overloaded_element . elements_list , & overloaded_element ) ;
1999-11-04 03:21:56 +08:00
fbc = ( zend_function * ) emalloc ( sizeof ( zend_function ) ) ;
fbc - > type = ZEND_OVERLOADED_FUNCTION ;
fbc - > common . arg_types = NULL ;
2000-04-11 04:21:13 +08:00
fbc - > overloaded_function . var = opline - > op1 . u . var ;
1999-04-08 02:10:10 +08:00
goto overloaded_function_call_cont ;
}
1999-10-28 23:53:31 +08:00
if ( ! object . ptr | | object . ptr - > type ! = IS_OBJECT ) {
1999-04-08 02:10:10 +08:00
zend_error ( E_ERROR , " Call to a member function on a non-object " ) ;
}
2000-07-07 06:08:22 +08:00
if ( ! object . ptr - > is_ref & & object . ptr - > refcount > 1 ) {
zend_error ( E_ERROR , " Bug: Problem in method call \n " ) ;
}
object . ptr - > is_ref = 1 ;
2000-04-11 04:21:13 +08:00
object . ptr - > refcount + + ; /* For $this pointer */
1999-07-28 01:30:16 +08:00
active_function_table = & ( object . ptr - > value . obj . ce - > function_table ) ;
1999-04-08 02:10:10 +08:00
}
} else { /* function pointer */
1999-07-28 01:30:16 +08:00
object . ptr = NULL ;
1999-04-08 02:10:10 +08:00
active_function_table = EG ( function_table ) ;
}
if ( zend_hash_find ( active_function_table , function_name - > value . str . val , function_name - > value . str . len + 1 , ( void * * ) & function ) = = FAILURE ) {
1999-05-15 23:47:24 +08:00
zend_error ( E_ERROR , " Call to undefined function: %s() " , function_name - > value . str . val ) ;
1999-04-08 02:10:10 +08:00
}
zval_dtor ( & tmp ) ;
1999-11-04 03:21:56 +08:00
fbc = function ;
1999-04-08 02:10:10 +08:00
overloaded_function_call_cont :
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op2 , EG ( free_op2 ) ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-06-09 02:33:31 +08:00
case ZEND_DO_FCALL_BY_NAME :
1999-11-04 03:21:56 +08:00
function_state . function = fbc ;
1999-06-09 02:33:31 +08:00
goto do_fcall_common ;
1999-04-13 03:40:48 +08:00
case ZEND_DO_FCALL : {
1999-08-16 03:29:39 +08:00
zval * fname = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-13 03:40:48 +08:00
1999-06-09 02:33:31 +08:00
if ( zend_hash_find ( EG ( function_table ) , fname - > value . str . val , fname - > value . str . len + 1 , ( void * * ) & function_state . function ) = = FAILURE ) {
zend_error ( E_ERROR , " Unknown function: %s() \n " , fname - > value . str . val ) ;
1999-04-08 02:10:10 +08:00
}
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
1999-10-12 04:29:55 +08:00
zend_ptr_stack_push ( & EG ( arg_types_stack ) , object . ptr ) ;
object . ptr = NULL ;
1999-06-09 02:33:31 +08:00
goto do_fcall_common ;
}
do_fcall_common :
{
1999-12-16 04:15:32 +08:00
zval * * original_return_value ;
1999-12-21 23:55:46 +08:00
int return_value_used = RETURN_VALUE_USED ( opline ) ;
1999-12-19 14:39:17 +08:00
2000-03-27 02:40:24 +08:00
zend_ptr_stack_n_push ( & EG ( argument_stack ) , 2 , ( void * ) opline - > extended_value , NULL ) ;
1999-12-20 02:54:40 +08:00
1999-12-16 04:15:32 +08:00
Ts [ opline - > result . u . var ] . var . ptr_ptr = & Ts [ opline - > result . u . var ] . var . ptr ;
1999-12-19 14:39:17 +08:00
if ( function_state . function - > type = = ZEND_INTERNAL_FUNCTION ) {
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( Ts [ opline - > result . u . var ] . var . ptr ) ;
1999-12-20 02:54:40 +08:00
INIT_ZVAL ( * ( Ts [ opline - > result . u . var ] . var . ptr ) ) ;
2001-07-27 18:10:39 +08:00
( ( zend_internal_function * ) function_state . function ) - > handler ( opline - > extended_value , Ts [ opline - > result . u . var ] . var . ptr , object . ptr , return_value_used TSRMLS_CC ) ;
1999-10-11 02:31:42 +08:00
if ( object . ptr ) {
object . ptr - > refcount - - ;
}
1999-12-16 04:15:32 +08:00
Ts [ opline - > result . u . var ] . var . ptr - > is_ref = 0 ;
Ts [ opline - > result . u . var ] . var . ptr - > refcount = 1 ;
1999-12-20 02:54:40 +08:00
if ( ! return_value_used ) {
zval_ptr_dtor ( & Ts [ opline - > result . u . var ] . var . ptr ) ;
}
1999-04-08 02:10:10 +08:00
} else if ( function_state . function - > type = = ZEND_USER_FUNCTION ) {
1999-08-16 03:29:39 +08:00
HashTable * calling_symbol_table ;
1999-12-20 02:54:40 +08:00
Ts [ opline - > result . u . var ] . var . ptr = NULL ;
1999-04-13 02:29:09 +08:00
if ( EG ( symtable_cache_ptr ) > = EG ( symtable_cache ) ) {
1999-06-10 05:02:59 +08:00
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
1999-04-13 02:29:09 +08:00
function_state . function_symbol_table = * ( EG ( symtable_cache_ptr ) - - ) ;
} else {
1999-12-28 03:07:33 +08:00
ALLOC_HASHTABLE ( function_state . function_symbol_table ) ;
1999-12-22 01:14:31 +08:00
zend_hash_init ( function_state . function_symbol_table , 0 , NULL , ZVAL_PTR_DTOR , 0 ) ;
1999-06-10 05:02:59 +08:00
/*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/
1999-04-13 02:29:09 +08:00
}
1999-04-13 04:49:02 +08:00
calling_symbol_table = EG ( active_symbol_table ) ;
1999-04-13 02:29:09 +08:00
EG ( active_symbol_table ) = function_state . function_symbol_table ;
1999-06-09 02:33:31 +08:00
if ( opline - > opcode = = ZEND_DO_FCALL_BY_NAME
1999-07-28 01:30:16 +08:00
& & object . ptr
1999-11-04 03:21:56 +08:00
& & fbc - > type ! = ZEND_OVERLOADED_FUNCTION ) {
1999-07-27 00:57:06 +08:00
zval * * this_ptr ;
2000-03-24 19:12:30 +08:00
zval * null_ptr = NULL ;
1999-04-13 03:40:48 +08:00
2000-03-24 19:12:30 +08:00
zend_hash_update ( function_state . function_symbol_table , " this " , sizeof ( " this " ) , & null_ptr , sizeof ( zval * ) , ( void * * ) & this_ptr ) ;
1999-07-28 01:30:16 +08:00
if ( ! PZVAL_IS_REF ( object . ptr ) ) {
2001-06-19 16:42:22 +08:00
zend_error ( E_WARNING , " Problem with method call - please report this bug " ) ;
1999-07-27 03:32:13 +08:00
}
1999-07-28 01:30:16 +08:00
* this_ptr = object . ptr ;
object . ptr = NULL ;
1999-04-13 03:40:48 +08:00
}
1999-12-16 04:15:32 +08:00
original_return_value = EG ( return_value_ptr_ptr ) ;
EG ( return_value_ptr_ptr ) = Ts [ opline - > result . u . var ] . var . ptr_ptr ;
1999-04-08 02:10:10 +08:00
EG ( active_op_array ) = ( zend_op_array * ) function_state . function ;
1999-12-20 02:54:40 +08:00
2001-07-27 18:10:39 +08:00
zend_execute ( EG ( active_op_array ) TSRMLS_CC ) ;
1999-12-20 02:54:40 +08:00
if ( return_value_used & & ! Ts [ opline - > result . u . var ] . var . ptr ) {
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( Ts [ opline - > result . u . var ] . var . ptr ) ;
1999-12-20 02:54:40 +08:00
INIT_ZVAL ( * Ts [ opline - > result . u . var ] . var . ptr ) ;
} else if ( ! return_value_used & & Ts [ opline - > result . u . var ] . var . ptr ) {
zval_ptr_dtor ( & Ts [ opline - > result . u . var ] . var . ptr ) ;
}
1999-04-08 02:10:10 +08:00
EG ( opline_ptr ) = & opline ;
EG ( active_op_array ) = op_array ;
1999-12-16 04:15:32 +08:00
EG ( return_value_ptr_ptr ) = original_return_value ;
1999-04-13 02:29:09 +08:00
if ( EG ( symtable_cache_ptr ) > = EG ( symtable_cache_limit ) ) {
zend_hash_destroy ( function_state . function_symbol_table ) ;
1999-12-28 03:07:33 +08:00
FREE_HASHTABLE ( function_state . function_symbol_table ) ;
1999-04-13 02:29:09 +08:00
} else {
* ( + + EG ( symtable_cache_ptr ) ) = function_state . function_symbol_table ;
zend_hash_clean ( * EG ( symtable_cache_ptr ) ) ;
}
1999-04-13 04:49:02 +08:00
EG ( active_symbol_table ) = calling_symbol_table ;
1999-04-08 02:10:10 +08:00
} else { /* ZEND_OVERLOADED_FUNCTION */
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( Ts [ opline - > result . u . var ] . var . ptr ) ;
1999-12-20 02:54:40 +08:00
INIT_ZVAL ( * ( Ts [ opline - > result . u . var ] . var . ptr ) ) ;
2001-07-27 18:10:39 +08:00
call_overloaded_function ( & Ts [ fbc - > overloaded_function . var ] , opline - > extended_value , Ts [ opline - > result . u . var ] . var . ptr TSRMLS_CC ) ;
1999-11-04 03:21:56 +08:00
efree ( fbc ) ;
1999-12-20 02:54:40 +08:00
if ( ! return_value_used ) {
zval_ptr_dtor ( & Ts [ opline - > result . u . var ] . var . ptr ) ;
}
1999-11-20 00:55:25 +08:00
}
1999-06-09 02:33:31 +08:00
if ( opline - > opcode = = ZEND_DO_FCALL_BY_NAME ) {
2001-02-09 20:47:57 +08:00
zend_ptr_stack_n_pop ( & EG ( arg_types_stack ) , 2 , & object . ptr , & fbc ) ;
} else {
object . ptr = zend_ptr_stack_pop ( & EG ( arg_types_stack ) ) ;
1999-06-09 02:33:31 +08:00
}
1999-04-08 02:10:10 +08:00
function_state . function = ( zend_function * ) op_array ;
EG ( function_state_ptr ) = & function_state ;
2001-07-27 18:10:39 +08:00
zend_ptr_stack_clear_multiple ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_RETURN : {
1999-12-16 04:15:32 +08:00
zval * retval_ptr ;
zval * * retval_ptr_ptr ;
if ( ( EG ( active_op_array ) - > return_reference = = ZEND_RETURN_REF ) & &
( opline - > op1 . op_type ! = IS_CONST ) & &
( opline - > op1 . op_type ! = IS_TMP_VAR ) ) {
retval_ptr_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_W ) ;
2001-07-19 22:11:40 +08:00
SEPARATE_ZVAL_TO_MAKE_IS_REF ( retval_ptr_ptr ) ;
( * retval_ptr_ptr ) - > refcount + + ;
2000-08-04 16:11:54 +08:00
1999-12-16 04:15:32 +08:00
( * EG ( return_value_ptr_ptr ) ) = ( * retval_ptr_ptr ) ;
} else {
retval_ptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
1999-12-16 04:15:32 +08:00
if ( ! EG ( free_op1 ) ) { /* Not a temp var */
if ( PZVAL_IS_REF ( retval_ptr ) & & retval_ptr - > refcount > 0 ) {
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( * ( EG ( return_value_ptr_ptr ) ) ) ;
1999-12-16 04:15:32 +08:00
* * EG ( return_value_ptr_ptr ) = * retval_ptr ;
( * EG ( return_value_ptr_ptr ) ) - > is_ref = 0 ;
( * EG ( return_value_ptr_ptr ) ) - > refcount = 1 ;
zval_copy_ctor ( * EG ( return_value_ptr_ptr ) ) ;
} else {
* EG ( return_value_ptr_ptr ) = retval_ptr ;
retval_ptr - > refcount + + ;
}
} else {
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( * ( EG ( return_value_ptr_ptr ) ) ) ;
1999-12-16 04:15:32 +08:00
* * EG ( return_value_ptr_ptr ) = * retval_ptr ;
( * EG ( return_value_ptr_ptr ) ) - > refcount = 1 ;
( * EG ( return_value_ptr_ptr ) ) - > is_ref = 0 ;
}
1999-04-08 02:10:10 +08:00
}
free_alloca ( Ts ) ;
2000-02-04 22:45:58 +08:00
EG ( in_execution ) = original_in_execution ;
1999-04-08 02:10:10 +08:00
return ;
}
break ;
case ZEND_SEND_VAL :
1999-06-09 02:33:31 +08:00
if ( opline - > extended_value = = ZEND_DO_FCALL_BY_NAME
1999-11-04 03:21:56 +08:00
& & ARG_SHOULD_BE_SENT_BY_REF ( opline - > op2 . u . opline_num , fbc , fbc - > common . arg_types ) ) {
1999-04-08 02:10:10 +08:00
zend_error ( E_ERROR , " Cannot pass parameter %d by reference " , opline - > op2 . u . opline_num ) ;
}
{
1999-12-27 05:21:33 +08:00
zval * valptr ;
2000-11-21 04:49:42 +08:00
zval * value ;
value = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( valptr ) ;
2000-11-21 04:49:42 +08:00
* valptr = * value ;
if ( ! EG ( free_op1 ) ) {
zval_copy_ctor ( valptr ) ;
}
1999-07-10 04:43:59 +08:00
INIT_PZVAL ( valptr ) ;
1999-04-13 02:29:09 +08:00
zend_ptr_stack_push ( & EG ( argument_stack ) , valptr ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
2000-10-30 03:16:29 +08:00
case ZEND_SEND_VAR_NO_REF :
2000-11-28 02:46:23 +08:00
if ( opline - > extended_value & ZEND_ARG_COMPILE_TIME_BOUND ) { /* Had function_ptr at compile_time */
if ( ! ( opline - > extended_value & ZEND_ARG_SEND_BY_REF ) ) {
goto send_by_var ;
2000-10-30 03:16:29 +08:00
}
2000-11-28 02:46:23 +08:00
} else if ( ! ARG_SHOULD_BE_SENT_BY_REF ( opline - > op2 . u . opline_num , fbc , fbc - > common . arg_types ) ) {
goto send_by_var ;
1999-04-08 02:10:10 +08:00
}
{
1999-12-16 04:15:32 +08:00
zval * varptr ;
varptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
2000-11-28 02:46:23 +08:00
if ( varptr ! = & EG ( uninitialized_zval ) & & ( PZVAL_IS_REF ( varptr ) | | varptr - > refcount = = 1 ) ) {
varptr - > is_ref = 1 ;
varptr - > refcount + + ;
zend_ptr_stack_push ( & EG ( argument_stack ) , varptr ) ;
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
}
2000-11-28 02:46:23 +08:00
zend_error ( E_ERROR , " Only variables can be passed by reference " ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
2000-11-28 02:46:23 +08:00
case ZEND_SEND_VAR :
if ( ( opline - > extended_value = = ZEND_DO_FCALL_BY_NAME )
& & ARG_SHOULD_BE_SENT_BY_REF ( opline - > op2 . u . opline_num , fbc , fbc - > common . arg_types ) ) {
goto send_by_ref ;
}
send_by_var :
{
zval * varptr ;
varptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
if ( varptr = = & EG ( uninitialized_zval ) ) {
ALLOC_ZVAL ( varptr ) ;
INIT_ZVAL ( * varptr ) ;
varptr - > refcount = 0 ;
} else if ( PZVAL_IS_REF ( varptr ) ) {
zval * original_var = varptr ;
ALLOC_ZVAL ( varptr ) ;
* varptr = * original_var ;
varptr - > is_ref = 0 ;
varptr - > refcount = 0 ;
zval_copy_ctor ( varptr ) ;
}
varptr - > refcount + + ;
zend_ptr_stack_push ( & EG ( argument_stack ) , varptr ) ;
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ; /* for string offsets */
}
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
send_by_ref :
case ZEND_SEND_REF : {
1999-12-16 04:15:32 +08:00
zval * * varptr_ptr ;
zval * varptr ;
varptr_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_W ) ;
2000-03-25 07:51:34 +08:00
if ( ! varptr_ptr ) {
zend_error ( E_ERROR , " Only variables can be passed by reference " ) ;
}
2000-08-04 16:11:54 +08:00
SEPARATE_ZVAL_TO_MAKE_IS_REF ( varptr_ptr ) ;
1999-12-16 04:15:32 +08:00
varptr = * varptr_ptr ;
1999-04-08 02:10:10 +08:00
varptr - > refcount + + ;
1999-04-13 02:29:09 +08:00
zend_ptr_stack_push ( & EG ( argument_stack ) , varptr ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_RECV : {
zval * * param ;
2001-07-27 18:10:39 +08:00
if ( zend_ptr_stack_get_arg ( opline - > op1 . u . constant . value . lval , ( void * * ) & param TSRMLS_CC ) = = FAILURE ) {
2001-07-30 15:43:02 +08:00
zend_error ( E_WARNING , " Missing argument %d for %s() \n " , opline - > op1 . u . constant . value . lval , get_active_function_name ( TSRMLS_C ) ) ;
1999-07-10 19:45:23 +08:00
if ( opline - > result . op_type = = IS_VAR ) {
1999-09-26 13:45:18 +08:00
PZVAL_UNLOCK ( * Ts [ opline - > result . u . var ] . var . ptr_ptr ) ;
1999-07-10 19:45:23 +08:00
}
1999-07-10 02:19:48 +08:00
} else if ( PZVAL_IS_REF ( * param ) ) {
2001-07-27 18:10:39 +08:00
zend_assign_to_variable_reference ( NULL , get_zval_ptr_ptr ( & opline - > result , Ts , BP_VAR_W ) , param , NULL TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
} else {
2001-07-27 18:10:39 +08:00
zend_assign_to_variable ( NULL , & opline - > result , NULL , * param , IS_VAR , Ts TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_RECV_INIT : {
zval * * param , * assignment_value ;
2001-07-27 18:10:39 +08:00
if ( zend_ptr_stack_get_arg ( opline - > op1 . u . constant . value . lval , ( void * * ) & param TSRMLS_CC ) = = FAILURE ) {
2000-06-01 03:07:09 +08:00
if ( opline - > op2 . u . constant . type = = IS_CONSTANT | | opline - > op2 . u . constant . type = = IS_CONSTANT_ARRAY ) {
1999-12-27 05:21:33 +08:00
zval * default_value ;
1999-04-08 02:10:10 +08:00
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( default_value ) ;
1999-04-08 02:10:10 +08:00
* default_value = opline - > op2 . u . constant ;
2000-06-01 03:07:09 +08:00
if ( opline - > op2 . u . constant . type = = IS_CONSTANT_ARRAY ) {
1999-04-08 02:10:10 +08:00
zval_copy_ctor ( default_value ) ;
}
2000-08-10 03:22:35 +08:00
default_value - > refcount = 1 ;
2001-07-31 12:53:54 +08:00
zval_update_constant ( & default_value , 0 TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
default_value - > refcount = 0 ;
1999-10-02 07:31:39 +08:00
default_value - > is_ref = 0 ;
1999-04-08 02:10:10 +08:00
param = & default_value ;
assignment_value = default_value ;
} else {
param = NULL ;
assignment_value = & opline - > op2 . u . constant ;
}
} else {
assignment_value = * param ;
}
2000-07-11 21:23:48 +08:00
if ( PZVAL_IS_REF ( assignment_value ) & & param ) {
2001-07-27 18:10:39 +08:00
zend_assign_to_variable_reference ( NULL , get_zval_ptr_ptr ( & opline - > result , Ts , BP_VAR_W ) , param , NULL TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
} else {
2001-07-27 18:10:39 +08:00
zend_assign_to_variable ( NULL , & opline - > result , NULL , assignment_value , IS_VAR , Ts TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_BOOL :
/* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */
1999-08-16 03:29:39 +08:00
Ts [ opline - > result . u . var ] . tmp_var . value . lval = zend_is_true ( get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ) ;
1999-04-08 02:10:10 +08:00
Ts [ opline - > result . u . var ] . tmp_var . type = IS_LONG ;
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_BRK :
case ZEND_CONT : {
1999-08-16 03:29:39 +08:00
zval * nest_levels_zval = get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
zval tmp ;
int array_offset , nest_levels , original_nest_levels ;
zend_brk_cont_element * jmp_to ;
if ( nest_levels_zval - > type ! = IS_LONG ) {
tmp = * nest_levels_zval ;
zval_copy_ctor ( & tmp ) ;
convert_to_long ( & tmp ) ;
nest_levels = tmp . value . lval ;
} else {
nest_levels = nest_levels_zval - > value . lval ;
}
original_nest_levels = nest_levels ;
array_offset = opline - > op1 . u . opline_num ;
do {
if ( array_offset = = - 1 ) {
zend_error ( E_ERROR , " Cannot break/continue %d levels \n " , original_nest_levels ) ;
}
jmp_to = & op_array - > brk_cont_array [ array_offset ] ;
1999-12-23 02:10:38 +08:00
if ( nest_levels > 1 ) {
zend_op * brk_opline = & op_array - > opcodes [ jmp_to - > brk ] ;
switch ( brk_opline - > opcode ) {
case ZEND_SWITCH_FREE :
2001-07-27 18:10:39 +08:00
zend_switch_free ( brk_opline , Ts TSRMLS_CC ) ;
1999-12-23 02:10:38 +08:00
break ;
case ZEND_FREE :
zendi_zval_dtor ( Ts [ brk_opline - > op1 . u . var ] . tmp_var ) ;
break ;
}
}
1999-04-08 02:10:10 +08:00
array_offset = jmp_to - > parent ;
} while ( - - nest_levels > 0 ) ;
if ( opline - > opcode = = ZEND_BRK ) {
opline = op_array - > opcodes + jmp_to - > brk ;
} else {
opline = op_array - > opcodes + jmp_to - > cont ;
}
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op2 , EG ( free_op2 ) ) ;
1999-04-08 02:10:10 +08:00
continue ;
}
2001-01-02 01:59:08 +08:00
/* Never reaches this point */
1999-07-24 02:41:58 +08:00
case ZEND_CASE : {
int switch_expr_is_overloaded = 0 ;
if ( opline - > op1 . op_type = = IS_VAR ) {
1999-09-26 13:45:18 +08:00
if ( Ts [ opline - > op1 . u . var ] . var . ptr_ptr ) {
PZVAL_LOCK ( * Ts [ opline - > op1 . u . var ] . var . ptr_ptr ) ;
1999-07-24 02:41:58 +08:00
} else {
switch_expr_is_overloaded = 1 ;
if ( Ts [ opline - > op1 . u . var ] . EA . type = = IS_STRING_OFFSET ) {
2000-04-07 00:34:55 +08:00
Ts [ opline - > op1 . u . var ] . EA . data . str_offset . str - > refcount + + ;
1999-07-24 02:41:58 +08:00
}
}
}
is_equal_function ( & Ts [ opline - > result . u . var ] . tmp_var ,
1999-08-16 03:29:39 +08:00
get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ,
2001-07-30 12:54:16 +08:00
get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) TSRMLS_CC ) ;
1999-07-24 02:41:58 +08:00
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op2 , EG ( free_op2 ) ) ;
1999-07-24 02:41:58 +08:00
if ( switch_expr_is_overloaded ) {
1999-07-24 19:24:19 +08:00
/* We only free op1 if this is a string offset,
* Since if it is a TMP_VAR , it ' ll be reused by
* other CASE opcodes ( whereas string offsets
* are allocated at each get_zval_ptr ( ) )
*/
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
1999-09-26 13:45:18 +08:00
Ts [ opline - > op1 . u . var ] . var . ptr_ptr = NULL ;
1999-09-29 00:03:09 +08:00
AI_USE_PTR ( Ts [ opline - > op1 . u . var ] . var ) ;
1999-07-24 02:41:58 +08:00
}
1999-04-14 03:28:03 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-07-24 19:24:19 +08:00
case ZEND_SWITCH_FREE :
2001-07-27 18:10:39 +08:00
zend_switch_free ( opline , Ts TSRMLS_CC ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_NEW : {
1999-08-16 03:29:39 +08:00
zval * tmp = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
zval class_name ;
zend_class_entry * ce ;
class_name = * tmp ;
zval_copy_ctor ( & class_name ) ;
convert_to_string ( & class_name ) ;
zend_str_tolower ( class_name . value . str . val , class_name . value . str . len ) ;
if ( zend_hash_find ( EG ( class_table ) , class_name . value . str . val , class_name . value . str . len + 1 , ( void * * ) & ce ) = = FAILURE ) {
2000-03-02 01:10:45 +08:00
zend_error ( E_ERROR , " Cannot instantiate non-existent class: %s " , class_name . value . str . val ) ;
1999-04-08 02:10:10 +08:00
}
2000-08-15 03:17:26 +08:00
Ts [ opline - > result . u . var ] . var . ptr_ptr = & Ts [ opline - > result . u . var ] . var . ptr ;
ALLOC_ZVAL ( Ts [ opline - > result . u . var ] . var . ptr ) ;
object_init_ex ( Ts [ opline - > result . u . var ] . var . ptr , ce ) ;
Ts [ opline - > result . u . var ] . var . ptr - > refcount = 1 ;
Ts [ opline - > result . u . var ] . var . ptr - > is_ref = 1 ;
1999-04-08 02:10:10 +08:00
zval_dtor ( & class_name ) ;
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_CONSTANT :
2001-07-30 15:43:02 +08:00
if ( ! zend_get_constant ( opline - > op1 . u . constant . value . str . val , opline - > op1 . u . constant . value . str . len , & Ts [ opline - > result . u . var ] . tmp_var TSRMLS_CC ) ) {
1999-04-08 02:10:10 +08:00
zend_error ( E_NOTICE , " Use of undefined constant %s - assumed '%s' " ,
opline - > op1 . u . constant . value . str . val ,
opline - > op1 . u . constant . value . str . val ) ;
Ts [ opline - > result . u . var ] . tmp_var = opline - > op1 . u . constant ;
zval_copy_ctor ( & Ts [ opline - > result . u . var ] . tmp_var ) ;
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_INIT_ARRAY :
case ZEND_ADD_ARRAY_ELEMENT : {
zval * array_ptr = & Ts [ opline - > result . u . var ] . tmp_var ;
1999-12-02 06:55:20 +08:00
zval * expr_ptr , * * expr_ptr_ptr = NULL ;
1999-08-16 03:29:39 +08:00
zval * offset = get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
1999-10-01 18:00:05 +08:00
if ( opline - > extended_value ) {
expr_ptr_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_R ) ;
expr_ptr = * expr_ptr_ptr ;
} else {
expr_ptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
}
1999-04-08 02:10:10 +08:00
if ( opline - > opcode = = ZEND_INIT_ARRAY ) {
array_init ( array_ptr ) ;
1999-10-01 18:00:05 +08:00
if ( ! expr_ptr ) {
2000-01-31 05:17:29 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
}
}
2000-07-10 04:21:20 +08:00
if ( ! opline - > extended_value & & EG ( free_op1 ) ) { /* temporary variable */
1999-12-27 05:21:33 +08:00
zval * new_expr ;
1999-04-08 02:10:10 +08:00
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( new_expr ) ;
1999-10-01 18:00:05 +08:00
* new_expr = * expr_ptr ;
expr_ptr = new_expr ;
INIT_PZVAL ( expr_ptr ) ;
1999-04-08 02:10:10 +08:00
} else {
1999-10-01 18:00:05 +08:00
if ( opline - > extended_value ) {
2000-08-04 16:11:54 +08:00
SEPARATE_ZVAL_TO_MAKE_IS_REF ( expr_ptr_ptr ) ;
expr_ptr = * expr_ptr_ptr ;
1999-10-01 18:00:05 +08:00
expr_ptr - > refcount + + ;
} else if ( PZVAL_IS_REF ( expr_ptr ) ) {
1999-12-27 05:21:33 +08:00
zval * new_expr ;
1999-04-08 02:10:10 +08:00
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( new_expr ) ;
1999-10-01 18:00:05 +08:00
* new_expr = * expr_ptr ;
expr_ptr = new_expr ;
zendi_zval_copy_ctor ( * expr_ptr ) ;
INIT_PZVAL ( expr_ptr ) ;
1999-04-08 02:10:10 +08:00
} else {
1999-10-01 18:00:05 +08:00
expr_ptr - > refcount + + ;
1999-04-08 02:10:10 +08:00
}
}
if ( offset ) {
switch ( offset - > type ) {
case IS_DOUBLE :
2001-05-06 23:39:27 +08:00
zend_hash_index_update ( array_ptr - > value . ht , ( long ) offset - > value . dval , & expr_ptr , sizeof ( zval * ) , NULL ) ;
1999-04-08 02:10:10 +08:00
break ;
case IS_LONG :
1999-10-01 18:00:05 +08:00
zend_hash_index_update ( array_ptr - > value . ht , offset - > value . lval , & expr_ptr , sizeof ( zval * ) , NULL ) ;
1999-04-08 02:10:10 +08:00
break ;
case IS_STRING :
1999-10-01 18:00:05 +08:00
zend_hash_update ( array_ptr - > value . ht , offset - > value . str . val , offset - > value . str . len + 1 , & expr_ptr , sizeof ( zval * ) , NULL ) ;
1999-04-08 02:10:10 +08:00
break ;
2000-09-15 04:30:06 +08:00
case IS_NULL :
zend_hash_update ( array_ptr - > value . ht , " " , sizeof ( " " ) , & expr_ptr , sizeof ( zval * ) , NULL ) ;
break ;
1999-04-08 02:10:10 +08:00
default :
2000-09-15 04:30:06 +08:00
zval_ptr_dtor ( & expr_ptr ) ;
1999-04-08 02:10:10 +08:00
/* do nothing */
break ;
}
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op2 , EG ( free_op2 ) ) ;
1999-04-08 02:10:10 +08:00
} else {
1999-10-01 18:00:05 +08:00
zend_hash_next_index_insert ( array_ptr - > value . ht , & expr_ptr , sizeof ( zval * ) , NULL ) ;
1999-04-08 02:10:10 +08:00
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_CAST : {
1999-08-16 03:29:39 +08:00
zval * expr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
zval * result = & Ts [ opline - > result . u . var ] . tmp_var ;
* result = * expr ;
1999-08-16 03:29:39 +08:00
if ( ! EG ( free_op1 ) ) {
1999-04-08 02:10:10 +08:00
zendi_zval_copy_ctor ( * result ) ;
}
2000-05-04 01:56:44 +08:00
switch ( opline - > extended_value ) {
2000-01-04 21:22:58 +08:00
case IS_NULL :
2000-02-19 21:11:39 +08:00
convert_to_null ( result ) ;
1999-12-31 21:56:59 +08:00
break ;
1999-06-11 19:17:43 +08:00
case IS_BOOL :
convert_to_boolean ( result ) ;
break ;
1999-04-08 02:10:10 +08:00
case IS_LONG :
convert_to_long ( result ) ;
break ;
case IS_DOUBLE :
convert_to_double ( result ) ;
break ;
case IS_STRING :
convert_to_string ( result ) ;
break ;
case IS_ARRAY :
convert_to_array ( result ) ;
break ;
case IS_OBJECT :
convert_to_object ( result ) ;
break ;
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_INCLUDE_OR_EVAL : {
zend_op_array * new_op_array = NULL ;
1999-12-19 14:39:17 +08:00
zval * * original_return_value = EG ( return_value_ptr_ptr ) ;
1999-12-21 23:55:46 +08:00
int return_value_used ;
2000-05-18 18:21:24 +08:00
zval * inc_filename = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
zval tmp_inc_filename ;
2001-08-03 01:27:19 +08:00
zend_bool failure_retval = 0 ;
2000-05-18 18:21:24 +08:00
if ( inc_filename - > type ! = IS_STRING ) {
tmp_inc_filename = * inc_filename ;
zval_copy_ctor ( & tmp_inc_filename ) ;
convert_to_string ( & tmp_inc_filename ) ;
inc_filename = & tmp_inc_filename ;
}
1999-12-21 23:55:46 +08:00
return_value_used = RETURN_VALUE_USED ( opline ) ;
1999-04-08 02:10:10 +08:00
switch ( opline - > op2 . u . constant . value . lval ) {
2000-08-10 03:22:35 +08:00
case ZEND_INCLUDE_ONCE :
case ZEND_REQUIRE_ONCE : {
2001-03-05 06:27:56 +08:00
char * opened_path = NULL ;
2000-04-08 06:03:46 +08:00
int dummy = 1 ;
zend_file_handle file_handle ;
2000-04-08 05:16:19 +08:00
2000-04-08 06:03:46 +08:00
file_handle . handle . fp = zend_fopen ( inc_filename - > value . str . val , & opened_path ) ;
file_handle . type = ZEND_HANDLE_FP ;
2000-08-14 02:00:50 +08:00
file_handle . filename = inc_filename - > value . str . val ;
file_handle . opened_path = opened_path ;
file_handle . free_filename = 0 ;
2000-04-08 06:03:46 +08:00
if ( file_handle . handle . fp ) {
if ( ! opened_path | | zend_hash_add ( & EG ( included_files ) , opened_path , strlen ( opened_path ) + 1 , ( void * ) & dummy , sizeof ( int ) , NULL ) = = SUCCESS ) {
2001-07-28 18:51:54 +08:00
new_op_array = zend_compile_file ( & file_handle , ( opline - > op2 . u . constant . value . lval = = ZEND_INCLUDE_ONCE ? ZEND_INCLUDE : ZEND_REQUIRE ) TSRMLS_CC ) ;
zend_destroy_file_handle ( & file_handle TSRMLS_CC ) ;
2000-08-15 04:16:27 +08:00
opened_path = NULL ; /* zend_destroy_file_handle() already frees it */
2000-04-12 01:30:37 +08:00
} else {
fclose ( file_handle . handle . fp ) ;
2001-08-03 01:27:19 +08:00
failure_retval = 1 ;
2000-04-08 06:03:46 +08:00
}
2000-06-09 23:42:49 +08:00
} else {
2000-08-15 04:16:27 +08:00
if ( opline - > op2 . u . constant . value . lval = = ZEND_INCLUDE_ONCE ) {
2000-08-10 03:22:35 +08:00
zend_message_dispatcher ( ZMSG_FAILED_INCLUDE_FOPEN , file_handle . filename ) ;
} else {
zend_message_dispatcher ( ZMSG_FAILED_REQUIRE_FOPEN , file_handle . filename ) ;
}
2000-03-11 00:36:30 +08:00
}
2000-08-15 04:16:27 +08:00
if ( opened_path ) {
2000-09-01 06:24:20 +08:00
efree ( opened_path ) ;
2000-08-15 04:16:27 +08:00
}
2000-04-08 06:03:46 +08:00
break ;
2000-03-11 00:36:30 +08:00
}
2000-04-08 05:16:19 +08:00
break ;
1999-04-08 02:10:10 +08:00
case ZEND_INCLUDE :
1999-12-23 23:03:25 +08:00
case ZEND_REQUIRE :
2001-07-28 18:51:54 +08:00
new_op_array = compile_filename ( opline - > op2 . u . constant . value . lval , inc_filename TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
break ;
2000-09-13 03:47:25 +08:00
case ZEND_EVAL : {
2001-07-30 09:48:22 +08:00
char * eval_desc = zend_make_compiled_string_description ( " eval()'d code " TSRMLS_CC ) ;
2000-09-13 03:47:25 +08:00
2001-07-28 18:51:54 +08:00
new_op_array = compile_string ( inc_filename , eval_desc TSRMLS_CC ) ;
2000-09-13 03:47:25 +08:00
efree ( eval_desc ) ;
}
1999-04-08 02:10:10 +08:00
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
2000-05-18 18:21:24 +08:00
if ( inc_filename = = & tmp_inc_filename ) {
zval_dtor ( & tmp_inc_filename ) ;
}
1999-08-18 05:36:30 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
1999-12-20 02:54:40 +08:00
Ts [ opline - > result . u . var ] . var . ptr_ptr = & Ts [ opline - > result . u . var ] . var . ptr ;
1999-04-08 02:10:10 +08:00
if ( new_op_array ) {
1999-12-20 02:54:40 +08:00
EG ( return_value_ptr_ptr ) = Ts [ opline - > result . u . var ] . var . ptr_ptr ;
1999-04-08 02:10:10 +08:00
EG ( active_op_array ) = new_op_array ;
2001-08-03 01:27:19 +08:00
Ts [ opline - > result . u . var ] . var . ptr = NULL ;
1999-12-19 14:39:17 +08:00
2001-07-27 18:10:39 +08:00
zend_execute ( new_op_array TSRMLS_CC ) ;
1999-12-21 23:55:46 +08:00
if ( ! return_value_used ) {
if ( Ts [ opline - > result . u . var ] . var . ptr ) {
zval_ptr_dtor ( & Ts [ opline - > result . u . var ] . var . ptr ) ;
}
} else { /* return value is used */
if ( ! Ts [ opline - > result . u . var ] . var . ptr ) { /* there was no return statement */
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( Ts [ opline - > result . u . var ] . var . ptr ) ;
1999-12-21 23:55:46 +08:00
INIT_PZVAL ( Ts [ opline - > result . u . var ] . var . ptr ) ;
Ts [ opline - > result . u . var ] . var . ptr - > value . lval = 1 ;
2001-08-03 01:27:19 +08:00
Ts [ opline - > result . u . var ] . var . ptr - > type = IS_BOOL ;
1999-12-21 23:55:46 +08:00
}
1999-12-20 02:54:40 +08:00
}
1999-12-19 14:39:17 +08:00
1999-04-08 02:10:10 +08:00
EG ( opline_ptr ) = & opline ;
EG ( active_op_array ) = op_array ;
EG ( function_state_ptr ) = & function_state ;
destroy_op_array ( new_op_array ) ;
efree ( new_op_array ) ;
} else {
1999-12-21 23:55:46 +08:00
if ( return_value_used ) {
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( Ts [ opline - > result . u . var ] . var . ptr ) ;
1999-12-21 23:55:46 +08:00
INIT_ZVAL ( * Ts [ opline - > result . u . var ] . var . ptr ) ;
2001-08-03 01:27:19 +08:00
Ts [ opline - > result . u . var ] . var . ptr - > value . lval = failure_retval ;
Ts [ opline - > result . u . var ] . var . ptr - > type = IS_BOOL ;
1999-12-21 23:55:46 +08:00
}
1999-04-08 02:10:10 +08:00
}
1999-12-19 14:39:17 +08:00
EG ( return_value_ptr_ptr ) = original_return_value ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-24 08:12:55 +08:00
case ZEND_UNSET_VAR : {
1999-08-16 03:29:39 +08:00
zval tmp , * variable = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
if ( variable - > type ! = IS_STRING ) {
tmp = * variable ;
zval_copy_ctor ( & tmp ) ;
convert_to_string ( & tmp ) ;
variable = & tmp ;
}
zend_hash_del ( EG ( active_symbol_table ) , variable - > value . str . val , variable - > value . str . len + 1 ) ;
if ( variable = = & tmp ) {
zval_dtor ( & tmp ) ;
}
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-24 08:12:55 +08:00
case ZEND_UNSET_DIM_OBJ : {
1999-04-08 02:10:10 +08:00
zval * * container = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_R ) ;
1999-08-16 03:29:39 +08:00
zval * offset = get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
if ( container ) {
HashTable * ht ;
switch ( ( * container ) - > type ) {
case IS_ARRAY :
ht = ( * container ) - > value . ht ;
break ;
case IS_OBJECT :
ht = ( * container ) - > value . obj . properties ;
break ;
default :
ht = NULL ;
break ;
}
2000-06-09 21:07:26 +08:00
if ( ht ) {
1999-04-08 02:10:10 +08:00
switch ( offset - > type ) {
2000-06-09 21:07:26 +08:00
case IS_DOUBLE :
case IS_RESOURCE :
case IS_BOOL :
1999-04-08 02:10:10 +08:00
case IS_LONG :
2000-06-09 21:07:26 +08:00
{
long index ;
if ( offset - > type = = IS_DOUBLE ) {
index = ( long ) offset - > value . lval ;
} else {
index = offset - > value . lval ;
}
zend_hash_index_del ( ht , index ) ;
break ;
}
case IS_STRING :
zend_hash_del ( ht , offset - > value . str . val , offset - > value . str . len + 1 ) ;
1999-04-08 02:10:10 +08:00
break ;
2000-06-09 18:59:21 +08:00
case IS_NULL :
2000-06-09 21:07:26 +08:00
zend_hash_del ( ht , " " , sizeof ( " " ) ) ;
2000-06-09 18:59:21 +08:00
break ;
2000-06-09 21:07:26 +08:00
default :
zend_error ( E_WARNING , " Illegal offset type in unset " ) ;
1999-04-08 02:10:10 +08:00
break ;
}
}
} else {
/* overloaded element */
}
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op2 , EG ( free_op2 ) ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FE_RESET : {
2000-08-11 06:08:02 +08:00
zval * array_ptr , * * array_ptr_ptr ;
2000-02-09 23:38:56 +08:00
HashTable * fe_ht ;
2000-02-01 02:21:54 +08:00
2000-08-11 06:08:02 +08:00
if ( opline - > extended_value ) {
array_ptr_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_R ) ;
2001-04-20 15:09:22 +08:00
if ( array_ptr_ptr = = NULL ) {
MAKE_STD_ZVAL ( array_ptr ) ;
} else {
SEPARATE_ZVAL_IF_NOT_REF ( array_ptr_ptr ) ;
array_ptr = * array_ptr_ptr ;
array_ptr - > refcount + + ;
}
2000-08-11 06:08:02 +08:00
} else {
array_ptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
if ( EG ( free_op1 ) ) { /* IS_TMP_VAR */
zval * tmp ;
ALLOC_ZVAL ( tmp ) ;
* tmp = * array_ptr ;
INIT_PZVAL ( tmp ) ;
array_ptr = tmp ;
} else {
array_ptr - > refcount + + ;
}
1999-04-08 02:10:10 +08:00
}
2000-02-01 02:21:54 +08:00
PZVAL_LOCK ( array_ptr ) ;
Ts [ opline - > result . u . var ] . var . ptr = array_ptr ;
2000-01-25 03:04:07 +08:00
Ts [ opline - > result . u . var ] . var . ptr_ptr = & Ts [ opline - > result . u . var ] . var . ptr ;
2000-02-09 23:38:56 +08:00
if ( ( fe_ht = HASH_OF ( array_ptr ) ) ! = NULL ) {
1999-04-08 02:10:10 +08:00
/* probably redundant */
2000-02-09 23:38:56 +08:00
zend_hash_internal_pointer_reset ( fe_ht ) ;
1999-04-08 02:10:10 +08:00
} else {
/* JMP to the end of foreach - TBD */
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_FE_FETCH : {
1999-08-16 03:29:39 +08:00
zval * array = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
zval * result = & Ts [ opline - > result . u . var ] . tmp_var ;
zval * * value , * key ;
char * str_key ;
ulong int_key ;
2000-02-09 23:38:56 +08:00
HashTable * fe_ht ;
1999-04-08 02:10:10 +08:00
2000-01-25 03:04:07 +08:00
PZVAL_LOCK ( array ) ;
2000-02-09 23:38:56 +08:00
fe_ht = HASH_OF ( array ) ;
2000-02-10 05:48:16 +08:00
if ( ! fe_ht ) {
2000-02-09 23:38:56 +08:00
zend_error ( E_WARNING , " Invalid argument supplied for foreach() " ) ;
1999-06-10 05:02:59 +08:00
opline = op_array - > opcodes + opline - > op2 . u . opline_num ;
continue ;
2000-02-09 23:38:56 +08:00
} else if ( zend_hash_get_current_data ( fe_ht , ( void * * ) & value ) = = FAILURE ) {
1999-04-08 02:10:10 +08:00
opline = op_array - > opcodes + opline - > op2 . u . opline_num ;
continue ;
}
array_init ( result ) ;
( * value ) - > refcount + + ;
zend_hash_index_update ( result - > value . ht , 0 , value , sizeof ( zval * ) , NULL ) ;
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( key ) ;
1999-07-10 04:43:59 +08:00
INIT_PZVAL ( key ) ;
2000-12-22 20:49:51 +08:00
switch ( zend_hash_get_current_key ( fe_ht , & str_key , & int_key , 1 ) ) {
1999-04-08 02:10:10 +08:00
case HASH_KEY_IS_STRING :
key - > value . str . val = str_key ;
key - > value . str . len = strlen ( str_key ) ;
key - > type = IS_STRING ;
break ;
case HASH_KEY_IS_LONG :
key - > value . lval = int_key ;
key - > type = IS_LONG ;
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-08 02:10:10 +08:00
}
zend_hash_index_update ( result - > value . ht , 1 , & key , sizeof ( zval * ) , NULL ) ;
2000-02-09 23:38:56 +08:00
zend_hash_move_forward ( fe_ht ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_JMP_NO_CTOR : {
1999-04-14 04:50:31 +08:00
zval * object ;
1999-04-08 02:10:10 +08:00
1999-07-27 00:57:06 +08:00
if ( opline - > op1 . op_type = = IS_VAR ) {
1999-09-26 13:45:18 +08:00
PZVAL_LOCK ( * Ts [ opline - > op1 . u . var ] . var . ptr_ptr ) ;
1999-07-27 00:57:06 +08:00
}
1999-08-16 03:29:39 +08:00
object = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
if ( ! object - > value . obj . ce - > handle_function_call
& & ! zend_hash_exists ( & object - > value . obj . ce - > function_table , object - > value . obj . ce - > name , object - > value . obj . ce - > name_length + 1 ) ) {
opline = op_array - > opcodes + opline - > op2 . u . opline_num ;
continue ;
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_ISSET_ISEMPTY : {
1999-10-23 06:35:16 +08:00
zval * * var = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_IS ) ;
1999-04-08 02:10:10 +08:00
int isset ;
1999-07-04 02:03:02 +08:00
if ( ! var ) {
if ( Ts [ opline - > op1 . u . var ] . EA . type = = IS_STRING_OFFSET ) {
2000-04-07 00:34:55 +08:00
if ( Ts [ opline - > op1 . u . var ] . EA . data . str_offset . offset > = 0
& & Ts [ opline - > op1 . u . var ] . EA . data . str_offset . offset < Ts [ opline - > op1 . u . var ] . EA . data . str_offset . str - > value . str . len ) {
1999-07-04 02:03:02 +08:00
isset = 1 ;
} else {
isset = 0 ;
}
} else {
isset = 1 ;
}
1999-10-23 06:35:16 +08:00
} else if ( * var = = EG ( uninitialized_zval_ptr )
2000-01-04 21:22:58 +08:00
| | ( ( * var ) - > type = = IS_NULL ) ) {
1999-04-08 02:10:10 +08:00
isset = 0 ;
} else {
isset = 1 ;
}
switch ( opline - > op2 . u . constant . value . lval ) {
case ZEND_ISSET :
Ts [ opline - > result . u . var ] . tmp_var . value . lval = isset ;
break ;
case ZEND_ISEMPTY :
1999-07-04 02:03:02 +08:00
if ( ! var ) {
if ( ! isset
2000-04-07 00:34:55 +08:00
| | Ts [ opline - > op1 . u . var ] . EA . data . str_offset . str - > value . str . val [ Ts [ opline - > op1 . u . var ] . EA . data . str_offset . offset ] = = ' 0 ' ) {
1999-07-04 02:03:02 +08:00
Ts [ opline - > result . u . var ] . tmp_var . value . lval = 1 ;
} else {
Ts [ opline - > result . u . var ] . tmp_var . value . lval = 0 ;
}
1999-10-23 06:35:16 +08:00
} else if ( ! isset | | ! zend_is_true ( ( * var ) ) ) {
1999-04-08 02:10:10 +08:00
Ts [ opline - > result . u . var ] . tmp_var . value . lval = 1 ;
} else {
Ts [ opline - > result . u . var ] . tmp_var . value . lval = 0 ;
}
break ;
}
Ts [ opline - > result . u . var ] . tmp_var . type = IS_BOOL ;
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_EXIT :
if ( opline - > op1 . op_type ! = IS_UNUSED ) {
2000-11-22 12:24:35 +08:00
zval * ptr ;
ptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
if ( Z_TYPE_P ( ptr ) = = IS_LONG ) {
EG ( exit_status ) = Z_LVAL_P ( ptr ) ;
}
zend_print_variable ( ptr ) ;
1999-08-16 03:29:39 +08:00
FREE_OP ( & opline - > op1 , EG ( free_op1 ) ) ;
1999-04-08 02:10:10 +08:00
}
zend_bailout ( ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_BEGIN_SILENCE :
Ts [ opline - > result . u . var ] . tmp_var . value . lval = EG ( error_reporting ) ;
Ts [ opline - > result . u . var ] . tmp_var . type = IS_LONG ; /* shouldn't be necessary */
EG ( error_reporting ) = 0 ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_END_SILENCE :
EG ( error_reporting ) = Ts [ opline - > op1 . u . var ] . tmp_var . value . lval ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_QM_ASSIGN : {
1999-08-16 03:29:39 +08:00
zval * value = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
1999-04-08 02:10:10 +08:00
Ts [ opline - > result . u . var ] . tmp_var = * value ;
1999-08-16 03:29:39 +08:00
if ( ! EG ( free_op1 ) ) {
1999-04-08 02:10:10 +08:00
zval_copy_ctor ( & Ts [ opline - > result . u . var ] . tmp_var ) ;
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_EXT_STMT :
if ( ! EG ( no_extensions ) ) {
2001-07-31 12:53:54 +08:00
zend_llist_apply_with_argument ( & zend_extensions , ( llist_apply_with_arg_func_t ) zend_extension_statement_handler , op_array TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_EXT_FCALL_BEGIN :
if ( ! EG ( no_extensions ) ) {
2001-07-31 12:53:54 +08:00
zend_llist_apply_with_argument ( & zend_extensions , ( llist_apply_with_arg_func_t ) zend_extension_fcall_begin_handler , op_array TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_EXT_FCALL_END :
if ( ! EG ( no_extensions ) ) {
2001-07-31 12:53:54 +08:00
zend_llist_apply_with_argument ( & zend_extensions , ( llist_apply_with_arg_func_t ) zend_extension_fcall_end_handler , op_array TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-05-15 23:47:24 +08:00
case ZEND_DECLARE_FUNCTION_OR_CLASS :
1999-07-27 05:18:35 +08:00
do_bind_function_or_class ( opline , EG ( function_table ) , EG ( class_table ) , 0 ) ;
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
2000-01-25 03:00:30 +08:00
case ZEND_TICKS :
if ( + + EG ( ticks_count ) = = opline - > op1 . u . constant . value . lval ) {
EG ( ticks_count ) = 0 ;
if ( zend_ticks_function ) {
zend_ticks_function ( opline - > op1 . u . constant . value . lval ) ;
}
}
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
1999-04-08 02:10:10 +08:00
case ZEND_EXT_NOP :
case ZEND_NOP :
2000-01-29 08:33:07 +08:00
NEXT_OPCODE ( ) ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
2000-06-16 22:27:28 +08:00
1999-04-08 02:10:10 +08:00
}
}
2001-07-15 22:08:58 +08:00
zend_error ( E_ERROR , " Arrived at end of main loop which shouldn't happen " ) ;
1999-04-08 02:10:10 +08:00
}