1999-04-08 02:10:10 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-12-31 23:59:15 +08:00
| Copyright ( c ) 1998 - 2003 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 , |
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 |
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$ */
1999-07-16 22:58:16 +08:00
2000-10-29 22:35:34 +08:00
# include "zend_language_parser.h"
1999-04-08 02:10:10 +08:00
# include "zend.h"
# include "zend_compile.h"
2003-04-11 01:02:31 +08:00
# include "zend_constants.h"
1999-04-08 02:10:10 +08:00
# include "zend_llist.h"
# include "zend_API.h"
1999-12-28 03:07:33 +08:00
# include "zend_fast_cache.h"
1999-04-08 02:10:10 +08:00
2003-02-21 03:01:53 +08:00
# define IN_NAMESPACE() (CG(active_namespace) != &CG(global_namespace))
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
ZEND_API zend_op_array * ( * zend_compile_file ) ( zend_file_handle * file_handle , int type TSRMLS_DC ) ;
1999-04-08 02:10:10 +08:00
# ifndef ZTS
ZEND_API zend_compiler_globals compiler_globals ;
ZEND_API zend_executor_globals executor_globals ;
# endif
2002-09-25 03:05:53 +08:00
static void build_runtime_defined_function_key ( zval * result , char * name , int name_length , zend_op * opline TSRMLS_DC )
1999-09-03 05:06:05 +08:00
{
char lineno_buf [ 32 ] ;
uint lineno_len ;
char * filename ;
lineno_len = zend_sprintf ( lineno_buf , " %d " , opline - > lineno ) ;
2000-08-10 03:22:35 +08:00
if ( CG ( active_op_array ) - > filename ) {
filename = CG ( active_op_array ) - > filename ;
1999-09-03 05:06:05 +08:00
} else {
filename = " - " ;
}
/* NULL, name length, filename length, line number length */
2002-09-25 03:05:53 +08:00
result - > value . str . len = 1 + name_length + strlen ( filename ) + lineno_len ;
2001-07-10 13:02:50 +08:00
result - > value . str . val = ( char * ) emalloc ( result - > value . str . len + 1 ) ;
2002-09-25 03:05:53 +08:00
sprintf ( result - > value . str . val , " %c%s%s%s " , ' \0 ' , name , filename , lineno_buf ) ;
1999-09-03 05:06:05 +08:00
result - > type = IS_STRING ;
result - > refcount = 1 ;
}
2003-03-02 18:04:53 +08:00
int zend_auto_global_arm ( zend_auto_global * auto_global TSRMLS_DC )
{
auto_global - > armed = ( auto_global - > auto_global_callback ? 1 : 0 ) ;
return 0 ;
}
2001-07-28 18:51:54 +08:00
static void init_compiler_declarables ( TSRMLS_D )
2000-01-25 03:00:30 +08:00
{
CG ( declarables ) . ticks . type = IS_LONG ;
CG ( declarables ) . ticks . value . lval = 0 ;
}
2001-05-07 03:30:31 +08:00
2001-07-28 18:51:54 +08:00
void zend_init_compiler_data_structures ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
zend_stack_init ( & CG ( bp_stack ) ) ;
zend_stack_init ( & CG ( function_call_stack ) ) ;
zend_stack_init ( & CG ( switch_cond_stack ) ) ;
1999-09-09 22:15:17 +08:00
zend_stack_init ( & CG ( foreach_copy_stack ) ) ;
1999-04-08 02:10:10 +08:00
zend_stack_init ( & CG ( object_stack ) ) ;
2000-01-25 03:00:30 +08:00
zend_stack_init ( & CG ( declare_stack ) ) ;
1999-04-08 02:10:10 +08:00
CG ( active_class_entry ) = NULL ;
2003-02-16 19:12:43 +08:00
CG ( active_namespace ) = & CG ( global_namespace ) ;
1999-04-08 02:10:10 +08:00
zend_llist_init ( & CG ( list_llist ) , sizeof ( list_llist_element ) , NULL , 0 ) ;
zend_llist_init ( & CG ( dimension_llist ) , sizeof ( int ) , NULL , 0 ) ;
2001-07-16 23:48:31 +08:00
zend_stack_init ( & CG ( list_stack ) ) ;
1999-04-08 02:10:10 +08:00
CG ( handle_op_arrays ) = 1 ;
2000-02-04 22:45:58 +08:00
CG ( in_compilation ) = 0 ;
2003-01-06 00:09:59 +08:00
CG ( start_lineno ) = 0 ;
2001-07-28 18:51:54 +08:00
init_compiler_declarables ( TSRMLS_C ) ;
2001-08-30 23:26:30 +08:00
CG ( throw_list ) = NULL ;
2002-10-08 05:20:23 +08:00
CG ( in_clone_method ) = 0 ;
2003-03-02 18:04:53 +08:00
zend_hash_apply ( CG ( auto_globals ) , ( apply_func_t ) zend_auto_global_arm TSRMLS_CC ) ;
2001-05-07 03:30:31 +08:00
}
2001-07-28 18:51:54 +08:00
void init_compiler ( TSRMLS_D )
2001-05-07 03:30:31 +08:00
{
2001-07-28 18:51:54 +08:00
zend_init_compiler_data_structures ( TSRMLS_C ) ;
2001-07-27 18:10:39 +08:00
zend_init_rsrc_list ( TSRMLS_C ) ;
2001-05-07 03:30:31 +08:00
zend_hash_init ( & CG ( filenames_table ) , 5 , NULL , ( dtor_func_t ) free_estring , 0 ) ;
2000-08-14 02:00:50 +08:00
zend_llist_init ( & CG ( open_files ) , sizeof ( zend_file_handle ) , ( void ( * ) ( void * ) ) zend_file_handle_dtor , 0 ) ;
2001-05-07 03:30:31 +08:00
CG ( unclean_shutdown ) = 0 ;
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
void shutdown_compiler ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
zend_stack_destroy ( & CG ( bp_stack ) ) ;
zend_stack_destroy ( & CG ( function_call_stack ) ) ;
zend_stack_destroy ( & CG ( switch_cond_stack ) ) ;
1999-09-09 22:15:17 +08:00
zend_stack_destroy ( & CG ( foreach_copy_stack ) ) ;
1999-04-08 02:10:10 +08:00
zend_stack_destroy ( & CG ( object_stack ) ) ;
2000-01-25 03:00:30 +08:00
zend_stack_destroy ( & CG ( declare_stack ) ) ;
2001-07-16 23:48:31 +08:00
zend_stack_destroy ( & CG ( list_stack ) ) ;
2000-08-20 01:50:42 +08:00
zend_hash_destroy ( & CG ( filenames_table ) ) ;
1999-05-22 10:13:01 +08:00
zend_llist_destroy ( & CG ( open_files ) ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-30 15:43:02 +08:00
ZEND_API char * zend_set_compiled_filename ( char * new_compiled_filename TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2000-08-20 01:50:42 +08:00
char * * pp , * p ;
int length = strlen ( new_compiled_filename ) ;
1999-04-08 02:10:10 +08:00
2000-08-20 01:50:42 +08:00
if ( zend_hash_find ( & CG ( filenames_table ) , new_compiled_filename , length + 1 , ( void * * ) & pp ) = = SUCCESS ) {
2000-09-17 16:58:39 +08:00
CG ( compiled_filename ) = * pp ;
2000-08-20 01:50:42 +08:00
return * pp ;
}
p = estrndup ( new_compiled_filename , length ) ;
zend_hash_update ( & CG ( filenames_table ) , new_compiled_filename , length + 1 , & p , sizeof ( char * ) , ( void * * ) & pp ) ;
1999-04-08 02:10:10 +08:00
CG ( compiled_filename ) = p ;
1999-08-03 02:40:10 +08:00
return p ;
1999-04-08 02:10:10 +08:00
}
2001-07-30 15:43:02 +08:00
ZEND_API void zend_restore_compiled_filename ( char * original_compiled_filename TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
CG ( compiled_filename ) = original_compiled_filename ;
}
2000-02-04 22:45:58 +08:00
2001-07-28 18:51:54 +08:00
ZEND_API char * zend_get_compiled_filename ( TSRMLS_D )
2000-02-04 22:45:58 +08:00
{
return CG ( compiled_filename ) ;
}
2001-07-28 18:51:54 +08:00
ZEND_API int zend_get_compiled_lineno ( TSRMLS_D )
2000-02-04 22:45:58 +08:00
{
return CG ( zend_lineno ) ;
}
2001-07-30 15:43:02 +08:00
ZEND_API zend_bool zend_is_compiling ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
2000-02-04 22:45:58 +08:00
return CG ( in_compilation ) ;
1999-04-08 02:10:10 +08:00
}
2000-03-13 23:49:47 +08:00
static zend_uint get_temporary_variable ( zend_op_array * op_array )
1999-04-08 02:10:10 +08:00
{
2002-10-24 04:40:07 +08:00
return ( op_array - > T ) + + * sizeof ( temp_variable ) ;
1999-04-08 02:10:10 +08:00
}
2003-04-10 23:43:47 +08:00
void zend_do_fold_binary_op ( zend_uchar op , znode * result , znode * op1 , znode * op2 TSRMLS_DC )
{
2003-04-11 04:08:02 +08:00
int ( * do_op ) ( zval * , zval * , zval * TSRMLS_DC ) ;
2003-04-10 23:43:47 +08:00
2003-04-11 04:08:02 +08:00
# define FOLD_CASE(val, func) \
case val : \
do_op = func ; \
break ;
switch ( op ) {
FOLD_CASE ( ZEND_SL , shift_left_function )
FOLD_CASE ( ZEND_SR , shift_right_function )
FOLD_CASE ( ZEND_BW_OR , bitwise_or_function )
FOLD_CASE ( ZEND_BW_AND , bitwise_and_function )
FOLD_CASE ( ZEND_BW_XOR , bitwise_xor_function )
FOLD_CASE ( ZEND_CONCAT , concat_function )
FOLD_CASE ( ZEND_ADD , add_function )
FOLD_CASE ( ZEND_SUB , sub_function )
FOLD_CASE ( ZEND_MUL , mul_function )
FOLD_CASE ( ZEND_DIV , div_function )
FOLD_CASE ( ZEND_MOD , mod_function )
FOLD_CASE ( ZEND_BOOL_XOR , boolean_xor_function )
case ZEND_BW_NOT :
bitwise_not_function ( & result - > u . constant , & op1 - > u . constant TSRMLS_CC ) ;
break ;
2003-04-10 23:43:47 +08:00
}
2003-04-11 04:08:02 +08:00
do_op ( & result - > u . constant , & op1 - > u . constant , & op2 - > u . constant TSRMLS_CC ) ;
2003-04-10 23:43:47 +08:00
}
2002-04-24 02:06:54 +08:00
void zend_do_binary_op ( zend_uchar op , znode * result , znode * op1 , znode * op2 TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = op ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * op1 ;
opline - > op2 = * op2 ;
* result = opline - > result ;
}
2002-04-24 02:06:54 +08:00
void zend_do_unary_op ( zend_uchar op , znode * result , znode * op1 TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = op ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * op1 ;
* result = opline - > result ;
SET_UNUSED ( opline - > op2 ) ;
}
2002-03-10 21:42:37 +08:00
# define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED; }
2003-01-27 23:13:01 +08:00
static void zend_do_op_data ( zend_op * data_op , znode * value TSRMLS_DC )
{
data_op - > opcode = ZEND_OP_DATA ;
data_op - > op1 = * value ;
SET_UNUSED ( data_op - > op2 ) ;
2002-03-10 21:42:37 +08:00
}
1999-04-08 02:10:10 +08:00
2002-04-24 02:06:54 +08:00
void zend_do_binary_assign_op ( zend_uchar op , znode * result , znode * op1 , znode * op2 TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2002-03-10 21:42:37 +08:00
int last_op_number = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-01-10 00:16:57 +08:00
zend_op * last_op = & CG ( active_op_array ) - > opcodes [ last_op_number ] ;
2003-01-27 23:13:01 +08:00
2002-09-15 15:45:26 +08:00
if ( last_op - > opcode = = ZEND_FETCH_OBJ_RW ) {
2002-11-30 19:20:25 +08:00
switch ( op ) {
2002-03-10 21:42:37 +08:00
case ZEND_ASSIGN_ADD :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_ADD_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_SUB :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_SUB_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_MUL :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_MUL_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_DIV :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_DIV_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_MOD :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_MOD_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_SL :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_SL_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_SR :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_SR_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_CONCAT :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_CONCAT_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_BW_OR :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_BW_OR_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_BW_AND :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_BW_AND_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
case ZEND_ASSIGN_BW_XOR :
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_BW_XOR_OBJ ;
2002-03-10 21:42:37 +08:00
break ;
default :
2002-06-29 16:42:17 +08:00
zend_error ( E_COMPILE_ERROR , " Unknown binary op opcode %d " , op ) ;
2002-03-10 21:42:37 +08:00
}
2003-01-27 23:13:01 +08:00
zend_do_op_data ( opline , op2 TSRMLS_CC ) ;
SET_UNUSED ( opline - > result ) ;
* result = last_op - > result ;
2002-03-10 21:42:37 +08:00
} else {
opline - > opcode = op ;
opline - > op1 = * op1 ;
opline - > op2 = * op2 ;
2003-01-27 23:13:01 +08:00
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
* result = opline - > result ;
2002-03-10 21:42:37 +08:00
}
1999-04-08 02:10:10 +08:00
}
2002-04-24 02:06:54 +08:00
void fetch_simple_variable_ex ( znode * result , znode * varname , int bp , zend_uchar op TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
1999-09-20 23:44:30 +08:00
zend_op opline ;
zend_op * opline_ptr ;
1999-04-08 02:10:10 +08:00
zend_llist * fetch_list_ptr ;
1999-09-20 23:44:30 +08:00
if ( bp ) {
opline_ptr = & opline ;
2001-07-28 18:51:54 +08:00
init_op ( opline_ptr TSRMLS_CC ) ;
1999-09-20 23:44:30 +08:00
} else {
2001-07-28 18:51:54 +08:00
opline_ptr = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-09-20 23:44:30 +08:00
}
opline_ptr - > opcode = op ;
opline_ptr - > result . op_type = IS_VAR ;
opline_ptr - > result . u . EA . type = 0 ;
opline_ptr - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline_ptr - > op1 = * varname ;
* result = opline_ptr - > result ;
SET_UNUSED ( opline_ptr - > op2 ) ;
2001-08-09 01:18:16 +08:00
2002-11-11 01:50:27 +08:00
opline_ptr - > op2 . u . EA . type = ZEND_FETCH_LOCAL ;
if ( varname - > op_type = = IS_CONST & & varname - > u . constant . type = = IS_STRING ) {
2003-03-06 05:36:30 +08:00
if ( zend_is_auto_global ( varname - > u . constant . value . str . val , varname - > u . constant . value . str . len TSRMLS_CC ) ) {
2002-11-11 01:50:27 +08:00
opline_ptr - > op2 . u . EA . type = ZEND_FETCH_GLOBAL ;
} else {
2003-01-20 01:25:39 +08:00
/* if (CG(active_op_array)->static_variables && zend_hash_exists(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1)) {
2002-11-11 01:50:27 +08:00
opline_ptr - > op2 . u . EA . type = ZEND_FETCH_STATIC ;
}
2003-01-20 01:25:39 +08:00
*/ }
2001-08-09 01:18:16 +08:00
}
1999-04-08 02:10:10 +08:00
if ( bp ) {
zend_stack_top ( & CG ( bp_stack ) , ( void * * ) & fetch_list_ptr ) ;
1999-09-20 23:44:30 +08:00
zend_llist_add_element ( fetch_list_ptr , opline_ptr ) ;
1999-04-08 02:10:10 +08:00
}
}
2001-07-28 18:51:54 +08:00
void fetch_simple_variable ( znode * result , znode * varname , int bp TSRMLS_DC )
1999-09-20 22:45:36 +08:00
{
/* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
2001-07-28 18:51:54 +08:00
fetch_simple_variable_ex ( result , varname , bp , ZEND_FETCH_W TSRMLS_CC ) ;
1999-09-20 22:45:36 +08:00
}
2002-11-06 01:21:23 +08:00
void zend_do_fetch_static_member ( znode * class_znode TSRMLS_DC )
2001-11-25 16:49:09 +08:00
{
zend_llist * fetch_list_ptr ;
zend_llist_element * le ;
zend_op * opline_ptr ;
zend_stack_top ( & CG ( bp_stack ) , ( void * * ) & fetch_list_ptr ) ;
le = fetch_list_ptr - > head ;
opline_ptr = ( zend_op * ) le - > data ;
2002-11-06 01:21:23 +08:00
opline_ptr - > op2 = * class_znode ;
2002-01-06 03:59:09 +08:00
opline_ptr - > op2 . u . EA . type = ZEND_FETCH_STATIC_MEMBER ;
2001-11-25 16:49:09 +08:00
}
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
void fetch_array_begin ( znode * result , znode * varname , znode * first_dim TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
fetch_simple_variable ( result , varname , 1 TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
fetch_array_dim ( result , result , first_dim TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
void fetch_array_dim ( znode * result , znode * parent , znode * dim TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
1999-09-20 23:44:30 +08:00
zend_op opline ;
1999-04-08 02:10:10 +08:00
zend_llist * fetch_list_ptr ;
2001-07-28 18:51:54 +08:00
init_op ( & opline TSRMLS_CC ) ;
1999-09-20 23:44:30 +08:00
opline . opcode = ZEND_FETCH_DIM_W ; /* the backpatching routine assumes W */
opline . result . op_type = IS_VAR ;
opline . result . u . EA . type = 0 ;
opline . result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline . op1 = * parent ;
opline . op2 = * dim ;
opline . extended_value = ZEND_FETCH_STANDARD ;
* result = opline . result ;
1999-04-08 02:10:10 +08:00
zend_stack_top ( & CG ( bp_stack ) , ( void * * ) & fetch_list_ptr ) ;
1999-09-20 23:44:30 +08:00
zend_llist_add_element ( fetch_list_ptr , & opline ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
void fetch_string_offset ( znode * result , znode * parent , znode * offset TSRMLS_DC )
2000-01-29 18:16:04 +08:00
{
2001-07-28 18:51:54 +08:00
fetch_array_dim ( result , parent , offset TSRMLS_CC ) ;
2000-01-29 18:16:04 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_print ( znode * result , znode * arg TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
1999-04-24 08:12:55 +08:00
opline - > opcode = ZEND_PRINT ;
1999-04-08 02:10:10 +08:00
opline - > op1 = * arg ;
SET_UNUSED ( opline - > op2 ) ;
* result = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_echo ( znode * arg TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
1999-04-24 08:12:55 +08:00
opline - > opcode = ZEND_ECHO ;
1999-04-08 02:10:10 +08:00
opline - > op1 = * arg ;
SET_UNUSED ( opline - > op2 ) ;
}
2003-02-11 17:48:37 +08:00
void zend_do_abstract_method ( znode * function_name , znode * modifiers , znode * body TSRMLS_DC )
2002-11-21 02:00:23 +08:00
{
2003-03-05 19:14:44 +08:00
char * method_type ;
if ( CG ( active_class_entry ) - > ce_flags & ZEND_ACC_INTERFACE ) {
modifiers - > u . constant . value . lval | = ZEND_ACC_ABSTRACT ;
method_type = " Interface " ;
} else {
method_type = " Abstract " ;
}
2003-02-11 17:48:37 +08:00
if ( modifiers - > u . constant . value . lval & ZEND_ACC_ABSTRACT ) {
2003-03-05 19:14:44 +08:00
if ( body - > u . constant . value . lval = = ZEND_ACC_ABSTRACT ) {
2003-02-11 17:48:37 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2002-11-21 02:00:23 +08:00
2003-02-11 17:48:37 +08:00
opline - > opcode = ZEND_RAISE_ABSTRACT_ERROR ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
} else {
/* we had code in the function body */
2003-03-05 19:14:44 +08:00
zend_error ( E_COMPILE_ERROR , " %s function %s::%s() cannot contain body " , method_type , CG ( active_class_entry ) - > name , function_name - > u . constant . value . str . val ) ;
2003-02-11 17:48:37 +08:00
}
} else {
2003-03-05 19:14:44 +08:00
if ( body - > u . constant . value . lval = = ZEND_ACC_ABSTRACT ) {
zend_error ( E_COMPILE_ERROR , " Non-abstract method %s::%s() must contain body " , CG ( active_class_entry ) - > name , function_name - > u . constant . value . str . val ) ;
2003-02-11 17:48:37 +08:00
}
}
2002-11-21 02:00:23 +08:00
}
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
void zend_do_assign ( znode * result , znode * variable , znode * value TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2002-03-10 21:42:37 +08:00
int last_op_number = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-01-10 00:16:57 +08:00
zend_op * last_op = & CG ( active_op_array ) - > opcodes [ last_op_number ] ;
1999-04-08 02:10:10 +08:00
2002-09-15 15:45:26 +08:00
if ( last_op - > opcode = = ZEND_FETCH_OBJ_W ) {
2003-01-27 23:13:01 +08:00
last_op - > opcode = ZEND_ASSIGN_OBJ ;
2002-03-10 21:42:37 +08:00
2003-01-27 23:13:01 +08:00
zend_do_op_data ( opline , value TSRMLS_CC ) ;
SET_UNUSED ( opline - > result ) ;
* result = last_op - > result ;
2002-03-10 21:42:37 +08:00
} else {
opline - > opcode = ZEND_ASSIGN ;
opline - > op1 = * variable ;
opline - > op2 = * value ;
2003-01-27 23:13:01 +08:00
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
* result = opline - > result ;
2002-03-10 21:42:37 +08:00
}
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_assign_ref ( znode * result , znode * lvar , znode * rvar TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
1999-04-24 08:12:55 +08:00
opline - > opcode = ZEND_ASSIGN_REF ;
1999-04-08 02:10:10 +08:00
if ( result ) {
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
* result = opline - > result ;
} else {
2000-08-14 12:10:02 +08:00
/* SET_UNUSED(opline->result); */
opline - > result . u . EA . type | = EXT_TYPE_UNUSED ;
1999-04-08 02:10:10 +08:00
}
opline - > op1 = * lvar ;
opline - > op2 = * rvar ;
}
2001-07-28 18:51:54 +08:00
static inline void do_begin_loop ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
zend_brk_cont_element * brk_cont_element ;
int parent ;
parent = CG ( active_op_array ) - > current_brk_cont ;
CG ( active_op_array ) - > current_brk_cont = CG ( active_op_array ) - > last_brk_cont ;
brk_cont_element = get_next_brk_cont_element ( CG ( active_op_array ) ) ;
brk_cont_element - > parent = parent ;
}
2001-07-28 18:51:54 +08:00
static inline void do_end_loop ( int cont_addr TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
CG ( active_op_array ) - > brk_cont_array [ CG ( active_op_array ) - > current_brk_cont ] . cont = cont_addr ;
CG ( active_op_array ) - > brk_cont_array [ CG ( active_op_array ) - > current_brk_cont ] . brk = get_next_op_number ( CG ( active_op_array ) ) ;
CG ( active_op_array ) - > current_brk_cont = CG ( active_op_array ) - > brk_cont_array [ CG ( active_op_array ) - > current_brk_cont ] . parent ;
}
2001-07-28 18:51:54 +08:00
void zend_do_while_cond ( znode * expr , znode * close_bracket_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int while_cond_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPZ ;
opline - > op1 = * expr ;
close_bracket_token - > u . opline_num = while_cond_op_number ;
SET_UNUSED ( opline - > op2 ) ;
2001-07-28 18:51:54 +08:00
do_begin_loop ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
INC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_while_end ( znode * while_token , znode * close_bracket_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
/* add unconditional jump */
opline - > opcode = ZEND_JMP ;
opline - > op1 . u . opline_num = while_token - > u . opline_num ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
/* update while's conditional jmp */
CG ( active_op_array ) - > opcodes [ close_bracket_token - > u . opline_num ] . op2 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
do_end_loop ( while_token - > u . opline_num TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
DEC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_for_cond ( znode * expr , znode * second_semicolon_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int for_cond_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPZNZ ;
2000-04-06 04:55:51 +08:00
opline - > op1 = * expr ; /* the conditional expression */
1999-04-08 02:10:10 +08:00
second_semicolon_token - > u . opline_num = for_cond_op_number ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_for_before_statement ( znode * cond_start , znode * second_semicolon_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMP ;
opline - > op1 . u . opline_num = cond_start - > u . opline_num ;
2000-04-18 01:16:47 +08:00
CG ( active_op_array ) - > opcodes [ second_semicolon_token - > u . opline_num ] . extended_value = get_next_op_number ( CG ( active_op_array ) ) ;
1999-04-08 02:10:10 +08:00
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
2001-07-28 18:51:54 +08:00
do_begin_loop ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
INC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_for_end ( znode * second_semicolon_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMP ;
opline - > op1 . u . opline_num = second_semicolon_token - > u . opline_num + 1 ;
2000-04-18 01:16:47 +08:00
CG ( active_op_array ) - > opcodes [ second_semicolon_token - > u . opline_num ] . op2 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
1999-04-08 02:10:10 +08:00
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
2001-07-28 18:51:54 +08:00
do_end_loop ( second_semicolon_token - > u . opline_num + 1 TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
DEC_BPC ( CG ( active_op_array ) ) ;
}
2002-04-24 02:06:54 +08:00
void zend_do_pre_incdec ( znode * result , znode * op1 , zend_uchar op TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2002-03-10 21:42:37 +08:00
int last_op_number = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-01-10 00:10:33 +08:00
zend_op * last_op = & CG ( active_op_array ) - > opcodes [ last_op_number ] ;
1999-04-08 02:10:10 +08:00
2002-09-15 15:45:26 +08:00
if ( last_op - > opcode = = ZEND_FETCH_OBJ_RW ) {
2002-03-10 21:42:37 +08:00
opline - > opcode = ( op = = ZEND_PRE_INC ) ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ ;
opline - > op1 = last_op - > op1 ;
opline - > op2 = last_op - > op2 ;
MAKE_NOP ( last_op ) ;
} else {
opline - > opcode = op ;
opline - > op1 = * op1 ;
SET_UNUSED ( opline - > op2 ) ;
}
1999-04-08 02:10:10 +08:00
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
* result = opline - > result ;
}
2002-04-24 02:06:54 +08:00
void zend_do_post_incdec ( znode * result , znode * op1 , zend_uchar op TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2002-03-10 21:42:37 +08:00
int last_op_number = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-01-10 00:10:33 +08:00
zend_op * last_op = & CG ( active_op_array ) - > opcodes [ last_op_number ] ;
1999-04-08 02:10:10 +08:00
2002-09-15 15:45:26 +08:00
if ( last_op - > opcode = = ZEND_FETCH_OBJ_RW ) {
2002-03-10 21:42:37 +08:00
opline - > opcode = ( op = = ZEND_POST_INC ) ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ ;
opline - > op1 = last_op - > op1 ;
opline - > op2 = last_op - > op2 ;
MAKE_NOP ( last_op ) ;
} else {
opline - > opcode = op ;
opline - > op1 = * op1 ;
SET_UNUSED ( opline - > op2 ) ;
}
1999-04-08 02:10:10 +08:00
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
* result = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_if_cond ( znode * cond , znode * closing_bracket_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int if_cond_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPZ ;
opline - > op1 = * cond ;
closing_bracket_token - > u . opline_num = if_cond_op_number ;
SET_UNUSED ( opline - > op2 ) ;
INC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_if_after_statement ( znode * closing_bracket_token , unsigned char initialize TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int if_end_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
zend_llist * jmp_list_ptr ;
opline - > opcode = ZEND_JMP ;
/* save for backpatching */
if ( initialize ) {
zend_llist jmp_list ;
zend_llist_init ( & jmp_list , sizeof ( int ) , NULL , 0 ) ;
zend_stack_push ( & CG ( bp_stack ) , ( void * ) & jmp_list , sizeof ( zend_llist ) ) ;
}
zend_stack_top ( & CG ( bp_stack ) , ( void * * ) & jmp_list_ptr ) ;
zend_llist_add_element ( jmp_list_ptr , & if_end_op_number ) ;
CG ( active_op_array ) - > opcodes [ closing_bracket_token - > u . opline_num ] . op2 . u . opline_num = if_end_op_number + 1 ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_if_end ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
int next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
zend_llist * jmp_list_ptr ;
zend_llist_element * le ;
zend_stack_top ( & CG ( bp_stack ) , ( void * * ) & jmp_list_ptr ) ;
for ( le = jmp_list_ptr - > head ; le ; le = le - > next ) {
CG ( active_op_array ) - > opcodes [ * ( ( int * ) le - > data ) ] . op1 . u . opline_num = next_op_number ;
}
zend_llist_destroy ( jmp_list_ptr ) ;
zend_stack_del_top ( & CG ( bp_stack ) ) ;
DEC_BPC ( CG ( active_op_array ) ) ;
}
2001-12-17 03:45:49 +08:00
#if 0
/* variable parsing type (compile-time) */
# define ZEND_PARSED_MEMBER (1<<0)
# define ZEND_PARSED_METHOD_CALL (1<<1)
# define ZEND_PARSED_STATIC_MEMBER (1<<2)
# define ZEND_PARSED_FUNCTION_CALL (1<<3)
# define ZEND_PARSED_VARIABLE (1<<4)
# endif
void zend_check_writable_variable ( znode * variable )
{
zend_uint type = variable - > u . EA . type ;
if ( type & ZEND_PARSED_METHOD_CALL ) {
2002-06-29 16:42:17 +08:00
zend_error ( E_COMPILE_ERROR , " Can't use method return value in write context " ) ;
2001-12-17 03:45:49 +08:00
}
2001-12-26 22:46:18 +08:00
if ( type = = ZEND_PARSED_FUNCTION_CALL ) {
2002-06-29 16:42:17 +08:00
zend_error ( E_COMPILE_ERROR , " Can't use function return value in write context " ) ;
2001-12-17 03:45:49 +08:00
}
}
1999-04-08 02:10:10 +08:00
2001-12-26 22:46:18 +08:00
zend_bool zend_is_function_or_method_call ( znode * variable )
2001-08-08 23:07:11 +08:00
{
2001-12-26 22:46:18 +08:00
zend_uint type = variable - > u . EA . type ;
2001-08-08 23:07:11 +08:00
2001-12-26 22:46:18 +08:00
return ( ( type & ZEND_PARSED_METHOD_CALL ) | | ( type = = ZEND_PARSED_FUNCTION_CALL ) ) ;
2001-08-08 23:07:11 +08:00
}
2003-03-05 19:14:44 +08:00
2002-03-03 04:38:52 +08:00
void zend_do_begin_import ( TSRMLS_D )
{
zend_llist_init ( & CG ( import_commands ) , sizeof ( zend_op ) , NULL , 0 ) ;
}
2003-03-05 19:14:44 +08:00
2002-03-03 04:38:52 +08:00
void zend_do_import ( int type , znode * what TSRMLS_DC )
{
zend_op opline ;
init_op ( & opline TSRMLS_CC ) ;
switch ( type ) {
case T_FUNCTION :
opline . opcode = ZEND_IMPORT_FUNCTION ;
break ;
case T_CLASS :
opline . opcode = ZEND_IMPORT_CLASS ;
break ;
case T_CONST :
opline . opcode = ZEND_IMPORT_CONST ;
break ;
}
if ( what ) {
if ( type = = T_FUNCTION | | type = = T_CLASS ) {
2002-10-09 22:21:40 +08:00
zend_str_tolower ( what - > u . constant . value . str . val , what - > u . constant . value . str . len ) ;
2002-03-03 04:38:52 +08:00
}
opline . op2 = * what ;
} else {
SET_UNUSED ( opline . op2 ) ;
}
zend_llist_add_element ( & CG ( import_commands ) , & opline ) ;
}
2003-03-05 19:14:44 +08:00
2002-03-03 04:38:52 +08:00
void zend_do_end_import ( znode * import_from TSRMLS_DC )
{
zend_llist_element * le ;
zend_op * opline , * opline_ptr ;
le = CG ( import_commands ) . head ;
while ( le ) {
opline_ptr = ( zend_op * ) le - > data ;
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
memcpy ( opline , opline_ptr , sizeof ( zend_op ) ) ;
opline - > op1 = * import_from ;
le = le - > next ;
}
zend_llist_destroy ( & CG ( import_commands ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_begin_variable_parse ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
zend_llist fetch_list ;
1999-09-20 23:44:30 +08:00
zend_llist_init ( & fetch_list , sizeof ( zend_op ) , NULL , 0 ) ;
1999-04-08 02:10:10 +08:00
zend_stack_push ( & CG ( bp_stack ) , ( void * ) & fetch_list , sizeof ( zend_llist ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_end_variable_parse ( int type , int arg_offset TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_llist * fetch_list_ptr ;
zend_llist_element * le ;
2002-11-05 01:35:41 +08:00
zend_op * opline , * opline_ptr = NULL ;
2002-03-15 23:09:46 +08:00
int num_of_created_opcodes = 0 ;
1999-04-08 02:10:10 +08:00
zend_stack_top ( & CG ( bp_stack ) , ( void * * ) & fetch_list_ptr ) ;
le = fetch_list_ptr - > head ;
while ( le ) {
1999-09-20 23:44:30 +08:00
opline_ptr = ( zend_op * ) le - > data ;
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-09-20 23:44:30 +08:00
memcpy ( opline , opline_ptr , sizeof ( zend_op ) ) ;
1999-04-08 02:10:10 +08:00
switch ( type ) {
case BP_VAR_R :
if ( opline - > opcode = = ZEND_FETCH_DIM_W & & opline - > op2 . op_type = = IS_UNUSED ) {
zend_error ( E_COMPILE_ERROR , " Cannot use [] for reading " ) ;
}
opline - > opcode - = 3 ;
break ;
case BP_VAR_W :
break ;
case BP_VAR_RW :
opline - > opcode + = 3 ;
break ;
case BP_VAR_IS :
opline - > opcode + = 6 ; /* 3+3 */
1999-09-30 01:18:36 +08:00
break ;
case BP_VAR_FUNC_ARG :
opline - > opcode + = 9 ; /* 3+3+3 */
opline - > extended_value = arg_offset ;
break ;
2000-02-15 04:31:01 +08:00
case BP_VAR_UNSET :
2001-11-16 07:26:52 +08:00
if ( opline - > opcode = = ZEND_FETCH_DIM_W & & opline - > op2 . op_type = = IS_UNUSED ) {
zend_error ( E_COMPILE_ERROR , " Cannot use [] for unsetting " ) ;
}
2000-02-15 04:31:01 +08:00
opline - > opcode + = 12 ; /* 3+3+3+3 */
break ;
1999-04-08 02:10:10 +08:00
}
le = le - > next ;
2002-03-15 23:09:46 +08:00
num_of_created_opcodes + + ;
}
if ( num_of_created_opcodes = = 1 ) {
if ( ( opline_ptr - > op1 . op_type = = IS_CONST ) & & ( opline_ptr - > op1 . u . constant . type = = IS_STRING ) & &
( opline_ptr - > op1 . u . constant . value . str . len = = ( sizeof ( " this " ) - 1 ) ) & &
! memcmp ( opline_ptr - > op1 . u . constant . value . str . val , " this " , sizeof ( " this " ) ) ) {
CG ( active_op_array ) - > uses_this = 1 ;
}
1999-04-08 02:10:10 +08:00
}
2002-03-15 23:09:46 +08:00
1999-04-08 02:10:10 +08:00
zend_llist_destroy ( fetch_list_ptr ) ;
zend_stack_del_top ( & CG ( bp_stack ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_init_string ( znode * result TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_INIT_STRING ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
* result = opline - > result ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_add_char ( znode * result , znode * op1 , znode * op2 TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_ADD_CHAR ;
opline - > op1 = * op1 ;
opline - > op2 = * op2 ;
opline - > op2 . op_type = IS_CONST ;
opline - > result = opline - > op1 ;
* result = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_add_string ( znode * result , znode * op1 , znode * op2 TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_ADD_STRING ;
opline - > op1 = * op1 ;
opline - > op2 = * op2 ;
opline - > op2 . op_type = IS_CONST ;
opline - > result = opline - > op1 ;
* result = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_add_variable ( znode * result , znode * op1 , znode * op2 TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_op * opline ;
if ( op1 - > op_type = = IS_CONST ) {
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_INIT_STRING ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
* result = opline - > result ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
if ( op1 - > u . constant . value . str . len > 0 ) {
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_ADD_STRING ;
opline - > result = * result ;
opline - > op1 = * result ;
opline - > op2 = * op1 ;
opline - > result = opline - > op1 ;
} else {
zval_dtor ( & op1 - > u . constant ) ;
}
} else {
* result = * op1 ;
}
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_ADD_VAR ;
opline - > result = * result ;
opline - > op1 = * result ;
opline - > op2 = * op2 ;
* result = opline - > result ;
}
2002-01-04 16:05:21 +08:00
static void zend_lowercase_znode_if_const ( znode * z )
{
if ( z - > op_type = = IS_CONST ) {
2002-10-09 22:21:40 +08:00
zend_str_tolower ( z - > u . constant . value . str . val , z - > u . constant . value . str . len ) ;
2002-01-04 16:05:21 +08:00
}
}
2001-07-28 18:51:54 +08:00
void zend_do_free ( znode * op1 TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
if ( op1 - > op_type = = IS_TMP_VAR ) {
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-11-17 02:46:32 +08:00
1999-12-21 04:01:19 +08:00
opline - > opcode = ZEND_FREE ;
opline - > op1 = * op1 ;
SET_UNUSED ( opline - > op2 ) ;
1999-07-24 19:24:19 +08:00
} else if ( op1 - > op_type = = IS_VAR ) {
1999-04-08 02:10:10 +08:00
zend_op * opline = & CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] ;
2003-01-27 23:13:01 +08:00
while ( opline - > opcode = = ZEND_END_SILENCE | | opline - > opcode = = ZEND_EXT_FCALL_END | | opline - > opcode = = ZEND_OP_DATA ) {
1999-12-21 04:01:19 +08:00
opline - - ;
}
1999-04-08 02:10:10 +08:00
if ( opline - > result . op_type = = op1 - > op_type
& & opline - > result . u . var = = op1 - > u . var ) {
opline - > result . u . EA . type | = EXT_TYPE_UNUSED ;
} else {
while ( opline > CG ( active_op_array ) - > opcodes ) {
2000-03-02 01:10:45 +08:00
/* This should be an object instantiation
2000-02-03 00:47:43 +08:00
* Find JMP_NO_CTOR , mark the preceding ASSIGN and the
* proceeding INIT_FCALL_BY_NAME as unused
*/
1999-04-08 02:10:10 +08:00
if ( opline - > opcode = = ZEND_JMP_NO_CTOR ) {
( opline - 1 ) - > result . u . EA . type | = EXT_TYPE_UNUSED ;
( opline + 1 ) - > op1 . u . EA . type | = EXT_TYPE_UNUSED ;
break ;
2000-02-03 00:47:43 +08:00
} else if ( opline - > opcode = = ZEND_FETCH_DIM_R
& & opline - > op1 . op_type = = IS_VAR
& & opline - > op1 . u . var = = op1 - > u . var ) {
/* This should the end of a list() construct
* Mark its result as unused
*/
opline - > extended_value = ZEND_FETCH_STANDARD ;
break ;
} else if ( opline - > result . op_type = = IS_VAR
& & opline - > result . u . var = = op1 - > u . var ) {
break ;
1999-04-08 02:10:10 +08:00
}
opline - - ;
}
}
2000-12-18 21:28:32 +08:00
} else if ( op1 - > op_type = = IS_CONST ) {
zval_dtor ( & op1 - > u . constant ) ;
}
1999-04-08 02:10:10 +08:00
}
2002-12-07 01:09:44 +08:00
int zend_do_verify_access_types ( znode * current_access_type , znode * new_modifier )
{
2003-02-11 17:48:37 +08:00
if ( ( current_access_type - > u . constant . value . lval & ZEND_ACC_PPP_MASK )
& & ( new_modifier - > u . constant . value . lval & ZEND_ACC_PPP_MASK )
2002-12-10 17:04:12 +08:00
& & ( ( current_access_type - > u . constant . value . lval & ZEND_ACC_PPP_MASK ) ! = ( new_modifier - > u . constant . value . lval & ZEND_ACC_PPP_MASK ) ) ) {
2002-12-07 01:09:44 +08:00
zend_error ( E_COMPILE_ERROR , " Multiple access type modifiers are not allowed " ) ;
}
2003-03-01 22:57:49 +08:00
if ( ( ( current_access_type - > u . constant . value . lval | new_modifier - > u . constant . value . lval ) & ( ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL ) ) = = ( ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL ) ) {
zend_error ( E_COMPILE_ERROR , " Cannot use the final modifier on an abstract class member " ) ;
}
2003-02-25 18:03:26 +08:00
if ( ( ( current_access_type - > u . constant . value . lval | new_modifier - > u . constant . value . lval ) & ( ZEND_ACC_PRIVATE | ZEND_ACC_FINAL ) ) = = ( ZEND_ACC_PRIVATE | ZEND_ACC_FINAL ) ) {
2003-02-24 20:05:58 +08:00
zend_error ( E_COMPILE_ERROR , " Cannot use the final modifier on a private class member " ) ;
}
2002-12-07 01:09:44 +08:00
return ( current_access_type - > u . constant . value . lval | new_modifier - > u . constant . value . lval ) ;
}
2003-03-05 19:14:44 +08:00
void zend_do_begin_function_declaration ( znode * function_token , znode * function_name , int is_method , int return_reference , znode * fn_flags_znode TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_op_array op_array ;
char * name = function_name - > u . constant . value . str . val ;
2003-01-16 04:35:06 +08:00
int name_len = function_name - > u . constant . value . str . len ;
1999-04-08 02:10:10 +08:00
int function_begin_line = function_token - > u . opline_num ;
2003-03-05 19:14:44 +08:00
zend_uint fn_flags ;
if ( is_method ) {
if ( CG ( active_class_entry ) - > ce_flags & ZEND_ACC_INTERFACE ) {
if ( ! ( fn_flags_znode - > u . constant . value . lval & ZEND_ACC_PUBLIC ) ) {
zend_error ( E_COMPILE_ERROR , " Access type for interface method %s::%s() must be omitted or declared public " , CG ( active_class_entry ) - > name , function_name - > u . constant . value . str . val ) ;
}
fn_flags_znode - > u . constant . value . lval | = ZEND_ACC_ABSTRACT ; /* propagates to the rest of the parser */
}
fn_flags = fn_flags_znode - > u . constant . value . lval ; /* must be done *after* the above check */
} else {
fn_flags = 0 ;
}
1999-04-08 02:10:10 +08:00
function_token - > u . op_array = CG ( active_op_array ) ;
2002-10-09 22:21:40 +08:00
zend_str_tolower ( name , name_len ) ;
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
init_op_array ( & op_array , ZEND_USER_FUNCTION , INITIAL_OP_ARRAY_SIZE TSRMLS_CC ) ;
1999-12-16 04:15:32 +08:00
1999-04-08 02:10:10 +08:00
op_array . function_name = name ;
op_array . arg_types = NULL ;
1999-12-16 04:15:32 +08:00
op_array . return_reference = return_reference ;
2002-11-24 04:44:12 +08:00
op_array . fn_flags = fn_flags ;
1999-04-08 02:10:10 +08:00
2002-03-01 22:04:51 +08:00
op_array . scope = CG ( active_class_entry ) ;
2003-02-19 01:18:28 +08:00
op_array . ns = CG ( active_namespace ) ;
2003-03-30 03:20:35 +08:00
op_array . prototype = NULL ;
2002-03-01 22:04:51 +08:00
2003-04-01 04:42:01 +08:00
op_array . line_start = zend_get_compiled_lineno ( TSRMLS_C ) ;
2003-03-20 05:17:47 +08:00
1999-04-08 02:10:10 +08:00
if ( is_method ) {
2002-07-22 02:50:10 +08:00
char * short_class_name = CG ( active_class_entry ) - > name ;
2003-02-02 13:20:31 +08:00
int short_class_name_length = CG ( active_class_entry ) - > name_length ;
2002-07-22 02:50:10 +08:00
zend_uint i ;
for ( i = 0 ; i < CG ( active_class_entry ) - > name_length ; i + + ) {
if ( CG ( active_class_entry ) - > name [ i ] = = ' : ' ) {
short_class_name = & CG ( active_class_entry ) - > name [ i + 1 ] ;
short_class_name_length = strlen ( short_class_name ) ;
}
}
2002-11-11 06:02:28 +08:00
if ( zend_hash_add ( & CG ( active_class_entry ) - > function_table , name , name_len + 1 , & op_array , sizeof ( zend_op_array ) , ( void * * ) & CG ( active_op_array ) ) = = FAILURE ) {
zend_op_array * child_op_array , * parent_op_array ;
if ( CG ( active_class_entry ) - > parent
& & ( zend_hash_find ( & CG ( active_class_entry ) - > function_table , name , name_len + 1 , ( void * * ) & child_op_array ) = = SUCCESS )
& & ( zend_hash_find ( & CG ( active_class_entry ) - > parent - > function_table , name , name_len + 1 , ( void * * ) & parent_op_array ) = = SUCCESS )
& & ( child_op_array = = parent_op_array ) ) {
zend_hash_update ( & CG ( active_class_entry ) - > function_table , name , name_len + 1 , & op_array , sizeof ( zend_op_array ) , ( void * * ) & CG ( active_op_array ) ) ;
} else {
2003-03-05 19:14:44 +08:00
zend_error ( E_COMPILE_ERROR , " Cannot redeclare %s::%s() " , CG ( active_class_entry ) - > name , name ) ;
2002-11-11 06:02:28 +08:00
}
}
2003-02-13 00:28:34 +08:00
2002-12-07 01:09:44 +08:00
if ( fn_flags & ZEND_ACC_ABSTRACT ) {
CG ( active_class_entry ) - > ce_flags | = ZEND_ACC_ABSTRACT ;
}
2002-11-11 06:02:28 +08:00
2003-02-13 00:28:34 +08:00
if ( ! ( fn_flags & ZEND_ACC_PPP_MASK ) ) {
fn_flags | = ZEND_ACC_PUBLIC ;
}
2003-03-01 22:57:49 +08:00
if ( ( short_class_name_length = = name_len ) & & ( ! memcmp ( short_class_name , name , name_len ) ) & & ! CG ( active_class_entry ) - > constructor ) {
2001-11-03 19:59:14 +08:00
CG ( active_class_entry ) - > constructor = ( zend_function * ) CG ( active_op_array ) ;
2001-12-28 00:35:07 +08:00
} else if ( ( function_name - > u . constant . value . str . len = = sizeof ( ZEND_CONSTRUCTOR_FUNC_NAME ) - 1 ) & & ( ! memcmp ( function_name - > u . constant . value . str . val , ZEND_CONSTRUCTOR_FUNC_NAME , sizeof ( ZEND_CONSTRUCTOR_FUNC_NAME ) ) ) ) {
2001-12-27 20:23:03 +08:00
CG ( active_class_entry ) - > constructor = ( zend_function * ) CG ( active_op_array ) ;
2001-12-28 00:35:07 +08:00
} else if ( ( function_name - > u . constant . value . str . len = = sizeof ( ZEND_DESTRUCTOR_FUNC_NAME ) - 1 ) & & ( ! memcmp ( function_name - > u . constant . value . str . val , ZEND_DESTRUCTOR_FUNC_NAME , sizeof ( ZEND_DESTRUCTOR_FUNC_NAME ) ) ) ) {
2001-12-27 22:35:09 +08:00
CG ( active_class_entry ) - > destructor = ( zend_function * ) CG ( active_op_array ) ;
2001-12-28 00:35:07 +08:00
} else if ( ( function_name - > u . constant . value . str . len = = sizeof ( ZEND_CLONE_FUNC_NAME ) - 1 ) & & ( ! memcmp ( function_name - > u . constant . value . str . val , ZEND_CLONE_FUNC_NAME , sizeof ( ZEND_CLONE_FUNC_NAME ) ) ) ) {
2001-12-27 03:54:20 +08:00
CG ( active_class_entry ) - > clone = ( zend_function * ) CG ( active_op_array ) ;
2002-10-08 05:20:23 +08:00
CG ( in_clone_method ) = 1 ;
2002-09-04 17:07:58 +08:00
} else if ( ( function_name - > u . constant . value . str . len = = sizeof ( ZEND_CALL_FUNC_NAME ) - 1 ) & & ( ! memcmp ( function_name - > u . constant . value . str . val , ZEND_CALL_FUNC_NAME , sizeof ( ZEND_CALL_FUNC_NAME ) ) ) ) {
CG ( active_class_entry ) - > __call = ( zend_function * ) CG ( active_op_array ) ;
} else if ( ( function_name - > u . constant . value . str . len = = sizeof ( ZEND_GET_FUNC_NAME ) - 1 ) & & ( ! memcmp ( function_name - > u . constant . value . str . val , ZEND_GET_FUNC_NAME , sizeof ( ZEND_GET_FUNC_NAME ) ) ) ) {
CG ( active_class_entry ) - > __get = ( zend_function * ) CG ( active_op_array ) ;
} else if ( ( function_name - > u . constant . value . str . len = = sizeof ( ZEND_SET_FUNC_NAME ) - 1 ) & & ( ! memcmp ( function_name - > u . constant . value . str . val , ZEND_SET_FUNC_NAME , sizeof ( ZEND_SET_FUNC_NAME ) ) ) ) {
CG ( active_class_entry ) - > __set = ( zend_function * ) CG ( active_op_array ) ;
2001-11-03 19:59:14 +08:00
}
2003-02-21 03:01:53 +08:00
} else if ( IN_NAMESPACE ( ) ) {
if ( zend_hash_add ( & CG ( active_namespace ) - > function_table , name , name_len + 1 , & op_array , sizeof ( zend_op_array ) , ( void * * ) & CG ( active_op_array ) ) = = FAILURE ) {
zend_error ( E_COMPILE_ERROR , " Cannot redeclare %s::%s() " , CG ( active_namespace ) - > name , name ) ;
}
1999-04-08 02:10:10 +08:00
} else {
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-05-15 23:47:24 +08:00
2002-09-25 03:05:53 +08:00
opline - > opcode = ZEND_DECLARE_FUNCTION ;
1999-05-15 23:47:24 +08:00
opline - > op1 . op_type = IS_CONST ;
2002-09-25 03:05:53 +08:00
build_runtime_defined_function_key ( & opline - > op1 . u . constant , function_name - > u . constant . value . str . val , function_name - > u . constant . value . str . len , opline TSRMLS_CC ) ;
1999-05-15 23:47:24 +08:00
opline - > op2 . op_type = IS_CONST ;
opline - > op2 . u . constant . type = IS_STRING ;
opline - > op2 . u . constant . value . str . val = estrndup ( name , name_len ) ;
opline - > op2 . u . constant . value . str . len = name_len ;
1999-09-03 05:06:05 +08:00
opline - > op2 . u . constant . refcount = 1 ;
1999-05-15 23:47:24 +08:00
opline - > extended_value = ZEND_DECLARE_FUNCTION ;
1999-09-03 05:06:05 +08:00
zend_hash_update ( CG ( function_table ) , opline - > op1 . u . constant . value . str . val , opline - > op1 . u . constant . value . str . len , & op_array , sizeof ( zend_op_array ) , ( void * * ) & CG ( active_op_array ) ) ;
1999-04-08 02:10:10 +08:00
}
if ( CG ( extended_info ) ) {
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_EXT_NOP ;
opline - > lineno = function_begin_line ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
1999-09-09 22:15:17 +08:00
{
/* Push a seperator to the switch and foreach stacks */
zend_switch_entry switch_entry ;
switch_entry . cond . op_type = IS_UNUSED ;
switch_entry . default_case = 0 ;
switch_entry . control_var = 0 ;
zend_stack_push ( & CG ( switch_cond_stack ) , ( void * ) & switch_entry , sizeof ( switch_entry ) ) ;
zend_stack_push ( & CG ( foreach_copy_stack ) , ( void * ) & switch_entry . cond , sizeof ( znode ) ) ;
}
2001-08-30 23:26:30 +08:00
function_token - > throw_list = CG ( throw_list ) ;
CG ( throw_list ) = NULL ;
2003-04-03 00:51:49 +08:00
if ( CG ( doc_comment ) ) {
CG ( active_op_array ) - > doc_comment = estrndup ( CG ( doc_comment ) , CG ( doc_comment_len ) ) ;
CG ( active_op_array ) - > doc_comment_len = CG ( doc_comment_len ) ;
RESET_DOC_COMMENT ( ) ;
}
1999-04-08 02:10:10 +08:00
}
2003-04-03 00:13:12 +08:00
void zend_do_end_function_declaration ( znode * function_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_do_extended_info ( TSRMLS_C ) ;
zend_do_return ( NULL , 0 TSRMLS_CC ) ;
2001-07-31 12:53:54 +08:00
pass_two ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-04-01 04:42:01 +08:00
CG ( active_op_array ) - > line_end = zend_get_compiled_lineno ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
CG ( active_op_array ) = function_token - > u . op_array ;
1999-09-09 22:15:17 +08:00
/* Pop the switch and foreach seperators */
zend_stack_del_top ( & CG ( switch_cond_stack ) ) ;
zend_stack_del_top ( & CG ( foreach_copy_stack ) ) ;
2001-08-30 23:26:30 +08:00
CG ( throw_list ) = function_token - > throw_list ;
2002-10-08 05:20:23 +08:00
CG ( in_clone_method ) = 0 ;
1999-04-08 02:10:10 +08:00
}
2003-05-08 06:19:43 +08:00
void zend_do_receive_arg ( zend_uchar op , znode * var , znode * offset , znode * initialization , znode * class_type , zend_uchar pass_type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = op ;
opline - > result = * var ;
opline - > op1 = * offset ;
1999-12-31 21:56:59 +08:00
if ( ( op = = ZEND_RECV_INIT ) ) {
1999-04-08 02:10:10 +08:00
opline - > op2 = * initialization ;
2000-02-02 00:02:38 +08:00
} else {
SET_UNUSED ( opline - > op2 ) ;
1999-04-08 02:10:10 +08:00
}
2000-05-12 02:31:21 +08:00
if ( ! CG ( active_op_array ) - > arg_types ) {
if ( pass_type = = BYREF_FORCE ) {
int i ;
1999-04-08 02:10:10 +08:00
2000-05-12 02:31:21 +08:00
CG ( active_op_array ) - > arg_types = ( unsigned char * ) emalloc ( sizeof ( unsigned char ) * ( offset - > u . constant . value . lval + 1 ) ) ;
for ( i = 1 ; i < offset - > u . constant . value . lval ; i + + ) {
CG ( active_op_array ) - > arg_types [ i ] = BYREF_NONE ;
}
CG ( active_op_array ) - > arg_types [ 0 ] = ( unsigned char ) offset - > u . constant . value . lval ;
2000-05-12 02:49:45 +08:00
CG ( active_op_array ) - > arg_types [ offset - > u . constant . value . lval ] = pass_type ;
1999-04-08 02:10:10 +08:00
}
2000-05-12 02:31:21 +08:00
} else {
1999-04-16 01:41:21 +08:00
CG ( active_op_array ) - > arg_types = ( unsigned char * ) erealloc ( CG ( active_op_array ) - > arg_types , sizeof ( unsigned char ) * ( offset - > u . constant . value . lval + 1 ) ) ;
2000-05-12 02:49:45 +08:00
CG ( active_op_array ) - > arg_types [ 0 ] = ( unsigned char ) offset - > u . constant . value . lval ;
1999-04-16 01:41:21 +08:00
CG ( active_op_array ) - > arg_types [ offset - > u . constant . value . lval ] = pass_type ;
1999-04-08 02:10:10 +08:00
}
2003-05-08 06:19:43 +08:00
if ( class_type - > op_type ! = IS_UNUSED ) {
2003-03-06 22:31:17 +08:00
znode passed_var = opline - > result ;
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-05-08 06:19:43 +08:00
opline - > opcode = ZEND_VERIFY_INSTANCEOF ;
opline - > op1 = * class_type ;
2003-03-06 22:31:17 +08:00
opline - > op2 = passed_var ;
opline - > extended_value = offset - > u . constant . value . lval ;
} else {
opline - > result . u . EA . type | = EXT_TYPE_UNUSED ;
}
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
int zend_do_begin_function_call ( znode * function_name TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_function * function ;
2002-10-09 22:21:40 +08:00
zend_str_tolower ( function_name - > u . constant . value . str . val , function_name - > u . constant . value . str . len ) ;
2001-08-11 23:56:40 +08:00
if ( zend_hash_find ( CG ( function_table ) , function_name - > u . constant . value . str . val , function_name - > u . constant . value . str . len + 1 , ( void * * ) & function ) = = FAILURE ) {
2001-12-11 02:57:17 +08:00
zend_do_begin_dynamic_function_call ( function_name TSRMLS_CC ) ;
1999-08-10 23:43:32 +08:00
return 1 ; /* Dynamic */
1999-04-08 02:10:10 +08:00
}
switch ( function - > type ) {
case ZEND_USER_FUNCTION : {
zend_op_array * op_array = ( zend_op_array * ) function ;
1999-06-07 01:35:42 +08:00
zend_stack_push ( & CG ( function_call_stack ) , ( void * ) & op_array , sizeof ( zend_function * ) ) ;
1999-04-08 02:10:10 +08:00
}
break ;
case ZEND_INTERNAL_FUNCTION : {
zend_internal_function * internal_function = ( zend_internal_function * ) function ;
1999-06-07 01:35:42 +08:00
zend_stack_push ( & CG ( function_call_stack ) , ( void * ) & internal_function , sizeof ( zend_function * ) ) ;
1999-04-08 02:10:10 +08:00
}
break ;
}
2001-07-28 18:51:54 +08:00
zend_do_extended_fcall_begin ( TSRMLS_C ) ;
1999-07-29 20:24:58 +08:00
return 0 ;
1999-04-08 02:10:10 +08:00
}
2001-08-08 23:07:11 +08:00
2001-12-27 01:49:22 +08:00
void zend_do_begin_method_call ( znode * left_bracket TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-09-07 22:46:12 +08:00
zend_op * last_op ;
int last_op_number ;
1999-04-08 02:10:10 +08:00
unsigned char * ptr = NULL ;
2000-07-04 03:17:57 +08:00
2001-08-10 22:18:38 +08:00
zend_do_end_variable_parse ( BP_VAR_R , 0 TSRMLS_CC ) ;
2001-08-08 23:07:11 +08:00
zend_do_begin_variable_parse ( TSRMLS_C ) ;
2001-09-07 22:46:12 +08:00
last_op_number = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
last_op = & CG ( active_op_array ) - > opcodes [ last_op_number ] ;
2001-12-27 01:49:22 +08:00
2001-12-28 00:35:07 +08:00
if ( ( last_op - > op2 . op_type = = IS_CONST ) & & ( last_op - > op2 . u . constant . value . str . len = = sizeof ( ZEND_CLONE_FUNC_NAME ) - 1 )
& & ! memcmp ( last_op - > op2 . u . constant . value . str . val , ZEND_CLONE_FUNC_NAME , sizeof ( ZEND_CLONE_FUNC_NAME ) ) ) {
2001-12-27 01:49:22 +08:00
last_op - > opcode = ZEND_CLONE ;
2003-05-20 01:12:56 +08:00
left_bracket - > op_type = IS_UNUSED ;
zval_dtor ( & last_op - > op2 . u . constant ) ;
SET_UNUSED ( last_op - > op2 ) ;
left_bracket - > u . constant . value . lval = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
2001-12-27 01:49:22 +08:00
zend_stack_push ( & CG ( function_call_stack ) , ( void * ) & ptr , sizeof ( zend_function * ) ) ;
zend_do_extended_fcall_begin ( TSRMLS_C ) ;
return ;
}
2002-01-04 16:07:39 +08:00
2002-01-04 16:05:21 +08:00
last_op - > opcode = ZEND_INIT_METHOD_CALL ;
2002-01-05 23:18:30 +08:00
2002-01-04 16:07:39 +08:00
left_bracket - > u . constant . value . lval = ZEND_INIT_FCALL_BY_NAME ;
2001-08-08 23:07:11 +08:00
zend_stack_push ( & CG ( function_call_stack ) , ( void * ) & ptr , sizeof ( zend_function * ) ) ;
zend_do_extended_fcall_begin ( TSRMLS_C ) ;
}
void zend_do_begin_dynamic_function_call ( znode * function_name TSRMLS_DC )
{
unsigned char * ptr = NULL ;
zend_op * opline ;
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_INIT_FCALL_BY_NAME ;
opline - > op2 = * function_name ;
opline - > extended_value = 0 ;
2003-05-29 04:42:40 +08:00
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > result . op_type = IS_TMP_VAR ;
2001-08-08 23:07:11 +08:00
SET_UNUSED ( opline - > op1 ) ;
1999-06-07 01:35:42 +08:00
zend_stack_push ( & CG ( function_call_stack ) , ( void * ) & ptr , sizeof ( zend_function * ) ) ;
2001-07-28 18:51:54 +08:00
zend_do_extended_fcall_begin ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
}
2003-03-10 06:17:15 +08:00
void zend_do_fetch_class ( znode * result , znode * namespace_name , znode * class_name , zend_bool global_namespace TSRMLS_DC )
2001-10-30 01:19:02 +08:00
{
2002-01-14 04:21:55 +08:00
long fetch_class_op_number ;
zend_op * opline ;
fetch_class_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2001-10-30 01:19:02 +08:00
opline - > opcode = ZEND_FETCH_CLASS ;
2003-02-16 19:12:43 +08:00
if ( namespace_name ) {
2003-03-10 06:02:37 +08:00
zend_str_tolower ( namespace_name - > u . constant . value . str . val , namespace_name - > u . constant . value . str . len ) ;
2003-02-16 19:12:43 +08:00
opline - > op1 = * namespace_name ;
2001-10-30 01:19:02 +08:00
} else {
SET_UNUSED ( opline - > op1 ) ;
2003-03-10 06:17:15 +08:00
if ( global_namespace ) {
2003-03-10 06:02:37 +08:00
opline - > extended_value = ZEND_FETCH_CLASS_GLOBAL ;
}
2001-10-30 01:19:02 +08:00
}
2003-02-24 21:35:47 +08:00
CG ( catch_begin ) = fetch_class_op_number ;
2003-03-10 06:02:37 +08:00
if ( class_name - > op_type = = IS_CONST ) {
zend_str_tolower ( class_name - > u . constant . value . str . val , class_name - > u . constant . value . str . len ) ;
if ( ( class_name - > u . constant . value . str . len = = ( sizeof ( " self " ) - 1 ) ) & &
! memcmp ( class_name - > u . constant . value . str . val , " self " , sizeof ( " self " ) ) ) {
SET_UNUSED ( opline - > op2 ) ;
opline - > extended_value = ZEND_FETCH_CLASS_SELF ;
zval_dtor ( & class_name - > u . constant ) ;
} else if ( ( class_name - > u . constant . value . str . len = = ( sizeof ( " parent " ) - 1 ) ) & &
! memcmp ( class_name - > u . constant . value . str . val , " parent " , sizeof ( " parent " ) ) ) {
SET_UNUSED ( opline - > op2 ) ;
opline - > extended_value = ZEND_FETCH_CLASS_PARENT ;
zval_dtor ( & class_name - > u . constant ) ;
2003-03-05 21:25:33 +08:00
} else {
opline - > op2 = * class_name ;
}
} else {
2003-03-10 06:02:37 +08:00
opline - > op2 = * class_name ;
2001-12-13 01:38:37 +08:00
}
2001-10-30 01:19:02 +08:00
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > result . op_type = IS_CONST ; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
* result = opline - > result ;
}
2001-12-01 00:29:47 +08:00
2003-03-10 04:53:57 +08:00
void zend_do_fetch_class_name ( znode * result , znode * class_name_entry , znode * class_name , zend_bool case_sensitive TSRMLS_DC )
2001-12-01 00:29:47 +08:00
{
zend_uint length ;
if ( ! result ) {
result = class_name_entry ;
} else {
* result = * class_name_entry ;
}
2001-12-29 00:36:04 +08:00
if ( ! case_sensitive ) {
2002-10-09 22:21:40 +08:00
zend_str_tolower ( class_name - > u . constant . value . str . val , class_name - > u . constant . value . str . len ) ;
2001-12-29 00:36:04 +08:00
}
2002-07-16 02:09:56 +08:00
2002-07-22 02:50:10 +08:00
length = sizeof ( " :: " ) - 1 + result - > u . constant . value . str . len + class_name - > u . constant . value . str . len ;
2001-12-01 00:29:47 +08:00
result - > u . constant . value . str . val = erealloc ( result - > u . constant . value . str . val , length + 1 ) ;
2002-07-22 02:50:10 +08:00
memcpy ( & result - > u . constant . value . str . val [ result - > u . constant . value . str . len ] , " :: " , sizeof ( " :: " ) - 1 ) ;
memcpy ( & result - > u . constant . value . str . val [ result - > u . constant . value . str . len + sizeof ( " :: " ) - 1 ] , class_name - > u . constant . value . str . val , class_name - > u . constant . value . str . len + 1 ) ;
2001-12-01 00:29:47 +08:00
STR_FREE ( class_name - > u . constant . value . str . val ) ;
result - > u . constant . value . str . len = length ;
}
2003-03-10 04:53:57 +08:00
void zend_do_begin_class_member_function_call ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
unsigned char * ptr = NULL ;
2003-03-10 04:53:57 +08:00
long fetch_const_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
zend_op * opline = & CG ( active_op_array ) - > opcodes [ fetch_const_op_number - 1 ] ;
1999-04-08 02:10:10 +08:00
2003-03-10 04:53:57 +08:00
/* a tmp var is leaked here */
2002-01-04 16:05:21 +08:00
opline - > opcode = ZEND_INIT_STATIC_METHOD_CALL ;
2003-03-10 04:53:57 +08:00
zend_lowercase_znode_if_const ( & opline - > op2 ) ;
2002-01-04 16:07:39 +08:00
1999-06-07 01:35:42 +08:00
zend_stack_push ( & CG ( function_call_stack ) , ( void * ) & ptr , sizeof ( zend_function * ) ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_end_function_call ( znode * function_name , znode * result , znode * argument_list , int is_method , int is_dynamic_fcall TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-12-27 01:49:22 +08:00
zend_op * opline ;
2003-05-20 01:12:56 +08:00
if ( is_method & & function_name & & function_name - > op_type = = IS_UNUSED ) {
/* clone */
if ( argument_list - > u . constant . value . lval ! = 0 ) {
zend_error ( E_WARNING , " Clone method does not require arguments " ) ;
}
opline = & CG ( active_op_array ) - > opcodes [ function_name - > u . constant . value . lval ] ;
1999-06-09 02:33:31 +08:00
} else {
2003-05-20 01:12:56 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
if ( ! is_method & & ! is_dynamic_fcall & & function_name - > op_type = = IS_CONST ) {
opline - > opcode = ZEND_DO_FCALL ;
opline - > op1 = * function_name ;
} else {
opline - > opcode = ZEND_DO_FCALL_BY_NAME ;
SET_UNUSED ( opline - > op1 ) ;
}
1999-06-09 02:33:31 +08:00
}
2001-11-05 03:30:49 +08:00
1999-04-08 02:10:10 +08:00
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
1999-12-16 04:15:32 +08:00
opline - > result . op_type = IS_VAR ;
1999-04-08 02:10:10 +08:00
* result = opline - > result ;
SET_UNUSED ( opline - > op2 ) ;
2001-08-30 23:26:30 +08:00
2001-08-30 23:31:35 +08:00
/* Check how much this is really needed
opline - > op2 . u . constant . value . lval = is_method ;
*/
2001-08-30 23:26:30 +08:00
if ( CG ( throw_list ) ! = NULL ) {
long op_number = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
zend_llist_add_element ( CG ( throw_list ) , & op_number ) ;
} else {
opline - > op2 . u . opline_num = - 1 ;
}
1999-04-08 02:10:10 +08:00
zend_stack_del_top ( & CG ( function_call_stack ) ) ;
1999-04-13 02:29:09 +08:00
opline - > extended_value = argument_list - > u . constant . value . lval ;
1999-04-08 02:10:10 +08:00
}
2002-04-24 02:06:54 +08:00
void zend_do_pass_param ( znode * param , zend_uchar op , int offset TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
1999-09-22 04:00:01 +08:00
zend_op * opline ;
1999-06-07 01:35:42 +08:00
unsigned char * arg_types ;
1999-04-08 02:10:10 +08:00
int original_op = op ;
1999-06-07 01:35:42 +08:00
zend_function * * function_ptr_ptr , * function_ptr ;
2000-11-28 02:46:23 +08:00
int send_by_reference ;
1999-04-08 02:10:10 +08:00
1999-12-16 04:15:32 +08:00
1999-06-07 01:35:42 +08:00
zend_stack_top ( & CG ( function_call_stack ) , ( void * * ) & function_ptr_ptr ) ;
function_ptr = * function_ptr_ptr ;
1999-12-16 04:15:32 +08:00
if ( original_op = = ZEND_SEND_REF
& & ! CG ( allow_call_time_pass_reference ) ) {
zend_error ( E_COMPILE_WARNING ,
" Call-time pass-by-reference has been deprecated - argument passed by value; "
" If you would like to pass it by reference, modify the declaration of %s(). "
2000-05-10 17:40:46 +08:00
" If you would like to enable call-time pass-by-reference, you can set "
1999-12-16 04:15:32 +08:00
" allow_call_time_pass_reference to true in your INI file. "
2000-05-10 17:40:46 +08:00
" However, future versions may not support this any longer. " ,
1999-12-16 04:15:32 +08:00
( function_ptr ? function_ptr - > common . function_name : " [runtime function name] " ) ,
offset + 1 ) ;
}
1999-06-07 01:35:42 +08:00
if ( function_ptr ) {
arg_types = function_ptr - > common . arg_types ;
} else {
arg_types = NULL ;
}
1999-04-08 02:10:10 +08:00
2000-11-28 02:46:23 +08:00
send_by_reference = ARG_SHOULD_BE_SENT_BY_REF ( offset , 1 , arg_types ) ? ZEND_ARG_SEND_BY_REF : 0 ;
2001-08-08 23:07:11 +08:00
2001-12-26 22:46:18 +08:00
if ( op = = ZEND_SEND_VAR & & zend_is_function_or_method_call ( param ) ) {
2001-08-08 23:07:11 +08:00
/* Method call */
op = ZEND_SEND_VAR_NO_REF ;
} else if ( op = = ZEND_SEND_VAL & & param - > op_type = = IS_VAR ) {
op = ZEND_SEND_VAR_NO_REF ;
1999-04-08 02:10:10 +08:00
}
2000-11-28 02:46:23 +08:00
if ( op ! = ZEND_SEND_VAR_NO_REF & & send_by_reference = = ZEND_ARG_SEND_BY_REF ) {
1999-04-08 02:10:10 +08:00
/* change to passing by reference */
switch ( param - > op_type ) {
case IS_VAR :
op = ZEND_SEND_REF ;
break ;
default :
zend_error ( E_COMPILE_ERROR , " Only variables can be passed by reference " ) ;
break ;
}
}
2000-11-28 02:46:23 +08:00
if ( original_op = = ZEND_SEND_VAR ) {
2002-11-30 19:20:25 +08:00
switch ( op ) {
2000-10-30 03:16:29 +08:00
case ZEND_SEND_VAR_NO_REF :
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_R , 0 TSRMLS_CC ) ;
2000-11-28 02:46:23 +08:00
break ;
1999-04-08 02:10:10 +08:00
case ZEND_SEND_VAR :
1999-06-07 01:35:42 +08:00
if ( function_ptr ) {
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_R , 0 TSRMLS_CC ) ;
1999-06-07 01:35:42 +08:00
} else {
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_FUNC_ARG , offset TSRMLS_CC ) ;
1999-06-07 01:35:42 +08:00
}
1999-04-08 02:10:10 +08:00
break ;
case ZEND_SEND_REF :
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_W , 0 TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
break ;
}
}
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2000-11-28 02:46:23 +08:00
if ( op = = ZEND_SEND_VAR_NO_REF ) {
if ( function_ptr ) {
opline - > extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference ;
} else {
opline - > extended_value = 0 ;
}
1999-09-22 04:00:01 +08:00
} else {
2000-11-28 02:46:23 +08:00
if ( function_ptr ) {
opline - > extended_value = ZEND_DO_FCALL ;
} else {
opline - > extended_value = ZEND_DO_FCALL_BY_NAME ;
}
1999-09-22 04:00:01 +08:00
}
1999-04-08 02:10:10 +08:00
opline - > opcode = op ;
opline - > op1 = * param ;
opline - > op2 . u . opline_num = offset ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-07-28 18:51:54 +08:00
static int generate_free_switch_expr ( zend_switch_entry * switch_entry TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
1999-09-09 22:15:17 +08:00
zend_op * opline ;
2000-03-30 06:28:04 +08:00
if ( switch_entry - > cond . op_type ! = IS_VAR & & switch_entry - > cond . op_type ! = IS_TMP_VAR ) {
1999-09-09 22:15:17 +08:00
return 1 ;
}
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
1999-07-24 19:43:21 +08:00
opline - > opcode = ZEND_SWITCH_FREE ;
opline - > op1 = switch_entry - > cond ;
SET_UNUSED ( opline - > op2 ) ;
2000-01-25 03:04:07 +08:00
opline - > extended_value = 0 ;
1999-09-09 22:15:17 +08:00
return 0 ;
1999-07-24 19:43:21 +08:00
}
2001-07-28 18:51:54 +08:00
static int generate_free_foreach_copy ( znode * foreach_copy TSRMLS_DC )
1999-09-09 22:15:17 +08:00
{
zend_op * opline ;
2000-03-30 06:28:04 +08:00
if ( foreach_copy - > op_type ! = IS_VAR & & foreach_copy - > op_type ! = IS_TMP_VAR ) {
1999-09-09 22:15:17 +08:00
return 1 ;
}
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-09-09 22:15:17 +08:00
2000-01-25 03:04:07 +08:00
opline - > opcode = ZEND_SWITCH_FREE ;
1999-09-09 22:15:17 +08:00
opline - > op1 = * foreach_copy ;
SET_UNUSED ( opline - > op2 ) ;
2000-01-25 03:04:07 +08:00
opline - > extended_value = 1 ;
1999-09-09 22:15:17 +08:00
return 0 ;
}
1999-07-24 19:43:21 +08:00
2001-07-28 18:51:54 +08:00
void zend_do_return ( znode * expr , int do_end_vparse TSRMLS_DC )
1999-07-24 19:43:21 +08:00
{
zend_op * opline ;
2001-07-19 23:53:38 +08:00
if ( do_end_vparse ) {
2002-03-19 04:27:03 +08:00
if ( CG ( active_op_array ) - > return_reference & & ! zend_is_function_or_method_call ( expr ) ) {
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_W , 0 TSRMLS_CC ) ;
2001-07-19 23:53:38 +08:00
} else {
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_R , 0 TSRMLS_CC ) ;
1999-12-16 04:15:32 +08:00
}
2001-07-20 02:33:22 +08:00
#if 0
2001-07-19 23:53:38 +08:00
} else if ( expr & & CG ( active_op_array ) - > return_reference ) {
zend_error ( E_COMPILE_ERROR , " Only variables may be returned by reference " ) ;
2001-07-20 02:33:22 +08:00
# endif
1999-12-16 04:15:32 +08:00
}
2001-07-19 23:53:38 +08:00
1999-07-24 19:43:21 +08:00
# ifdef ZTS
2001-07-28 18:51:54 +08:00
zend_stack_apply_with_argument ( & CG ( switch_cond_stack ) , ZEND_STACK_APPLY_TOPDOWN , ( int ( * ) ( void * element , void * ) ) generate_free_switch_expr TSRMLS_CC ) ;
zend_stack_apply_with_argument ( & CG ( foreach_copy_stack ) , ZEND_STACK_APPLY_TOPDOWN , ( int ( * ) ( void * element , void * ) ) generate_free_foreach_copy TSRMLS_CC ) ;
1999-07-24 19:43:21 +08:00
# else
2000-03-30 06:28:04 +08:00
zend_stack_apply ( & CG ( switch_cond_stack ) , ZEND_STACK_APPLY_TOPDOWN , ( int ( * ) ( void * element ) ) generate_free_switch_expr ) ;
zend_stack_apply ( & CG ( foreach_copy_stack ) , ZEND_STACK_APPLY_TOPDOWN , ( int ( * ) ( void * element ) ) generate_free_foreach_copy ) ;
1999-07-24 19:43:21 +08:00
# endif
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-07-24 19:43:21 +08:00
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_RETURN ;
1999-12-16 04:15:32 +08:00
1999-04-08 02:10:10 +08:00
if ( expr ) {
opline - > op1 = * expr ;
} else {
opline - > op1 . op_type = IS_CONST ;
1999-12-19 14:39:17 +08:00
INIT_ZVAL ( opline - > op1 . u . constant ) ;
1999-04-08 02:10:10 +08:00
}
SET_UNUSED ( opline - > op2 ) ;
}
2001-08-31 01:27:43 +08:00
void zend_do_try ( znode * try_token TSRMLS_DC )
2001-08-30 23:26:30 +08:00
{
try_token - > throw_list = ( void * ) CG ( throw_list ) ;
CG ( throw_list ) = ( zend_llist * ) emalloc ( sizeof ( zend_llist ) ) ;
zend_llist_init ( CG ( throw_list ) , sizeof ( long ) , NULL , 0 ) ;
2001-08-30 23:31:35 +08:00
/* Initialize try backpatch list used to backpatch throw, do_fcall */
2001-08-30 23:26:30 +08:00
}
static void throw_list_applier ( long * opline_num , long * catch_opline )
{
zend_op * opline ;
2001-08-31 01:27:43 +08:00
TSRMLS_FETCH ( ) ; /* Pass this by argument */
2001-08-30 23:26:30 +08:00
opline = & CG ( active_op_array ) - > opcodes [ * opline_num ] ;
2001-08-30 23:31:35 +08:00
/* Backpatch the opline of the catch statement */
2001-08-30 23:26:30 +08:00
switch ( opline - > opcode ) {
case ZEND_DO_FCALL :
case ZEND_DO_FCALL_BY_NAME :
case ZEND_THROW :
opline - > op2 . u . opline_num = * catch_opline ;
break ;
default :
2002-06-29 16:42:17 +08:00
zend_error ( E_COMPILE_ERROR , " Bad opcode in throw list " ) ;
2001-08-30 23:26:30 +08:00
break ;
}
}
2002-02-14 03:26:07 +08:00
void zend_do_begin_catch ( znode * try_token , znode * catch_class , znode * catch_var , zend_bool first_catch TSRMLS_DC )
2001-08-30 23:26:30 +08:00
{
long catch_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
zend_op * opline ;
2001-08-31 01:27:43 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2001-08-30 23:26:30 +08:00
opline - > opcode = ZEND_CATCH ;
2002-01-14 04:21:55 +08:00
opline - > op1 = * catch_class ;
SET_UNUSED ( opline - > op1 ) ; /* FIXME: Define IS_CLASS or something like that */
opline - > op2 = * catch_var ;
2001-08-30 23:26:30 +08:00
2002-02-14 03:26:07 +08:00
if ( first_catch ) {
zend_llist_apply_with_argument ( CG ( throw_list ) , ( llist_apply_with_arg_func_t ) throw_list_applier , & CG ( catch_begin ) TSRMLS_CC ) ;
zend_llist_destroy ( CG ( throw_list ) ) ;
efree ( CG ( throw_list ) ) ;
CG ( throw_list ) = ( void * ) try_token - > throw_list ;
}
2001-08-30 23:26:30 +08:00
try_token - > u . opline_num = catch_op_number ;
}
2001-08-31 01:27:43 +08:00
void zend_do_end_catch ( znode * try_token TSRMLS_DC )
2001-08-30 23:26:30 +08:00
{
2002-01-14 04:21:55 +08:00
CG ( active_op_array ) - > opcodes [ try_token - > u . opline_num ] . extended_value = get_next_op_number ( CG ( active_op_array ) ) ;
2001-08-30 23:26:30 +08:00
}
2001-08-31 01:27:43 +08:00
void zend_do_throw ( znode * expr TSRMLS_DC )
2001-08-30 23:26:30 +08:00
{
zend_op * opline ;
long throw_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-08-31 01:27:43 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2001-08-30 23:26:30 +08:00
opline - > opcode = ZEND_THROW ;
opline - > op1 = * expr ;
SET_UNUSED ( opline - > op2 ) ;
if ( CG ( throw_list ) ! = NULL ) {
zend_llist_add_element ( CG ( throw_list ) , & throw_op_number ) ;
} else {
opline - > op2 . u . opline_num = - 1 ;
}
}
2000-06-14 03:01:22 +08:00
ZEND_API void function_add_ref ( zend_function * function )
1999-07-09 00:55:27 +08:00
{
if ( function - > type = = ZEND_USER_FUNCTION ) {
1999-12-24 03:23:36 +08:00
zend_op_array * op_array = & function - > op_array ;
( * op_array - > refcount ) + + ;
if ( op_array - > static_variables ) {
HashTable * static_variables = op_array - > static_variables ;
zval * tmp_zval ;
1999-12-28 03:07:33 +08:00
ALLOC_HASHTABLE ( op_array - > static_variables ) ;
1999-12-24 03:23:36 +08:00
zend_hash_init ( op_array - > static_variables , 2 , NULL , ZVAL_PTR_DTOR , 0 ) ;
2000-02-05 23:11:24 +08:00
zend_hash_copy ( op_array - > static_variables , static_variables , ( copy_ctor_func_t ) zval_add_ref , ( void * ) & tmp_zval , sizeof ( zval * ) ) ;
1999-12-24 03:23:36 +08:00
}
1999-07-09 00:55:27 +08:00
}
}
1999-07-28 04:34:31 +08:00
static void do_inherit_parent_constructor ( zend_class_entry * ce )
{
2002-06-23 23:46:58 +08:00
zend_function * function ;
1999-07-28 04:34:31 +08:00
2003-05-08 23:04:43 +08:00
if ( ! ce - > parent ) {
return ;
}
if ( ! ce - > __get ) {
ce - > __get = ce - > parent - > __get ;
}
if ( ! ce - > __set ) {
ce - > __set = ce - > parent - > __set ;
}
if ( ! ce - > __call ) {
ce - > __call = ce - > parent - > __call ;
}
ce - > create_object = ce - > parent - > create_object ;
if ( ce - > constructor ) {
2002-06-23 23:46:58 +08:00
return ;
}
if ( zend_hash_find ( & ce - > parent - > function_table , ZEND_CONSTRUCTOR_FUNC_NAME , sizeof ( ZEND_CONSTRUCTOR_FUNC_NAME ) , ( void * * ) & function ) = = SUCCESS ) {
/* inherit parent's constructor */
zend_hash_update ( & ce - > function_table , ZEND_CONSTRUCTOR_FUNC_NAME , sizeof ( ZEND_CONSTRUCTOR_FUNC_NAME ) , function , sizeof ( zend_function ) , NULL ) ;
function_add_ref ( function ) ;
2003-05-05 02:56:35 +08:00
} else {
/* don't inherit the old style constructor if we already have the new style cconstructor */
if ( ! zend_hash_exists ( & ce - > function_table , ce - > name , ce - > name_length + 1 ) ) {
if ( zend_hash_find ( & ce - > parent - > function_table , ce - > parent - > name , ce - > parent - > name_length + 1 , ( void * * ) & function ) = = SUCCESS ) {
/* inherit parent's constructor */
zend_hash_update ( & ce - > function_table , ce - > name , ce - > name_length + 1 , function , sizeof ( zend_function ) , NULL ) ;
function_add_ref ( function ) ;
}
}
2002-06-23 23:46:58 +08:00
}
ce - > constructor = ce - > parent - > constructor ;
1999-07-28 04:34:31 +08:00
}
2002-12-07 01:09:44 +08:00
char * zend_visibility_string ( zend_uint fn_flags )
{
if ( fn_flags & ZEND_ACC_PRIVATE ) {
return " private " ;
}
if ( fn_flags & ZEND_ACC_PROTECTED ) {
return " protected " ;
}
if ( fn_flags & ZEND_ACC_PUBLIC ) {
return " public " ;
}
return " " ;
}
2003-02-23 21:58:48 +08:00
static void do_inherit_method ( zend_function * function )
2002-12-07 01:09:44 +08:00
{
/* The class entry of the derived function intentionally remains the same
* as that of the parent class . That allows us to know in which context
* we ' re running , and handle private method calls properly .
*/
function_add_ref ( function ) ;
}
2003-03-29 19:19:38 +08:00
static zend_bool zend_do_perform_implementation_check ( zend_function * fe )
{
zend_op * op , * proto_op ;
if ( ! fe - > common . prototype ) {
return 1 ;
}
if ( ( fe - > common . arg_types & & ! fe - > common . prototype - > common . arg_types )
| | ( ! fe - > common . arg_types & & fe - > common . prototype - > common . arg_types ) ) {
return 0 ;
}
if ( fe - > common . arg_types ) {
if ( fe - > common . arg_types [ 0 ] ! = fe - > common . prototype - > common . arg_types [ 0 ] ) {
return 0 ;
}
if ( memcmp ( fe - > common . arg_types + 1 , fe - > common . prototype - > common . arg_types + 1 , fe - > common . arg_types [ 0 ] * sizeof ( zend_uchar ) ) ! = 0 ) {
return 0 ;
}
}
if ( fe - > common . prototype - > type = = ZEND_INTERNAL_FUNCTION ) {
return 1 ; /* nothing further we can do here */
}
op = fe - > op_array . opcodes ;
proto_op = fe - > common . prototype - > op_array . opcodes ;
while ( proto_op - > opcode ! = ZEND_RAISE_ABSTRACT_ERROR ) {
if ( proto_op - > opcode ! = op - > opcode ) {
return 0 ;
}
switch ( proto_op - > opcode ) {
case ZEND_FETCH_CLASS :
if ( zend_binary_zval_strcasecmp ( & op - > op2 . u . constant , & proto_op - > op2 . u . constant ) ! = 0 ) {
return 0 ;
}
break ;
}
proto_op + + ;
op + + ;
}
return 1 ;
}
2003-02-23 21:58:48 +08:00
static zend_bool do_inherit_method_check ( HashTable * child_function_table , zend_function * parent , zend_hash_key * hash_key , zend_class_entry * child_ce )
2002-12-07 01:09:44 +08:00
{
2003-02-04 20:12:34 +08:00
zend_uint child_flags ;
2002-11-24 04:46:39 +08:00
zend_uint parent_flags = parent - > common . fn_flags ;
2003-02-04 20:12:34 +08:00
zend_function * child ;
2002-11-24 04:44:12 +08:00
2003-02-04 20:12:34 +08:00
if ( zend_hash_quick_find ( child_function_table , hash_key - > arKey , hash_key - > nKeyLength , hash_key - > h , ( void * * ) & child ) = = FAILURE ) {
2003-02-23 21:58:48 +08:00
if ( parent_flags & ZEND_ACC_ABSTRACT ) {
child_ce - > ce_flags | = ZEND_ACC_ABSTRACT ;
}
2003-02-04 20:12:34 +08:00
return 1 ; /* method doesn't exist in child, copy from parent */
}
2003-02-24 20:05:58 +08:00
if ( parent_flags & ZEND_ACC_FINAL ) {
zend_error ( E_COMPILE_ERROR , " Cannot override final method %s::%s() " , ZEND_FN_SCOPE_NAME ( parent ) , child - > common . function_name ) ;
}
2003-02-04 20:12:34 +08:00
child_flags = child - > common . fn_flags ;
2002-11-24 04:44:12 +08:00
/* You cannot change from static to non static and vice versa.
*/
2002-12-07 01:09:44 +08:00
if ( ( child_flags & ZEND_ACC_STATIC ) ! = ( parent_flags & ZEND_ACC_STATIC ) ) {
if ( child - > common . fn_flags & ZEND_ACC_STATIC ) {
zend_error ( E_COMPILE_ERROR , " Cannot make non static method %s::%s() static in class %s " , ZEND_FN_SCOPE_NAME ( parent ) , child - > common . function_name , ZEND_FN_SCOPE_NAME ( child ) ) ;
2002-11-24 04:44:12 +08:00
} else {
2002-12-07 01:09:44 +08:00
zend_error ( E_COMPILE_ERROR , " Cannot make static method %s::%s() non static in class %s " , ZEND_FN_SCOPE_NAME ( parent ) , child - > common . function_name , ZEND_FN_SCOPE_NAME ( child ) ) ;
2002-11-24 04:44:12 +08:00
}
}
2002-12-08 05:46:12 +08:00
2003-02-23 21:58:48 +08:00
/* Disallow making an inherited method abstract. */
2002-12-08 05:46:12 +08:00
if ( ( child_flags & ZEND_ACC_ABSTRACT ) & & ! ( parent_flags & ZEND_ACC_ABSTRACT ) ) {
zend_error ( E_COMPILE_ERROR , " Cannot make non abstract method %s::%s() abstract in class %s " , ZEND_FN_SCOPE_NAME ( parent ) , child - > common . function_name , ZEND_FN_SCOPE_NAME ( child ) ) ;
2002-11-24 04:44:12 +08:00
}
2002-12-09 20:10:17 +08:00
2003-01-02 21:58:08 +08:00
if ( parent_flags & ZEND_ACC_CHANGED ) {
child - > common . fn_flags | = ZEND_ACC_CHANGED ;
} else {
/* Prevent derived classes from restricting access that was available in parent classes
*/
if ( ( child_flags & ZEND_ACC_PPP_MASK ) > ( parent_flags & ZEND_ACC_PPP_MASK ) ) {
2003-02-06 08:39:58 +08:00
zend_error ( E_COMPILE_ERROR , " Access level to %s::%s() must be %s (as in class %s)%s " , ZEND_FN_SCOPE_NAME ( child ) , child - > common . function_name , zend_visibility_string ( parent_flags ) , ZEND_FN_SCOPE_NAME ( parent ) , ( parent_flags & ZEND_ACC_PUBLIC ) ? " " : " or weaker " ) ;
2003-01-02 21:58:08 +08:00
} else if ( ( ( child_flags & ZEND_ACC_PPP_MASK ) < ( parent_flags & ZEND_ACC_PPP_MASK ) )
& & ( ( parent_flags & ZEND_ACC_PPP_MASK ) & ZEND_ACC_PRIVATE ) ) {
child - > common . fn_flags | = ZEND_ACC_CHANGED ;
}
2002-12-09 20:10:17 +08:00
}
2002-12-27 00:27:59 +08:00
2003-03-29 19:19:38 +08:00
if ( parent_flags & ( ZEND_ACC_ABSTRACT | ZEND_ACC_ABSTRACT ) ) {
child - > common . prototype = parent ;
} else if ( parent - > common . prototype ) {
child - > common . prototype = parent - > common . prototype ;
}
if ( ! zend_do_perform_implementation_check ( child ) ) {
zend_error ( E_COMPILE_ERROR , " Declaration of %s::%s() must be the same as %s::%s() " , ZEND_FN_SCOPE_NAME ( child ) , child - > common . function_name , ZEND_FN_SCOPE_NAME ( child - > common . prototype ) , child - > common . prototype - > common . function_name ) ;
}
2002-12-27 00:27:59 +08:00
return 0 ;
2002-11-24 04:44:12 +08:00
}
2002-12-07 01:09:44 +08:00
2003-02-04 20:12:34 +08:00
static zend_bool do_inherit_property_access_check ( HashTable * target_ht , zend_property_info * parent_info , zend_hash_key * hash_key , zend_class_entry * ce )
{
zend_property_info * child_info ;
zend_class_entry * parent_ce = ce - > parent ;
if ( parent_info - > flags & ZEND_ACC_PRIVATE ) {
2003-03-19 00:30:23 +08:00
if ( zend_hash_quick_find ( & ce - > properties_info , hash_key - > arKey , hash_key - > nKeyLength , hash_key - > h , ( void * * ) & child_info ) = = SUCCESS ) {
child_info - > flags | = ZEND_ACC_CHANGED ;
}
2003-02-04 20:12:34 +08:00
return 0 ; /* don't copy access information to child */
}
2003-02-05 21:35:52 +08:00
if ( zend_hash_quick_find ( & ce - > properties_info , hash_key - > arKey , hash_key - > nKeyLength , hash_key - > h , ( void * * ) & child_info ) = = SUCCESS ) {
2003-02-04 20:12:34 +08:00
if ( ( child_info - > flags & ZEND_ACC_PPP_MASK ) > ( parent_info - > flags & ZEND_ACC_PPP_MASK ) ) {
zend_error ( E_COMPILE_ERROR , " Access level to %s::$%s must be %s (as in class %s)%s " , ce - > name , hash_key - > arKey , zend_visibility_string ( parent_info - > flags ) , parent_ce - > name , ( parent_info - > flags & ZEND_ACC_PUBLIC ) ? " " : " or weaker " ) ;
2003-02-10 20:46:58 +08:00
} else if ( child_info - > flags & ZEND_ACC_IMPLICIT_PUBLIC ) {
2003-03-23 16:14:41 +08:00
/* Explicitly copy the value from the parent */
zval * * pvalue ;
if ( zend_hash_quick_find ( & parent_ce - > default_properties , hash_key - > arKey , hash_key - > nKeyLength , hash_key - > h , ( void * * ) & pvalue ) = = SUCCESS ) {
zend_hash_quick_update ( & ce - > default_properties , hash_key - > arKey , hash_key - > nKeyLength , hash_key - > h , pvalue , sizeof ( zval * ) , NULL ) ;
( * pvalue ) - > refcount + + ;
}
2003-02-10 20:46:58 +08:00
return 1 ; /* Inherit from the parent */
2003-02-04 20:12:34 +08:00
}
return 0 ; /* Don't copy from parent */
} else {
return 1 ; /* Copy from parent */
}
}
2003-05-30 03:00:40 +08:00
ZEND_API void zend_do_inherit_interfaces ( zend_class_entry * ce , zend_class_entry * ce2 )
{
int num = ce2 - > num_interfaces ;
if ( num ) {
if ( ce - > type = = ZEND_INTERNAL_CLASS ) {
ce - > interfaces = ( zend_class_entry * * ) realloc ( ce - > interfaces , sizeof ( zend_class_entry * ) * ( ce - > num_interfaces + num ) ) ;
} else {
ce - > interfaces = ( zend_class_entry * * ) erealloc ( ce - > interfaces , sizeof ( zend_class_entry * ) * ( ce - > num_interfaces + num ) ) ;
}
memcpy ( & ce - > interfaces [ ce - > num_interfaces ] , ce2 - > interfaces , num * sizeof ( zend_class_entry * ) ) ;
ce - > num_interfaces + = num ;
}
}
2000-11-03 03:27:55 +08:00
void zend_do_inheritance ( zend_class_entry * ce , zend_class_entry * parent_ce )
2000-06-09 22:40:14 +08:00
{
2003-03-05 19:14:44 +08:00
if ( ( ce - > ce_flags & ZEND_ACC_INTERFACE )
& & ! ( parent_ce - > ce_flags & ZEND_ACC_INTERFACE ) ) {
zend_error ( E_ERROR , " Interface %s may not inherit from class (%s) " , ce - > name , parent_ce - > name ) ;
}
2003-02-04 20:12:34 +08:00
ce - > parent = parent_ce ;
2003-05-30 03:00:40 +08:00
/* Inherit interfaces */
zend_do_inherit_interfaces ( ce , parent_ce ) ;
2000-06-09 22:40:14 +08:00
2003-02-04 20:12:34 +08:00
/* Inherit properties */
zend_hash_merge ( & ce - > default_properties , & parent_ce - > default_properties , ( void ( * ) ( void * ) ) zval_add_ref , NULL , sizeof ( zval * ) , 0 ) ;
2003-02-05 21:35:52 +08:00
zend_hash_merge_ex ( & ce - > properties_info , & parent_ce - > properties_info , ( copy_ctor_func_t ) zend_duplicate_property_info , sizeof ( zend_property_info ) , ( merge_checker_func_t ) do_inherit_property_access_check , ce ) ;
2002-07-16 02:09:56 +08:00
2001-11-25 16:49:09 +08:00
/* STATIC_MEMBERS_FIXME */
2002-10-17 02:29:41 +08:00
/* zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); */
2003-02-04 20:12:34 +08:00
zend_hash_merge ( & ce - > constants_table , & parent_ce - > constants_table , ( void ( * ) ( void * ) ) zval_add_ref , NULL , sizeof ( zval * ) , 0 ) ;
2003-02-23 20:51:40 +08:00
zend_hash_merge_ex ( & ce - > function_table , & parent_ce - > function_table , ( copy_ctor_func_t ) do_inherit_method , sizeof ( zend_function ) , ( merge_checker_func_t ) do_inherit_method_check , ce ) ;
2000-06-09 22:40:14 +08:00
do_inherit_parent_constructor ( ce ) ;
}
2003-03-05 19:14:44 +08:00
2003-05-30 03:00:40 +08:00
ZEND_API void zend_do_implement_interface ( zend_class_entry * ce , zend_class_entry * iface )
2003-03-05 19:14:44 +08:00
{
zend_hash_merge ( & ce - > constants_table , & iface - > constants_table , ( void ( * ) ( void * ) ) zval_add_ref , NULL , sizeof ( zval * ) , 0 ) ;
zend_hash_merge_ex ( & ce - > function_table , & iface - > function_table , ( copy_ctor_func_t ) do_inherit_method , sizeof ( zend_function ) , ( merge_checker_func_t ) do_inherit_method_check , ce ) ;
2003-05-30 03:00:40 +08:00
zend_do_inherit_interfaces ( ce , iface ) ;
2003-03-05 19:14:44 +08:00
}
2002-09-25 03:05:53 +08:00
ZEND_API int do_bind_function ( zend_op * opline , HashTable * function_table , HashTable * class_table , int compile_time )
{
zend_function * function ;
1999-05-15 23:47:24 +08:00
2003-01-28 19:34:24 +08:00
if ( opline - > opcode ! = ZEND_DECLARE_FUNCTION ) {
2003-02-16 19:12:43 +08:00
zend_error ( E_COMPILE_ERROR , " Internal compiler error. Please report! " ) ;
2003-01-28 19:34:24 +08:00
}
2002-09-25 03:05:53 +08:00
zend_hash_find ( function_table , opline - > op1 . u . constant . value . str . val , opline - > op1 . u . constant . value . str . len , ( void * ) & function ) ;
if ( zend_hash_add ( function_table , opline - > op2 . u . constant . value . str . val , opline - > op2 . u . constant . value . str . len + 1 , function , sizeof ( zend_function ) , NULL ) = = FAILURE ) {
int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR ;
zend_function * function ;
if ( zend_hash_find ( function_table , opline - > op2 . u . constant . value . str . val , opline - > op2 . u . constant . value . str . len + 1 , ( void * ) & function ) = = SUCCESS
& & function - > type = = ZEND_USER_FUNCTION
& & ( ( zend_op_array * ) function ) - > last > 0 ) {
zend_error ( error_level , " Cannot redeclare %s() (previously declared in %s:%d) " ,
opline - > op2 . u . constant . value . str . val ,
( ( zend_op_array * ) function ) - > filename ,
( ( zend_op_array * ) function ) - > opcodes [ 0 ] . lineno ) ;
} else {
zend_error ( error_level , " Cannot redeclare %s() " , opline - > op2 . u . constant . value . str . val ) ;
}
return FAILURE ;
} else {
( * function - > op_array . refcount ) + + ;
function - > op_array . static_variables = NULL ; /* NULL out the unbound function */
return SUCCESS ;
}
}
1999-07-09 00:55:27 +08:00
2003-03-05 19:14:44 +08:00
ZEND_API zend_class_entry * do_bind_class ( zend_op * opline , HashTable * function_table , HashTable * class_table TSRMLS_DC )
2002-09-25 03:05:53 +08:00
{
zend_class_entry * ce , * * pce ;
if ( zend_hash_find ( class_table , opline - > op1 . u . constant . value . str . val , opline - > op1 . u . constant . value . str . len , ( void * * ) & pce ) = = FAILURE ) {
2003-02-16 19:12:43 +08:00
zend_error ( E_COMPILE_ERROR , " Internal Zend error - Missing class information for %s " , opline - > op1 . u . constant . value . str . val ) ;
2003-03-05 19:14:44 +08:00
return NULL ;
2002-09-25 03:05:53 +08:00
} else {
ce = * pce ;
}
ce - > refcount + + ;
if ( zend_hash_add ( class_table , opline - > op2 . u . constant . value . str . val , opline - > op2 . u . constant . value . str . len + 1 , & ce , sizeof ( zend_class_entry * ) , NULL ) = = FAILURE ) {
ce - > refcount - - ;
2003-02-16 19:12:43 +08:00
zend_error ( E_COMPILE_ERROR , " Cannot redeclare class %s " , opline - > op2 . u . constant . value . str . val ) ;
2003-03-05 19:14:44 +08:00
return NULL ;
2002-09-25 03:05:53 +08:00
} else {
2003-03-05 19:14:44 +08:00
return ce ;
2002-09-25 03:05:53 +08:00
}
}
2000-05-26 00:26:22 +08:00
2003-03-05 19:14:44 +08:00
ZEND_API zend_class_entry * do_bind_inherited_class ( zend_op * opline , HashTable * function_table , HashTable * class_table , zend_class_entry * parent_ce TSRMLS_DC )
2002-09-25 03:05:53 +08:00
{
zend_class_entry * ce , * * pce ;
int found_ce ;
2002-09-15 15:54:01 +08:00
2002-09-25 03:05:53 +08:00
found_ce = zend_hash_find ( class_table , opline - > op1 . u . constant . value . str . val , opline - > op1 . u . constant . value . str . len , ( void * * ) & pce ) ;
if ( found_ce = = FAILURE ) {
2003-03-29 19:27:17 +08:00
zend_error ( E_COMPILE_ERROR , " Cannot redeclare class %s " , opline - > op2 . u . constant . value . str . val ) ;
2003-03-05 19:14:44 +08:00
return NULL ;
2002-09-25 03:05:53 +08:00
} else {
ce = * pce ;
}
zend_do_inheritance ( ce , parent_ce ) ;
2002-09-25 03:32:01 +08:00
ce - > refcount + + ;
2002-09-25 03:05:53 +08:00
/* Register the derived class */
if ( zend_hash_add ( class_table , opline - > op2 . u . constant . value . str . val , opline - > op2 . u . constant . value . str . len + 1 , pce , sizeof ( zend_class_entry * ) , NULL ) = = FAILURE ) {
2003-02-16 19:12:43 +08:00
zend_error ( E_COMPILE_ERROR , " Cannot redeclare class %s " , opline - > op2 . u . constant . value . str . val ) ;
2002-09-25 03:05:53 +08:00
ce - > refcount - - ;
zend_hash_destroy ( & ce - > function_table ) ;
zend_hash_destroy ( & ce - > default_properties ) ;
2003-02-05 21:35:52 +08:00
zend_hash_destroy ( & ce - > properties_info ) ;
2002-09-25 03:05:53 +08:00
zend_hash_destroy ( ce - > static_members ) ;
zend_hash_destroy ( & ce - > constants_table ) ;
2003-03-05 19:14:44 +08:00
return NULL ;
2002-09-25 03:05:53 +08:00
}
2003-03-05 19:14:44 +08:00
return ce ;
1999-05-15 23:47:24 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_early_binding ( TSRMLS_D )
1999-05-15 23:47:24 +08:00
{
zend_op * opline = & CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] ;
2003-01-28 19:34:24 +08:00
while ( opline - > opcode = = ZEND_TICKS & & opline > CG ( active_op_array ) - > opcodes ) {
opline - - ;
}
2002-09-25 03:05:53 +08:00
if ( do_bind_function ( opline , CG ( function_table ) , CG ( class_table ) , 1 ) = = FAILURE ) {
1999-07-27 05:18:35 +08:00
return ;
}
2002-09-25 03:05:53 +08:00
zend_hash_del ( CG ( function_table ) , opline - > op1 . u . constant . value . str . val , opline - > op1 . u . constant . value . str . len ) ;
1999-09-03 05:06:05 +08:00
zval_dtor ( & opline - > op1 . u . constant ) ;
1999-05-15 23:47:24 +08:00
zval_dtor ( & opline - > op2 . u . constant ) ;
opline - > opcode = ZEND_NOP ;
2000-05-09 05:46:48 +08:00
memset ( & opline - > op1 , 0 , sizeof ( znode ) ) ;
memset ( & opline - > op2 , 0 , sizeof ( znode ) ) ;
1999-05-15 23:47:24 +08:00
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_boolean_or_begin ( znode * expr1 , znode * op_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPNZ_EX ;
if ( expr1 - > op_type = = IS_TMP_VAR ) {
opline - > result = * expr1 ;
} else {
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > result . op_type = IS_TMP_VAR ;
}
opline - > op1 = * expr1 ;
SET_UNUSED ( opline - > op2 ) ;
op_token - > u . opline_num = next_op_number ;
* expr1 = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_boolean_or_end ( znode * result , znode * expr1 , znode * expr2 , znode * op_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
* result = * expr1 ; /* we saved the original result in expr1 */
opline - > opcode = ZEND_BOOL ;
opline - > result = * result ;
opline - > op1 = * expr2 ;
SET_UNUSED ( opline - > op2 ) ;
CG ( active_op_array ) - > opcodes [ op_token - > u . opline_num ] . op2 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_boolean_and_begin ( znode * expr1 , znode * op_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPZ_EX ;
if ( expr1 - > op_type = = IS_TMP_VAR ) {
opline - > result = * expr1 ;
} else {
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > result . op_type = IS_TMP_VAR ;
}
opline - > op1 = * expr1 ;
SET_UNUSED ( opline - > op2 ) ;
op_token - > u . opline_num = next_op_number ;
* expr1 = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_boolean_and_end ( znode * result , znode * expr1 , znode * expr2 , znode * op_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
* result = * expr1 ; /* we saved the original result in expr1 */
opline - > opcode = ZEND_BOOL ;
opline - > result = * result ;
opline - > op1 = * expr2 ;
SET_UNUSED ( opline - > op2 ) ;
CG ( active_op_array ) - > opcodes [ op_token - > u . opline_num ] . op2 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_do_while_begin ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
do_begin_loop ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
INC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_do_while_end ( znode * do_token , znode * expr_open_bracket , znode * expr TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPNZ ;
opline - > op1 = * expr ;
opline - > op2 . u . opline_num = do_token - > u . opline_num ;
1999-06-23 04:24:51 +08:00
SET_UNUSED ( opline - > op2 ) ;
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
do_end_loop ( expr_open_bracket - > u . opline_num TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
DEC_BPC ( CG ( active_op_array ) ) ;
}
2002-04-24 02:06:54 +08:00
void zend_do_brk_cont ( zend_uchar op , znode * expr TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = op ;
opline - > op1 . u . opline_num = CG ( active_op_array ) - > current_brk_cont ;
SET_UNUSED ( opline - > op1 ) ;
if ( expr ) {
opline - > op2 = * expr ;
} else {
opline - > op2 . u . constant . type = IS_LONG ;
opline - > op2 . u . constant . value . lval = 1 ;
1999-07-10 04:43:59 +08:00
INIT_PZVAL ( & opline - > op2 . u . constant ) ;
1999-04-08 02:10:10 +08:00
opline - > op2 . op_type = IS_CONST ;
}
}
2001-07-28 18:51:54 +08:00
void zend_do_switch_cond ( znode * cond TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_switch_entry switch_entry ;
2000-08-11 04:42:57 +08:00
zend_op * opline ;
/* Initialize the conditional value */
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2000-08-11 04:42:57 +08:00
opline - > opcode = ZEND_BOOL ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > op1 . op_type = IS_CONST ;
opline - > op1 . u . constant . type = IS_BOOL ;
opline - > op1 . u . constant . value . lval = 0 ;
INIT_PZVAL ( & opline - > op1 . u . constant ) ;
SET_UNUSED ( opline - > op2 ) ;
1999-04-08 02:10:10 +08:00
switch_entry . cond = * cond ;
switch_entry . default_case = - 1 ;
2000-08-11 04:42:57 +08:00
switch_entry . control_var = opline - > result . u . var ;
1999-04-08 02:10:10 +08:00
zend_stack_push ( & CG ( switch_cond_stack ) , ( void * ) & switch_entry , sizeof ( switch_entry ) ) ;
2001-07-28 18:51:54 +08:00
do_begin_loop ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
INC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_switch_end ( znode * case_list TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_op * opline ;
zend_switch_entry * switch_entry_ptr ;
zend_stack_top ( & CG ( switch_cond_stack ) , ( void * * ) & switch_entry_ptr ) ;
2000-04-11 02:24:38 +08:00
if ( case_list - > op_type ! = IS_UNUSED ) { /* non-empty switch */
1999-04-08 02:10:10 +08:00
int next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
CG ( active_op_array ) - > opcodes [ case_list - > u . opline_num ] . op1 . u . opline_num = next_op_number ;
}
/* add code to jmp to default case */
if ( switch_entry_ptr - > default_case ! = - 1 ) {
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPZ ;
opline - > op1 . op_type = IS_TMP_VAR ;
opline - > op1 . u . var = switch_entry_ptr - > control_var ;
opline - > op2 . u . opline_num = switch_entry_ptr - > default_case ;
SET_UNUSED ( opline - > op2 ) ;
}
/* remember break/continue loop information */
CG ( active_op_array ) - > brk_cont_array [ CG ( active_op_array ) - > current_brk_cont ] . cont = CG ( active_op_array ) - > brk_cont_array [ CG ( active_op_array ) - > current_brk_cont ] . brk = get_next_op_number ( CG ( active_op_array ) ) ;
CG ( active_op_array ) - > current_brk_cont = CG ( active_op_array ) - > brk_cont_array [ CG ( active_op_array ) - > current_brk_cont ] . parent ;
2000-03-30 06:28:04 +08:00
if ( switch_entry_ptr - > cond . op_type = = IS_VAR | | switch_entry_ptr - > cond . op_type = = IS_TMP_VAR ) {
/* emit free for the switch condition*/
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2000-03-30 06:28:04 +08:00
opline - > opcode = ZEND_SWITCH_FREE ;
opline - > op1 = switch_entry_ptr - > cond ;
SET_UNUSED ( opline - > op2 ) ;
}
1999-04-08 02:10:10 +08:00
if ( switch_entry_ptr - > cond . op_type = = IS_CONST ) {
zval_dtor ( & switch_entry_ptr - > cond . u . constant ) ;
}
zend_stack_del_top ( & CG ( switch_cond_stack ) ) ;
DEC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_case_before_statement ( znode * case_list , znode * case_token , znode * case_expr TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
int next_op_number ;
zend_switch_entry * switch_entry_ptr ;
znode result ;
zend_stack_top ( & CG ( switch_cond_stack ) , ( void * * ) & switch_entry_ptr ) ;
opline - > opcode = ZEND_CASE ;
opline - > result . u . var = switch_entry_ptr - > control_var ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > op1 = switch_entry_ptr - > cond ;
opline - > op2 = * case_expr ;
if ( opline - > op1 . op_type = = IS_CONST ) {
zval_copy_ctor ( & opline - > op1 . u . constant ) ;
}
result = opline - > result ;
next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPZ ;
opline - > op1 = result ;
SET_UNUSED ( opline - > op2 ) ;
case_token - > u . opline_num = next_op_number ;
2000-04-11 02:02:40 +08:00
if ( case_list - > op_type = = IS_UNUSED ) {
1999-04-08 02:10:10 +08:00
return ;
}
next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
CG ( active_op_array ) - > opcodes [ case_list - > u . opline_num ] . op1 . u . opline_num = next_op_number ;
}
2001-07-28 18:51:54 +08:00
void zend_do_case_after_statement ( znode * result , znode * case_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMP ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
result - > u . opline_num = next_op_number ;
switch ( CG ( active_op_array ) - > opcodes [ case_token - > u . opline_num ] . opcode ) {
case ZEND_JMP :
CG ( active_op_array ) - > opcodes [ case_token - > u . opline_num ] . op1 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
break ;
case ZEND_JMPZ :
CG ( active_op_array ) - > opcodes [ case_token - > u . opline_num ] . op2 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
break ;
}
}
2001-07-28 18:51:54 +08:00
void zend_do_default_before_statement ( znode * case_list , znode * default_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
zend_switch_entry * switch_entry_ptr ;
zend_stack_top ( & CG ( switch_cond_stack ) , ( void * * ) & switch_entry_ptr ) ;
opline - > opcode = ZEND_JMP ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
default_token - > u . opline_num = next_op_number ;
next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_BOOL ;
opline - > result . u . var = switch_entry_ptr - > control_var ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > op1 . op_type = IS_CONST ;
2000-08-11 04:42:57 +08:00
opline - > op1 . u . constant . type = IS_BOOL ;
1999-04-08 02:10:10 +08:00
opline - > op1 . u . constant . value . lval = 1 ;
1999-07-10 04:43:59 +08:00
INIT_PZVAL ( & opline - > op1 . u . constant ) ;
1999-04-08 02:10:10 +08:00
SET_UNUSED ( opline - > op2 ) ;
switch_entry_ptr - > default_case = next_op_number ;
2000-04-11 02:24:38 +08:00
if ( case_list - > op_type = = IS_UNUSED ) {
1999-04-08 02:10:10 +08:00
return ;
}
2000-08-11 04:42:57 +08:00
next_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
1999-04-08 02:10:10 +08:00
CG ( active_op_array ) - > opcodes [ case_list - > u . opline_num ] . op1 . u . opline_num = next_op_number ;
}
2001-12-13 01:38:37 +08:00
void zend_do_begin_class_declaration ( znode * class_token , znode * class_name , znode * parent_class_name TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-10-30 01:19:02 +08:00
zend_op * opline ;
2002-09-25 03:05:53 +08:00
int doing_inheritance = 0 ;
2002-03-12 18:08:47 +08:00
zend_class_entry * new_class_entry = emalloc ( sizeof ( zend_class_entry ) ) ;
2001-10-30 01:19:02 +08:00
2003-03-04 21:52:03 +08:00
zend_str_tolower ( class_name - > u . constant . value . str . val , class_name - > u . constant . value . str . len ) ;
2002-12-07 23:51:25 +08:00
if ( ! ( strcmp ( class_name - > u . constant . value . str . val , " main " ) & & strcmp ( class_name - > u . constant . value . str . val , " self " ) & &
strcmp ( class_name - > u . constant . value . str . val , " parent " ) ) ) {
zend_error ( E_COMPILE_ERROR , " Cannot use '%s' as class name as it is reserved " , class_name - > u . constant . value . str . val ) ;
}
2003-02-11 00:11:24 +08:00
2003-03-10 11:04:02 +08:00
new_class_entry - > type = ZEND_USER_CLASS ;
2003-03-04 21:36:16 +08:00
new_class_entry - > name = class_name - > u . constant . value . str . val ;
new_class_entry - > name_length = class_name - > u . constant . value . str . len ;
1999-04-08 02:10:10 +08:00
2003-02-16 19:34:49 +08:00
zend_initialize_class_data ( new_class_entry , 1 TSRMLS_CC ) ;
2003-04-01 04:42:01 +08:00
new_class_entry - > filename = zend_get_compiled_filename ( TSRMLS_C ) ;
new_class_entry - > line_start = zend_get_compiled_lineno ( TSRMLS_C ) ;
2003-03-07 06:53:23 +08:00
new_class_entry - > ce_flags | = class_token - > u . constant . value . lval ;
1999-04-08 02:10:10 +08:00
2002-09-25 03:05:53 +08:00
if ( parent_class_name - > op_type ! = IS_UNUSED ) {
doing_inheritance = 1 ;
2001-10-30 01:19:02 +08:00
}
2003-02-11 00:11:24 +08:00
zend_str_tolower ( new_class_entry - > name , new_class_entry - > name_length ) ;
2001-10-30 01:19:02 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-05-15 23:47:24 +08:00
opline - > op1 . op_type = IS_CONST ;
2002-09-25 03:05:53 +08:00
build_runtime_defined_function_key ( & opline - > op1 . u . constant , new_class_entry - > name , new_class_entry - > name_length , opline TSRMLS_CC ) ;
1999-05-15 23:47:24 +08:00
opline - > op2 . op_type = IS_CONST ;
opline - > op2 . u . constant . type = IS_STRING ;
1999-09-03 05:06:05 +08:00
opline - > op2 . u . constant . refcount = 1 ;
2003-02-16 19:12:43 +08:00
2002-09-25 03:05:53 +08:00
if ( doing_inheritance ) {
opline - > extended_value = parent_class_name - > u . var ;
opline - > opcode = ZEND_DECLARE_INHERITED_CLASS ;
1999-07-09 00:55:27 +08:00
} else {
2002-09-25 03:05:53 +08:00
opline - > opcode = ZEND_DECLARE_CLASS ;
1999-07-09 00:55:27 +08:00
}
2002-09-25 03:05:53 +08:00
opline - > op2 . u . constant . value . str . val = estrndup ( new_class_entry - > name , new_class_entry - > name_length ) ;
opline - > op2 . u . constant . value . str . len = new_class_entry - > name_length ;
2003-02-16 19:12:43 +08:00
2002-03-12 18:08:47 +08:00
zend_hash_update ( CG ( class_table ) , opline - > op1 . u . constant . value . str . val , opline - > op1 . u . constant . value . str . len , & new_class_entry , sizeof ( zend_class_entry * ) , NULL ) ;
CG ( active_class_entry ) = new_class_entry ;
2003-03-05 19:14:44 +08:00
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > result . op_type = IS_CONST ;
CG ( implementing_class ) = opline - > result ;
2003-04-03 00:51:49 +08:00
if ( CG ( doc_comment ) ) {
CG ( active_class_entry ) - > doc_comment = estrndup ( CG ( doc_comment ) , CG ( doc_comment_len ) ) ;
CG ( active_class_entry ) - > doc_comment_len = CG ( doc_comment_len ) ;
RESET_DOC_COMMENT ( ) ;
}
1999-04-08 02:10:10 +08:00
}
2003-03-07 07:45:50 +08:00
static void do_verify_abstract_class ( TSRMLS_D )
2003-03-07 06:53:23 +08:00
{
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_VERIFY_ABSTRACT_CLASS ;
opline - > op1 = CG ( implementing_class ) ;
}
2003-04-03 00:13:12 +08:00
void zend_do_end_class_declaration ( znode * class_token , znode * parent_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2003-05-30 03:00:40 +08:00
zend_class_entry * ce = CG ( active_class_entry ) ;
do_inherit_parent_constructor ( ce ) ;
2003-03-07 06:53:23 +08:00
2003-05-30 03:00:40 +08:00
ce - > line_end = zend_get_compiled_lineno ( TSRMLS_C ) ;
2003-04-01 04:42:01 +08:00
2003-05-30 03:00:40 +08:00
/* Inherit interfaces */
if ( ce - > num_interfaces > 0 ) {
ce - > interfaces = ( zend_class_entry * * ) erealloc ( ce - > interfaces , sizeof ( zend_class_entry * ) * ce - > num_interfaces ) ;
2003-03-05 19:14:44 +08:00
}
2003-05-30 03:00:40 +08:00
if ( ! ( ce - > ce_flags & ZEND_ACC_INTERFACE )
& & ! ( ce - > ce_flags & ZEND_ACC_ABSTRACT_CLASS )
& & ( ( parent_token - > op_type ! = IS_UNUSED ) | | ( ce - > num_interfaces > 0 ) ) ) {
2003-03-07 06:53:23 +08:00
do_verify_abstract_class ( TSRMLS_C ) ;
}
2003-02-16 19:12:43 +08:00
CG ( active_class_entry ) = NULL ;
1999-04-08 02:10:10 +08:00
}
2003-03-05 19:14:44 +08:00
void zend_do_implements_interface ( znode * interface_znode TSRMLS_DC )
{
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_ADD_INTERFACE ;
opline - > op1 = CG ( implementing_class ) ;
opline - > op2 = * interface_znode ;
opline - > extended_value = CG ( active_class_entry ) - > num_interfaces + + ;
}
2002-07-16 02:09:56 +08:00
void mangle_property_name ( char * * dest , int * dest_length , char * src1 , int src1_length , char * src2 , int src2_length )
2002-02-21 19:50:44 +08:00
{
2002-07-16 02:09:56 +08:00
char * prop_name ;
int prop_name_length ;
prop_name_length = 1 + src1_length + 1 + src2_length ;
prop_name = emalloc ( prop_name_length + 1 ) ;
prop_name [ 0 ] = ' \0 ' ;
memcpy ( prop_name + 1 , src1 , src1_length + 1 ) ;
memcpy ( prop_name + 1 + src1_length + 1 , src2 , src2_length + 1 ) ;
2002-02-21 19:50:44 +08:00
2002-07-16 02:09:56 +08:00
* dest = prop_name ;
* dest_length = prop_name_length ;
2002-02-21 19:50:44 +08:00
}
1999-04-08 02:10:10 +08:00
2002-12-07 01:09:44 +08:00
2003-02-10 20:46:58 +08:00
void zend_do_declare_property ( znode * var_name , znode * value , zend_uint access_type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2002-02-14 12:01:53 +08:00
zval * property ;
2003-02-04 20:12:34 +08:00
zend_property_info property_info ;
2003-02-10 20:46:58 +08:00
zend_property_info * existing_property_info ;
2003-02-05 21:35:52 +08:00
HashTable * target_symbol_table ;
2003-03-02 03:08:41 +08:00
zend_bool free_var_name = 0 ;
1999-12-27 05:21:33 +08:00
2003-03-05 19:14:44 +08:00
if ( CG ( active_class_entry ) - > ce_flags & ZEND_ACC_INTERFACE ) {
zend_error ( E_COMPILE_ERROR , " Interfaces may not include member variables " ) ;
}
2003-02-11 17:48:37 +08:00
if ( access_type & ZEND_ACC_ABSTRACT ) {
zend_error ( E_COMPILE_ERROR , " Properties cannot be declared abstract " ) ;
}
2003-04-20 22:52:40 +08:00
if ( access_type & ZEND_ACC_FINAL ) {
zend_error ( E_COMPILE_ERROR , " Cannot declare property $%s::%s final, the final modifier is allowed only for methods " ,
CG ( active_class_entry ) - > name , var_name - > u . constant . value . str . val ) ;
}
2003-02-13 00:28:34 +08:00
if ( ! ( access_type & ZEND_ACC_PPP_MASK ) ) {
access_type | = ZEND_ACC_PUBLIC ;
}
2003-02-10 20:46:58 +08:00
if ( zend_hash_find ( & CG ( active_class_entry ) - > properties_info , var_name - > u . constant . value . str . val , var_name - > u . constant . value . str . len + 1 , ( void * * ) & existing_property_info ) = = SUCCESS ) {
if ( ! ( existing_property_info - > flags & ZEND_ACC_IMPLICIT_PUBLIC ) ) {
zend_error ( E_COMPILE_ERROR , " Cannot redeclare %s::$%s " , CG ( active_class_entry ) - > name , var_name - > u . constant . value . str . val ) ;
}
}
2002-02-14 12:01:53 +08:00
ALLOC_ZVAL ( property ) ;
1999-04-08 02:10:10 +08:00
2002-02-14 12:01:53 +08:00
if ( value ) {
1999-04-08 02:10:10 +08:00
* property = value - > u . constant ;
2002-02-14 12:01:53 +08:00
} else {
INIT_PZVAL ( property ) ;
property - > type = IS_NULL ;
}
2003-02-10 20:46:58 +08:00
if ( access_type & ZEND_ACC_STATIC ) {
2003-02-05 21:35:52 +08:00
target_symbol_table = CG ( active_class_entry ) - > static_members ;
} else {
target_symbol_table = & CG ( active_class_entry ) - > default_properties ;
2002-12-09 20:10:17 +08:00
}
2003-02-10 20:46:58 +08:00
switch ( access_type & ZEND_ACC_PPP_MASK ) {
2003-02-04 20:12:34 +08:00
case ZEND_ACC_PRIVATE : {
2002-02-21 19:50:44 +08:00
char * priv_name ;
int priv_name_length ;
2003-02-04 20:12:34 +08:00
2002-07-16 02:09:56 +08:00
mangle_property_name ( & priv_name , & priv_name_length , CG ( active_class_entry ) - > name , CG ( active_class_entry ) - > name_length , var_name - > u . constant . value . str . val , var_name - > u . constant . value . str . len ) ;
2003-03-02 03:08:41 +08:00
free_var_name = 1 ;
2003-02-05 21:35:52 +08:00
zend_hash_update ( target_symbol_table , priv_name , priv_name_length + 1 , & property , sizeof ( zval * ) , NULL ) ;
2003-02-04 20:12:34 +08:00
property_info . name = priv_name ;
property_info . name_length = priv_name_length ;
2002-02-21 19:50:44 +08:00
}
2003-02-04 20:12:34 +08:00
break ;
case ZEND_ACC_PROTECTED : {
2002-07-16 02:09:56 +08:00
char * prot_name ;
int prot_name_length ;
mangle_property_name ( & prot_name , & prot_name_length , " * " , 1 , var_name - > u . constant . value . str . val , var_name - > u . constant . value . str . len ) ;
2003-03-02 03:08:41 +08:00
free_var_name = 1 ;
2003-02-05 21:35:52 +08:00
zend_hash_update ( target_symbol_table , prot_name , prot_name_length + 1 , & property , sizeof ( zval * ) , NULL ) ;
2003-02-04 20:12:34 +08:00
property_info . name = prot_name ;
property_info . name_length = prot_name_length ;
2002-07-16 02:09:56 +08:00
}
2003-02-04 20:12:34 +08:00
break ;
2002-12-07 01:09:44 +08:00
case ZEND_ACC_PUBLIC :
2003-02-05 21:35:52 +08:00
zend_hash_update ( target_symbol_table , var_name - > u . constant . value . str . val , var_name - > u . constant . value . str . len + 1 , & property , sizeof ( zval * ) , NULL ) ;
2003-02-04 20:12:34 +08:00
property_info . name = var_name - > u . constant . value . str . val ;
property_info . name_length = var_name - > u . constant . value . str . len ;
2002-02-14 12:01:53 +08:00
break ;
1999-04-08 02:10:10 +08:00
}
2003-02-10 20:46:58 +08:00
property_info . flags = access_type ;
2003-02-04 20:12:34 +08:00
property_info . h = zend_get_hash_value ( property_info . name , property_info . name_length + 1 ) ;
2003-02-05 21:35:52 +08:00
zend_hash_update ( & CG ( active_class_entry ) - > properties_info , var_name - > u . constant . value . str . val , var_name - > u . constant . value . str . len + 1 , & property_info , sizeof ( zend_property_info ) , NULL ) ;
2003-03-02 03:08:41 +08:00
if ( free_var_name ) {
efree ( var_name - > u . constant . value . str . val ) ;
}
1999-04-08 02:10:10 +08:00
}
2002-12-07 01:09:44 +08:00
void zend_do_declare_class_constant ( znode * var_name , znode * value TSRMLS_DC )
{
zval * property ;
ALLOC_ZVAL ( property ) ;
if ( value ) {
* property = value - > u . constant ;
} else {
INIT_PZVAL ( property ) ;
property - > type = IS_NULL ;
}
zend_hash_update ( & CG ( active_class_entry ) - > constants_table , var_name - > u . constant . value . str . val , var_name - > u . constant . value . str . len + 1 , & property , sizeof ( zval * ) , NULL ) ;
FREE_PNODE ( var_name ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_fetch_property ( znode * result , znode * object , znode * property TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
1999-09-20 23:44:30 +08:00
zend_op opline ;
1999-04-08 02:10:10 +08:00
zend_llist * fetch_list_ptr ;
2002-11-05 01:35:41 +08:00
zend_op * opline_ptr = NULL ;
2002-07-16 02:09:56 +08:00
2002-01-05 23:18:30 +08:00
zend_stack_top ( & CG ( bp_stack ) , ( void * * ) & fetch_list_ptr ) ;
2002-07-16 02:09:56 +08:00
2002-01-05 23:18:30 +08:00
if ( fetch_list_ptr - > count = = 1 ) {
zend_llist_element * le ;
le = fetch_list_ptr - > head ;
opline_ptr = ( zend_op * ) le - > data ;
2002-10-08 05:20:23 +08:00
2002-03-15 23:09:46 +08:00
if ( ( opline_ptr - > op1 . op_type = = IS_CONST ) & & ( opline_ptr - > op1 . u . constant . type = = IS_STRING ) & &
2002-10-08 05:20:23 +08:00
( opline_ptr - > op1 . u . constant . value . str . len = = ( sizeof ( " this " ) - 1 ) ) & &
! memcmp ( opline_ptr - > op1 . u . constant . value . str . val , " this " , sizeof ( " this " ) ) ) {
2002-03-15 23:09:46 +08:00
efree ( opline_ptr - > op1 . u . constant . value . str . val ) ;
2002-10-17 02:06:36 +08:00
SET_UNUSED ( opline_ptr - > op1 ) ; /* this means $this for objects */
opline_ptr - > op2 = * property ;
/* if it was usual fetch, we change it to object fetch */
2002-11-30 19:20:25 +08:00
switch ( opline_ptr - > opcode ) {
2002-10-17 02:06:36 +08:00
case ZEND_FETCH_W :
opline_ptr - > opcode = ZEND_FETCH_OBJ_W ;
break ;
case ZEND_FETCH_R :
opline_ptr - > opcode = ZEND_FETCH_OBJ_R ;
break ;
case ZEND_FETCH_RW :
opline_ptr - > opcode = ZEND_FETCH_OBJ_RW ;
break ;
case ZEND_FETCH_IS :
opline_ptr - > opcode = ZEND_FETCH_OBJ_IS ;
break ;
case ZEND_FETCH_UNSET :
opline_ptr - > opcode = ZEND_FETCH_OBJ_UNSET ;
break ;
case ZEND_FETCH_FUNC_ARG :
opline_ptr - > opcode = ZEND_FETCH_OBJ_FUNC_ARG ;
break ;
}
2002-01-05 23:18:30 +08:00
* result = opline_ptr - > result ;
2003-02-10 20:46:58 +08:00
if ( CG ( active_class_entry )
2003-03-12 17:38:19 +08:00
& & property - > op_type = = IS_CONST
2003-02-10 20:46:58 +08:00
& & ! zend_hash_exists ( & CG ( active_class_entry ) - > properties_info , property - > u . constant . value . str . val , property - > u . constant . value . str . len + 1 ) ) {
2003-02-11 00:11:24 +08:00
property - > u . constant . value . str . val = estrndup ( property - > u . constant . value . str . val , property - > u . constant . value . str . len ) ;
2003-02-10 20:46:58 +08:00
zend_do_declare_property ( property , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC ) ;
}
2002-01-05 23:18:30 +08:00
return ;
}
}
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
init_op ( & opline TSRMLS_CC ) ;
1999-09-20 23:44:30 +08:00
opline . opcode = ZEND_FETCH_OBJ_W ; /* the backpatching routine assumes W */
opline . result . op_type = IS_VAR ;
opline . result . u . EA . type = 0 ;
opline . result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline . op1 = * object ;
2002-07-16 02:09:56 +08:00
opline . op2 = * property ;
1999-09-20 23:44:30 +08:00
* result = opline . result ;
1999-04-08 02:10:10 +08:00
1999-09-20 23:44:30 +08:00
zend_llist_add_element ( fetch_list_ptr , & opline ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_push_object ( znode * object TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_stack_push ( & CG ( object_stack ) , object , sizeof ( znode ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_pop_object ( znode * object TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
znode * tmp ;
zend_stack_top ( & CG ( object_stack ) , ( void * * ) & tmp ) ;
* object = * tmp ;
zend_stack_del_top ( & CG ( object_stack ) ) ;
}
2001-11-05 03:30:49 +08:00
void zend_do_begin_new_object ( znode * new_token , znode * class_type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
unsigned char * ptr = NULL ;
opline - > opcode = ZEND_NEW ;
2000-08-15 03:17:26 +08:00
opline - > result . op_type = IS_VAR ;
1999-04-08 02:10:10 +08:00
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
2001-11-05 03:30:49 +08:00
opline - > op1 = * class_type ;
1999-04-08 02:10:10 +08:00
SET_UNUSED ( opline - > op2 ) ;
new_token - > u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMP_NO_CTOR ;
1999-07-27 00:57:06 +08:00
opline - > op1 = ( opline - 1 ) - > result ;
1999-04-08 02:10:10 +08:00
SET_UNUSED ( opline - > op2 ) ;
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2002-01-04 14:44:19 +08:00
opline - > opcode = ZEND_INIT_CTOR_CALL ;
1999-07-27 00:57:06 +08:00
opline - > op1 = ( opline - 2 ) - > result ;
2001-11-03 19:59:14 +08:00
SET_UNUSED ( opline - > op2 ) ;
1999-04-08 02:10:10 +08:00
zend_stack_push ( & CG ( function_call_stack ) , ( void * ) & ptr , sizeof ( unsigned char * ) ) ;
}
2001-11-05 03:30:49 +08:00
void zend_do_end_new_object ( znode * result , znode * new_token , znode * argument_list TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
znode ctor_result ;
2001-11-05 03:30:49 +08:00
zend_do_end_function_call ( NULL , & ctor_result , argument_list , 1 , 0 TSRMLS_CC ) ;
2001-07-28 18:51:54 +08:00
zend_do_free ( & ctor_result TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
CG ( active_op_array ) - > opcodes [ new_token - > u . opline_num ] . op2 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
1999-07-27 00:57:06 +08:00
* result = CG ( active_op_array ) - > opcodes [ new_token - > u . opline_num ] . op1 ;
1999-04-08 02:10:10 +08:00
}
2003-04-10 23:43:47 +08:00
void zend_do_fold_constant ( znode * result , znode * constant_name TSRMLS_DC )
{
zval * * zresult ;
if ( zend_hash_find ( & CG ( active_class_entry ) - > constants_table , constant_name - > u . constant . value . str . val ,
constant_name - > u . constant . value . str . len + 1 , ( void * * ) & zresult ) ! = SUCCESS ) {
2003-04-11 01:02:31 +08:00
if ( zend_get_constant ( constant_name - > u . constant . value . str . val , constant_name - > u . constant . value . str . len , & result - > u . constant TSRMLS_CC ) ) {
2003-04-10 23:43:47 +08:00
return ;
} else {
zend_error ( E_COMPILE_ERROR , " Cannot find %s constant in class %s \n " ,
constant_name - > u . constant . value . str . val , CG ( active_class_entry ) - > name ) ;
}
}
result - > u . constant = * * zresult ;
zval_copy_ctor ( & result - > u . constant ) ;
}
1999-04-08 02:10:10 +08:00
2001-12-01 00:29:47 +08:00
void zend_do_fetch_constant ( znode * result , znode * constant_container , znode * constant_name , int mode TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
switch ( mode ) {
case ZEND_CT :
2001-12-01 00:29:47 +08:00
if ( constant_container ) {
2003-03-10 04:53:57 +08:00
zend_do_fetch_class_name ( NULL , constant_container , constant_name , 1 TSRMLS_CC ) ;
2001-12-01 00:29:47 +08:00
* result = * constant_container ;
} else {
* result = * constant_name ;
}
1999-04-08 02:10:10 +08:00
result - > u . constant . type = IS_CONSTANT ;
break ;
2001-12-01 00:29:47 +08:00
case ZEND_RT :
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_FETCH_CONSTANT ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
2001-12-01 00:29:47 +08:00
if ( constant_container ) {
opline - > op1 = * constant_container ;
} else {
SET_UNUSED ( opline - > op1 ) ;
}
opline - > op2 = * constant_name ;
1999-04-08 02:10:10 +08:00
* result = opline - > result ;
}
break ;
}
}
2001-07-28 18:51:54 +08:00
void zend_do_shell_exec ( znode * result , znode * cmd TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
switch ( cmd - > op_type ) {
case IS_TMP_VAR :
opline - > opcode = ZEND_SEND_VAL ;
break ;
default :
opline - > opcode = ZEND_SEND_VAR ;
break ;
}
opline - > op1 = * cmd ;
opline - > op2 . u . opline_num = 0 ;
1999-06-09 02:33:31 +08:00
opline - > extended_value = ZEND_DO_FCALL ;
1999-04-08 02:10:10 +08:00
SET_UNUSED ( opline - > op2 ) ;
2001-08-30 23:31:35 +08:00
/* FIXME: exception support not added to this op2 */
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_DO_FCALL ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
2000-01-30 01:49:05 +08:00
opline - > result . op_type = IS_VAR ;
2001-08-11 23:56:40 +08:00
opline - > op1 . u . constant . value . str . val = estrndup ( " shell_exec " , sizeof ( " shell_exec " ) - 1 ) ;
1999-04-08 02:10:10 +08:00
opline - > op1 . u . constant . value . str . len = sizeof ( " shell_exec " ) - 1 ;
1999-07-10 04:43:59 +08:00
INIT_PZVAL ( & opline - > op1 . u . constant ) ;
1999-04-08 02:10:10 +08:00
opline - > op1 . u . constant . type = IS_STRING ;
opline - > op1 . op_type = IS_CONST ;
1999-06-01 02:33:12 +08:00
opline - > extended_value = 1 ;
1999-04-08 02:10:10 +08:00
SET_UNUSED ( opline - > op2 ) ;
* result = opline - > result ;
}
2002-04-24 02:06:54 +08:00
void zend_do_init_array ( znode * result , znode * expr , znode * offset , zend_bool is_ref TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_INIT_ARRAY ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > result . op_type = IS_TMP_VAR ;
* result = opline - > result ;
if ( expr ) {
opline - > op1 = * expr ;
if ( offset ) {
opline - > op2 = * offset ;
} else {
SET_UNUSED ( opline - > op2 ) ;
}
} else {
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
1999-10-01 18:00:05 +08:00
opline - > extended_value = is_ref ;
1999-04-08 02:10:10 +08:00
}
2002-04-24 02:06:54 +08:00
void zend_do_add_array_element ( znode * result , znode * expr , znode * offset , zend_bool is_ref TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_ADD_ARRAY_ELEMENT ;
opline - > result = * result ;
opline - > op1 = * expr ;
if ( offset ) {
opline - > op2 = * offset ;
} else {
SET_UNUSED ( opline - > op2 ) ;
}
1999-10-01 18:00:05 +08:00
opline - > extended_value = is_ref ;
1999-04-08 02:10:10 +08:00
}
2000-11-03 03:27:55 +08:00
void zend_do_add_static_array_element ( znode * result , znode * offset , znode * expr )
1999-04-08 02:10:10 +08:00
{
1999-12-27 05:21:33 +08:00
zval * element ;
1999-04-08 02:10:10 +08:00
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( element ) ;
1999-04-08 02:10:10 +08:00
* element = expr - > u . constant ;
if ( offset ) {
switch ( offset - > u . constant . type ) {
2000-12-07 18:36:45 +08:00
case IS_CONSTANT :
2001-07-16 19:41:06 +08:00
/* Ugly hack to denote that this value has a constant index */
element - > type | = IS_CONSTANT_INDEX ;
/* break missing intentionally */
1999-04-08 02:10:10 +08:00
case IS_STRING :
zend_hash_update ( result - > u . constant . value . ht , offset - > u . constant . value . str . val , offset - > u . constant . value . str . len + 1 , & element , sizeof ( zval * ) , NULL ) ;
1999-06-23 03:05:40 +08:00
zval_dtor ( & offset - > u . constant ) ;
1999-04-08 02:10:10 +08:00
break ;
case IS_LONG :
zend_hash_index_update ( result - > u . constant . value . ht , offset - > u . constant . value . lval , & element , sizeof ( zval * ) , NULL ) ;
break ;
}
} else {
zend_hash_next_index_insert ( result - > u . constant . value . ht , & element , sizeof ( zval * ) , NULL ) ;
}
}
2001-07-28 18:51:54 +08:00
void zend_do_add_list_element ( znode * element TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
list_llist_element lle ;
1999-05-23 00:10:51 +08:00
if ( element ) {
2002-03-18 03:13:46 +08:00
zend_check_writable_variable ( element ) ;
1999-04-08 02:10:10 +08:00
lle . var = * element ;
zend_llist_copy ( & lle . dimensions , & CG ( dimension_llist ) ) ;
2000-02-06 04:19:46 +08:00
zend_llist_prepend_element ( & CG ( list_llist ) , & lle ) ;
1999-04-08 02:10:10 +08:00
}
( * ( ( int * ) CG ( dimension_llist ) . tail - > data ) ) + + ;
}
2001-07-28 18:51:54 +08:00
void zend_do_new_list_begin ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
int current_dimension = 0 ;
zend_llist_add_element ( & CG ( dimension_llist ) , & current_dimension ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_new_list_end ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
zend_llist_remove_tail ( & CG ( dimension_llist ) ) ;
( * ( ( int * ) CG ( dimension_llist ) . tail - > data ) ) + + ;
}
2001-07-28 18:51:54 +08:00
void zend_do_list_init ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
2001-07-16 23:48:31 +08:00
zend_stack_push ( & CG ( list_stack ) , & CG ( list_llist ) , sizeof ( zend_llist ) ) ;
zend_stack_push ( & CG ( list_stack ) , & CG ( dimension_llist ) , sizeof ( zend_llist ) ) ;
1999-04-08 02:10:10 +08:00
zend_llist_init ( & CG ( list_llist ) , sizeof ( list_llist_element ) , NULL , 0 ) ;
zend_llist_init ( & CG ( dimension_llist ) , sizeof ( int ) , NULL , 0 ) ;
2001-07-28 18:51:54 +08:00
zend_do_new_list_begin ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_list_end ( znode * result , znode * expr TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_llist_element * le ;
zend_llist_element * dimension ;
zend_op * opline ;
znode last_container ;
le = CG ( list_llist ) . head ;
while ( le ) {
zend_llist * tmp_dimension_llist = & ( ( list_llist_element * ) le - > data ) - > dimensions ;
dimension = tmp_dimension_llist - > head ;
while ( dimension ) {
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
if ( dimension = = tmp_dimension_llist - > head ) { /* first */
last_container = * expr ;
2002-11-30 19:20:25 +08:00
switch ( expr - > op_type ) {
1999-04-08 02:10:10 +08:00
case IS_VAR :
opline - > opcode = ZEND_FETCH_DIM_R ;
break ;
case IS_TMP_VAR :
2000-10-19 17:36:53 +08:00
opline - > opcode = ZEND_FETCH_DIM_TMP_VAR ;
break ;
1999-04-08 02:10:10 +08:00
case IS_CONST : /* fetch_dim_tmp_var will handle this bogus fetch */
2000-10-19 17:36:53 +08:00
zval_copy_ctor ( & expr - > u . constant ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_FETCH_DIM_TMP_VAR ;
break ;
}
} else {
opline - > opcode = ZEND_FETCH_DIM_R ;
}
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = last_container ;
opline - > op2 . op_type = IS_CONST ;
opline - > op2 . u . constant . type = IS_LONG ;
opline - > op2 . u . constant . value . lval = * ( ( int * ) dimension - > data ) ;
1999-07-10 04:43:59 +08:00
INIT_PZVAL ( & opline - > op2 . u . constant ) ;
2000-02-03 00:47:43 +08:00
opline - > extended_value = ZEND_FETCH_ADD_LOCK ;
1999-04-08 02:10:10 +08:00
last_container = opline - > result ;
dimension = dimension - > next ;
}
( ( list_llist_element * ) le - > data ) - > value = last_container ;
zend_llist_destroy ( & ( ( list_llist_element * ) le - > data ) - > dimensions ) ;
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_W , 0 TSRMLS_CC ) ;
zend_do_assign ( result , & ( ( list_llist_element * ) le - > data ) - > var , & ( ( list_llist_element * ) le - > data ) - > value TSRMLS_CC ) ;
1999-04-13 02:29:09 +08:00
CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] . result . u . EA . type | = EXT_TYPE_UNUSED ;
1999-04-08 02:10:10 +08:00
le = le - > next ;
}
zend_llist_destroy ( & CG ( dimension_llist ) ) ;
zend_llist_destroy ( & CG ( list_llist ) ) ;
* result = * expr ;
2001-07-16 23:48:31 +08:00
{
zend_llist * p ;
/* restore previous lists */
zend_stack_top ( & CG ( list_stack ) , ( void * * ) & p ) ;
CG ( dimension_llist ) = * p ;
zend_stack_del_top ( & CG ( list_stack ) ) ;
zend_stack_top ( & CG ( list_stack ) , ( void * * ) & p ) ;
CG ( list_llist ) = * p ;
zend_stack_del_top ( & CG ( list_stack ) ) ;
}
1999-04-08 02:10:10 +08:00
}
2002-11-11 01:50:27 +08:00
void zend_do_fetch_static_variable ( znode * varname , znode * static_assignment , int fetch_type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2002-11-11 01:50:27 +08:00
zval * tmp ;
2003-01-20 01:25:39 +08:00
zend_op * opline ;
znode lval ;
znode result ;
1999-04-08 02:10:10 +08:00
2002-11-11 01:50:27 +08:00
ALLOC_ZVAL ( tmp ) ;
convert_to_string ( & varname - > u . constant ) ;
2002-11-30 19:20:25 +08:00
if ( static_assignment ) {
1999-04-08 02:10:10 +08:00
* tmp = static_assignment - > u . constant ;
2002-11-11 01:50:27 +08:00
} else {
INIT_ZVAL ( * tmp ) ;
}
if ( ! CG ( active_op_array ) - > static_variables ) {
ALLOC_HASHTABLE ( CG ( active_op_array ) - > static_variables ) ;
zend_hash_init ( CG ( active_op_array ) - > static_variables , 2 , NULL , ZVAL_PTR_DTOR , 0 ) ;
1999-04-08 02:10:10 +08:00
}
2002-11-11 01:50:27 +08:00
zend_hash_update ( CG ( active_op_array ) - > static_variables , varname - > u . constant . value . str . val , varname - > u . constant . value . str . len + 1 , & tmp , sizeof ( zval * ) , NULL ) ;
2003-01-20 01:25:39 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_FETCH_W ; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * varname ;
SET_UNUSED ( opline - > op2 ) ;
opline - > op2 . u . EA . type = fetch_type ;
result = opline - > result ;
if ( varname - > op_type = = IS_CONST ) {
zval_copy_ctor ( & varname - > u . constant ) ;
}
fetch_simple_variable ( & lval , varname , 0 TSRMLS_CC ) ; /* Relies on the fact that the default fetch is BP_VAR_W */
zend_do_assign_ref ( NULL , & lval , & result TSRMLS_CC ) ;
CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] . result . u . EA . type | = EXT_TYPE_UNUSED ;
/* zval_dtor(&varname->u.constant); */
2002-11-11 01:50:27 +08:00
}
1999-04-08 02:10:10 +08:00
2002-11-11 01:50:27 +08:00
void zend_do_fetch_global_variable ( znode * varname , znode * static_assignment , int fetch_type TSRMLS_DC )
{
zend_op * opline ;
znode lval ;
znode result ;
1999-04-08 02:10:10 +08:00
2002-11-11 01:50:27 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_FETCH_W ; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * varname ;
SET_UNUSED ( opline - > op2 ) ;
2002-01-06 03:59:09 +08:00
opline - > op2 . u . EA . type = fetch_type ;
2000-03-31 23:17:43 +08:00
result = opline - > result ;
1999-04-08 02:10:10 +08:00
if ( varname - > op_type = = IS_CONST ) {
zval_copy_ctor ( & varname - > u . constant ) ;
}
2001-07-28 18:51:54 +08:00
fetch_simple_variable ( & lval , varname , 0 TSRMLS_CC ) ; /* Relies on the fact that the default fetch is BP_VAR_W */
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
zend_do_assign_ref ( NULL , & lval , & result TSRMLS_CC ) ;
1999-04-08 08:18:29 +08:00
CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] . result . u . EA . type | = EXT_TYPE_UNUSED ;
1999-04-08 02:10:10 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_cast ( znode * result , znode * expr , int type TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_CAST ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * expr ;
SET_UNUSED ( opline - > op2 ) ;
2000-05-04 01:56:44 +08:00
opline - > extended_value = type ;
1999-04-08 02:10:10 +08:00
* result = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_include_or_eval ( int type , znode * result , znode * op1 TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_do_extended_fcall_begin ( TSRMLS_C ) ;
2000-09-11 23:15:57 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
2000-09-11 23:15:57 +08:00
opline - > opcode = ZEND_INCLUDE_OR_EVAL ;
opline - > result . op_type = IS_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * op1 ;
SET_UNUSED ( opline - > op2 ) ;
opline - > op2 . u . constant . value . lval = type ;
* result = opline - > result ;
1999-12-23 23:03:25 +08:00
}
2001-07-28 18:51:54 +08:00
zend_do_extended_fcall_end ( TSRMLS_C ) ;
1999-12-23 23:03:25 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_indirect_references ( znode * result , znode * num_references , znode * variable TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int i ;
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_R , 0 TSRMLS_CC ) ;
1999-09-20 22:45:36 +08:00
for ( i = 1 ; i < num_references - > u . constant . value . lval ; i + + ) {
2001-07-28 18:51:54 +08:00
fetch_simple_variable_ex ( result , variable , 0 , ZEND_FETCH_R TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
* variable = * result ;
}
2001-07-28 18:51:54 +08:00
zend_do_begin_variable_parse ( TSRMLS_C ) ;
fetch_simple_variable ( result , variable , 1 TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
2002-07-15 03:23:18 +08:00
void zend_do_unset ( znode * variable TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
zend_op * last_op ;
2002-03-18 03:13:46 +08:00
zend_check_writable_variable ( variable ) ;
1999-04-08 02:10:10 +08:00
last_op = & CG ( active_op_array ) - > opcodes [ get_next_op_number ( CG ( active_op_array ) ) - 1 ] ;
switch ( last_op - > opcode ) {
2000-02-15 04:31:01 +08:00
case ZEND_FETCH_UNSET :
1999-04-24 08:12:55 +08:00
last_op - > opcode = ZEND_UNSET_VAR ;
1999-04-08 02:10:10 +08:00
break ;
2000-02-15 04:31:01 +08:00
case ZEND_FETCH_DIM_UNSET :
case ZEND_FETCH_OBJ_UNSET :
1999-04-24 08:12:55 +08:00
last_op - > opcode = ZEND_UNSET_DIM_OBJ ;
1999-04-08 02:10:10 +08:00
break ;
}
}
2001-07-28 18:51:54 +08:00
void zend_do_isset_or_isempty ( int type , znode * result , znode * variable TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2002-02-05 03:29:56 +08:00
zend_op * last_op ;
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
zend_do_end_variable_parse ( BP_VAR_IS , 0 TSRMLS_CC ) ;
2001-12-26 22:46:18 +08:00
2002-03-18 03:13:46 +08:00
zend_check_writable_variable ( variable ) ;
2002-02-05 03:29:56 +08:00
last_op = & CG ( active_op_array ) - > opcodes [ get_next_op_number ( CG ( active_op_array ) ) - 1 ] ;
switch ( last_op - > opcode ) {
case ZEND_FETCH_IS :
last_op - > opcode = ZEND_ISSET_ISEMPTY_VAR ;
break ;
case ZEND_FETCH_DIM_IS :
case ZEND_FETCH_OBJ_IS :
last_op - > opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ ;
break ;
}
last_op - > result . op_type = IS_TMP_VAR ;
last_op - > extended_value = type ;
* result = last_op - > result ;
1999-04-08 02:10:10 +08:00
}
2003-01-15 05:29:23 +08:00
void zend_do_instanceof ( znode * result , znode * expr , znode * class_znode , int type TSRMLS_DC )
2002-07-30 12:07:15 +08:00
{
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-01-15 05:29:23 +08:00
opline - > opcode = ZEND_INSTANCEOF ;
2002-07-30 12:07:15 +08:00
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * expr ;
2002-11-06 01:21:23 +08:00
opline - > op2 = * class_znode ;
2002-07-30 12:07:15 +08:00
* result = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_foreach_begin ( znode * foreach_token , znode * array , znode * open_brackets_token , znode * as_token , int variable TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-08-08 23:07:11 +08:00
zend_op * opline ;
zend_bool is_variable ;
if ( variable ) {
2001-12-26 22:46:18 +08:00
if ( zend_is_function_or_method_call ( array ) ) {
2001-08-08 23:07:11 +08:00
is_variable = 0 ;
} else {
is_variable = 1 ;
}
zend_do_end_variable_parse ( BP_VAR_W , 0 TSRMLS_CC ) ;
} else {
is_variable = 0 ;
}
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
/* Preform array reset */
opline - > opcode = ZEND_FE_RESET ;
2000-01-25 03:04:07 +08:00
opline - > result . op_type = IS_VAR ;
1999-04-08 02:10:10 +08:00
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * array ;
SET_UNUSED ( opline - > op2 ) ;
2001-08-08 23:07:11 +08:00
opline - > extended_value = is_variable ;
1999-04-08 02:10:10 +08:00
* open_brackets_token = opline - > result ;
1999-09-09 22:15:17 +08:00
zend_stack_push ( & CG ( foreach_copy_stack ) , ( void * ) & opline - > result , sizeof ( znode ) ) ;
1999-04-08 02:10:10 +08:00
/* save the location of the beginning of the loop (array fetching) */
foreach_token - > u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_FE_FETCH ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * open_brackets_token ;
SET_UNUSED ( opline - > op2 ) ;
* as_token = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_foreach_cont ( znode * value , znode * key , znode * as_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
znode result_value , result_key , dummy ;
if ( key - > op_type ! = IS_UNUSED ) {
znode * tmp ;
/* switch between the key and value... */
tmp = key ;
key = value ;
value = tmp ;
}
opline - > opcode = ZEND_FETCH_DIM_TMP_VAR ;
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . opline_num = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * as_token ;
opline - > op2 . op_type = IS_CONST ;
opline - > op2 . u . constant . type = IS_LONG ;
opline - > op2 . u . constant . value . lval = 0 ;
1999-05-23 00:10:51 +08:00
opline - > extended_value = ZEND_FETCH_STANDARD ; /* ignored in fetch_dim_tmp_var, but what the hell. */
1999-04-08 02:10:10 +08:00
result_value = opline - > result ;
if ( key - > op_type ! = IS_UNUSED ) {
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_FETCH_DIM_TMP_VAR ;
opline - > result . op_type = IS_VAR ;
opline - > result . u . EA . type = 0 ;
opline - > result . u . opline_num = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * as_token ;
opline - > op2 . op_type = IS_CONST ;
opline - > op2 . u . constant . type = IS_LONG ;
opline - > op2 . u . constant . value . lval = 1 ;
1999-05-23 00:10:51 +08:00
opline - > extended_value = ZEND_FETCH_STANDARD ; /* ignored in fetch_dim_tmp_var, but what the hell. */
1999-04-08 02:10:10 +08:00
result_key = opline - > result ;
}
2001-07-28 18:51:54 +08:00
zend_do_assign ( & dummy , value , & result_value TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] . result . u . EA . type | = EXT_TYPE_UNUSED ;
if ( key - > op_type ! = IS_UNUSED ) {
2001-07-28 18:51:54 +08:00
zend_do_assign ( & dummy , key , & result_key TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] . result . u . EA . type | = EXT_TYPE_UNUSED ;
}
2001-07-28 18:51:54 +08:00
zend_do_free ( as_token TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
do_begin_loop ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
INC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_foreach_end ( znode * foreach_token , znode * open_brackets_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMP ;
opline - > op1 . u . opline_num = foreach_token - > u . opline_num ;
1999-10-28 23:53:31 +08:00
SET_UNUSED ( opline - > op1 ) ;
1999-04-08 02:10:10 +08:00
SET_UNUSED ( opline - > op2 ) ;
CG ( active_op_array ) - > opcodes [ foreach_token - > u . opline_num ] . op2 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
do_end_loop ( foreach_token - > u . opline_num TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
2001-07-28 18:51:54 +08:00
generate_free_foreach_copy ( open_brackets_token TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
1999-09-09 22:15:17 +08:00
zend_stack_del_top ( & CG ( foreach_copy_stack ) ) ;
1999-04-08 02:10:10 +08:00
DEC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_declare_begin ( TSRMLS_D )
2000-01-25 03:00:30 +08:00
{
zend_stack_push ( & CG ( declare_stack ) , & CG ( declarables ) , sizeof ( zend_declarables ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_declare_stmt ( znode * var , znode * val TSRMLS_DC )
2000-01-25 03:00:30 +08:00
{
convert_to_string ( & var - > u . constant ) ;
if ( ! zend_binary_strcasecmp ( var - > u . constant . value . str . val , var - > u . constant . value . str . len , " ticks " , sizeof ( " ticks " ) - 1 ) ) {
convert_to_long ( & val - > u . constant ) ;
CG ( declarables ) . ticks = val - > u . constant ;
}
zval_dtor ( & var - > u . constant ) ;
}
2002-08-14 09:40:59 +08:00
void zend_do_declare_end ( znode * declare_token TSRMLS_DC )
2000-01-25 03:00:30 +08:00
{
zend_declarables * declarables ;
zend_stack_top ( & CG ( declare_stack ) , ( void * * ) & declarables ) ;
2002-07-31 06:19:50 +08:00
/* We should restore if there was more than (current - start) - (ticks?1:0) opcodes */
2002-08-14 09:40:59 +08:00
if ( ( get_next_op_number ( CG ( active_op_array ) ) - declare_token - > u . opline_num ) - ( ( CG ( declarables ) . ticks . value . lval ) ? 1 : 0 ) ) {
2002-07-31 06:19:50 +08:00
CG ( declarables ) = * declarables ;
}
2000-01-25 03:00:30 +08:00
}
2001-07-28 18:51:54 +08:00
void zend_do_end_heredoc ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
int opline_num = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
zend_op * opline = & CG ( active_op_array ) - > opcodes [ opline_num ] ;
if ( opline - > opcode ! = ZEND_ADD_STRING ) {
return ;
}
opline - > op2 . u . constant . value . str . val [ ( opline - > op2 . u . constant . value . str . len - - ) - 1 ] = 0 ;
if ( opline - > op2 . u . constant . value . str . len > 0 ) {
if ( opline - > op2 . u . constant . value . str . val [ opline - > op2 . u . constant . value . str . len - 1 ] = = ' \r ' ) {
opline - > op2 . u . constant . value . str . val [ ( opline - > op2 . u . constant . value . str . len - - ) - 1 ] = 0 ;
}
}
}
2001-07-28 18:51:54 +08:00
void zend_do_exit ( znode * result , znode * message TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_EXIT ;
opline - > op1 = * message ;
SET_UNUSED ( opline - > op2 ) ;
result - > op_type = IS_CONST ;
result - > u . constant . type = IS_BOOL ;
result - > u . constant . value . lval = 1 ;
}
2001-07-28 18:51:54 +08:00
void zend_do_begin_silence ( znode * strudel_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_BEGIN_SILENCE ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
* strudel_token = opline - > result ;
}
2001-07-28 18:51:54 +08:00
void zend_do_end_silence ( znode * strudel_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_END_SILENCE ;
opline - > op1 = * strudel_token ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_begin_qm_op ( znode * cond , znode * qm_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int jmpz_op_number = get_next_op_number ( CG ( active_op_array ) ) ;
zend_op * opline ;
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMPZ ;
opline - > op1 = * cond ;
SET_UNUSED ( opline - > op2 ) ;
opline - > op2 . u . opline_num = jmpz_op_number ;
* qm_token = opline - > op2 ;
INC_BPC ( CG ( active_op_array ) ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_qm_true ( znode * true_value , znode * qm_token , znode * colon_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
CG ( active_op_array ) - > opcodes [ qm_token - > u . opline_num ] . op2 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) + 1 ; /* jmp over the ZEND_JMP */
opline - > opcode = ZEND_QM_ASSIGN ;
opline - > result . op_type = IS_TMP_VAR ;
opline - > result . u . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op1 = * true_value ;
SET_UNUSED ( opline - > op2 ) ;
* qm_token = opline - > result ;
colon_token - > u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_JMP ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_qm_false ( znode * result , znode * false_value , znode * qm_token , znode * colon_token TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_QM_ASSIGN ;
opline - > result = * qm_token ;
opline - > op1 = * false_value ;
SET_UNUSED ( opline - > op2 ) ;
CG ( active_op_array ) - > opcodes [ colon_token - > u . opline_num ] . op1 . u . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
* result = opline - > result ;
DEC_BPC ( CG ( active_op_array ) ) ;
}
2000-01-25 03:00:30 +08:00
2001-07-28 18:51:54 +08:00
void zend_do_extended_info ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
zend_op * opline ;
if ( ! CG ( extended_info ) ) {
return ;
}
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_EXT_STMT ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2000-01-25 03:00:30 +08:00
2001-07-28 18:51:54 +08:00
void zend_do_extended_fcall_begin ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
zend_op * opline ;
if ( ! CG ( extended_info ) ) {
return ;
}
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_EXT_FCALL_BEGIN ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-07-28 18:51:54 +08:00
void zend_do_extended_fcall_end ( TSRMLS_D )
1999-04-08 02:10:10 +08:00
{
zend_op * opline ;
if ( ! CG ( extended_info ) ) {
return ;
}
2001-07-28 18:51:54 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
opline - > opcode = ZEND_EXT_FCALL_END ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2001-08-09 01:18:16 +08:00
2001-07-28 18:51:54 +08:00
void zend_do_ticks ( TSRMLS_D )
2000-01-25 03:00:30 +08:00
{
if ( CG ( declarables ) . ticks . value . lval ) {
2001-07-28 18:51:54 +08:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2000-01-25 03:00:30 +08:00
opline - > opcode = ZEND_TICKS ;
opline - > op1 . u . constant = CG ( declarables ) . ticks ;
opline - > op1 . op_type = IS_CONST ;
SET_UNUSED ( opline - > op2 ) ;
}
}
2003-03-02 18:04:53 +08:00
void zend_auto_global_dtor ( zend_auto_global * auto_global )
{
free ( auto_global - > name ) ;
}
2003-03-02 21:33:31 +08:00
zend_bool zend_is_auto_global ( char * name , uint name_len TSRMLS_DC )
{
zend_auto_global * auto_global ;
if ( zend_hash_find ( CG ( auto_globals ) , name , name_len + 1 , ( void * * ) & auto_global ) = = SUCCESS ) {
if ( auto_global - > armed ) {
auto_global - > armed = auto_global - > auto_global_callback ( auto_global - > name , auto_global - > name_len TSRMLS_CC ) ;
}
return 1 ;
}
return 0 ;
}
2003-03-02 18:04:53 +08:00
int zend_register_auto_global ( char * name , uint name_len , zend_auto_global_callback auto_global_callback TSRMLS_DC )
2001-08-09 01:18:16 +08:00
{
2003-03-02 18:04:53 +08:00
zend_auto_global auto_global ;
auto_global . name = zend_strndup ( name , name_len ) ;
auto_global . name_len = name_len ;
auto_global . auto_global_callback = auto_global_callback ;
return zend_hash_add ( CG ( auto_globals ) , name , name_len + 1 , & auto_global , sizeof ( zend_auto_global ) , NULL ) ;
2001-08-09 01:18:16 +08:00
}
2001-07-28 18:51:54 +08:00
int zendlex ( znode * zendlval TSRMLS_DC )
1999-04-08 02:10:10 +08:00
{
int retval ;
2003-05-29 17:01:55 +08:00
again :
2001-08-06 22:36:46 +08:00
if ( CG ( increment_lineno ) ) {
CG ( zend_lineno ) + + ;
CG ( increment_lineno ) = 0 ;
}
1999-04-08 02:10:10 +08:00
zendlval - > u . constant . type = IS_LONG ;
2001-07-28 18:51:54 +08:00
retval = lex_scan ( & zendlval - > u . constant TSRMLS_CC ) ;
2002-11-30 19:20:25 +08:00
switch ( retval ) {
1999-04-23 07:08:42 +08:00
case T_COMMENT :
2003-04-03 00:13:12 +08:00
case T_DOC_COMMENT :
1999-04-23 07:08:42 +08:00
case T_OPEN_TAG :
1999-04-08 02:10:10 +08:00
case T_WHITESPACE :
2003-05-29 17:01:55 +08:00
goto again ;
1999-04-23 07:08:42 +08:00
case T_CLOSE_TAG :
2001-08-06 22:36:46 +08:00
if ( LANG_SCNG ( yy_text ) [ LANG_SCNG ( yy_leng ) - 1 ] = = ' \n '
| | ( LANG_SCNG ( yy_text ) [ LANG_SCNG ( yy_leng ) - 2 ] = = ' \r ' & & LANG_SCNG ( yy_text ) [ LANG_SCNG ( yy_leng ) - 1 ] ) ) {
CG ( increment_lineno ) = 1 ;
}
1999-04-08 02:10:10 +08:00
retval = ' ; ' ; /* implicit ; */
break ;
1999-04-23 07:08:42 +08:00
case T_OPEN_TAG_WITH_ECHO :
retval = T_ECHO ;
1999-04-08 02:10:10 +08:00
break ;
2000-02-08 02:39:14 +08:00
case T_END_HEREDOC :
efree ( zendlval - > u . constant . value . str . val ) ;
break ;
1999-04-08 02:10:10 +08:00
}
1999-07-10 04:43:59 +08:00
INIT_PZVAL ( & zendlval - > u . constant ) ;
1999-04-08 02:10:10 +08:00
zendlval - > op_type = IS_CONST ;
return retval ;
}
2003-02-01 09:49:15 +08:00
2003-02-04 20:12:34 +08:00
void zend_duplicate_property_info ( zend_property_info * property_info )
{
property_info - > name = estrndup ( property_info - > name , property_info - > name_length ) ;
}
void zend_destroy_property_info ( zend_property_info * property_info )
{
efree ( property_info - > name ) ;
}
2003-02-16 19:12:43 +08:00
void zend_init_namespace ( zend_namespace * ns TSRMLS_DC )
{
2003-04-02 03:37:04 +08:00
zend_bool persistent_hashes = ( ns - > type = = ZEND_INTERNAL_NAMESPACE ) ? 1 : 0 ;
2003-04-01 04:42:01 +08:00
ns - > refcount = 1 ;
ns - > constants_updated = 0 ;
ns - > ce_flags = 0 ;
ns - > filename = NULL ;
ns - > doc_comment = NULL ;
ns - > doc_comment_len = 0 ;
2003-04-02 03:37:04 +08:00
if ( persistent_hashes ) {
ns - > static_members = ( HashTable * ) malloc ( sizeof ( HashTable ) ) ;
} else {
ALLOC_HASHTABLE ( ns - > static_members ) ;
}
zend_hash_init_ex ( ns - > static_members , 0 , NULL , ZVAL_PTR_DTOR , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ns - > function_table , 10 , NULL , ZEND_FUNCTION_DTOR , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ns - > class_table , 10 , NULL , ZEND_CLASS_DTOR , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ns - > constants_table , 10 , NULL , ZVAL_PTR_DTOR , persistent_hashes , 0 ) ;
2003-04-01 04:42:01 +08:00
ns - > parent = NULL ;
2003-04-03 22:44:41 +08:00
ns - > num_interfaces = 0 ;
ns - > interfaces = NULL ;
2003-04-01 04:42:01 +08:00
ns - > ns = NULL ;
2003-02-16 19:12:43 +08:00
ns - > constructor = NULL ;
2003-04-01 04:42:01 +08:00
ns - > destructor = NULL ;
ns - > clone = NULL ;
ns - > __get = NULL ;
ns - > __set = NULL ;
ns - > __call = NULL ;
ns - > create_object = NULL ;
2003-02-16 19:12:43 +08:00
}
void zend_do_begin_namespace ( znode * ns_token , znode * ns_name TSRMLS_DC )
{
2003-02-21 03:01:53 +08:00
zend_namespace * ns , * * pns ;
2003-02-16 19:12:43 +08:00
zend_op * opline ;
zend_str_tolower ( ns_name - > u . constant . value . str . val , ns_name - > u . constant . value . str . len ) ;
2003-02-21 03:01:53 +08:00
if ( zend_hash_find ( & CG ( global_namespace ) . class_table , ns_name - > u . constant . value . str . val , ns_name - > u . constant . value . str . len + 1 , ( void * * ) & pns ) = = SUCCESS ) {
ns = * pns ;
2003-04-02 03:37:04 +08:00
if ( ns - > type ! = ZEND_USER_NAMESPACE | | ns = = CG ( active_namespace ) ) {
2003-02-21 03:01:53 +08:00
zend_error ( E_COMPILE_ERROR , " Cannot redefine namespace '%s' - class or namespace with this name already defined " , ns - > name ) ;
2003-03-27 01:06:08 +08:00
}
FREE_PNODE ( ns_name ) ;
2003-02-21 03:01:53 +08:00
} else {
ns = emalloc ( sizeof ( zend_namespace ) ) ;
ns - > name = ns_name - > u . constant . value . str . val ;
ns - > name_length = ns_name - > u . constant . value . str . len ;
2003-04-02 03:37:04 +08:00
ns - > type = ZEND_USER_NAMESPACE ;
2003-02-21 03:01:53 +08:00
zend_hash_add ( & CG ( global_namespace ) . class_table , ns - > name , ns - > name_length + 1 , ( void * * ) & ns , sizeof ( zend_namespace * ) , NULL ) ;
zend_init_namespace ( ns TSRMLS_CC ) ;
2003-04-01 04:42:01 +08:00
ns - > line_start = zend_get_compiled_lineno ( TSRMLS_C ) ;
2003-02-16 19:12:43 +08:00
}
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-02-21 03:01:53 +08:00
opline - > opcode = ZEND_START_NAMESPACE ;
2003-02-16 19:12:43 +08:00
opline - > op1 . op_type = IS_CONST ;
opline - > op1 . u . constant . type = IS_STRING ;
opline - > op1 . u . constant . value . str . val = estrndup ( ns - > name , ns - > name_length ) ;
opline - > op1 . u . constant . value . str . len = ns - > name_length ;
opline - > op1 . u . constant . refcount = 1 ;
SET_UNUSED ( opline - > op2 ) ;
2003-02-21 03:01:53 +08:00
ns_token - > u . previously_active_namespace = CG ( active_namespace ) ;
2003-02-16 19:12:43 +08:00
CG ( active_namespace ) = ns ;
2003-04-03 00:51:49 +08:00
if ( CG ( doc_comment ) ) {
/*
* Do not overwrite previously declared doc comment in case the namespace is
* split over several parts .
*/
if ( CG ( active_namespace ) - > doc_comment = = NULL ) {
CG ( active_namespace ) - > doc_comment = estrndup ( CG ( doc_comment ) , CG ( doc_comment_len ) ) ;
CG ( active_namespace ) - > doc_comment_len = CG ( doc_comment_len ) ;
}
RESET_DOC_COMMENT ( ) ;
}
2003-02-16 19:12:43 +08:00
/* new symbol tables */
CG ( class_table ) = & ns - > class_table ;
CG ( function_table ) = & ns - > function_table ;
}
2003-04-03 00:13:12 +08:00
void zend_do_end_namespace ( znode * ns_token TSRMLS_DC )
2003-02-16 19:12:43 +08:00
{
2003-02-21 03:01:53 +08:00
zend_namespace * ns = ns_token - > u . previously_active_namespace ;
zend_op * opline ;
2003-02-16 19:12:43 +08:00
2003-04-01 04:42:01 +08:00
/*
* If the filename field has not been initialized yet , it means that we are
* on the first definition of namespace and should capture the definition
* information .
*/
if ( CG ( active_namespace ) - > filename = = NULL ) {
CG ( active_namespace ) - > filename = zend_get_compiled_filename ( TSRMLS_C ) ;
CG ( active_namespace ) - > line_end = zend_get_compiled_lineno ( TSRMLS_C ) ;
}
2003-02-21 03:01:53 +08:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2003-02-16 19:12:43 +08:00
2003-02-21 03:01:53 +08:00
opline - > opcode = ZEND_START_NAMESPACE ;
if ( ns ! = & CG ( global_namespace ) ) {
opline - > op1 . op_type = IS_CONST ;
opline - > op1 . u . constant . type = IS_STRING ;
opline - > op1 . u . constant . value . str . val = estrndup ( ns - > name , ns - > name_length ) ;
opline - > op1 . u . constant . value . str . len = ns - > name_length ;
opline - > op1 . u . constant . refcount = 1 ;
} else {
SET_UNUSED ( opline - > op1 ) ;
}
SET_UNUSED ( opline - > op2 ) ;
2003-02-16 19:12:43 +08:00
CG ( active_namespace ) = ns ;
2003-02-21 03:01:53 +08:00
/* restore symbol tables */
2003-02-16 19:12:43 +08:00
CG ( class_table ) = & CG ( active_namespace ) - > class_table ;
CG ( function_table ) = & CG ( active_namespace ) - > function_table ;
}
void zend_do_declare_namespace_var ( znode * var_name , znode * value TSRMLS_DC )
{
zval * var ;
ALLOC_ZVAL ( var ) ;
if ( value ) {
* var = value - > u . constant ;
} else {
INIT_PZVAL ( var ) ;
var - > type = IS_NULL ;
}
zend_hash_update ( CG ( active_namespace ) - > static_members , var_name - > u . constant . value . str . val , var_name - > u . constant . value . str . len + 1 , & var , sizeof ( zval * ) , NULL ) ;
FREE_PNODE ( var_name ) ;
}
void zend_do_declare_namespace_constant ( znode * var_name , znode * value TSRMLS_DC )
{
zval * var ;
ALLOC_ZVAL ( var ) ;
if ( value ) {
* var = value - > u . constant ;
} else {
INIT_PZVAL ( var ) ;
var - > type = IS_NULL ;
}
zend_hash_update ( & CG ( active_namespace ) - > constants_table , var_name - > u . constant . value . str . val , var_name - > u . constant . value . str . len + 1 , & var , sizeof ( zval * ) , NULL ) ;
FREE_PNODE ( var_name ) ;
}
2003-02-04 20:12:34 +08:00
2003-02-16 19:34:49 +08:00
void zend_initialize_class_data ( zend_class_entry * ce , zend_bool nullify_handlers TSRMLS_DC )
2003-02-11 00:11:24 +08:00
{
2003-02-11 00:46:05 +08:00
zend_bool persistent_hashes = ( ce - > type = = ZEND_INTERNAL_CLASS ) ? 1 : 0 ;
2003-02-11 00:11:24 +08:00
ce - > refcount = 1 ;
ce - > constants_updated = 0 ;
ce - > ce_flags = 0 ;
2003-04-01 04:42:01 +08:00
ce - > doc_comment = NULL ;
ce - > doc_comment_len = 0 ;
2003-02-11 00:11:24 +08:00
2003-02-11 00:46:05 +08:00
zend_hash_init_ex ( & ce - > default_properties , 0 , NULL , ZVAL_PTR_DTOR , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ce - > properties_info , 0 , NULL , ( dtor_func_t ) zend_destroy_property_info , persistent_hashes , 0 ) ;
if ( persistent_hashes ) {
ce - > static_members = ( HashTable * ) malloc ( sizeof ( HashTable ) ) ;
} else {
ALLOC_HASHTABLE ( ce - > static_members ) ;
}
zend_hash_init_ex ( ce - > static_members , 0 , NULL , ZVAL_PTR_DTOR , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ce - > constants_table , 0 , NULL , ZVAL_PTR_DTOR , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ce - > function_table , 0 , NULL , ZEND_FUNCTION_DTOR , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ce - > class_table , 10 , NULL , ZEND_CLASS_DTOR , persistent_hashes , 0 ) ;
2003-02-11 00:11:24 +08:00
if ( nullify_handlers ) {
ce - > constructor = NULL ;
ce - > destructor = NULL ;
ce - > clone = NULL ;
ce - > __get = NULL ;
ce - > __set = NULL ;
ce - > __call = NULL ;
ce - > create_object = NULL ;
}
2003-02-16 19:12:43 +08:00
2003-04-03 22:44:41 +08:00
ce - > parent = NULL ;
ce - > num_interfaces = 0 ;
ce - > interfaces = NULL ;
2003-02-19 01:18:28 +08:00
ce - > ns = CG ( active_namespace ) ;
2003-02-11 00:11:24 +08:00
}
2003-02-01 09:49:15 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/