1999-04-08 02:10:10 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-05 07:53:05 +08:00
| Copyright ( c ) 1998 - 2006 Zend Technologies Ltd . ( http : //www.zend.com) |
1999-04-08 02:10:10 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2001-12-11 23:16:21 +08:00
| This source file is subject to version 2.00 of the Zend license , |
2002-10-25 02:04:12 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
2001-12-11 23:16:21 +08:00
| http : //www.zend.com/license/2_00.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 > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2003-02-01 09:49:15 +08:00
/* $Id$ */
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"
2002-11-20 01:51:30 +08:00
# include "zend_ini.h"
2004-02-12 18:38:14 +08:00
# include "zend_exceptions.h"
2004-09-24 05:43:32 +08:00
# include "zend_vm.h"
2004-10-23 05:42:14 +08:00
# define _CONST_CODE 0
# define _TMP_CODE 1
# define _VAR_CODE 2
# define _UNUSED_CODE 3
# define _CV_CODE 4
2004-09-24 05:43:32 +08:00
typedef int ( * incdec_t ) ( zval * ) ;
1999-04-08 02:10:10 +08:00
2004-10-05 03:54:35 +08:00
# define get_zval_ptr(node, Ts, should_free, type) _get_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
# define get_zval_ptr_ptr(node, Ts, should_free, type) _get_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
# define get_obj_zval_ptr(node, Ts, should_free, type) _get_obj_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
# define get_obj_zval_ptr_ptr(node, Ts, should_free, type) _get_obj_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
1999-04-08 02:10:10 +08:00
/* Prototypes */
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))
2002-10-24 04:40:07 +08:00
# define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
# define T(offset) (*(temp_variable *)((char *) Ts + offset))
2002-10-24 04:26:28 +08:00
2004-08-02 10:35:01 +08:00
# define TEMP_VAR_STACK_LIMIT 2000
2003-08-19 07:11:58 +08:00
2004-08-20 04:03:06 +08:00
static inline void zend_pzval_unlock_func ( zval * z , zend_free_op * should_free )
2003-08-19 07:11:58 +08:00
{
2004-08-20 04:03:06 +08:00
if ( ! - - z - > refcount ) {
2003-08-19 07:11:58 +08:00
z - > refcount = 1 ;
z - > is_ref = 0 ;
2004-08-20 04:03:06 +08:00
should_free - > var = z ;
2004-09-24 05:43:32 +08:00
/* should_free->is_var = 1; */
2004-08-20 04:03:06 +08:00
} else {
should_free - > var = 0 ;
2005-06-23 16:21:03 +08:00
if ( z - > is_ref & & z - > refcount = = 1 ) {
z - > is_ref = 0 ;
}
2003-08-19 07:11:58 +08:00
}
}
2004-08-20 04:03:06 +08:00
static inline void zend_pzval_unlock_free_func ( zval * z )
2003-08-19 07:11:58 +08:00
{
2004-08-20 04:03:06 +08:00
if ( ! - - z - > refcount ) {
zval_dtor ( z ) ;
safe_free_zval_ptr ( z ) ;
2003-08-19 07:11:58 +08:00
}
}
2004-08-20 04:03:06 +08:00
# define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f)
# define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z)
# define PZVAL_LOCK(z) (z)->refcount++
2004-02-12 00:28:46 +08:00
# define RETURN_VALUE_UNUSED(pzn) (((pzn)->u.EA.type & EXT_TYPE_UNUSED))
# define SELECTIVE_PZVAL_LOCK(pzv, pzn) if (!RETURN_VALUE_UNUSED(pzn)) { PZVAL_LOCK(pzv); }
2004-08-20 04:03:06 +08:00
# define AI_USE_PTR(ai) \
if ( ( ai ) . ptr_ptr ) { \
( ai ) . ptr = * ( ( ai ) . ptr_ptr ) ; \
( ai ) . ptr_ptr = & ( ( ai ) . ptr ) ; \
} else { \
( ai ) . ptr = NULL ; \
}
# define FREE_OP(should_free) \
if ( should_free . var ) { \
2004-09-24 05:43:32 +08:00
if ( ( long ) should_free . var & 1L ) { \
zval_dtor ( ( zval * ) ( ( long ) should_free . var & ~ 1L ) ) ; \
2004-08-20 04:03:06 +08:00
} else { \
zval_ptr_dtor ( & should_free . var ) ; \
} \
}
2004-09-24 05:43:32 +08:00
# define FREE_OP_IF_VAR(should_free) \
if ( should_free . var ! = NULL & & ( ( ( long ) should_free . var & 1L ) = = 0 ) ) { \
2004-08-20 04:03:06 +08:00
zval_ptr_dtor ( & should_free . var ) ; \
}
# define FREE_OP_VAR_PTR(should_free) \
if ( should_free . var ) { \
zval_ptr_dtor ( & should_free . var ) ; \
}
2004-09-24 05:43:32 +08:00
# define TMP_FREE(z) (zval*)(((long)(z)) | 1L)
# define IS_TMP_FREE(should_free) ((long)should_free.var & 1L)
# define INIT_PZVAL_COPY(z,v) \
( z ) - > value = ( v ) - > value ; \
( z ) - > type = ( v ) - > type ; \
( z ) - > refcount = 1 ; \
( z ) - > is_ref = 0 ;
2003-08-19 07:11:58 +08:00
2005-06-03 19:16:19 +08:00
# define MAKE_REAL_ZVAL_PTR(val) \
do { \
zval * _tmp ; \
ALLOC_ZVAL ( _tmp ) ; \
_tmp - > value = ( val ) - > value ; \
_tmp - > type = ( val ) - > type ; \
_tmp - > refcount = 1 ; \
_tmp - > is_ref = 0 ; \
val = _tmp ; \
} while ( 0 )
2003-08-19 07:11:58 +08:00
/* End of zend_execute_locks.h */
2004-10-05 03:54:35 +08:00
# define CV_OF(i) (EG(current_execute_data)->CVs[i])
# define CV_DEF_OF(i) (EG(active_op_array)->vars[i])
2005-01-22 10:29:18 +08:00
ZEND_API zval * * zend_get_compiled_variable_value ( zend_execute_data * execute_data_ptr , zend_uint var )
{
return execute_data_ptr - > CVs [ var ] ;
}
2004-10-05 03:54:35 +08:00
static inline void zend_get_cv_address ( zend_compiled_variable * cv , zval * * * ptr , temp_variable * Ts TSRMLS_DC )
{
zval * new_zval = & EG ( uninitialized_zval ) ;
new_zval - > refcount + + ;
zend_hash_quick_update ( EG ( active_symbol_table ) , cv - > name , cv - > name_len + 1 , cv - > hash_value , & new_zval , sizeof ( zval * ) , ( void * * ) ptr ) ;
}
2005-06-14 01:50:07 +08:00
static inline zval * _get_zval_ptr_tmp ( znode * node , temp_variable * Ts , zend_free_op * should_free TSRMLS_DC )
{
return should_free - > var = & T ( node - > u . var ) . tmp_var ;
}
2005-03-24 05:05:56 +08:00
static inline zval * _get_zval_ptr_var ( znode * node , temp_variable * Ts , zend_free_op * should_free TSRMLS_DC )
{
2005-06-14 01:50:07 +08:00
zval * ptr = T ( node - > u . var ) . var . ptr ;
if ( ptr ) {
PZVAL_UNLOCK ( ptr , should_free ) ;
return ptr ;
2005-03-24 05:05:56 +08:00
} else {
temp_variable * T = & T ( node - > u . var ) ;
zval * str = T - > str_offset . str ;
/* string offset */
ALLOC_ZVAL ( ptr ) ;
T - > str_offset . ptr = ptr ;
should_free - > var = ptr ;
if ( T - > str_offset . str - > type ! = IS_STRING
2006-02-26 18:57:00 +08:00
| | ( ( int ) T - > str_offset . offset < 0 )
| | ( T - > str_offset . str - > value . str . len < = ( int ) T - > str_offset . offset ) ) {
2005-03-24 05:05:56 +08:00
zend_error ( E_NOTICE , " Uninitialized string offset: %d " , T - > str_offset . offset ) ;
ptr - > value . str . val = STR_EMPTY_ALLOC ( ) ;
ptr - > value . str . len = 0 ;
} else {
char c = str - > value . str . val [ T - > str_offset . offset ] ;
ptr - > value . str . val = estrndup ( & c , 1 ) ;
ptr - > value . str . len = 1 ;
}
PZVAL_UNLOCK_FREE ( str ) ;
ptr - > refcount = 1 ;
ptr - > is_ref = 1 ;
ptr - > type = IS_STRING ;
return ptr ;
}
}
2005-06-14 01:50:07 +08:00
static inline zval * _get_zval_ptr_cv ( znode * node , temp_variable * Ts , int type TSRMLS_DC )
2004-10-05 03:54:35 +08:00
{
zval * * * ptr = & CV_OF ( node - > u . var ) ;
if ( ! * ptr ) {
zend_compiled_variable * cv = & CV_DEF_OF ( node - > u . var ) ;
if ( zend_hash_quick_find ( EG ( active_symbol_table ) , cv - > name , cv - > name_len + 1 , cv - > hash_value , ( void * * ) ptr ) = = FAILURE ) {
switch ( type ) {
case BP_VAR_R :
2004-10-05 17:09:18 +08:00
case BP_VAR_UNSET :
2004-12-27 21:43:26 +08:00
zend_error ( E_NOTICE , " Undefined variable: %s " , cv - > name ) ;
2004-10-05 03:54:35 +08:00
/* break missing intentionally */
case BP_VAR_IS :
return & EG ( uninitialized_zval ) ;
break ;
case BP_VAR_RW :
2004-12-27 21:43:26 +08:00
zend_error ( E_NOTICE , " Undefined variable: %s " , cv - > name ) ;
2004-10-05 03:54:35 +08:00
/* break missing intentionally */
case BP_VAR_W :
zend_get_cv_address ( cv , ptr , Ts TSRMLS_CC ) ;
break ;
}
}
}
return * * ptr ;
}
2005-06-14 01:50:07 +08:00
static inline zval * _get_zval_ptr ( znode * node , temp_variable * Ts , zend_free_op * should_free , int type TSRMLS_DC )
2004-09-24 05:43:32 +08:00
{
2005-06-14 01:50:07 +08:00
/* should_free->is_var = 0; */
switch ( node - > op_type ) {
case IS_CONST :
should_free - > var = 0 ;
return & node - > u . constant ;
break ;
case IS_TMP_VAR :
should_free - > var = TMP_FREE ( & T ( node - > u . var ) . tmp_var ) ;
return & T ( node - > u . var ) . tmp_var ;
break ;
case IS_VAR :
return _get_zval_ptr_var ( node , Ts , should_free TSRMLS_CC ) ;
break ;
case IS_UNUSED :
should_free - > var = 0 ;
return NULL ;
break ;
case IS_CV :
should_free - > var = 0 ;
return _get_zval_ptr_cv ( node , Ts , type TSRMLS_CC ) ;
break ;
EMPTY_SWITCH_DEFAULT_CASE ( )
}
2004-09-24 05:43:32 +08:00
return NULL ;
}
static inline zval * * _get_zval_ptr_ptr_var ( znode * node , temp_variable * Ts , zend_free_op * should_free TSRMLS_DC )
{
2005-06-14 01:50:07 +08:00
zval * * ptr_ptr = T ( node - > u . var ) . var . ptr_ptr ;
if ( ptr_ptr ) {
PZVAL_UNLOCK ( * ptr_ptr , should_free ) ;
2003-10-05 15:52:28 +08:00
} else {
2004-09-24 05:43:32 +08:00
/* string offset */
PZVAL_UNLOCK ( T ( node - > u . var ) . str_offset . str , should_free ) ;
2002-03-10 21:42:37 +08:00
}
2005-06-14 01:50:07 +08:00
return ptr_ptr ;
2004-09-24 05:43:32 +08:00
}
2005-06-14 01:50:07 +08:00
static inline zval * * _get_zval_ptr_ptr_cv ( znode * node , temp_variable * Ts , int type TSRMLS_DC )
2004-10-05 03:54:35 +08:00
{
zval * * * ptr = & CV_OF ( node - > u . var ) ;
if ( ! * ptr ) {
zend_compiled_variable * cv = & CV_DEF_OF ( node - > u . var ) ;
if ( zend_hash_quick_find ( EG ( active_symbol_table ) , cv - > name , cv - > name_len + 1 , cv - > hash_value , ( void * * ) ptr ) = = FAILURE ) {
switch ( type ) {
case BP_VAR_R :
2004-10-05 17:09:18 +08:00
case BP_VAR_UNSET :
2004-12-27 21:43:26 +08:00
zend_error ( E_NOTICE , " Undefined variable: %s " , cv - > name ) ;
2004-10-05 03:54:35 +08:00
/* break missing intentionally */
case BP_VAR_IS :
return & EG ( uninitialized_zval_ptr ) ;
break ;
case BP_VAR_RW :
2004-12-27 21:43:26 +08:00
zend_error ( E_NOTICE , " Undefined variable: %s " , cv - > name ) ;
2004-10-05 03:54:35 +08:00
/* break missing intentionally */
case BP_VAR_W :
zend_get_cv_address ( cv , ptr , Ts TSRMLS_CC ) ;
break ;
}
}
}
return * ptr ;
}
2005-06-14 01:50:07 +08:00
static inline zval * * _get_zval_ptr_ptr ( znode * node , temp_variable * Ts , zend_free_op * should_free , int type TSRMLS_DC )
2004-10-05 03:54:35 +08:00
{
2005-06-14 01:50:07 +08:00
if ( node - > op_type = = IS_CV ) {
should_free - > var = 0 ;
return _get_zval_ptr_ptr_cv ( node , Ts , type TSRMLS_CC ) ;
} else if ( node - > op_type = = IS_VAR ) {
return _get_zval_ptr_ptr_var ( node , Ts , should_free TSRMLS_CC ) ;
} else {
should_free - > var = 0 ;
return NULL ;
}
2004-10-05 03:54:35 +08:00
}
2005-06-14 01:50:07 +08:00
static inline zval * _get_obj_zval_ptr_unused ( TSRMLS_D )
2004-09-24 05:43:32 +08:00
{
if ( EG ( This ) ) {
return EG ( This ) ;
} else {
zend_error_noreturn ( E_ERROR , " Using $this when not in object context " ) ;
return NULL ;
1999-04-08 02:10:10 +08:00
}
}
2005-06-14 01:50:07 +08:00
static inline zval * * _get_obj_zval_ptr_ptr ( znode * op , temp_variable * Ts , zend_free_op * should_free , int type TSRMLS_DC )
2004-10-05 03:54:35 +08:00
{
2005-06-14 01:50:07 +08:00
if ( op - > op_type = = IS_UNUSED ) {
if ( EG ( This ) ) {
/* this should actually never be modified, _ptr_ptr is modified only when
the object is empty */
should_free - > var = 0 ;
return & EG ( This ) ;
} else {
zend_error_noreturn ( E_ERROR , " Using $this when not in object context " ) ;
}
}
return get_zval_ptr_ptr ( op , Ts , should_free , type ) ;
2004-10-05 03:54:35 +08:00
}
2005-06-14 01:50:07 +08:00
static inline zval * * _get_obj_zval_ptr_ptr_unused ( TSRMLS_D )
2004-09-24 05:43:32 +08:00
{
if ( EG ( This ) ) {
return & EG ( This ) ;
} else {
zend_error_noreturn ( E_ERROR , " Using $this when not in object context " ) ;
return NULL ;
}
}
1999-12-23 02:10:38 +08:00
2005-06-14 01:50:07 +08:00
static inline zval * _get_obj_zval_ptr ( znode * op , temp_variable * Ts , zend_free_op * should_free , int type TSRMLS_DC )
{
if ( op - > op_type = = IS_UNUSED ) {
if ( EG ( This ) ) {
should_free - > var = 0 ;
return EG ( This ) ;
} else {
zend_error_noreturn ( E_ERROR , " Using $this when not in object context " ) ;
}
}
return get_zval_ptr ( op , Ts , should_free , type ) ;
}
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 :
2002-10-24 04:26:28 +08:00
if ( ! T ( opline - > op1 . u . var ) . var . ptr_ptr ) {
2003-11-30 01:33:25 +08:00
temp_variable * T = & T ( opline - > op1 . u . var ) ;
/* perform the equivalent of equivalent of a
* quick & silent get_zval_ptr , and FREE_OP
*/
2004-08-20 04:03:06 +08:00
PZVAL_UNLOCK_FREE ( T - > str_offset . str ) ;
1999-12-23 02:10:38 +08:00
} else {
2002-10-24 04:26:28 +08:00
zval_ptr_dtor ( & T ( opline - > op1 . u . var ) . var . ptr ) ;
2000-01-25 03:04:07 +08:00
if ( opline - > extended_value ) { /* foreach() free */
2002-10-24 04:26:28 +08:00
zval_ptr_dtor ( & T ( opline - > op1 . u . var ) . var . ptr ) ;
2000-01-25 03:04:07 +08:00
}
1999-12-23 02:10:38 +08:00
}
break ;
case IS_TMP_VAR :
2002-10-24 04:26:28 +08:00
zendi_zval_dtor ( T ( opline - > op1 . u . var ) . tmp_var ) ;
1999-12-23 02:10:38 +08:00
break ;
2000-01-29 05:43:46 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-12-23 02:10:38 +08:00
}
}
2004-09-24 05:43:32 +08:00
static void zend_assign_to_variable_reference ( zval * * variable_ptr_ptr , zval * * value_ptr_ptr TSRMLS_DC )
2001-06-22 05:17:10 +08:00
{
zval * variable_ptr ;
zval * value_ptr ;
if ( ! value_ptr_ptr | | ! variable_ptr_ptr ) {
2004-09-24 05:43:32 +08:00
zend_error_noreturn ( E_ERROR , " Cannot create references to/from string offsets nor overloaded objects " ) ;
2001-06-22 05:17:10 +08:00
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 ) ;
2003-02-17 03:18:23 +08:00
} else if ( variable_ptr ! = value_ptr ) {
2001-06-22 05:17:10 +08:00
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 + + ;
2005-09-01 21:21:37 +08:00
variable_ptr - > refcount - - ;
if ( variable_ptr - > refcount = = 0 ) {
zendi_zval_dtor ( * variable_ptr ) ;
FREE_ZVAL ( variable_ptr ) ;
}
2003-02-17 03:18:23 +08:00
} else if ( ! variable_ptr - > is_ref ) {
if ( variable_ptr_ptr = = value_ptr_ptr ) {
2003-02-17 02:34:48 +08:00
SEPARATE_ZVAL ( variable_ptr_ptr ) ;
2003-02-17 03:18:23 +08:00
} else if ( variable_ptr = = EG ( uninitialized_zval_ptr )
| | variable_ptr - > refcount > 2 ) {
/* we need to separate */
variable_ptr - > refcount - = 2 ;
ALLOC_ZVAL ( * variable_ptr_ptr ) ;
* * variable_ptr_ptr = * variable_ptr ;
zval_copy_ctor ( * variable_ptr_ptr ) ;
* value_ptr_ptr = * variable_ptr_ptr ;
( * variable_ptr_ptr ) - > refcount = 2 ;
2001-06-22 05:17:10 +08:00
}
( * variable_ptr_ptr ) - > is_ref = 1 ;
}
}
2002-03-11 05:02:00 +08:00
static inline void make_real_object ( zval * * object_ptr TSRMLS_DC )
{
2002-10-17 02:06:36 +08:00
/* this should modify object only if it's empty */
2002-03-10 21:42:37 +08:00
if ( ( * object_ptr ) - > type = = IS_NULL
| | ( ( * object_ptr ) - > type = = IS_BOOL & & ( * object_ptr ) - > value . lval = = 0 )
| | ( ( * object_ptr ) - > type = = IS_STRING & & ( * object_ptr ) - > value . str . len = = 0 ) ) {
if ( ! PZVAL_IS_REF ( * object_ptr ) ) {
SEPARATE_ZVAL ( object_ptr ) ;
}
2003-12-01 20:35:46 +08:00
zend_error ( E_STRICT , " Creating default object from empty value " ) ;
2005-12-22 17:16:11 +08:00
zval_dtor ( * object_ptr ) ;
2002-03-10 21:42:37 +08:00
object_init ( * object_ptr ) ;
}
}
2002-10-17 02:06:36 +08:00
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
static inline void zend_verify_arg_type ( zend_function * zf , zend_uint arg_num , zval * arg TSRMLS_DC )
{
zend_arg_info * cur_arg_info ;
2005-08-05 17:35:09 +08:00
zend_execute_data * ptr = EG ( current_execute_data ) - > prev_execute_data ;
2005-09-15 02:23:48 +08:00
char * fclass , * fsep , * fname ;
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
if ( ! zf - > common . arg_info
| | arg_num > zf - > common . num_args ) {
return ;
}
cur_arg_info = & zf - > common . arg_info [ arg_num - 1 ] ;
2005-09-15 02:23:48 +08:00
fname = zf - > common . function_name ;
fsep = zf - > common . scope ? " :: " : " " ;
fclass = zf - > common . scope ? zf - > common . scope - > name : " " ;
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
if ( cur_arg_info - > class_name ) {
if ( ! arg ) {
2005-09-15 21:10:31 +08:00
if ( ptr & & ptr - > op_array ) {
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must be an object of class %s, called in %s on line %d and defined " , arg_num , fclass , fsep , fname , cur_arg_info - > class_name , ptr - > op_array - > filename , ptr - > opline - > lineno ) ;
2005-08-05 17:35:09 +08:00
} else {
2005-09-15 21:10:31 +08:00
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must be an object of class %s " , arg_num , fclass , fsep , fname , cur_arg_info - > class_name ) ;
2005-08-05 17:35:09 +08:00
}
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
}
switch ( Z_TYPE_P ( arg ) ) {
case IS_NULL :
if ( ! cur_arg_info - > allow_null ) {
2005-09-15 21:10:31 +08:00
if ( ptr & & ptr - > op_array ) {
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must not be null, called in %s on line %d and defined " , arg_num , fclass , fsep , fname , ptr - > op_array - > filename , ptr - > opline - > lineno ) ;
2005-08-05 17:35:09 +08:00
} else {
2005-09-15 21:10:31 +08:00
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must not be null " , arg_num , fclass , fsep , fname ) ;
2005-08-05 17:35:09 +08:00
}
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
}
break ;
case IS_OBJECT : {
zend_class_entry * ce = zend_fetch_class ( cur_arg_info - > class_name , cur_arg_info - > class_name_len , ZEND_FETCH_CLASS_AUTO TSRMLS_CC ) ;
if ( ! instanceof_function ( Z_OBJCE_P ( arg ) , ce TSRMLS_CC ) ) {
char * error_msg ;
if ( ce - > ce_flags & ZEND_ACC_INTERFACE ) {
error_msg = " implement interface " ;
} else {
error_msg = " be an instance of " ;
}
2005-09-15 21:10:31 +08:00
if ( ptr & & ptr - > op_array ) {
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must %s %s, called in %s on line %d and defined " , arg_num , fclass , fsep , fname , error_msg , ce - > name , ptr - > op_array - > filename , ptr - > opline - > lineno ) ;
2005-08-05 17:35:09 +08:00
} else {
2005-09-15 21:10:31 +08:00
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must %s %s " , arg_num , fclass , fsep , fname , error_msg , ce - > name ) ;
2005-08-05 17:35:09 +08:00
}
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
}
}
break ;
default :
2005-09-15 21:10:31 +08:00
if ( ptr & & ptr - > op_array ) {
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must be an object of class %s, called in %s on line %d and defined " , arg_num , fclass , fsep , fname , cur_arg_info - > class_name , ptr - > op_array - > filename , ptr - > opline - > lineno ) ;
2005-08-05 17:35:09 +08:00
} else {
2005-09-15 21:10:31 +08:00
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must be an object of class %s " , arg_num , fclass , fsep , fname , cur_arg_info - > class_name ) ;
2005-08-05 17:35:09 +08:00
}
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
break ;
}
2005-09-15 21:10:31 +08:00
} else if ( cur_arg_info - > array_type_hint ) {
2005-05-26 21:46:17 +08:00
if ( ! arg ) {
2005-08-05 17:35:09 +08:00
if ( ptr & & ptr - > op_array ) {
2005-09-15 21:10:31 +08:00
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must be an array, called in %s on line %d and defined " , arg_num , fclass , fsep , fname , ptr - > op_array - > filename , ptr - > opline - > lineno ) ;
2005-08-05 17:35:09 +08:00
} else {
2005-09-15 21:10:31 +08:00
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must be an array " , arg_num , fclass , fsep , fname ) ;
2005-08-05 17:35:09 +08:00
}
2005-05-26 21:46:17 +08:00
}
switch ( Z_TYPE_P ( arg ) ) {
case IS_NULL :
if ( ! cur_arg_info - > allow_null ) {
2005-09-15 21:10:31 +08:00
if ( ptr & & ptr - > op_array ) {
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must not be null, called in %s on line %d and defined " , arg_num , fclass , fsep , fname , ptr - > op_array - > filename , ptr - > opline - > lineno ) ;
2005-08-05 17:35:09 +08:00
} else {
2005-09-15 21:10:31 +08:00
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must not be null " , arg_num , fclass , fsep , fname ) ;
2005-08-05 17:35:09 +08:00
}
2005-05-26 21:46:17 +08:00
}
break ;
case IS_ARRAY :
break ;
default :
2005-09-15 21:10:31 +08:00
if ( ptr & & ptr - > op_array ) {
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must be an array, called in %s on line %d and defined " , arg_num , fclass , fsep , fname , ptr - > op_array - > filename , ptr - > opline - > lineno ) ;
2005-08-05 17:35:09 +08:00
} else {
2005-09-15 21:10:31 +08:00
zend_error_noreturn ( E_ERROR , " Argument %d passed to %s%s%s() must be an array " , arg_num , fclass , fsep , fname ) ;
2005-08-05 17:35:09 +08:00
}
2005-05-26 21:46:17 +08:00
break ;
}
}
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
}
2004-09-24 05:43:32 +08:00
2003-07-07 17:00:36 +08:00
static inline void zend_assign_to_object ( znode * result , zval * * object_ptr , znode * op2 , znode * value_op , temp_variable * Ts , int opcode TSRMLS_DC )
2002-03-10 21:42:37 +08:00
{
zval * object ;
2004-08-20 04:03:06 +08:00
zend_free_op free_op2 , free_value ;
zval * property_name = get_zval_ptr ( op2 , Ts , & free_op2 , BP_VAR_R ) ;
2003-01-27 23:13:01 +08:00
zval * value = get_zval_ptr ( value_op , Ts , & free_value , BP_VAR_R ) ;
2002-10-24 04:26:28 +08:00
zval * * retval = & T ( result - > u . var ) . var . ptr ;
2002-03-10 21:42:37 +08:00
2006-01-19 15:23:32 +08:00
if ( * object_ptr = = EG ( error_zval_ptr ) ) {
FREE_OP ( free_op2 ) ;
if ( ! RETURN_VALUE_UNUSED ( result ) ) {
* retval = EG ( uninitialized_zval_ptr ) ;
PZVAL_LOCK ( * retval ) ;
}
FREE_OP ( free_value ) ;
return ;
}
2002-10-17 02:06:36 +08:00
make_real_object ( object_ptr TSRMLS_CC ) ; /* this should modify object only if it's empty */
2002-03-10 21:42:37 +08:00
object = * object_ptr ;
2005-12-26 16:18:38 +08:00
if ( object - > type ! = IS_OBJECT | | ( opcode = = ZEND_ASSIGN_OBJ & & ! Z_OBJ_HT_P ( object ) - > write_property ) ) {
2002-03-10 21:42:37 +08:00
zend_error ( E_WARNING , " Attempt to assign property of non-object " ) ;
2004-08-20 04:03:06 +08:00
FREE_OP ( free_op2 ) ;
if ( ! RETURN_VALUE_UNUSED ( result ) ) {
* retval = EG ( uninitialized_zval_ptr ) ;
PZVAL_LOCK ( * retval ) ;
}
2004-10-22 09:55:39 +08:00
FREE_OP ( free_value ) ;
2002-03-10 21:42:37 +08:00
return ;
}
/* here we are sure we are dealing with an object */
2003-01-29 16:55:12 +08:00
/* separate our value if necessary */
2004-03-24 18:55:04 +08:00
if ( EG ( ze1_compatibility_mode ) & & Z_TYPE_P ( value ) = = IS_OBJECT ) {
zval * orig_value = value ;
2005-06-28 18:49:56 +08:00
char * class_name ;
zend_uint class_name_len ;
int dup ;
2004-03-24 18:55:04 +08:00
ALLOC_ZVAL ( value ) ;
* value = * orig_value ;
value - > is_ref = 0 ;
value - > refcount = 0 ;
2005-06-28 18:49:56 +08:00
dup = zend_get_object_classname ( orig_value , & class_name , & class_name_len TSRMLS_CC ) ;
2004-03-28 22:57:29 +08:00
if ( Z_OBJ_HANDLER_P ( value , clone_obj ) = = NULL ) {
2005-06-28 18:49:56 +08:00
zend_error_noreturn ( E_ERROR , " Trying to clone an uncloneable object of class %s " , class_name ) ;
2004-03-24 18:55:04 +08:00
}
2005-06-28 18:49:56 +08:00
zend_error ( E_STRICT , " Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode' " , class_name ) ;
2004-03-28 22:57:29 +08:00
value - > value . obj = Z_OBJ_HANDLER_P ( orig_value , clone_obj ) ( orig_value TSRMLS_CC ) ;
2005-06-29 16:44:01 +08:00
if ( ! dup ) {
2005-06-28 20:42:56 +08:00
efree ( class_name ) ;
}
2004-03-24 18:55:04 +08:00
} else if ( value_op - > op_type = = IS_TMP_VAR ) {
2003-01-29 16:55:12 +08:00
zval * orig_value = value ;
ALLOC_ZVAL ( value ) ;
* value = * orig_value ;
value - > is_ref = 0 ;
value - > refcount = 0 ;
2004-02-12 03:12:16 +08:00
} else if ( value_op - > op_type = = IS_CONST ) {
zval * orig_value = value ;
ALLOC_ZVAL ( value ) ;
* value = * orig_value ;
value - > is_ref = 0 ;
value - > refcount = 0 ;
zval_copy_ctor ( value ) ;
2003-01-29 16:55:12 +08:00
}
2004-03-24 18:55:04 +08:00
2004-02-12 03:12:16 +08:00
value - > refcount + + ;
2003-07-07 17:00:36 +08:00
if ( opcode = = ZEND_ASSIGN_OBJ ) {
2005-06-03 19:16:19 +08:00
if ( IS_TMP_FREE ( free_op2 ) ) {
MAKE_REAL_ZVAL_PTR ( property_name ) ;
2004-02-11 23:56:13 +08:00
}
Z_OBJ_HT_P ( object ) - > write_property ( object , property_name , value TSRMLS_CC ) ;
2003-07-07 17:00:36 +08:00
} else {
2004-02-11 23:56:13 +08:00
/* Note: property_name in this case is really the array index! */
2003-07-31 01:12:06 +08:00
if ( ! Z_OBJ_HT_P ( object ) - > write_dimension ) {
2004-09-24 05:43:32 +08:00
zend_error_noreturn ( E_ERROR , " Cannot use object as array " ) ;
2003-07-31 01:12:06 +08:00
}
2005-06-03 19:16:19 +08:00
if ( IS_TMP_FREE ( free_op2 ) ) {
MAKE_REAL_ZVAL_PTR ( property_name ) ;
}
2004-02-11 23:56:13 +08:00
Z_OBJ_HT_P ( object ) - > write_dimension ( object , property_name , value TSRMLS_CC ) ;
2002-03-10 21:42:37 +08:00
}
2004-08-20 04:03:06 +08:00
if ( result & & ! RETURN_VALUE_UNUSED ( result ) ) {
2002-10-24 04:26:28 +08:00
T ( result - > u . var ) . var . ptr = value ;
2004-04-29 17:47:29 +08:00
T ( result - > u . var ) . var . ptr_ptr = & T ( result - > u . var ) . var . ptr ; /* this is so that we could use it in FETCH_DIM_R, etc. - see bug #27876 */
2004-08-20 04:03:06 +08:00
PZVAL_LOCK ( value ) ;
2002-03-10 21:42:37 +08:00
}
2005-06-03 19:16:19 +08:00
if ( IS_TMP_FREE ( free_op2 ) ) {
zval_ptr_dtor ( & property_name ) ;
} else {
FREE_OP ( free_op2 ) ;
}
2004-03-18 22:03:58 +08:00
zval_ptr_dtor ( & value ) ;
2004-09-24 05:43:32 +08:00
FREE_OP_IF_VAR ( free_value ) ;
2002-03-10 21:42:37 +08:00
}
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
{
2004-08-20 04:03:06 +08:00
zend_free_op free_op1 ;
zval * * variable_ptr_ptr = get_zval_ptr_ptr ( op1 , Ts , & free_op1 , BP_VAR_W ) ;
1999-04-08 02:10:10 +08:00
zval * variable_ptr ;
1999-10-02 07:26:00 +08:00
1999-04-08 02:10:10 +08:00
if ( ! variable_ptr_ptr ) {
2003-12-14 20:32:02 +08:00
temp_variable * T = & T ( op1 - > u . var ) ;
1999-04-08 02:10:10 +08:00
2004-01-19 20:22:02 +08:00
if ( T - > str_offset . str - > type = = IS_STRING ) do {
2003-12-14 20:32:02 +08:00
zval tmp ;
zval * final_value = value ;
1999-04-08 02:10:10 +08:00
2004-01-19 20:22:02 +08:00
if ( ( ( int ) T - > str_offset . offset < 0 ) ) {
zend_error ( E_WARNING , " Illegal string offset: %d " , T - > str_offset . offset ) ;
2003-12-14 20:32:02 +08:00
break ;
}
2006-02-26 18:57:00 +08:00
if ( ( int ) T - > str_offset . offset > = T - > str_offset . str - > value . str . len ) {
2003-12-14 20:32:02 +08:00
zend_uint i ;
2001-06-27 23:40:49 +08:00
2004-01-19 20:22:02 +08:00
if ( T - > str_offset . str - > value . str . len = = 0 ) {
STR_FREE ( T - > str_offset . str - > value . str . val ) ;
T - > str_offset . str - > value . str . val = ( char * ) emalloc ( T - > str_offset . offset + 1 + 1 ) ;
2003-12-14 20:32:02 +08:00
} else {
2004-01-19 20:22:02 +08:00
T - > str_offset . str - > value . str . val = ( char * ) erealloc ( T - > str_offset . str - > value . str . val , T - > str_offset . offset + 1 + 1 ) ;
2003-12-14 20:32:02 +08:00
}
2004-01-19 20:22:02 +08:00
for ( i = T - > str_offset . str - > value . str . len ; i < T - > str_offset . offset ; i + + ) {
T - > str_offset . str - > value . str . val [ i ] = ' ' ;
2003-12-14 20:32:02 +08:00
}
2004-01-19 20:22:02 +08:00
T - > str_offset . str - > value . str . val [ T - > str_offset . offset + 1 ] = 0 ;
T - > str_offset . str - > value . str . len = T - > str_offset . offset + 1 ;
2003-12-14 20:32:02 +08:00
}
1999-04-08 02:10:10 +08:00
2003-12-14 20:32:02 +08:00
if ( value - > type ! = IS_STRING ) {
tmp = * value ;
2004-10-05 03:54:35 +08:00
if ( op2 - > op_type & ( IS_VAR | IS_CV ) ) {
2003-12-14 20:32:02 +08:00
zval_copy_ctor ( & tmp ) ;
}
convert_to_string ( & tmp ) ;
final_value = & tmp ;
}
2004-01-19 20:22:02 +08:00
T - > str_offset . str - > value . str . val [ T - > str_offset . offset ] = final_value - > value . str . val [ 0 ] ;
2003-12-14 20:32:02 +08:00
2004-09-24 05:43:32 +08:00
if ( op2 - > op_type = = IS_TMP_VAR ) {
if ( final_value = = & T ( op2 - > u . var ) . tmp_var ) {
/* we can safely free final_value here
* because separation is done only
* in case op2 - > op_type = = IS_VAR */
STR_FREE ( final_value - > value . str . val ) ;
2004-09-09 06:14:12 +08:00
}
2003-12-14 20:32:02 +08:00
}
if ( final_value = = & tmp ) {
zval_dtor ( final_value ) ;
}
/*
* the value of an assignment to a string offset is undefined
2004-01-19 20:22:02 +08:00
T ( result - > u . var ) . var = & T - > str_offset . str ;
2003-12-14 20:32:02 +08:00
*/
} while ( 0 ) ;
2004-01-19 20:22:02 +08:00
/* zval_ptr_dtor(&T->str_offset.str); Nuke this line if it doesn't cause a leak */
2003-12-14 20:32:02 +08:00
2003-06-16 23:41:02 +08:00
/* T(result->u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); */
2004-08-20 04:03:06 +08:00
if ( ! RETURN_VALUE_UNUSED ( result ) ) {
T ( result - > u . var ) . var . ptr_ptr = & value ;
PZVAL_LOCK ( * T ( result - > u . var ) . var . ptr_ptr ) ;
AI_USE_PTR ( T ( result - > u . var ) . var ) ;
}
FREE_OP_VAR_PTR ( free_op1 ) ;
1999-04-08 02:10:10 +08:00
return ;
}
variable_ptr = * variable_ptr_ptr ;
if ( variable_ptr = = EG ( error_zval_ptr ) ) {
2004-08-20 04:03:06 +08:00
if ( result & & ! RETURN_VALUE_UNUSED ( result ) ) {
2002-10-24 04:26:28 +08:00
T ( result - > u . var ) . var . ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
2004-08-20 04:03:06 +08:00
PZVAL_LOCK ( * T ( result - > u . var ) . var . ptr_ptr ) ;
2002-10-24 04:26:28 +08:00
AI_USE_PTR ( T ( 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 ) ;
}
2004-08-20 04:03:06 +08:00
FREE_OP_VAR_PTR ( free_op1 ) ;
1999-04-08 02:10:10 +08:00
return ;
}
2004-03-25 21:03:04 +08:00
2004-03-28 22:57:29 +08:00
if ( Z_TYPE_P ( variable_ptr ) = = IS_OBJECT & & Z_OBJ_HANDLER_P ( variable_ptr , set ) ) {
/* TODO? ze1_compatibility_mode support */
Z_OBJ_HANDLER_P ( variable_ptr , set ) ( variable_ptr_ptr , value TSRMLS_CC ) ;
goto done_setting_var ;
}
2004-03-24 18:55:04 +08:00
if ( EG ( ze1_compatibility_mode ) & & Z_TYPE_P ( value ) = = IS_OBJECT ) {
2005-06-28 18:49:56 +08:00
char * class_name ;
zend_uint class_name_len ;
int dup ;
dup = zend_get_object_classname ( value , & class_name , & class_name_len TSRMLS_CC ) ;
2004-03-28 22:57:29 +08:00
if ( Z_OBJ_HANDLER_P ( value , clone_obj ) = = NULL ) {
2005-06-28 18:49:56 +08:00
zend_error_noreturn ( E_ERROR , " Trying to clone an uncloneable object of class %s " , class_name ) ;
2004-03-24 18:55:04 +08:00
} else if ( PZVAL_IS_REF ( variable_ptr ) ) {
2005-04-29 15:03:54 +08:00
if ( variable_ptr ! = value ) {
2004-03-24 18:55:04 +08:00
zend_uint refcount = variable_ptr - > refcount ;
zval garbage ;
if ( type ! = IS_TMP_VAR ) {
value - > refcount + + ;
}
garbage = * variable_ptr ;
* variable_ptr = * value ;
variable_ptr - > refcount = refcount ;
variable_ptr - > is_ref = 1 ;
2005-06-28 18:49:56 +08:00
zend_error ( E_STRICT , " Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode' " , class_name ) ;
2004-03-28 22:57:29 +08:00
variable_ptr - > value . obj = Z_OBJ_HANDLER_P ( value , clone_obj ) ( value TSRMLS_CC ) ;
2004-03-24 18:55:04 +08:00
if ( type ! = IS_TMP_VAR ) {
value - > refcount - - ;
}
zendi_zval_dtor ( garbage ) ;
}
} else {
2005-04-29 15:03:54 +08:00
if ( variable_ptr ! = value ) {
value - > refcount + + ;
variable_ptr - > refcount - - ;
if ( variable_ptr - > refcount = = 0 ) {
zendi_zval_dtor ( * variable_ptr ) ;
} else {
ALLOC_ZVAL ( variable_ptr ) ;
* variable_ptr_ptr = variable_ptr ;
}
* variable_ptr = * value ;
INIT_PZVAL ( variable_ptr ) ;
2005-06-28 18:49:56 +08:00
zend_error ( E_STRICT , " Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode' " , class_name ) ;
2005-04-29 15:03:54 +08:00
variable_ptr - > value . obj = Z_OBJ_HANDLER_P ( value , clone_obj ) ( value TSRMLS_CC ) ;
zval_ptr_dtor ( & value ) ;
2004-03-24 18:55:04 +08:00
}
}
2005-06-29 16:44:01 +08:00
if ( ! dup ) {
2005-06-28 18:49:56 +08:00
efree ( class_name ) ;
}
2004-03-24 18:55:04 +08:00
} else if ( PZVAL_IS_REF ( variable_ptr ) ) {
1999-04-08 02:10:10 +08:00
if ( variable_ptr ! = value ) {
2002-04-24 02:06:54 +08:00
zend_uint refcount = variable_ptr - > refcount ;
2000-02-09 04:10:47 +08:00
zval garbage ;
2004-03-25 21:03:04 +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 ) {
2004-10-05 03:54:35 +08:00
case IS_CV :
1999-04-08 02:10:10 +08:00
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 ;
2004-03-25 21:03:04 +08:00
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 ;
2004-03-25 21:03:04 +08:00
EMPTY_SWITCH_DEFAULT_CASE ( )
}
1999-04-08 02:10:10 +08:00
} else { /* we need to split */
switch ( type ) {
2004-10-05 03:54:35 +08:00
case IS_CV :
1999-04-08 02:10:10 +08:00
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 ;
2004-03-25 21:03:04 +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
}
2004-03-28 22:57:29 +08:00
done_setting_var :
2004-08-20 04:03:06 +08:00
if ( result & & ! RETURN_VALUE_UNUSED ( result ) ) {
2002-10-24 04:26:28 +08:00
T ( result - > u . var ) . var . ptr_ptr = variable_ptr_ptr ;
2004-08-20 04:03:06 +08:00
PZVAL_LOCK ( * variable_ptr_ptr ) ;
2002-10-24 04:26:28 +08:00
AI_USE_PTR ( T ( result - > u . var ) . var ) ;
1999-07-10 04:43:59 +08:00
}
2004-08-20 04:03:06 +08:00
FREE_OP_VAR_PTR ( free_op1 ) ;
1999-04-08 02:10:10 +08:00
}
2004-09-24 05:43:32 +08:00
static inline void zend_receive ( zval * * variable_ptr_ptr , zval * value TSRMLS_DC )
{
zval * variable_ptr = * variable_ptr_ptr ;
if ( EG ( ze1_compatibility_mode ) & & Z_TYPE_P ( value ) = = IS_OBJECT ) {
2005-06-28 18:49:56 +08:00
char * class_name ;
zend_uint class_name_len ;
int dup ;
dup = zend_get_object_classname ( value , & class_name , & class_name_len TSRMLS_CC ) ;
if ( Z_OBJ_HANDLER_P ( value , clone_obj ) = = NULL ) {
zend_error_noreturn ( E_ERROR , " Trying to clone an uncloneable object of class %s " , class_name ) ;
2004-09-24 05:43:32 +08:00
} else {
variable_ptr - > refcount - - ;
ALLOC_ZVAL ( variable_ptr ) ;
* variable_ptr_ptr = variable_ptr ;
* variable_ptr = * value ;
INIT_PZVAL ( variable_ptr ) ;
2005-06-28 18:49:56 +08:00
zend_error ( E_STRICT , " Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode' " , class_name ) ;
2004-09-24 05:43:32 +08:00
variable_ptr - > value . obj = Z_OBJ_HANDLER_P ( value , clone_obj ) ( value TSRMLS_CC ) ;
}
2005-06-29 16:44:01 +08:00
if ( ! dup ) {
2005-06-28 18:49:56 +08:00
efree ( class_name ) ;
}
2004-09-24 05:43:32 +08:00
} else {
variable_ptr - > refcount - - ;
* variable_ptr_ptr = value ;
value - > refcount + + ;
}
}
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 ) ;
}
}
2002-10-17 02:29:41 +08:00
static inline HashTable * zend_get_target_symbol_table ( zend_op * opline , temp_variable * Ts , int type , zval * variable TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2002-01-06 03:59:09 +08:00
switch ( opline - > op2 . u . EA . type ) {
1999-04-08 02:10:10 +08:00
case ZEND_FETCH_LOCAL :
2002-02-05 03:29:56 +08:00
return EG ( active_symbol_table ) ;
1999-04-08 02:10:10 +08:00
break ;
case ZEND_FETCH_GLOBAL :
2005-07-04 21:24:46 +08:00
case ZEND_FETCH_GLOBAL_LOCK :
2002-02-05 03:29:56 +08:00
return & EG ( symbol_table ) ;
1999-04-08 02:10:10 +08:00
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
}
2002-02-05 03:29:56 +08:00
return EG ( active_op_array ) - > static_variables ;
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
}
2002-02-07 22:08:43 +08:00
return NULL ;
2002-02-05 03:29:56 +08:00
}
2004-09-24 05:43:32 +08:00
static inline zval * * zend_fetch_dimension_address_inner ( HashTable * ht , zval * dim , int type TSRMLS_DC )
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 :
2003-05-23 23:11:15 +08:00
2000-01-04 01:26:24 +08:00
offset_key = dim - > value . str . val ;
offset_key_length = dim - > value . str . len ;
2003-05-23 23:11:15 +08:00
2000-01-04 01:26:24 +08:00
fetch_string_dim :
2003-07-23 00:06:07 +08:00
if ( zend_symtable_find ( ht , offset_key , offset_key_length + 1 , ( void * * ) & retval ) = = FAILURE ) {
2000-01-04 01:26:24 +08:00
switch ( type ) {
2004-02-11 21:58:29 +08:00
case BP_VAR_R :
zend_error ( E_NOTICE , " Undefined index: %s " , offset_key ) ;
2000-01-04 01:26:24 +08:00
/* break missing intentionally */
2004-02-11 21:58:29 +08:00
case BP_VAR_UNSET :
2000-01-04 01:26:24 +08:00
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 + + ;
2003-07-24 20:56:05 +08:00
zend_symtable_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-10-06 23:09:26 +08:00
case IS_RESOURCE :
2004-06-25 00:35:34 +08:00
zend_error ( E_STRICT , " Resource ID#%ld used as offset, casting to integer (%ld) " , dim - > value . lval , dim - > value . lval ) ;
2004-06-24 07:20:44 +08:00
/* Fall Through */
case IS_DOUBLE :
2000-01-19 06:18:17 +08:00
case IS_BOOL :
2003-07-23 00:06:07 +08:00
case IS_LONG : {
long index ;
1999-09-09 04:38:08 +08:00
2003-07-23 00:06:07 +08:00
if ( dim - > type = = IS_DOUBLE ) {
index = ( long ) dim - > value . dval ;
} else {
index = dim - > value . lval ;
}
if ( zend_hash_index_find ( ht , index , ( void * * ) & retval ) = = FAILURE ) {
switch ( type ) {
2004-02-11 21:58:29 +08:00
case BP_VAR_R :
2003-08-29 00:41:20 +08:00
zend_error ( E_NOTICE , " Undefined offset: %ld " , index ) ;
2003-07-23 00:06:07 +08:00
/* break missing intentionally */
2004-02-11 21:58:29 +08:00
case BP_VAR_UNSET :
2003-07-23 00:06:07 +08:00
case BP_VAR_IS :
retval = & EG ( uninitialized_zval_ptr ) ;
break ;
case BP_VAR_RW :
2003-08-29 00:41:20 +08:00
zend_error ( E_NOTICE , " Undefined offset: %ld " , index ) ;
2003-07-23 00:06:07 +08:00
/* break missing intentionally */
case BP_VAR_W : {
zval * new_zval = & EG ( uninitialized_zval ) ;
new_zval - > refcount + + ;
zend_hash_index_update ( ht , index , & new_zval , sizeof ( zval * ) , ( void * * ) & retval ) ;
}
break ;
1999-04-08 02:10:10 +08:00
}
}
}
break ;
default :
zend_error ( E_WARNING , " Illegal offset type " ) ;
2004-02-11 21:58:29 +08:00
switch ( type ) {
case BP_VAR_R :
case BP_VAR_IS :
case BP_VAR_UNSET :
retval = & EG ( uninitialized_zval_ptr ) ;
break ;
default :
retval = & EG ( error_zval_ptr ) ;
break ;
1999-04-08 02:10:10 +08:00
}
break ;
}
return retval ;
}
2005-06-03 19:16:19 +08:00
static void zend_fetch_dimension_address ( temp_variable * result , zval * * container_ptr , zval * dim , int dim_is_tmp_var , int type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zval * container ;
2002-11-13 23:13:24 +08:00
if ( ! container_ptr ) {
2004-09-24 05:43:32 +08:00
zend_error_noreturn ( E_ERROR , " Cannot use string offset as an array " ) ;
2002-11-13 23:13:24 +08:00
}
1999-04-08 02:10:10 +08:00
container = * container_ptr ;
if ( container = = EG ( error_zval_ptr ) ) {
2004-09-24 05:43:32 +08:00
if ( result ) {
result - > var . ptr_ptr = & EG ( error_zval_ptr ) ;
PZVAL_LOCK ( * result - > var . ptr_ptr ) ;
2004-08-20 04:03:06 +08:00
if ( type = = BP_VAR_R | | type = = BP_VAR_IS ) {
2004-09-24 05:43:32 +08:00
AI_USE_PTR ( result - > var ) ;
2004-08-20 04:03:06 +08:00
}
}
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
}
2005-09-13 01:44:21 +08:00
zval_dtor ( container ) ;
1999-04-08 02:10:10 +08:00
array_init ( container ) ;
break ;
}
}
switch ( container - > type ) {
2004-09-24 05:43:32 +08:00
zval * * retval ;
1999-04-08 02:10:10 +08:00
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 ;
}
2004-09-24 05:43:32 +08:00
if ( dim = = NULL ) {
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 + + ;
2004-09-24 05:43:32 +08:00
if ( zend_hash_next_index_insert ( container - > value . ht , & new_zval , sizeof ( zval * ) , ( void * * ) & retval ) = = FAILURE ) {
2002-11-12 02:27:32 +08:00
zend_error ( E_WARNING , " Cannot add element to the array as the next element is already occupied " ) ;
2005-06-07 18:21:52 +08:00
retval = & EG ( error_zval_ptr ) ;
2002-08-02 00:07:19 +08:00
new_zval - > refcount - - ;
}
1999-04-08 02:10:10 +08:00
} else {
2004-09-24 05:43:32 +08:00
retval = zend_fetch_dimension_address_inner ( container - > value . ht , dim , type TSRMLS_CC ) ;
}
if ( result ) {
result - > var . ptr_ptr = retval ;
PZVAL_LOCK ( * result - > var . ptr_ptr ) ;
1999-04-08 02:10:10 +08:00
}
break ;
2004-08-20 04:03:06 +08:00
case IS_NULL : {
1999-12-31 21:56:59 +08:00
/* for read-mode only */
2004-09-24 05:43:32 +08:00
if ( result ) {
result - > var . ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
PZVAL_LOCK ( * result - > var . ptr_ptr ) ;
}
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 ;
2004-08-20 04:03:06 +08:00
}
1999-04-08 02:10:10 +08:00
case IS_STRING : {
1999-12-31 21:56:59 +08:00
zval tmp ;
1999-04-08 02:10:10 +08:00
2004-09-24 05:43:32 +08:00
if ( dim = = NULL ) {
zend_error_noreturn ( E_ERROR , " [] operator not supported for strings " ) ;
2000-01-04 04:01:54 +08:00
}
2005-01-14 17:01:22 +08:00
if ( dim - > type ! = IS_LONG ) {
2004-09-24 05:43:32 +08:00
tmp = * dim ;
1999-12-31 21:56:59 +08:00
zval_copy_ctor ( & tmp ) ;
convert_to_long ( & tmp ) ;
2004-09-24 05:43:32 +08:00
dim = & tmp ;
1999-12-31 21:56:59 +08:00
}
2004-02-11 21:58:29 +08:00
switch ( type ) {
case BP_VAR_R :
case BP_VAR_IS :
case BP_VAR_UNSET :
/* do nothing... */
break ;
default :
SEPARATE_ZVAL_IF_NOT_REF ( container_ptr ) ;
break ;
1999-04-08 02:10:10 +08:00
}
2004-09-24 05:43:32 +08:00
if ( result ) {
container = * container_ptr ;
result - > str_offset . str = container ;
PZVAL_LOCK ( container ) ;
result - > str_offset . offset = dim - > value . lval ;
result - > var . ptr_ptr = NULL ;
if ( type = = BP_VAR_R | | type = = BP_VAR_IS ) {
AI_USE_PTR ( result - > var ) ;
}
2004-08-20 04:03:06 +08:00
}
1999-12-31 21:56:59 +08:00
return ;
1999-04-08 02:10:10 +08:00
}
break ;
2003-07-07 18:53:27 +08:00
case IS_OBJECT :
2004-02-09 01:23:20 +08:00
if ( ! Z_OBJ_HT_P ( container ) - > read_dimension ) {
2004-09-24 05:43:32 +08:00
zend_error_noreturn ( E_ERROR , " Cannot use object as array " ) ;
2004-02-09 01:23:20 +08:00
} else {
2005-06-03 19:16:19 +08:00
zval * overloaded_result ;
if ( dim_is_tmp_var ) {
zval * orig = dim ;
MAKE_REAL_ZVAL_PTR ( dim ) ;
ZVAL_NULL ( orig ) ;
}
overloaded_result = Z_OBJ_HT_P ( container ) - > read_dimension ( container , dim , type TSRMLS_CC ) ;
2003-11-25 04:57:54 +08:00
2004-02-09 01:23:20 +08:00
if ( overloaded_result ) {
2004-02-11 23:50:23 +08:00
switch ( type ) {
case BP_VAR_RW :
case BP_VAR_W :
if ( overloaded_result - > type ! = IS_OBJECT
& & ! overloaded_result - > is_ref ) {
2004-09-24 05:43:32 +08:00
zend_error_noreturn ( E_ERROR , " Objects used as arrays in post/pre increment/decrement must return values by reference " ) ;
2004-02-11 23:50:23 +08:00
}
break ;
2003-12-11 17:52:33 +08:00
}
2004-02-09 01:23:20 +08:00
2004-09-24 05:43:32 +08:00
retval = & overloaded_result ;
2004-02-09 01:23:20 +08:00
} else {
2004-09-24 05:43:32 +08:00
retval = & EG ( error_zval_ptr ) ;
2003-07-31 01:12:06 +08:00
}
2004-09-24 05:43:32 +08:00
if ( result ) {
result - > var . ptr_ptr = retval ;
AI_USE_PTR ( result - > var ) ;
PZVAL_LOCK ( * result - > var . ptr_ptr ) ;
2005-07-19 15:33:00 +08:00
} else if ( ( * retval ) - > refcount = = 0 ) {
/* Destroy unused result from offsetGet() magic method */
( * retval ) - > refcount = 1 ;
zval_ptr_dtor ( retval ) ;
2004-09-24 05:43:32 +08:00
}
2005-06-03 19:16:19 +08:00
if ( dim_is_tmp_var ) {
zval_ptr_dtor ( & dim ) ;
}
2004-09-24 05:43:32 +08:00
return ;
2003-07-07 18:53:27 +08:00
}
break ;
2004-09-24 05:43:32 +08:00
default : {
2004-02-11 21:58:29 +08:00
switch ( type ) {
case BP_VAR_UNSET :
zend_error ( E_WARNING , " Cannot unset offset in a non-array variable " ) ;
/* break missing intentionally */
case BP_VAR_R :
case BP_VAR_IS :
2004-09-24 05:43:32 +08:00
retval = & EG ( uninitialized_zval_ptr ) ;
2004-02-11 21:58:29 +08:00
break ;
default :
2004-09-24 05:43:32 +08:00
retval = & EG ( error_zval_ptr ) ;
2004-02-11 21:58:29 +08:00
break ;
1999-04-08 02:10:10 +08:00
}
2004-09-24 05:43:32 +08:00
if ( result ) {
result - > var . ptr_ptr = retval ;
PZVAL_LOCK ( * result - > var . ptr_ptr ) ;
}
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 ;
}
2004-09-24 05:43:32 +08:00
if ( result & & ( type = = BP_VAR_R | | type = = BP_VAR_IS ) ) {
AI_USE_PTR ( result - > var ) ;
1999-04-08 02:10:10 +08:00
}
}
2005-06-03 19:16:19 +08:00
static void zend_fetch_property_address ( temp_variable * result , zval * * container_ptr , zval * prop_ptr , int type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zval * container ;
2002-02-07 22:08:43 +08:00
1999-04-08 02:10:10 +08:00
container = * container_ptr ;
if ( container = = EG ( error_zval_ptr ) ) {
2004-09-24 05:43:32 +08:00
if ( result ) {
result - > var . ptr_ptr = & EG ( error_zval_ptr ) ;
PZVAL_LOCK ( * result - > var . ptr_ptr ) ;
2004-08-20 04:03:06 +08:00
}
1999-04-08 02:10:10 +08:00
return ;
}
2002-10-17 02:06:36 +08:00
/* this should modify object only if it's empty */
2002-02-07 22:08:43 +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 ;
}
}
2002-02-07 22:08:43 +08:00
1999-04-08 02:10:10 +08:00
if ( container - > type ! = IS_OBJECT ) {
2004-09-24 05:43:32 +08:00
if ( result ) {
2004-08-20 04:03:06 +08:00
if ( type = = BP_VAR_R | | type = = BP_VAR_IS ) {
2004-09-24 05:43:32 +08:00
result - > var . ptr_ptr = & EG ( uninitialized_zval_ptr ) ;
2004-08-20 04:03:06 +08:00
} else {
2004-09-24 05:43:32 +08:00
result - > var . ptr_ptr = & EG ( error_zval_ptr ) ;
2004-08-20 04:03:06 +08:00
}
2004-09-24 05:43:32 +08:00
PZVAL_LOCK ( * result - > var . ptr_ptr ) ;
1999-04-08 02:10:10 +08:00
}
1999-10-03 02:02:10 +08:00
return ;
1999-04-08 02:10:10 +08:00
}
2004-09-24 05:43:32 +08:00
if ( Z_OBJ_HT_P ( container ) - > get_property_ptr_ptr ) {
zval * * ptr_ptr = Z_OBJ_HT_P ( container ) - > get_property_ptr_ptr ( container , prop_ptr TSRMLS_CC ) ;
if ( NULL = = ptr_ptr ) {
2005-01-18 17:05:39 +08:00
zval * ptr ;
if ( Z_OBJ_HT_P ( container ) - > read_property & &
( ptr = Z_OBJ_HT_P ( container ) - > read_property ( container , prop_ptr , BP_VAR_W TSRMLS_CC ) ) ! = NULL ) {
if ( result ) {
result - > var . ptr = ptr ;
result - > var . ptr_ptr = & result - > var . ptr ;
}
} else {
zend_error ( E_ERROR , " Cannot access undefined property for object with overloaded property access " ) ;
}
} else if ( result ) {
2004-09-24 05:43:32 +08:00
result - > var . ptr_ptr = ptr_ptr ;
2002-02-07 22:08:43 +08:00
}
2004-09-24 05:43:32 +08:00
} else if ( Z_OBJ_HT_P ( container ) - > read_property ) {
if ( result ) {
result - > var . ptr = Z_OBJ_HT_P ( container ) - > read_property ( container , prop_ptr , BP_VAR_W TSRMLS_CC ) ;
result - > var . ptr_ptr = & result - > var . ptr ;
2002-02-07 22:08:43 +08:00
}
2004-09-24 05:43:32 +08:00
} else {
zend_error ( E_WARNING , " This object doesn't support property references " ) ;
if ( result ) {
result - > var . ptr_ptr = & EG ( error_zval_ptr ) ;
2004-02-12 00:28:46 +08:00
}
2001-05-03 03:51:33 +08:00
}
2002-02-07 22:08:43 +08:00
2004-09-24 05:43:32 +08:00
if ( result ) {
PZVAL_LOCK ( * result - > var . ptr_ptr ) ;
}
1999-04-08 02:10:10 +08:00
}
2004-09-24 05:43:32 +08:00
static inline zend_brk_cont_element * zend_brk_cont ( zval * nest_levels_zval , int array_offset , zend_op_array * op_array , temp_variable * Ts TSRMLS_DC )
2002-03-10 21:42:37 +08:00
{
2004-09-24 05:43:32 +08:00
zval tmp ;
int nest_levels , original_nest_levels ;
zend_brk_cont_element * jmp_to ;
2002-03-10 21:42:37 +08:00
2004-09-24 05:43:32 +08:00
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 ;
2004-09-10 00:47:22 +08:00
}
2004-09-24 05:43:32 +08:00
original_nest_levels = nest_levels ;
do {
if ( array_offset = = - 1 ) {
zend_error_noreturn ( E_ERROR , " Cannot break/continue %d level%s " , original_nest_levels , ( original_nest_levels = = 1 ) ? " " : " s " ) ;
2004-09-10 00:47:22 +08:00
}
2004-09-24 05:43:32 +08:00
jmp_to = & op_array - > brk_cont_array [ array_offset ] ;
if ( nest_levels > 1 ) {
zend_op * brk_opline = & op_array - > opcodes [ jmp_to - > brk ] ;
2004-09-10 00:47:22 +08:00
2004-09-24 05:43:32 +08:00
switch ( brk_opline - > opcode ) {
case ZEND_SWITCH_FREE :
zend_switch_free ( brk_opline , Ts TSRMLS_CC ) ;
break ;
case ZEND_FREE :
zendi_zval_dtor ( T ( brk_opline - > op1 . u . var ) . tmp_var ) ;
break ;
2004-09-10 00:47:22 +08:00
}
}
2004-09-24 05:43:32 +08:00
array_offset = jmp_to - > parent ;
} while ( - - nest_levels > 0 ) ;
return jmp_to ;
2002-03-10 21:42:37 +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 ) {
2002-02-07 22:08:43 +08:00
/* OBJ-TBI - doesn't support new object model! */
2001-08-06 10:52:03 +08:00
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
2004-09-24 05:43:32 +08:00
ZEND_API opcode_handler_t * zend_opcode_handlers ;
2001-08-30 23:26:30 +08:00
2003-01-12 00:12:44 +08:00
ZEND_API void execute_internal ( zend_execute_data * execute_data_ptr , int return_value_used TSRMLS_DC )
{
2005-06-16 22:56:13 +08:00
zval * * return_value_ptr = & ( * ( temp_variable * ) ( ( char * ) execute_data_ptr - > Ts + execute_data_ptr - > opline - > result . u . var ) ) . var . ptr ;
( ( zend_internal_function * ) execute_data_ptr - > function_state . function ) - > handler ( execute_data_ptr - > opline - > extended_value , * return_value_ptr , execute_data_ptr - > function_state . function - > common . return_reference ? return_value_ptr : NULL , execute_data_ptr - > object , return_value_used TSRMLS_CC ) ;
2003-01-12 00:12:44 +08:00
}
2004-10-23 05:42:14 +08:00
# define ZEND_VM_NEXT_OPCODE() \
CHECK_SYMBOL_TABLES ( ) \
EX ( opline ) + + ; \
ZEND_VM_CONTINUE ( )
# define ZEND_VM_SET_OPCODE(new_op) \
CHECK_SYMBOL_TABLES ( ) \
EX ( opline ) = new_op
2005-11-01 03:25:14 +08:00
# define ZEND_VM_JMP(new_op) \
CHECK_SYMBOL_TABLES ( ) \
EX ( opline ) = EG ( exception ) ? EX ( opline ) + 1 : new_op ; \
ZEND_VM_CONTINUE ( )
2004-10-23 05:42:14 +08:00
# define ZEND_VM_INC_OPCODE() \
if ( ! EG ( exception ) ) { \
CHECK_SYMBOL_TABLES ( ) \
EX ( opline ) + + ; \
}
# define ZEND_VM_RETURN_FROM_EXECUTE_LOOP() \
free_alloca ( EX ( CVs ) ) ; \
if ( EX ( op_array ) - > T < TEMP_VAR_STACK_LIMIT ) { \
free_alloca ( EX ( Ts ) ) ; \
} else { \
efree ( EX ( Ts ) ) ; \
} \
EG ( in_execution ) = EX ( original_in_execution ) ; \
EG ( current_execute_data ) = EX ( prev_execute_data ) ; \
ZEND_VM_RETURN ( )
# include "zend_vm_execute.h"
2003-02-01 09:49:15 +08:00
2005-06-10 17:54:38 +08:00
ZEND_API int zend_set_user_opcode_handler ( zend_uchar opcode , opcode_handler_t handler )
{
if ( opcode ! = ZEND_USER_OPCODE ) {
zend_user_opcodes [ opcode ] = ZEND_USER_OPCODE ;
zend_user_opcode_handlers [ opcode ] = handler ;
return SUCCESS ;
}
return FAILURE ;
}
ZEND_API opcode_handler_t zend_get_user_opcode_handler ( zend_uchar opcode )
{
return zend_user_opcode_handlers [ opcode ] ;
}
2005-06-16 22:27:08 +08:00
ZEND_API zval * zend_get_zval_ptr ( znode * node , temp_variable * Ts , zend_free_op * should_free , int type TSRMLS_DC ) {
2005-06-17 01:29:29 +08:00
return get_zval_ptr ( node , Ts , should_free , type ) ;
2005-06-16 19:50:08 +08:00
}
2005-06-16 22:27:08 +08:00
ZEND_API zval * * zend_get_zval_ptr_ptr ( znode * node , temp_variable * Ts , zend_free_op * should_free , int type TSRMLS_DC ) {
2005-06-17 01:29:29 +08:00
return get_zval_ptr_ptr ( node , Ts , should_free , type ) ;
2005-06-16 19:50:08 +08:00
}
2003-02-01 09:49:15 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/