1999-04-08 02:10:10 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2007-12-31 15:17:19 +08:00
| Copyright ( c ) 1998 - 2008 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 , |
2003-08-07 15:37:19 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
2001-12-11 23:16:21 +08:00
| http : //www.zend.com/license/2_00.txt. |
1999-07-16 22:58:16 +08:00
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ zend . com so we can mail you a copy immediately . |
1999-04-08 02:10:10 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Andi Gutmans < andi @ zend . com > |
| Zeev Suraski < zeev @ zend . com > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2003-02-01 09:49:15 +08:00
/* $Id$ */
1999-07-16 22:58:16 +08:00
1999-04-08 02:10:10 +08:00
# include <stdio.h>
# include <signal.h>
# include "zend.h"
# include "zend_compile.h"
# include "zend_execute.h"
# include "zend_API.h"
# include "zend_ptr_stack.h"
# include "zend_constants.h"
# include "zend_extensions.h"
2004-02-12 18:38:14 +08:00
# include "zend_exceptions.h"
2008-07-14 17:49:03 +08:00
# include "zend_closures.h"
2004-09-24 05:43:32 +08:00
# include "zend_vm.h"
2001-05-30 16:23:15 +08:00
# ifdef HAVE_SYS_TIME_H
2000-06-16 10:49:21 +08:00
# include <sys/time.h>
# endif
1999-04-08 02:10:10 +08:00
2001-07-27 18:10:39 +08:00
ZEND_API void ( * zend_execute ) ( zend_op_array * op_array TSRMLS_DC ) ;
2003-01-12 00:12:44 +08:00
ZEND_API void ( * zend_execute_internal ) ( zend_execute_data * execute_data_ptr , int return_value_used TSRMLS_DC ) ;
1999-04-08 02:10:10 +08:00
2003-08-06 15:38:56 +08:00
/* true globals */
2008-08-13 05:45:52 +08:00
ZEND_API const zend_fcall_info empty_fcall_info = { 0 , NULL , NULL , NULL , NULL , 0 , NULL , NULL , 0 } ;
ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0 , NULL , NULL , NULL , NULL } ;
2003-08-05 18:24:40 +08:00
2003-08-06 07:50:59 +08:00
# ifdef ZEND_WIN32
# include <process.h>
2000-06-16 09:54:56 +08:00
static WNDCLASS wc ;
2000-06-16 22:27:28 +08:00
static HWND timeout_window ;
static HANDLE timeout_thread_event ;
2005-12-10 02:10:45 +08:00
static HANDLE timeout_thread_handle ;
2000-06-16 22:27:28 +08:00
static DWORD timeout_thread_id ;
static int timeout_thread_initialized = 0 ;
2000-06-16 09:54:56 +08:00
# endif
2006-03-17 16:47:41 +08:00
#if 0 &&ZEND_DEBUG
1999-04-08 02:10:10 +08:00
static void ( * original_sigsegv_handler ) ( int ) ;
2007-11-03 03:40:39 +08:00
static void zend_handle_sigsegv ( int dummy ) /* { { { */
1999-04-08 02:10:10 +08:00
{
fflush ( stdout ) ;
1999-05-22 19:20:56 +08:00
fflush ( stderr ) ;
2007-11-03 03:40:39 +08:00
if ( original_sigsegv_handler = = zend_handle_sigsegv ) {
1999-07-09 15:35:13 +08:00
signal ( SIGSEGV , original_sigsegv_handler ) ;
} else {
signal ( SIGSEGV , SIG_DFL ) ;
}
1999-05-23 00:10:51 +08:00
{
2001-07-27 18:10:39 +08:00
TSRMLS_FETCH ( ) ;
1999-05-23 00:10:51 +08:00
fprintf ( stderr , " SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d \n \n " ,
active_opline - > opcode ,
active_opline - EG ( active_op_array ) - > opcodes ,
2001-07-30 15:43:02 +08:00
get_active_function_name ( TSRMLS_C ) ,
2001-07-27 18:10:39 +08:00
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ) ;
1999-05-23 00:10:51 +08:00
}
1999-07-09 15:35:13 +08:00
if ( original_sigsegv_handler ! = zend_handle_sigsegv ) {
original_sigsegv_handler ( dummy ) ;
}
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-07-09 15:35:13 +08:00
# endif
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
static void zend_extension_activator ( zend_extension * extension TSRMLS_DC ) /* { { { */
1999-04-08 02:10:10 +08:00
{
if ( extension - > activate ) {
extension - > activate ( ) ;
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
static void zend_extension_deactivator ( zend_extension * extension TSRMLS_DC ) /* { { { */
1999-04-08 02:10:10 +08:00
{
if ( extension - > deactivate ) {
extension - > deactivate ( ) ;
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
static int clean_non_persistent_function ( zend_function * function TSRMLS_DC ) /* { { { */
2000-06-05 06:09:16 +08:00
{
2006-03-13 19:13:42 +08:00
return ( function - > type = = ZEND_INTERNAL_FUNCTION ) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE ;
2000-06-05 06:09:16 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-06-05 06:09:16 +08:00
2007-11-03 03:40:39 +08:00
static int clean_non_persistent_function_full ( zend_function * function TSRMLS_DC ) /* { { { */
2000-06-05 06:09:16 +08:00
{
2006-03-14 19:24:45 +08:00
return ( function - > type ! = ZEND_INTERNAL_FUNCTION ) ;
2006-03-13 19:13:42 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2006-03-13 19:13:42 +08:00
2007-11-03 03:40:39 +08:00
static int clean_non_persistent_class ( zend_class_entry * * ce TSRMLS_DC ) /* { { { */
2006-03-13 19:13:42 +08:00
{
return ( ( * ce ) - > type = = ZEND_INTERNAL_CLASS ) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
2006-03-13 19:13:42 +08:00
2007-11-03 03:40:39 +08:00
static int clean_non_persistent_class_full ( zend_class_entry * * ce TSRMLS_DC ) /* { { { */
2006-03-13 19:13:42 +08:00
{
2006-03-14 19:24:45 +08:00
return ( ( * ce ) - > type ! = ZEND_INTERNAL_CLASS ) ;
2000-06-05 06:09:16 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-06-05 06:09:16 +08:00
2007-11-03 03:40:39 +08:00
void init_executor ( TSRMLS_D ) /* { { { */
1999-04-08 02:10:10 +08:00
{
1999-12-19 14:39:17 +08:00
INIT_ZVAL ( EG ( uninitialized_zval ) ) ;
2007-11-03 03:40:39 +08:00
/* trick to make uninitialized_zval never be modified, passed by ref, etc. */
2007-10-07 13:22:07 +08:00
Z_ADDREF ( EG ( uninitialized_zval ) ) ;
1999-12-19 14:39:17 +08:00
INIT_ZVAL ( EG ( error_zval ) ) ;
1999-04-08 02:10:10 +08:00
EG ( uninitialized_zval_ptr ) = & EG ( uninitialized_zval ) ;
EG ( error_zval_ptr ) = & EG ( error_zval ) ;
zend_ptr_stack_init ( & EG ( arg_types_stack ) ) ;
1999-07-15 20:17:34 +08:00
/* destroys stack frame, therefore makes core dumps worthless */
1999-12-20 02:54:40 +08:00
#if 0 &&ZEND_DEBUG
1999-04-08 02:10:10 +08:00
original_sigsegv_handler = signal ( SIGSEGV , zend_handle_sigsegv ) ;
1999-07-15 20:17:34 +08:00
# endif
2001-09-10 08:07:32 +08:00
EG ( return_value_ptr_ptr ) = NULL ;
1999-12-19 14:39:17 +08:00
2007-11-03 03:40:39 +08:00
EG ( symtable_cache_ptr ) = EG ( symtable_cache ) - 1 ;
EG ( symtable_cache_limit ) = EG ( symtable_cache ) + SYMTABLE_CACHE_SIZE - 1 ;
EG ( no_extensions ) = 0 ;
1999-04-08 02:10:10 +08:00
EG ( function_table ) = CG ( function_table ) ;
EG ( class_table ) = CG ( class_table ) ;
2000-02-04 22:45:58 +08:00
EG ( in_execution ) = 0 ;
2004-03-24 22:30:59 +08:00
EG ( in_autoload ) = NULL ;
2004-08-24 04:57:40 +08:00
EG ( autoload_func ) = NULL ;
2000-02-04 22:45:58 +08:00
2008-01-24 17:41:39 +08:00
zend_vm_stack_init ( TSRMLS_C ) ;
zend_vm_stack_push ( ( void * ) NULL TSRMLS_CC ) ;
1999-04-13 02:29:09 +08:00
1999-12-22 01:14:31 +08:00
zend_hash_init ( & EG ( symbol_table ) , 50 , NULL , ZVAL_PTR_DTOR , 0 ) ;
2002-01-21 04:42:15 +08:00
{
zval * globals ;
ALLOC_ZVAL ( globals ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( globals , 1 ) ;
Z_SET_ISREF_P ( globals ) ;
2006-05-10 07:53:23 +08:00
Z_TYPE_P ( globals ) = IS_ARRAY ;
Z_ARRVAL_P ( globals ) = & EG ( symbol_table ) ;
2002-01-21 04:42:15 +08:00
zend_hash_update ( & EG ( symbol_table ) , " GLOBALS " , sizeof ( " GLOBALS " ) , & globals , sizeof ( zval * ) , NULL ) ;
}
1999-04-08 02:10:10 +08:00
EG ( active_symbol_table ) = & EG ( symbol_table ) ;
2003-08-07 15:37:19 +08:00
2001-07-31 12:53:54 +08:00
zend_llist_apply ( & zend_extensions , ( llist_apply_func_t ) zend_extension_activator TSRMLS_CC ) ;
1999-05-26 06:55:13 +08:00
EG ( opline_ptr ) = NULL ;
1999-12-01 04:15:04 +08:00
2000-03-11 00:36:30 +08:00
zend_hash_init ( & EG ( included_files ) , 5 , NULL , NULL , 0 ) ;
2000-01-25 03:00:30 +08:00
EG ( ticks_count ) = 0 ;
2000-04-19 23:08:06 +08:00
EG ( user_error_handler ) = NULL ;
2000-06-16 22:27:28 +08:00
2003-02-14 20:25:09 +08:00
EG ( current_execute_data ) = NULL ;
2004-01-10 19:43:42 +08:00
zend_stack_init ( & EG ( user_error_handlers_error_reporting ) ) ;
2000-06-18 02:04:58 +08:00
zend_ptr_stack_init ( & EG ( user_error_handlers ) ) ;
2002-08-16 08:41:37 +08:00
zend_ptr_stack_init ( & EG ( user_exception_handlers ) ) ;
2000-06-18 02:04:58 +08:00
2002-05-31 20:09:19 +08:00
zend_objects_store_init ( & EG ( objects_store ) , 1024 ) ;
2001-10-26 22:13:42 +08:00
EG ( full_tables_cleanup ) = 0 ;
2000-06-16 22:27:28 +08:00
# ifdef ZEND_WIN32
EG ( timed_out ) = 0 ;
# endif
2001-08-30 23:26:30 +08:00
EG ( exception ) = NULL ;
2001-12-07 01:47:04 +08:00
2002-03-01 22:27:26 +08:00
EG ( scope ) = NULL ;
2007-09-29 15:28:34 +08:00
EG ( called_scope ) = NULL ;
2001-12-14 00:55:04 +08:00
2002-03-01 22:27:26 +08:00
EG ( This ) = NULL ;
2007-11-03 03:40:39 +08:00
2006-10-12 00:11:56 +08:00
EG ( active_op_array ) = NULL ;
2006-09-11 22:30:08 +08:00
EG ( active ) = 1 ;
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
static int zval_call_destructor ( zval * * zv TSRMLS_DC ) /* { { { */
2006-07-12 15:54:00 +08:00
{
2007-10-07 13:22:07 +08:00
if ( Z_TYPE_PP ( zv ) = = IS_OBJECT & & Z_REFCOUNT_PP ( zv ) = = 1 ) {
2006-07-12 15:54:00 +08:00
return ZEND_HASH_APPLY_REMOVE ;
} else {
return ZEND_HASH_APPLY_KEEP ;
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
2006-07-12 15:54:00 +08:00
2007-11-03 03:40:39 +08:00
void shutdown_destructors ( TSRMLS_D ) /* { { { */
{
2004-07-25 15:14:49 +08:00
zend_try {
2006-07-12 15:54:00 +08:00
int symbols ;
do {
symbols = zend_hash_num_elements ( & EG ( symbol_table ) ) ;
zend_hash_reverse_apply ( & EG ( symbol_table ) , ( apply_func_t ) zval_call_destructor TSRMLS_CC ) ;
} while ( symbols ! = zend_hash_num_elements ( & EG ( symbol_table ) ) ) ;
2004-07-25 15:14:49 +08:00
zend_objects_store_call_destructors ( & EG ( objects_store ) TSRMLS_CC ) ;
2004-09-17 18:13:52 +08:00
} zend_catch {
/* if we couldn't destruct cleanly, mark all objects as destructed anyway */
zend_objects_store_mark_destructed ( & EG ( objects_store ) TSRMLS_CC ) ;
2004-07-25 15:14:49 +08:00
} zend_end_try ( ) ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
2004-07-25 15:14:49 +08:00
2007-11-03 03:40:39 +08:00
void shutdown_executor ( TSRMLS_D ) /* { { { */
1999-04-08 02:10:10 +08:00
{
2001-07-21 22:25:27 +08:00
zend_try {
2007-11-03 03:40:39 +08:00
2003-01-29 22:33:18 +08:00
/* Removed because this can not be safely done, e.g. in this situation:
Object 1 creates object 2
Object 3 holds reference to object 2.
Now when 1 and 2 are destroyed , 3 can still access 2 in its destructor , with
very problematic results */
/* zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); */
/* Moved after symbol table cleaners, because some of the cleaners can call
destructors , which would use EG ( symtable_cache_ptr ) and thus leave leaks */
/* while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
2001-07-20 22:20:34 +08:00
zend_hash_destroy ( * EG ( symtable_cache_ptr ) ) ;
efree ( * EG ( symtable_cache_ptr ) ) ;
EG ( symtable_cache_ptr ) - - ;
}
2003-01-29 22:33:18 +08:00
*/
2001-07-31 12:53:54 +08:00
zend_llist_apply ( & zend_extensions , ( llist_apply_func_t ) zend_extension_deactivator TSRMLS_CC ) ;
2003-12-17 22:25:12 +08:00
zend_hash_graceful_reverse_destroy ( & EG ( symbol_table ) ) ;
2003-07-27 21:47:58 +08:00
} zend_end_try ( ) ;
2003-07-27 23:59:37 +08:00
zend_try {
zval * zeh ;
/* remove error handlers before destroying classes and functions,
2007-11-03 03:40:39 +08:00
* so that if handler used some class , crash would not happen */
2003-07-27 23:59:37 +08:00
if ( EG ( user_error_handler ) ) {
zeh = EG ( user_error_handler ) ;
EG ( user_error_handler ) = NULL ;
zval_dtor ( zeh ) ;
FREE_ZVAL ( zeh ) ;
}
if ( EG ( user_exception_handler ) ) {
zeh = EG ( user_exception_handler ) ;
EG ( user_exception_handler ) = NULL ;
zval_dtor ( zeh ) ;
FREE_ZVAL ( zeh ) ;
}
2004-01-10 19:43:42 +08:00
zend_stack_destroy ( & EG ( user_error_handlers_error_reporting ) ) ;
zend_stack_init ( & EG ( user_error_handlers_error_reporting ) ) ;
2003-07-27 23:59:37 +08:00
zend_ptr_stack_clean ( & EG ( user_error_handlers ) , ZVAL_DESTRUCTOR , 1 ) ;
zend_ptr_stack_clean ( & EG ( user_exception_handlers ) , ZVAL_DESTRUCTOR , 1 ) ;
} zend_end_try ( ) ;
2003-08-07 15:37:19 +08:00
2003-07-27 21:47:58 +08:00
zend_try {
2003-01-30 01:54:48 +08:00
/* Cleanup static data for functions and arrays.
2007-11-03 03:40:39 +08:00
* We need a separate cleanup stage because of the following problem :
* Suppose we destroy class X , which destroys the class ' s function table ,
* and in the function table we have function foo ( ) that has static $ bar .
* Now if an object of class X is assigned to $ bar , its destructor will be
* called and will fail since X ' s function table is in mid - destruction .
* So we want first of all to clean up all data and then move to tables destruction .
* Note that only run - time accessed data need to be cleaned up , pre - defined data can
* not contain objects and thus are not probelmatic */
2006-03-13 19:13:42 +08:00
if ( EG ( full_tables_cleanup ) ) {
zend_hash_apply ( EG ( function_table ) , ( apply_func_t ) zend_cleanup_function_data_full TSRMLS_CC ) ;
} else {
zend_hash_reverse_apply ( EG ( function_table ) , ( apply_func_t ) zend_cleanup_function_data TSRMLS_CC ) ;
}
2003-01-30 08:44:56 +08:00
zend_hash_apply ( EG ( class_table ) , ( apply_func_t ) zend_cleanup_class_data TSRMLS_CC ) ;
2003-03-02 23:24:04 +08:00
2008-01-24 17:41:39 +08:00
zend_vm_stack_destroy ( TSRMLS_C ) ;
2003-03-02 23:24:04 +08:00
2008-08-12 01:44:15 +08:00
zend_objects_store_free_object_storage ( & EG ( objects_store ) TSRMLS_CC ) ;
2001-07-20 22:20:34 +08:00
/* Destroy all op arrays */
2001-10-26 22:13:42 +08:00
if ( EG ( full_tables_cleanup ) ) {
2006-03-13 19:13:42 +08:00
zend_hash_apply ( EG ( function_table ) , ( apply_func_t ) clean_non_persistent_function_full TSRMLS_CC ) ;
zend_hash_apply ( EG ( class_table ) , ( apply_func_t ) clean_non_persistent_class_full TSRMLS_CC ) ;
2001-10-23 09:23:36 +08:00
} else {
2006-03-13 19:13:42 +08:00
zend_hash_reverse_apply ( EG ( function_table ) , ( apply_func_t ) clean_non_persistent_function TSRMLS_CC ) ;
zend_hash_reverse_apply ( EG ( class_table ) , ( apply_func_t ) clean_non_persistent_class TSRMLS_CC ) ;
2001-10-23 09:23:36 +08:00
}
2003-01-29 22:33:18 +08:00
while ( EG ( symtable_cache_ptr ) > = EG ( symtable_cache ) ) {
zend_hash_destroy ( * EG ( symtable_cache_ptr ) ) ;
2003-10-14 22:36:23 +08:00
FREE_HASHTABLE ( * EG ( symtable_cache_ptr ) ) ;
2003-01-29 22:33:18 +08:00
EG ( symtable_cache_ptr ) - - ;
}
2001-07-21 22:25:27 +08:00
} zend_end_try ( ) ;
2000-06-05 06:09:16 +08:00
2002-09-16 09:36:48 +08:00
zend_try {
clean_non_persistent_constants ( TSRMLS_C ) ;
} zend_end_try ( ) ;
2001-07-21 22:25:27 +08:00
zend_try {
2006-03-17 16:47:41 +08:00
#if 0 &&ZEND_DEBUG
1999-07-09 15:35:13 +08:00
signal ( SIGSEGV , original_sigsegv_handler ) ;
# endif
2000-02-01 19:41:15 +08:00
2001-07-20 22:20:34 +08:00
zend_hash_destroy ( & EG ( included_files ) ) ;
2000-04-19 23:08:06 +08:00
2003-08-04 19:02:53 +08:00
zend_ptr_stack_destroy ( & EG ( arg_types_stack ) ) ;
2004-01-10 19:43:42 +08:00
zend_stack_destroy ( & EG ( user_error_handlers_error_reporting ) ) ;
2001-07-20 22:20:34 +08:00
zend_ptr_stack_destroy ( & EG ( user_error_handlers ) ) ;
2002-08-16 08:41:37 +08:00
zend_ptr_stack_destroy ( & EG ( user_exception_handlers ) ) ;
2002-05-31 20:09:19 +08:00
zend_objects_store_destroy ( & EG ( objects_store ) ) ;
2004-03-24 22:30:59 +08:00
if ( EG ( in_autoload ) ) {
zend_hash_destroy ( EG ( in_autoload ) ) ;
2004-03-25 16:14:33 +08:00
FREE_HASHTABLE ( EG ( in_autoload ) ) ;
2004-03-24 22:30:59 +08:00
}
2001-07-21 22:25:27 +08:00
} zend_end_try ( ) ;
2006-09-11 22:30:08 +08:00
EG ( active ) = 0 ;
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2004-03-16 18:14:57 +08:00
/* return class name and "::" or "". */
2007-11-03 03:40:39 +08:00
ZEND_API char * get_active_class_name ( char * * space TSRMLS_DC ) /* { { { */
2004-03-16 18:14:57 +08:00
{
if ( ! zend_is_executing ( TSRMLS_C ) ) {
if ( space ) {
* space = " " ;
}
return " " ;
}
2007-11-20 17:51:12 +08:00
switch ( EG ( current_execute_data ) - > function_state . function - > type ) {
2004-03-16 18:14:57 +08:00
case ZEND_USER_FUNCTION :
case ZEND_INTERNAL_FUNCTION :
{
2007-11-20 17:51:12 +08:00
zend_class_entry * ce = EG ( current_execute_data ) - > function_state . function - > common . scope ;
2004-03-16 18:14:57 +08:00
if ( space ) {
* space = ce ? " :: " : " " ;
}
return ce ? ce - > name : " " ;
}
default :
if ( space ) {
* space = " " ;
}
return " " ;
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
2004-03-16 18:14:57 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API char * get_active_function_name ( TSRMLS_D ) /* { { { */
1999-04-08 02:10:10 +08:00
{
2002-04-21 04:14:14 +08:00
if ( ! zend_is_executing ( TSRMLS_C ) ) {
return NULL ;
}
2007-11-20 17:51:12 +08:00
switch ( EG ( current_execute_data ) - > function_state . function - > type ) {
1999-04-08 02:10:10 +08:00
case ZEND_USER_FUNCTION : {
2007-11-20 17:51:12 +08:00
char * function_name = ( ( zend_op_array * ) EG ( current_execute_data ) - > function_state . function ) - > function_name ;
2003-08-07 15:37:19 +08:00
1999-04-08 02:10:10 +08:00
if ( function_name ) {
return function_name ;
} else {
return " main " ;
}
}
break ;
case ZEND_INTERNAL_FUNCTION :
2007-11-20 17:51:12 +08:00
return ( ( zend_internal_function * ) EG ( current_execute_data ) - > function_state . function ) - > function_name ;
1999-04-08 02:10:10 +08:00
break ;
default :
return NULL ;
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API char * zend_get_executed_filename ( TSRMLS_D ) /* { { { */
1999-04-08 02:10:10 +08:00
{
2000-08-10 03:22:35 +08:00
if ( EG ( active_op_array ) ) {
return EG ( active_op_array ) - > filename ;
1999-05-26 06:55:13 +08:00
} else {
return " [no active file] " ;
}
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API uint zend_get_executed_lineno ( TSRMLS_D ) /* { { { */
1999-04-08 02:10:10 +08:00
{
1999-05-26 06:55:13 +08:00
if ( EG ( opline_ptr ) ) {
return active_opline - > lineno ;
} else {
return 0 ;
}
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API zend_bool zend_is_executing ( TSRMLS_D ) /* { { { */
2000-02-04 22:45:58 +08:00
{
return EG ( in_execution ) ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-02-04 22:45:58 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API void _zval_ptr_dtor ( zval * * zval_ptr ZEND_FILE_LINE_DC ) /* { { { */
1999-04-08 02:10:10 +08:00
{
# if DEBUG_ZEND>=2
2007-11-03 03:40:39 +08:00
printf ( " Reducing refcount for %x (%x): %d->%d \n " , * zval_ptr , zval_ptr , Z_REFCOUNT_PP ( zval_ptr ) , Z_REFCOUNT_PP ( zval_ptr ) - 1 ) ;
1999-04-08 02:10:10 +08:00
# endif
2007-10-07 13:22:07 +08:00
Z_DELREF_PP ( zval_ptr ) ;
2007-11-03 03:40:39 +08:00
if ( Z_REFCOUNT_PP ( zval_ptr ) = = 0 ) {
2008-05-07 00:03:16 +08:00
TSRMLS_FETCH ( ) ;
if ( * zval_ptr ! = & EG ( uninitialized_zval ) ) {
GC_REMOVE_ZVAL_FROM_BUFFER ( * zval_ptr ) ;
zval_dtor ( * zval_ptr ) ;
efree_rel ( * zval_ptr ) ;
}
2008-01-22 17:27:48 +08:00
} else {
TSRMLS_FETCH ( ) ;
2006-06-05 21:58:52 +08:00
2008-01-22 17:27:48 +08:00
if ( Z_REFCOUNT_PP ( zval_ptr ) = = 1 ) {
Z_UNSET_ISREF_PP ( zval_ptr ) ;
2006-06-05 21:58:52 +08:00
}
2008-01-22 17:27:48 +08:00
GC_ZVAL_CHECK_POSSIBLE_ROOT ( * zval_ptr ) ;
1999-04-08 02:10:10 +08:00
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
2003-08-07 15:37:19 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API void _zval_internal_ptr_dtor ( zval * * zval_ptr ZEND_FILE_LINE_DC ) /* { { { */
2003-08-25 01:32:47 +08:00
{
# if DEBUG_ZEND>=2
2007-11-03 03:40:39 +08:00
printf ( " Reducing refcount for %x (%x): %d->%d \n " , * zval_ptr , zval_ptr , Z_REFCOUNT_PP ( zval_ptr ) , Z_REFCOUNT_PP ( zval_ptr ) - 1 ) ;
2003-08-25 01:32:47 +08:00
# endif
2007-10-07 13:22:07 +08:00
Z_DELREF_PP ( zval_ptr ) ;
2007-11-03 03:40:39 +08:00
if ( Z_REFCOUNT_PP ( zval_ptr ) = = 0 ) {
2003-08-25 01:32:47 +08:00
zval_internal_dtor ( * zval_ptr ) ;
free ( * zval_ptr ) ;
2007-10-07 13:22:07 +08:00
} else if ( Z_REFCOUNT_PP ( zval_ptr ) = = 1 ) {
Z_UNSET_ISREF_PP ( zval_ptr ) ;
2003-08-25 01:32:47 +08:00
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
2003-08-25 01:32:47 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API int zend_is_true ( zval * op ) /* { { { */
1999-04-08 02:10:10 +08:00
{
return i_zend_is_true ( op ) ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2001-12-01 00:29:47 +08:00
# include "../TSRM/tsrm_strtok_r.h"
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
# define IS_VISITED_CONSTANT IS_CONSTANT_INDEX
# define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT)
# define Z_REAL_TYPE_P(p) (Z_TYPE_P(p) & ~IS_VISITED_CONSTANT)
# define MARK_CONSTANT_VISITED(p) Z_TYPE_P(p) |= IS_VISITED_CONSTANT
2007-06-14 00:48:10 +08:00
2008-03-04 19:43:51 +08:00
static void zval_deep_copy ( zval * * p )
{
zval * value ;
ALLOC_ZVAL ( value ) ;
* value = * * p ;
Z_TYPE_P ( value ) & = ~ IS_CONSTANT_INDEX ;
zval_copy_ctor ( value ) ;
Z_TYPE_P ( value ) = Z_TYPE_PP ( p ) ;
INIT_PZVAL ( value ) ;
* p = value ;
}
2007-11-03 03:40:39 +08:00
ZEND_API int zval_update_constant_ex ( zval * * pp , void * arg , zend_class_entry * scope TSRMLS_DC ) /* { { { */
1999-04-08 02:10:10 +08:00
{
1999-11-22 02:11:10 +08:00
zval * p = * pp ;
2007-04-16 16:09:56 +08:00
zend_bool inline_change = ( zend_bool ) ( zend_uintptr_t ) arg ;
2001-07-16 19:41:06 +08:00
zval const_value ;
2007-06-13 22:50:13 +08:00
char * colon ;
1999-11-22 02:11:10 +08:00
2007-06-14 00:48:10 +08:00
if ( IS_CONSTANT_VISITED ( p ) ) {
zend_error ( E_ERROR , " Cannot declare self-referencing constant '%s' " , Z_STRVAL_P ( p ) ) ;
2007-09-29 03:52:53 +08:00
} else if ( ( Z_TYPE_P ( p ) & IS_CONSTANT_TYPE_MASK ) = = IS_CONSTANT ) {
2000-04-27 06:10:06 +08:00
int refcount ;
2005-06-08 21:21:28 +08:00
zend_uchar is_ref ;
2000-04-27 06:10:06 +08:00
2005-06-08 21:21:28 +08:00
SEPARATE_ZVAL_IF_NOT_REF ( pp ) ;
2000-04-27 06:10:06 +08:00
p = * pp ;
2007-06-14 00:48:10 +08:00
MARK_CONSTANT_VISITED ( p ) ;
2007-10-07 13:22:07 +08:00
refcount = Z_REFCOUNT_P ( p ) ;
is_ref = Z_ISREF_P ( p ) ;
1999-04-08 02:10:10 +08:00
2007-10-01 17:32:48 +08:00
if ( ! zend_get_constant_ex ( p - > value . str . val , p - > value . str . len , & const_value , scope , Z_REAL_TYPE_P ( p ) TSRMLS_CC ) ) {
2007-12-08 01:11:24 +08:00
if ( ( colon = zend_memrchr ( Z_STRVAL_P ( p ) , ' : ' , Z_STRLEN_P ( p ) ) ) & &
colon > Z_STRVAL_P ( p ) & &
* ( colon - 1 ) = = ' : ' ) {
if ( ( Z_TYPE_P ( p ) & IS_CONSTANT_RT_NS_CHECK ) = = 0 ) {
zend_error ( E_ERROR , " Undefined class constant '%s' " , Z_STRVAL_P ( p ) ) ;
} else if ( Z_TYPE_P ( p ) & ZEND_FETCH_CLASS_RT_NS_CHECK ) {
zend_error ( E_ERROR , " Undefined constant '%s' " , Z_STRVAL_P ( p ) ) ;
}
Z_STRLEN_P ( p ) - = ( ( colon - Z_STRVAL_P ( p ) ) + 1 ) ;
if ( inline_change ) {
colon = estrndup ( colon + 1 , Z_STRLEN_P ( p ) ) ;
efree ( Z_STRVAL_P ( p ) ) ;
Z_STRVAL_P ( p ) = colon ;
} else {
Z_STRVAL_P ( p ) = colon + 1 ;
}
} else if ( Z_TYPE_P ( p ) & ZEND_FETCH_CLASS_RT_NS_CHECK ) {
zend_error ( E_ERROR , " Undefined constant '%s' " , Z_STRVAL_P ( p ) ) ;
2007-06-13 22:50:13 +08:00
}
2007-11-03 03:40:39 +08:00
zend_error ( E_NOTICE , " Use of undefined constant %s - assumed '%s' " , Z_STRVAL_P ( p ) , Z_STRVAL_P ( p ) ) ;
2003-06-15 22:46:15 +08:00
p - > type = IS_STRING ;
if ( ! inline_change ) {
zval_copy_ctor ( p ) ;
2001-12-01 00:29:47 +08:00
}
2003-06-15 22:46:15 +08:00
} else {
2000-06-01 03:07:09 +08:00
if ( inline_change ) {
2007-11-03 03:40:39 +08:00
STR_FREE ( Z_STRVAL_P ( p ) ) ;
2000-06-01 03:07:09 +08:00
}
2001-07-16 19:41:06 +08:00
* p = const_value ;
1999-04-08 02:10:10 +08:00
}
2003-06-15 22:46:15 +08:00
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( p , refcount ) ;
Z_SET_ISREF_TO_P ( p , is_ref ) ;
2006-05-10 07:53:23 +08:00
} else if ( Z_TYPE_P ( p ) = = IS_CONSTANT_ARRAY ) {
2003-06-10 01:02:32 +08:00
zval * * element , * new_val ;
2001-07-16 19:41:06 +08:00
char * str_index ;
2001-08-21 20:29:12 +08:00
uint str_index_len ;
ulong num_index ;
2001-07-16 19:41:06 +08:00
2005-06-08 21:21:28 +08:00
SEPARATE_ZVAL_IF_NOT_REF ( pp ) ;
2000-04-27 06:10:06 +08:00
p = * pp ;
2006-05-10 07:53:23 +08:00
Z_TYPE_P ( p ) = IS_ARRAY ;
2003-08-07 15:37:19 +08:00
2008-03-04 19:43:51 +08:00
if ( ! inline_change ) {
zval * tmp ;
HashTable * tmp_ht = NULL ;
ALLOC_HASHTABLE ( tmp_ht ) ;
zend_hash_init ( tmp_ht , zend_hash_num_elements ( Z_ARRVAL_P ( p ) ) , NULL , ZVAL_PTR_DTOR , 0 ) ;
zend_hash_copy ( tmp_ht , Z_ARRVAL_P ( p ) , ( copy_ctor_func_t ) zval_deep_copy , ( void * ) & tmp , sizeof ( zval * ) ) ;
Z_ARRVAL_P ( p ) = tmp_ht ;
}
2001-07-16 19:41:06 +08:00
/* First go over the array and see if there are any constant indices */
2006-05-10 07:53:23 +08:00
zend_hash_internal_pointer_reset ( Z_ARRVAL_P ( p ) ) ;
2007-11-03 03:40:39 +08:00
while ( zend_hash_get_current_data ( Z_ARRVAL_P ( p ) , ( void * * ) & element ) = = SUCCESS ) {
2001-07-16 19:41:06 +08:00
if ( ! ( Z_TYPE_PP ( element ) & IS_CONSTANT_INDEX ) ) {
2006-05-10 07:53:23 +08:00
zend_hash_move_forward ( Z_ARRVAL_P ( p ) ) ;
2001-07-16 19:41:06 +08:00
continue ;
}
Z_TYPE_PP ( element ) & = ~ IS_CONSTANT_INDEX ;
2007-11-03 03:40:39 +08:00
if ( zend_hash_get_current_key_ex ( Z_ARRVAL_P ( p ) , & str_index , & str_index_len , & num_index , 0 , NULL ) ! = HASH_KEY_IS_STRING ) {
2006-05-10 07:53:23 +08:00
zend_hash_move_forward ( Z_ARRVAL_P ( p ) ) ;
2001-07-16 19:41:06 +08:00
continue ;
}
2007-11-03 03:40:39 +08:00
if ( ! zend_get_constant_ex ( str_index , str_index_len - 3 , & const_value , scope , str_index [ str_index_len - 2 ] TSRMLS_CC ) ) {
2007-12-08 01:11:24 +08:00
if ( ( colon = zend_memrchr ( str_index , ' : ' , str_index_len - 3 ) ) & &
colon > str_index & &
* ( colon - 1 ) = = ' : ' ) {
if ( ( str_index [ str_index_len - 2 ] & IS_CONSTANT_RT_NS_CHECK ) = = 0 ) {
zend_error ( E_ERROR , " Undefined class constant '%s' " , str_index ) ;
} else if ( str_index [ str_index_len - 2 ] & ZEND_FETCH_CLASS_RT_NS_CHECK ) {
zend_error ( E_ERROR , " Undefined constant '%s' " , str_index ) ;
}
str_index_len - = ( ( colon - str_index ) + 1 ) ;
str_index = colon + 1 ;
} else if ( str_index [ str_index_len - 2 ] & ZEND_FETCH_CLASS_RT_NS_CHECK ) {
zend_error ( E_ERROR , " Undefined constant '%s' " , str_index ) ;
}
2001-07-16 19:41:06 +08:00
zend_error ( E_NOTICE , " Use of undefined constant %s - assumed '%s' " , str_index , str_index ) ;
2007-11-02 18:11:42 +08:00
ZVAL_STRINGL ( & const_value , str_index , str_index_len - 3 , 1 ) ;
2001-07-16 19:41:06 +08:00
}
2003-08-07 15:37:19 +08:00
2007-11-02 18:11:42 +08:00
if ( Z_REFCOUNT_PP ( element ) > 1 ) {
ALLOC_ZVAL ( new_val ) ;
* new_val = * * element ;
zval_copy_ctor ( new_val ) ;
Z_SET_REFCOUNT_P ( new_val , 1 ) ;
Z_UNSET_ISREF_P ( new_val ) ;
/* preserve this bit for inheritance */
Z_TYPE_PP ( element ) | = IS_CONSTANT_INDEX ;
zval_ptr_dtor ( element ) ;
* element = new_val ;
2002-09-10 16:35:50 +08:00
}
2006-05-10 07:53:23 +08:00
switch ( Z_TYPE ( const_value ) ) {
2005-12-05 16:56:09 +08:00
case IS_STRING :
2008-08-01 22:22:03 +08:00
zend_symtable_update_current_key ( Z_ARRVAL_P ( p ) , Z_STRVAL ( const_value ) , Z_STRLEN ( const_value ) + 1 , HASH_UPDATE_KEY_IF_BEFORE ) ;
2001-07-16 19:41:06 +08:00
break ;
2005-02-13 00:38:47 +08:00
case IS_BOOL :
2001-07-16 19:41:06 +08:00
case IS_LONG :
2008-08-01 22:22:03 +08:00
zend_hash_update_current_key_ex ( Z_ARRVAL_P ( p ) , HASH_KEY_IS_LONG , NULL , 0 , Z_LVAL ( const_value ) , HASH_UPDATE_KEY_IF_BEFORE , NULL ) ;
2005-07-07 23:16:57 +08:00
break ;
case IS_DOUBLE :
2008-08-01 22:22:03 +08:00
zend_hash_update_current_key_ex ( Z_ARRVAL_P ( p ) , HASH_KEY_IS_LONG , NULL , 0 , ( long ) Z_DVAL ( const_value ) , HASH_UPDATE_KEY_IF_BEFORE , NULL ) ;
2005-07-07 23:16:57 +08:00
break ;
case IS_NULL :
2008-08-01 22:22:03 +08:00
zend_hash_update_current_key_ex ( Z_ARRVAL_P ( p ) , HASH_KEY_IS_STRING , " " , 1 , 0 , HASH_UPDATE_KEY_IF_BEFORE , NULL ) ;
2001-07-16 19:41:06 +08:00
break ;
}
2006-05-10 07:53:23 +08:00
zend_hash_move_forward ( Z_ARRVAL_P ( p ) ) ;
2002-09-10 16:35:50 +08:00
zval_dtor ( & const_value ) ;
2001-07-16 19:41:06 +08:00
}
2006-05-10 07:53:23 +08:00
zend_hash_apply_with_argument ( Z_ARRVAL_P ( p ) , ( apply_func_arg_t ) zval_update_constant , ( void * ) 1 TSRMLS_CC ) ;
zend_hash_internal_pointer_reset ( Z_ARRVAL_P ( p ) ) ;
1999-04-08 02:10:10 +08:00
}
1999-11-22 02:11:10 +08:00
return 0 ;
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API int zval_update_constant ( zval * * pp , void * arg TSRMLS_DC ) /* { { { */
2006-10-19 00:35:15 +08:00
{
2006-10-19 01:04:49 +08:00
return zval_update_constant_ex ( pp , arg , NULL TSRMLS_CC ) ;
2006-10-19 00:35:15 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-08-06 23:24:10 +08:00
2007-11-03 03:40:39 +08:00
int call_user_function ( HashTable * function_table , zval * * object_pp , zval * function_name , zval * retval_ptr , zend_uint param_count , zval * params [ ] TSRMLS_DC ) /* { { { */
1999-08-06 23:24:10 +08:00
{
2004-07-18 17:55:02 +08:00
zval * * * params_array ;
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
zend_uint i ;
1999-08-06 23:24:10 +08:00
int ex_retval ;
2005-07-27 02:33:15 +08:00
zval * local_retval_ptr = NULL ;
1999-08-06 23:24:10 +08:00
2004-07-18 17:55:02 +08:00
if ( param_count ) {
params_array = ( zval * * * ) emalloc ( sizeof ( zval * * ) * param_count ) ;
for ( i = 0 ; i < param_count ; i + + ) {
params_array [ i ] = & params [ i ] ;
}
} else {
params_array = NULL ;
1999-08-06 23:24:10 +08:00
}
2001-07-30 15:43:02 +08:00
ex_retval = call_user_function_ex ( function_table , object_pp , function_name , & local_retval_ptr , param_count , params_array , 1 , NULL TSRMLS_CC ) ;
1999-12-20 02:54:40 +08:00
if ( local_retval_ptr ) {
COPY_PZVAL_TO_ZVAL ( * retval_ptr , local_retval_ptr ) ;
} else {
INIT_ZVAL ( * retval_ptr ) ;
}
2004-07-18 17:55:02 +08:00
if ( params_array ) {
efree ( params_array ) ;
}
1999-08-06 23:24:10 +08:00
return ex_retval ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-08-06 23:24:10 +08:00
2007-11-03 03:40:39 +08:00
int call_user_function_ex ( HashTable * function_table , zval * * object_pp , zval * function_name , zval * * retval_ptr_ptr , zend_uint param_count , zval * * params [ ] , int no_separation , HashTable * symbol_table TSRMLS_DC ) /* { { { */
2003-05-21 00:44:42 +08:00
{
2003-08-05 18:24:40 +08:00
zend_fcall_info fci ;
fci . size = sizeof ( fci ) ;
fci . function_table = function_table ;
fci . object_pp = object_pp ;
fci . function_name = function_name ;
fci . retval_ptr_ptr = retval_ptr_ptr ;
fci . param_count = param_count ;
fci . params = params ;
fci . no_separation = ( zend_bool ) no_separation ;
fci . symbol_table = symbol_table ;
return zend_call_function ( & fci , NULL TSRMLS_CC ) ;
2003-05-21 00:44:42 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2003-05-21 00:44:42 +08:00
2007-11-03 03:40:39 +08:00
int zend_call_function ( zend_fcall_info * fci , zend_fcall_info_cache * fci_cache TSRMLS_DC ) /* { { { */
1999-04-08 02:10:10 +08:00
{
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-04 01:40:44 +08:00
zend_uint i ;
1999-12-20 02:54:40 +08:00
zval * * original_return_value ;
1999-04-08 02:10:10 +08:00
HashTable * calling_symbol_table ;
zend_op_array * original_op_array ;
zend_op * * original_opline_ptr ;
2002-03-01 22:27:26 +08:00
zend_class_entry * current_scope ;
2007-09-29 15:28:34 +08:00
zend_class_entry * current_called_scope ;
2002-03-01 22:27:26 +08:00
zend_class_entry * calling_scope = NULL ;
2008-07-24 17:42:18 +08:00
zend_class_entry * called_scope = NULL ;
2002-01-05 23:18:30 +08:00
zval * current_this ;
2002-08-23 21:50:42 +08:00
zend_execute_data execute_data ;
2007-04-27 16:12:24 +08:00
* fci - > retval_ptr_ptr = NULL ;
2006-09-11 22:30:08 +08:00
if ( ! EG ( active ) ) {
return FAILURE ; /* executor is already inactive */
}
2005-03-19 22:25:42 +08:00
if ( EG ( exception ) ) {
return FAILURE ; /* we would result in an instable executor otherwise */
}
2003-08-05 18:24:40 +08:00
switch ( fci - > size ) {
case sizeof ( zend_fcall_info ) :
break ; /* nothing to do currently */
default :
zend_error ( E_ERROR , " Corrupted fcall_info provided to zend_call_function() " ) ;
break ;
}
2002-08-23 21:50:42 +08:00
/* Initialize execute_data */
2004-02-05 07:48:39 +08:00
if ( EG ( current_execute_data ) ) {
execute_data = * EG ( current_execute_data ) ;
2005-06-22 23:26:05 +08:00
EX ( op_array ) = NULL ;
EX ( opline ) = NULL ;
2007-11-03 03:40:39 +08:00
EX ( object ) = NULL ;
2004-02-05 07:48:39 +08:00
} else {
2004-02-11 21:01:39 +08:00
/* This only happens when we're called outside any execute()'s
* It shouldn ' t be strictly necessary to NULL execute_data out ,
* but it may make bugs easier to spot
*/
2004-02-05 07:48:39 +08:00
memset ( & execute_data , 0 , sizeof ( zend_execute_data ) ) ;
}
2000-01-16 06:52:24 +08:00
2003-08-05 18:24:40 +08:00
if ( ! fci_cache | | ! fci_cache - > initialized ) {
2008-07-26 21:14:04 +08:00
zend_fcall_info_cache fci_cache_local ;
char * callable_name ;
char * error = NULL ;
2000-06-03 11:28:08 +08:00
2008-07-26 21:14:04 +08:00
if ( ! fci_cache ) {
fci_cache = & fci_cache_local ;
2003-07-02 22:44:41 +08:00
}
2008-07-26 21:14:04 +08:00
if ( ! zend_is_callable_ex ( fci - > function_name , fci - > object_pp , IS_CALLABLE_CHECK_SILENT , & callable_name , NULL , fci_cache , & error TSRMLS_CC ) ) {
if ( error ) {
zend_error ( E_WARNING , " Invalid callback %s, %s " , callable_name , error ) ;
efree ( error ) ;
2008-07-14 17:49:03 +08:00
}
2008-07-27 03:14:38 +08:00
if ( callable_name ) {
efree ( callable_name ) ;
}
1999-04-08 02:10:10 +08:00
return FAILURE ;
2008-07-26 21:14:04 +08:00
} else if ( error ) {
/* Capitalize the first latter of the error message */
if ( error [ 0 ] > = ' a ' & & error [ 0 ] < = ' z ' ) {
error [ 0 ] + = ( ' A ' - ' a ' ) ;
2003-07-03 17:18:41 +08:00
}
2008-07-26 21:14:04 +08:00
zend_error ( E_STRICT , " %s " , error ) ;
efree ( error ) ;
2003-05-21 00:44:42 +08:00
}
2008-07-27 03:14:38 +08:00
efree ( callable_name ) ;
2008-07-26 21:14:04 +08:00
}
2008-07-14 17:49:03 +08:00
2008-07-26 21:14:04 +08:00
EX ( function_state ) . function = fci_cache - > function_handler ;
calling_scope = fci_cache - > calling_scope ;
called_scope = fci_cache - > called_scope ;
fci - > object_pp = fci_cache - > object_pp ;
EX ( object ) = fci - > object_pp ? * fci - > object_pp : NULL ;
if ( fci - > object_pp & & * fci - > object_pp & & Z_TYPE_PP ( fci - > object_pp ) = = IS_OBJECT & &
( ! EG ( objects_store ) . object_buckets | | ! EG ( objects_store ) . object_buckets [ Z_OBJ_HANDLE_PP ( fci - > object_pp ) ] . valid ) ) {
return FAILURE ;
1999-04-08 02:10:10 +08:00
}
2006-05-10 07:53:23 +08:00
2006-02-26 02:25:45 +08:00
if ( EX ( function_state ) . function - > common . fn_flags & ( ZEND_ACC_ABSTRACT | ZEND_ACC_DEPRECATED ) ) {
if ( EX ( function_state ) . function - > common . fn_flags & ZEND_ACC_ABSTRACT ) {
2006-04-21 06:49:20 +08:00
zend_error_noreturn ( E_ERROR , " Cannot call abstract method %s::%s() " , EX ( function_state ) . function - > common . scope - > name , EX ( function_state ) . function - > common . function_name ) ;
2006-02-26 02:25:45 +08:00
}
if ( EX ( function_state ) . function - > common . fn_flags & ZEND_ACC_DEPRECATED ) {
2008-03-10 04:52:29 +08:00
zend_error ( E_DEPRECATED , " Function %s%s%s() is deprecated " ,
2006-02-26 02:25:45 +08:00
EX ( function_state ) . function - > common . scope ? EX ( function_state ) . function - > common . scope - > name : " " ,
EX ( function_state ) . function - > common . scope ? " :: " : " " ,
EX ( function_state ) . function - > common . function_name ) ;
}
}
2003-08-07 15:37:19 +08:00
2008-07-26 21:14:04 +08:00
ZEND_VM_STACK_GROW_IF_NEEDED ( fci - > param_count + 1 ) ;
2008-01-24 17:41:39 +08:00
2003-08-05 18:24:40 +08:00
for ( i = 0 ; i < fci - > param_count ; i + + ) {
1999-04-08 02:10:10 +08:00
zval * param ;
2007-11-03 03:40:39 +08:00
if ( ARG_SHOULD_BE_SENT_BY_REF ( EX ( function_state ) . function , i + 1 )
2003-08-05 18:24:40 +08:00
& & ! PZVAL_IS_REF ( * fci - > params [ i ] ) ) {
2008-01-10 17:38:23 +08:00
2007-11-03 03:40:39 +08:00
if ( Z_REFCOUNT_PP ( fci - > params [ i ] ) > 1 ) {
1999-08-06 23:24:10 +08:00
zval * new_zval ;
2003-08-05 18:24:40 +08:00
if ( fci - > no_separation ) {
2005-05-19 02:02:50 +08:00
if ( i ) {
/* hack to clean up the stack */
2008-01-24 17:41:39 +08:00
zend_vm_stack_push_nocheck ( ( void * ) ( zend_uintptr_t ) i TSRMLS_CC ) ;
zend_vm_stack_clear_multiple ( TSRMLS_C ) ;
2005-05-19 02:02:50 +08:00
}
2006-12-21 19:08:00 +08:00
2008-01-10 17:38:23 +08:00
zend_error ( E_WARNING , " Parameter %d to %s%s%s() expected to be a reference, value given " ,
i + 1 ,
EX ( function_state ) . function - > common . scope ? EX ( function_state ) . function - > common . scope - > name : " " ,
EX ( function_state ) . function - > common . scope ? " :: " : " " ,
EX ( function_state ) . function - > common . function_name ) ;
1999-08-06 23:24:10 +08:00
return FAILURE ;
}
2008-01-10 17:38:23 +08:00
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( new_zval ) ;
2003-08-05 18:24:40 +08:00
* new_zval = * * fci - > params [ i ] ;
1999-08-07 05:43:49 +08:00
zval_copy_ctor ( new_zval ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( new_zval , 1 ) ;
Z_DELREF_PP ( fci - > params [ i ] ) ;
2003-08-05 18:24:40 +08:00
* fci - > params [ i ] = new_zval ;
1999-08-06 23:24:10 +08:00
}
2007-10-07 13:22:07 +08:00
Z_ADDREF_PP ( fci - > params [ i ] ) ;
Z_SET_ISREF_PP ( fci - > params [ i ] ) ;
2003-08-05 18:24:40 +08:00
param = * fci - > params [ i ] ;
} else if ( * fci - > params [ i ] ! = & EG ( uninitialized_zval ) ) {
2007-10-07 13:22:07 +08:00
Z_ADDREF_PP ( fci - > params [ i ] ) ;
2003-08-05 18:24:40 +08:00
param = * fci - > params [ i ] ;
1999-08-06 23:24:10 +08:00
} else {
1999-12-27 05:21:33 +08:00
ALLOC_ZVAL ( param ) ;
2003-08-05 18:24:40 +08:00
* param = * * ( fci - > params [ i ] ) ;
1999-08-06 23:24:10 +08:00
INIT_PZVAL ( param ) ;
}
2008-07-26 21:14:04 +08:00
zend_vm_stack_push_nocheck ( param TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
}
2008-01-24 17:41:39 +08:00
EX ( function_state ) . arguments = zend_vm_stack_top ( TSRMLS_C ) ;
zend_vm_stack_push_nocheck ( ( void * ) ( zend_uintptr_t ) fci - > param_count TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
2002-03-01 22:27:26 +08:00
current_scope = EG ( scope ) ;
EG ( scope ) = calling_scope ;
2001-12-27 04:17:34 +08:00
2002-03-01 22:27:26 +08:00
current_this = EG ( This ) ;
2002-01-05 23:18:30 +08:00
2007-09-29 15:28:34 +08:00
current_called_scope = EG ( called_scope ) ;
2008-07-24 17:42:18 +08:00
if ( called_scope ) {
EG ( called_scope ) = called_scope ;
2007-09-29 15:28:34 +08:00
} else if ( EX ( function_state ) . function - > type ! = ZEND_INTERNAL_FUNCTION ) {
EG ( called_scope ) = NULL ;
}
2007-11-03 03:40:39 +08:00
2003-08-05 18:24:40 +08:00
if ( fci - > object_pp ) {
2004-03-16 22:59:06 +08:00
if ( ( EX ( function_state ) . function - > common . fn_flags & ZEND_ACC_STATIC ) ) {
EG ( This ) = NULL ;
} else {
2004-03-16 22:49:52 +08:00
EG ( This ) = * fci - > object_pp ;
2002-01-15 00:55:23 +08:00
2004-03-16 22:49:52 +08:00
if ( ! PZVAL_IS_REF ( EG ( This ) ) ) {
2007-10-07 13:22:07 +08:00
Z_ADDREF_P ( EG ( This ) ) ; /* For $this pointer */
2004-03-16 22:49:52 +08:00
} else {
zval * this_ptr ;
2002-01-05 23:18:30 +08:00
2004-03-16 22:49:52 +08:00
ALLOC_ZVAL ( this_ptr ) ;
* this_ptr = * EG ( This ) ;
INIT_PZVAL ( this_ptr ) ;
zval_copy_ctor ( this_ptr ) ;
EG ( This ) = this_ptr ;
}
2002-01-05 23:18:30 +08:00
}
2002-01-15 00:55:23 +08:00
} else {
2002-03-01 22:27:26 +08:00
EG ( This ) = NULL ;
2002-01-05 23:18:30 +08:00
}
2002-08-23 21:50:42 +08:00
EX ( prev_execute_data ) = EG ( current_execute_data ) ;
EG ( current_execute_data ) = & execute_data ;
2002-01-05 23:18:30 +08:00
2002-08-23 21:50:42 +08:00
if ( EX ( function_state ) . function - > type = = ZEND_USER_FUNCTION ) {
1999-04-14 03:28:03 +08:00
calling_symbol_table = EG ( active_symbol_table ) ;
2003-09-12 01:04:26 +08:00
EG ( scope ) = EX ( function_state ) . function - > common . scope ;
2003-08-05 18:24:40 +08:00
if ( fci - > symbol_table ) {
EG ( active_symbol_table ) = fci - > symbol_table ;
2000-06-18 00:50:38 +08:00
} else {
2008-05-07 01:00:56 +08:00
EG ( active_symbol_table ) = NULL ;
2000-06-18 00:50:38 +08:00
}
2002-01-05 23:18:30 +08:00
1999-12-20 02:54:40 +08:00
original_return_value = EG ( return_value_ptr_ptr ) ;
1999-04-08 02:10:10 +08:00
original_op_array = EG ( active_op_array ) ;
2003-08-05 18:24:40 +08:00
EG ( return_value_ptr_ptr ) = fci - > retval_ptr_ptr ;
2002-08-23 21:50:42 +08:00
EG ( active_op_array ) = ( zend_op_array * ) EX ( function_state ) . function ;
1999-12-20 02:54:40 +08:00
original_opline_ptr = EG ( opline_ptr ) ;
2001-07-27 18:10:39 +08:00
zend_execute ( EG ( active_op_array ) TSRMLS_CC ) ;
2008-05-07 01:00:56 +08:00
if ( ! fci - > symbol_table & & EG ( active_symbol_table ) ) {
if ( EG ( symtable_cache_ptr ) > = EG ( symtable_cache_limit ) ) {
zend_hash_destroy ( EG ( active_symbol_table ) ) ;
FREE_HASHTABLE ( EG ( active_symbol_table ) ) ;
} else {
/* clean before putting into the cache, since clean
could call dtors , which could use cached hash */
zend_hash_clean ( EG ( active_symbol_table ) ) ;
* ( + + EG ( symtable_cache_ptr ) ) = EG ( active_symbol_table ) ;
}
2000-06-18 00:50:38 +08:00
}
1999-04-14 03:28:03 +08:00
EG ( active_symbol_table ) = calling_symbol_table ;
1999-04-08 02:10:10 +08:00
EG ( active_op_array ) = original_op_array ;
1999-12-20 02:54:40 +08:00
EG ( return_value_ptr_ptr ) = original_return_value ;
1999-04-08 02:10:10 +08:00
EG ( opline_ptr ) = original_opline_ptr ;
2008-07-27 01:01:40 +08:00
} else if ( EX ( function_state ) . function - > type = = ZEND_INTERNAL_FUNCTION ) {
2008-07-26 21:14:04 +08:00
int call_via_handler = ( EX ( function_state ) . function - > common . fn_flags & ZEND_ACC_CALL_VIA_HANDLER ) ! = 0 ;
2008-08-09 01:47:31 +08:00
zend_error_handling error_handling ;
zend_save_error_handling ( & error_handling TSRMLS_CC ) ;
2003-08-05 18:24:40 +08:00
ALLOC_INIT_ZVAL ( * fci - > retval_ptr_ptr ) ;
2003-09-12 01:06:53 +08:00
if ( EX ( function_state ) . function - > common . scope ) {
2003-09-12 01:04:26 +08:00
EG ( scope ) = EX ( function_state ) . function - > common . scope ;
}
2007-11-03 03:40:39 +08:00
( ( zend_internal_function * ) EX ( function_state ) . function ) - > handler ( fci - > param_count , * fci - > retval_ptr_ptr , fci - > retval_ptr_ptr , ( fci - > object_pp ? * fci - > object_pp : NULL ) , 1 TSRMLS_CC ) ;
2008-08-09 01:47:31 +08:00
zend_restore_error_handling ( & error_handling TSRMLS_CC ) ;
2007-11-03 03:40:39 +08:00
/* We shouldn't fix bad extensions here,
because it can break proper ones ( Bug # 34045 )
if ( ! EX ( function_state ) . function - > common . return_reference )
{
INIT_PZVAL ( * fci - > retval_ptr_ptr ) ;
} */
2008-01-15 02:13:12 +08:00
if ( EG ( exception ) & & fci - > retval_ptr_ptr ) {
zval_ptr_dtor ( fci - > retval_ptr_ptr ) ;
2008-01-15 19:47:05 +08:00
* fci - > retval_ptr_ptr = NULL ;
2008-01-15 02:13:12 +08:00
}
2008-07-26 21:14:04 +08:00
if ( call_via_handler ) {
/* We must re-initialize function again */
fci_cache - > initialized = 0 ;
}
2008-07-27 01:01:40 +08:00
} else { /* ZEND_OVERLOADED_FUNCTION */
ALLOC_INIT_ZVAL ( * fci - > retval_ptr_ptr ) ;
2008-08-08 21:21:52 +08:00
/* Not sure what should be done here if it's a static method */
2008-07-27 01:01:40 +08:00
if ( fci - > object_pp ) {
2008-08-09 01:47:31 +08:00
zend_error_handling error_handling ;
zend_save_error_handling ( & error_handling TSRMLS_CC ) ;
2008-07-27 01:01:40 +08:00
Z_OBJ_HT_PP ( fci - > object_pp ) - > call_method ( EX ( function_state ) . function - > common . function_name , fci - > param_count , * fci - > retval_ptr_ptr , fci - > retval_ptr_ptr , * fci - > object_pp , 1 TSRMLS_CC ) ;
2008-08-09 01:47:31 +08:00
zend_restore_error_handling ( & error_handling TSRMLS_CC ) ;
2008-07-27 01:01:40 +08:00
} else {
zend_error_noreturn ( E_ERROR , " Cannot call overloaded function for non-object " ) ;
}
if ( EX ( function_state ) . function - > type = = ZEND_OVERLOADED_FUNCTION_TEMPORARY ) {
efree ( EX ( function_state ) . function - > common . function_name ) ;
}
efree ( EX ( function_state ) . function ) ;
if ( EG ( exception ) & & fci - > retval_ptr_ptr ) {
zval_ptr_dtor ( fci - > retval_ptr_ptr ) ;
* fci - > retval_ptr_ptr = NULL ;
}
1999-04-08 02:10:10 +08:00
}
2008-01-24 17:41:39 +08:00
zend_vm_stack_clear_multiple ( TSRMLS_C ) ;
1999-04-08 02:10:10 +08:00
2002-03-01 22:27:26 +08:00
if ( EG ( This ) ) {
zval_ptr_dtor ( & EG ( This ) ) ;
2002-01-05 23:18:30 +08:00
}
2007-09-29 15:28:34 +08:00
EG ( called_scope ) = current_called_scope ;
2002-03-01 22:27:26 +08:00
EG ( scope ) = current_scope ;
EG ( This ) = current_this ;
2003-08-05 18:24:40 +08:00
EG ( current_execute_data ) = EX ( prev_execute_data ) ;
2004-02-03 20:17:09 +08:00
if ( EG ( exception ) ) {
zend_throw_exception_internal ( NULL TSRMLS_CC ) ;
}
2003-08-05 18:24:40 +08:00
return SUCCESS ;
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API int zend_lookup_class_ex ( const char * name , int name_length , int use_autoload , zend_class_entry * * * ce TSRMLS_DC ) /* { { { */
2002-06-17 02:25:05 +08:00
{
2002-06-26 23:13:14 +08:00
zval * * args [ 1 ] ;
2003-11-07 19:47:50 +08:00
zval autoload_function ;
2005-05-26 22:28:24 +08:00
zval * class_name_ptr ;
2005-12-20 19:25:34 +08:00
zval * retval_ptr = NULL ;
2002-06-26 23:13:14 +08:00
int retval ;
2003-11-25 02:13:29 +08:00
char * lc_name ;
2007-09-29 03:52:53 +08:00
char * lc_free ;
2003-12-12 02:18:52 +08:00
zval * exception ;
2004-08-24 04:57:40 +08:00
zend_fcall_info fcall_info ;
zend_fcall_info_cache fcall_cache ;
2007-11-22 21:27:13 +08:00
char dummy = 1 ;
ALLOCA_FLAG ( use_heap )
2004-11-17 20:06:27 +08:00
2007-03-03 21:45:14 +08:00
if ( name = = NULL | | ! name_length ) {
2004-11-17 20:06:27 +08:00
return FAILURE ;
}
2007-11-03 03:40:39 +08:00
2007-11-22 21:27:13 +08:00
lc_free = lc_name = do_alloca ( name_length + 1 , use_heap ) ;
2003-12-15 15:17:27 +08:00
zend_str_tolower_copy ( lc_name , name , name_length ) ;
2003-11-25 02:13:29 +08:00
2007-09-29 03:52:53 +08:00
if ( lc_name [ 0 ] = = ' : ' & & lc_name [ 1 ] = = ' : ' ) {
lc_name + = 2 ;
name_length - = 2 ;
}
2007-11-03 03:40:39 +08:00
if ( zend_hash_find ( EG ( class_table ) , lc_name , name_length + 1 , ( void * * ) ce ) = = SUCCESS ) {
2007-11-22 21:27:13 +08:00
free_alloca ( lc_free , use_heap ) ;
2002-06-26 23:13:14 +08:00
return SUCCESS ;
}
2004-03-28 17:37:30 +08:00
/* The compiler is not-reentrant. Make sure we __autoload() only during run-time
* ( doesn ' t impact fuctionality of __autoload ( )
*/
2005-09-09 14:48:49 +08:00
if ( ! use_autoload | | zend_is_compiling ( TSRMLS_C ) ) {
2007-11-22 21:27:13 +08:00
free_alloca ( lc_free , use_heap ) ;
2004-03-28 17:37:30 +08:00
return FAILURE ;
}
2004-03-24 22:30:59 +08:00
if ( EG ( in_autoload ) = = NULL ) {
2004-03-25 16:14:33 +08:00
ALLOC_HASHTABLE ( EG ( in_autoload ) ) ;
2007-11-03 03:40:39 +08:00
zend_hash_init ( EG ( in_autoload ) , 0 , NULL , NULL , 0 ) ;
2004-03-24 22:30:59 +08:00
}
2007-11-03 03:40:39 +08:00
if ( zend_hash_add ( EG ( in_autoload ) , lc_name , name_length + 1 , ( void * * ) & dummy , sizeof ( char ) , NULL ) = = FAILURE ) {
2007-11-22 21:27:13 +08:00
free_alloca ( lc_free , use_heap ) ;
2003-12-23 18:45:10 +08:00
return FAILURE ;
}
2007-11-03 03:40:39 +08:00
ZVAL_STRINGL ( & autoload_function , ZEND_AUTOLOAD_FUNC_NAME , sizeof ( ZEND_AUTOLOAD_FUNC_NAME ) - 1 , 0 ) ;
2002-06-17 02:25:05 +08:00
2005-05-26 22:28:24 +08:00
ALLOC_ZVAL ( class_name_ptr ) ;
2003-11-07 19:47:50 +08:00
INIT_PZVAL ( class_name_ptr ) ;
2005-05-26 22:28:24 +08:00
ZVAL_STRINGL ( class_name_ptr , name , name_length , 1 ) ;
2007-11-03 03:40:39 +08:00
2003-11-07 19:47:50 +08:00
args [ 0 ] = & class_name_ptr ;
2006-05-10 07:53:23 +08:00
2004-08-24 04:57:40 +08:00
fcall_info . size = sizeof ( fcall_info ) ;
fcall_info . function_table = EG ( function_table ) ;
fcall_info . function_name = & autoload_function ;
fcall_info . symbol_table = NULL ;
fcall_info . retval_ptr_ptr = & retval_ptr ;
fcall_info . param_count = 1 ;
fcall_info . params = args ;
fcall_info . object_pp = NULL ;
fcall_info . no_separation = 1 ;
fcall_cache . initialized = EG ( autoload_func ) ? 1 : 0 ;
fcall_cache . function_handler = EG ( autoload_func ) ;
fcall_cache . calling_scope = NULL ;
2008-07-25 16:23:07 +08:00
fcall_cache . called_scope = NULL ;
2004-08-24 04:57:40 +08:00
fcall_cache . object_pp = NULL ;
2002-06-26 23:13:14 +08:00
2003-12-12 02:18:52 +08:00
exception = EG ( exception ) ;
EG ( exception ) = NULL ;
2004-08-24 04:57:40 +08:00
retval = zend_call_function ( & fcall_info , & fcall_cache TSRMLS_CC ) ;
EG ( autoload_func ) = fcall_cache . function_handler ;
2003-08-07 15:37:19 +08:00
2005-05-26 22:28:24 +08:00
zval_ptr_dtor ( & class_name_ptr ) ;
2007-11-03 03:40:39 +08:00
zend_hash_del ( EG ( in_autoload ) , lc_name , name_length + 1 ) ;
2003-12-23 18:45:10 +08:00
2002-06-26 23:13:14 +08:00
if ( retval = = FAILURE ) {
2003-12-12 02:18:52 +08:00
EG ( exception ) = exception ;
2007-11-22 21:27:13 +08:00
free_alloca ( lc_free , use_heap ) ;
2002-06-26 23:13:14 +08:00
return FAILURE ;
}
2005-02-14 07:04:49 +08:00
if ( EG ( exception ) & & exception ) {
2007-11-22 21:27:13 +08:00
free_alloca ( lc_free , use_heap ) ;
2004-08-02 16:27:57 +08:00
zend_error ( E_ERROR , " Function %s(%s) threw an exception of type '%s' " , ZEND_AUTOLOAD_FUNC_NAME , name , Z_OBJCE_P ( EG ( exception ) ) - > name ) ;
2003-12-12 02:18:52 +08:00
return FAILURE ;
2002-08-14 00:46:40 +08:00
}
2005-02-14 07:04:49 +08:00
if ( ! EG ( exception ) ) {
EG ( exception ) = exception ;
2005-12-20 19:25:34 +08:00
}
if ( retval_ptr ) {
2005-02-14 07:04:49 +08:00
zval_ptr_dtor ( & retval_ptr ) ;
}
2002-06-26 23:13:14 +08:00
2003-11-25 02:13:29 +08:00
retval = zend_hash_find ( EG ( class_table ) , lc_name , name_length + 1 , ( void * * ) ce ) ;
2007-11-22 21:27:13 +08:00
free_alloca ( lc_free , use_heap ) ;
2003-11-25 02:13:29 +08:00
return retval ;
2002-06-26 23:13:14 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API int zend_lookup_class ( const char * name , int name_length , zend_class_entry * * * ce TSRMLS_DC ) /* { { { */
2005-09-09 14:48:49 +08:00
{
return zend_lookup_class_ex ( name , name_length , 1 , ce TSRMLS_CC ) ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
2005-09-09 14:48:49 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API int zend_eval_string ( char * str , zval * retval_ptr , char * string_name TSRMLS_DC ) /* { { { */
1999-04-08 02:10:10 +08:00
{
zval pv ;
zend_op_array * new_op_array ;
zend_op_array * original_active_op_array = EG ( active_op_array ) ;
2008-03-18 16:36:30 +08:00
zend_uint original_compiler_options ;
2000-05-07 02:49:46 +08:00
int retval ;
1999-04-08 02:10:10 +08:00
1999-12-20 02:54:40 +08:00
if ( retval_ptr ) {
2006-12-28 08:17:48 +08:00
int l = strlen ( str ) ;
2007-11-03 03:40:39 +08:00
Z_STRLEN ( pv ) = l + sizeof ( " return ; " ) - 1 ;
2006-12-28 08:17:48 +08:00
Z_STRVAL ( pv ) = emalloc ( Z_STRLEN ( pv ) + 1 ) ;
2007-11-03 03:40:39 +08:00
memcpy ( Z_STRVAL ( pv ) , " return " , sizeof ( " return " ) - 1 ) ;
memcpy ( Z_STRVAL ( pv ) + sizeof ( " return " ) - 1 , str , l ) ;
Z_STRVAL ( pv ) [ Z_STRLEN ( pv ) - 2 ] = ' ' ;
Z_STRVAL ( pv ) [ Z_STRLEN ( pv ) - 1 ] = ' ; ' ;
2006-12-28 08:17:48 +08:00
Z_STRVAL ( pv ) [ Z_STRLEN ( pv ) ] = ' \0 ' ;
1999-04-08 02:10:10 +08:00
} else {
2007-11-03 03:40:39 +08:00
Z_STRLEN ( pv ) = strlen ( str ) ;
2008-04-11 17:43:28 +08:00
Z_STRVAL ( pv ) = str ;
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
Z_TYPE ( pv ) = IS_STRING ;
1999-04-08 02:10:10 +08:00
/*printf("Evaluating '%s'\n", pv.value.str.val);*/
2008-03-18 16:36:30 +08:00
original_compiler_options = CG ( compiler_options ) ;
CG ( compiler_options ) = ZEND_COMPILE_DEFAULT_FOR_EVAL ;
2006-06-13 20:57:48 +08:00
new_op_array = zend_compile_string ( & pv , string_name TSRMLS_CC ) ;
2008-03-18 16:36:30 +08:00
CG ( compiler_options ) = original_compiler_options ;
1999-04-08 02:10:10 +08:00
if ( new_op_array ) {
1999-12-20 02:54:40 +08:00
zval * local_retval_ptr = NULL ;
zval * * original_return_value_ptr_ptr = EG ( return_value_ptr_ptr ) ;
1999-04-08 02:10:10 +08:00
zend_op * * original_opline_ptr = EG ( opline_ptr ) ;
2003-08-07 15:37:19 +08:00
1999-12-20 02:54:40 +08:00
EG ( return_value_ptr_ptr ) = & local_retval_ptr ;
1999-04-08 02:10:10 +08:00
EG ( active_op_array ) = new_op_array ;
EG ( no_extensions ) = 1 ;
2008-04-29 17:18:26 +08:00
if ( ! EG ( active_symbol_table ) ) {
zend_rebuild_symbol_table ( TSRMLS_C ) ;
}
1999-12-20 02:54:40 +08:00
2001-07-27 18:10:39 +08:00
zend_execute ( new_op_array TSRMLS_CC ) ;
1999-12-20 02:54:40 +08:00
if ( local_retval_ptr ) {
if ( retval_ptr ) {
COPY_PZVAL_TO_ZVAL ( * retval_ptr , local_retval_ptr ) ;
} else {
zval_ptr_dtor ( & local_retval_ptr ) ;
}
} else {
if ( retval_ptr ) {
INIT_ZVAL ( * retval_ptr ) ;
}
}
1999-04-08 02:10:10 +08:00
EG ( no_extensions ) = 0 ;
EG ( opline_ptr ) = original_opline_ptr ;
EG ( active_op_array ) = original_active_op_array ;
2003-03-26 15:44:11 +08:00
destroy_op_array ( new_op_array TSRMLS_CC ) ;
1999-04-08 02:10:10 +08:00
efree ( new_op_array ) ;
1999-12-20 02:54:40 +08:00
EG ( return_value_ptr_ptr ) = original_return_value_ptr_ptr ;
2000-05-07 02:49:46 +08:00
retval = SUCCESS ;
1999-04-08 02:10:10 +08:00
} else {
2000-05-07 02:49:46 +08:00
retval = FAILURE ;
1999-04-08 02:10:10 +08:00
}
2008-04-11 17:43:28 +08:00
if ( retval_ptr ) {
zval_dtor ( & pv ) ;
}
2000-05-07 02:49:46 +08:00
return retval ;
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-08 02:10:10 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API int zend_eval_string_ex ( char * str , zval * retval_ptr , char * string_name , int handle_exceptions TSRMLS_DC ) /* { { { */
2003-08-24 21:10:03 +08:00
{
int result ;
result = zend_eval_string ( str , retval_ptr , string_name TSRMLS_CC ) ;
if ( handle_exceptions & & EG ( exception ) ) {
zend_exception_error ( EG ( exception ) TSRMLS_CC ) ;
result = FAILURE ;
}
return result ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
2003-08-24 21:10:03 +08:00
2007-11-03 03:40:39 +08:00
void execute_new_code ( TSRMLS_D ) /* { { { */
1999-04-08 02:10:10 +08:00
{
2004-03-16 22:59:06 +08:00
zend_op * opline , * end ;
2001-07-15 22:08:58 +08:00
zend_op * ret_opline ;
1999-04-08 02:10:10 +08:00
2007-02-15 18:38:28 +08:00
if ( ! ( CG ( active_op_array ) - > fn_flags & ZEND_ACC_INTERACTIVE )
1999-04-27 19:00:59 +08:00
| | CG ( active_op_array ) - > backpatch_count > 0
| | CG ( active_op_array ) - > function_name
| | CG ( active_op_array ) - > type ! = ZEND_USER_FUNCTION ) {
1999-04-08 02:10:10 +08:00
return ;
}
2001-04-30 12:50:34 +08:00
2001-07-28 18:51:54 +08:00
ret_opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2001-07-15 22:08:58 +08:00
ret_opline - > opcode = ZEND_RETURN ;
ret_opline - > op1 . op_type = IS_CONST ;
INIT_ZVAL ( ret_opline - > op1 . u . constant ) ;
SET_UNUSED ( ret_opline - > op2 ) ;
if ( ! CG ( active_op_array ) - > start_op ) {
CG ( active_op_array ) - > start_op = CG ( active_op_array ) - > opcodes ;
}
2003-08-07 15:37:19 +08:00
2001-07-15 22:08:58 +08:00
opline = CG ( active_op_array ) - > start_op ;
2001-05-06 23:00:58 +08:00
end = CG ( active_op_array ) - > opcodes + CG ( active_op_array ) - > last ;
2001-04-30 12:50:34 +08:00
2004-03-16 22:59:06 +08:00
while ( opline < end ) {
2007-11-03 03:40:39 +08:00
if ( opline - > op1 . op_type = = IS_CONST ) {
2007-10-07 13:22:07 +08:00
Z_SET_ISREF ( opline - > op1 . u . constant ) ;
Z_SET_REFCOUNT ( opline - > op1 . u . constant , 2 ) ; /* Make sure is_ref won't be reset */
2004-03-16 22:59:06 +08:00
}
2007-11-03 03:40:39 +08:00
if ( opline - > op2 . op_type = = IS_CONST ) {
2007-10-07 13:22:07 +08:00
Z_SET_ISREF ( opline - > op2 . u . constant ) ;
Z_SET_REFCOUNT ( opline - > op2 . u . constant , 2 ) ;
2004-03-16 22:59:06 +08:00
}
2005-03-26 10:43:02 +08:00
switch ( opline - > opcode ) {
2008-03-28 22:35:01 +08:00
case ZEND_GOTO :
if ( Z_TYPE ( opline - > op2 . u . constant ) ! = IS_LONG ) {
zend_resolve_goto_label ( CG ( active_op_array ) , opline , 1 TSRMLS_CC ) ;
}
/* break omitted intentionally */
2005-03-26 10:43:02 +08:00
case ZEND_JMP :
opline - > op1 . u . jmp_addr = & CG ( active_op_array ) - > opcodes [ opline - > op1 . u . opline_num ] ;
break ;
case ZEND_JMPZ :
case ZEND_JMPNZ :
case ZEND_JMPZ_EX :
case ZEND_JMPNZ_EX :
2007-11-21 17:41:35 +08:00
case ZEND_JMP_SET :
2005-03-26 10:43:02 +08:00
opline - > op2 . u . jmp_addr = & CG ( active_op_array ) - > opcodes [ opline - > op2 . u . opline_num ] ;
break ;
}
2004-09-24 05:43:32 +08:00
ZEND_VM_SET_OPCODE_HANDLER ( opline ) ;
2003-06-15 19:44:30 +08:00
opline + + ;
2004-03-16 22:59:06 +08:00
}
2008-03-28 22:35:01 +08:00
zend_release_labels ( TSRMLS_C ) ;
2008-04-11 17:43:28 +08:00
EG ( return_value_ptr_ptr ) = NULL ;
1999-04-08 02:10:10 +08:00
EG ( active_op_array ) = CG ( active_op_array ) ;
2001-07-27 18:10:39 +08:00
zend_execute ( CG ( active_op_array ) TSRMLS_CC ) ;
2001-09-10 08:07:32 +08:00
2005-11-24 19:33:11 +08:00
if ( EG ( exception ) ) {
zend_exception_error ( EG ( exception ) TSRMLS_CC ) ;
}
2008-01-22 03:39:55 +08:00
CG ( active_op_array ) - > last - = 1 ; /* get rid of that ZEND_RETURN */
2001-07-15 22:08:58 +08:00
CG ( active_op_array ) - > start_op = CG ( active_op_array ) - > opcodes + CG ( active_op_array ) - > last ;
1999-04-08 02:10:10 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
1999-04-13 02:29:09 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API void zend_timeout ( int dummy ) /* { { { */
2000-06-16 09:54:56 +08:00
{
2001-07-27 18:10:39 +08:00
TSRMLS_FETCH ( ) ;
2000-06-16 09:54:56 +08:00
2002-09-19 23:58:01 +08:00
if ( zend_on_timeout ) {
zend_on_timeout ( EG ( timeout_seconds ) TSRMLS_CC ) ;
}
2003-01-23 13:15:42 +08:00
2007-11-03 03:40:39 +08:00
zend_error ( E_ERROR , " Maximum execution time of %d second%s exceeded " , EG ( timeout_seconds ) , EG ( timeout_seconds ) = = 1 ? " " : " s " ) ;
2000-06-16 09:54:56 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-06-16 09:54:56 +08:00
2000-06-16 10:49:21 +08:00
# ifdef ZEND_WIN32
2007-11-03 03:40:39 +08:00
static LRESULT CALLBACK zend_timeout_WndProc ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam ) /* { { { */
2000-06-16 09:54:56 +08:00
{
switch ( message ) {
case WM_DESTROY :
PostQuitMessage ( 0 ) ;
2000-06-16 22:27:28 +08:00
break ;
case WM_REGISTER_ZEND_TIMEOUT :
/* wParam is the thread id pointer, lParam is the timeout amount in seconds */
2007-11-03 03:40:39 +08:00
if ( lParam = = 0 ) {
2000-06-26 23:17:36 +08:00
KillTimer ( timeout_window , wParam ) ;
} else {
2004-05-19 04:14:54 +08:00
# ifdef ZTS
2004-01-28 17:07:02 +08:00
void * * * tsrm_ls ;
2004-05-19 04:14:54 +08:00
# endif
2000-06-26 23:17:36 +08:00
SetTimer ( timeout_window , wParam , lParam * 1000 , NULL ) ;
2004-05-19 04:14:54 +08:00
# ifdef ZTS
2004-01-28 17:07:02 +08:00
tsrm_ls = ts_resource_ex ( 0 , & wParam ) ;
if ( ! tsrm_ls ) {
/* shouldn't normally happen */
break ;
}
2004-05-19 04:14:54 +08:00
# endif
2004-01-28 17:07:02 +08:00
EG ( timed_out ) = 0 ;
2000-06-26 23:17:36 +08:00
}
2000-06-16 22:27:28 +08:00
break ;
case WM_UNREGISTER_ZEND_TIMEOUT :
/* wParam is the thread id pointer */
KillTimer ( timeout_window , wParam ) ;
break ;
case WM_TIMER : {
# ifdef ZTS
2001-07-28 18:51:54 +08:00
void * * * tsrm_ls ;
2000-06-16 22:27:28 +08:00
2001-07-28 18:51:54 +08:00
tsrm_ls = ts_resource_ex ( 0 , & wParam ) ;
if ( ! tsrm_ls ) {
2000-06-16 22:27:28 +08:00
/* Thread died before receiving its timeout? */
break ;
}
# endif
KillTimer ( timeout_window , wParam ) ;
2001-07-28 18:51:54 +08:00
EG ( timed_out ) = 1 ;
2000-06-16 22:27:28 +08:00
}
break ;
2000-06-16 09:54:56 +08:00
default :
2001-08-11 23:56:40 +08:00
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
2000-06-16 09:54:56 +08:00
}
2000-06-16 22:27:28 +08:00
return 0 ;
2000-06-16 09:54:56 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-06-16 09:54:56 +08:00
2007-11-03 03:40:39 +08:00
static unsigned __stdcall timeout_thread_proc ( void * pArgs ) /* { { { */
2000-06-16 09:54:56 +08:00
{
2000-06-16 22:27:28 +08:00
MSG message ;
2000-06-16 09:54:56 +08:00
wc . style = 0 ;
wc . lpfnWndProc = zend_timeout_WndProc ;
wc . cbClsExtra = 0 ;
wc . cbWndExtra = 0 ;
wc . hInstance = NULL ;
wc . hIcon = NULL ;
wc . hCursor = NULL ;
wc . hbrBackground = ( HBRUSH ) ( COLOR_BACKGROUND + 5 ) ;
wc . lpszMenuName = NULL ;
wc . lpszClassName = " Zend Timeout Window " ;
2001-04-28 02:51:56 +08:00
if ( ! RegisterClass ( & wc ) ) {
2000-06-16 22:27:28 +08:00
return - 1 ;
}
timeout_window = CreateWindow ( wc . lpszClassName , wc . lpszClassName , 0 , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , NULL , NULL , NULL , NULL ) ;
SetEvent ( timeout_thread_event ) ;
while ( GetMessage ( & message , NULL , 0 , 0 ) ) {
SendMessage ( timeout_window , message . message , message . wParam , message . lParam ) ;
if ( message . message = = WM_QUIT ) {
break ;
}
2000-06-16 09:54:56 +08:00
}
2000-06-16 22:27:28 +08:00
DestroyWindow ( timeout_window ) ;
UnregisterClass ( wc . lpszClassName , NULL ) ;
2005-12-23 00:46:15 +08:00
SetEvent ( timeout_thread_handle ) ;
2000-06-16 22:27:28 +08:00
return 0 ;
2000-06-16 09:54:56 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-06-16 09:54:56 +08:00
2007-11-03 03:40:39 +08:00
void zend_init_timeout_thread ( void ) /* { { { */
2000-06-16 09:54:56 +08:00
{
2000-06-16 22:27:28 +08:00
timeout_thread_event = CreateEvent ( NULL , FALSE , FALSE , NULL ) ;
2005-12-23 00:46:15 +08:00
timeout_thread_handle = CreateEvent ( NULL , FALSE , FALSE , NULL ) ;
_beginthreadex ( NULL , 0 , timeout_thread_proc , NULL , 0 , & timeout_thread_id ) ;
2000-06-16 22:27:28 +08:00
WaitForSingleObject ( timeout_thread_event , INFINITE ) ;
2000-06-16 09:54:56 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-06-16 09:54:56 +08:00
2007-11-03 03:40:39 +08:00
void zend_shutdown_timeout_thread ( void ) /* { { { */
2000-06-16 09:54:56 +08:00
{
2000-06-16 22:27:28 +08:00
if ( ! timeout_thread_initialized ) {
return ;
}
PostThreadMessage ( timeout_thread_id , WM_QUIT , 0 , 0 ) ;
2005-12-10 02:10:45 +08:00
/* Wait for thread termination */
WaitForSingleObject ( timeout_thread_handle , 5000 ) ;
CloseHandle ( timeout_thread_handle ) ;
2006-05-25 15:46:25 +08:00
timeout_thread_initialized = 0 ;
2000-06-16 09:54:56 +08:00
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-06-16 22:27:28 +08:00
2000-06-16 09:54:56 +08:00
# endif
/* This one doesn't exists on QNX */
# ifndef SIGPROF
# define SIGPROF 27
# endif
2008-03-19 05:42:50 +08:00
void zend_set_timeout ( long seconds , int reset_signals ) /* { { { */
2000-06-16 09:54:56 +08:00
{
2001-07-27 18:10:39 +08:00
TSRMLS_FETCH ( ) ;
2000-06-16 09:54:56 +08:00
EG ( timeout_seconds ) = seconds ;
2008-03-19 23:22:17 +08:00
2000-06-16 09:54:56 +08:00
# ifdef ZEND_WIN32
2008-03-19 23:30:49 +08:00
if ( ! seconds ) {
return ;
}
2007-11-03 03:40:39 +08:00
if ( timeout_thread_initialized = = 0 & & InterlockedIncrement ( & timeout_thread_initialized ) = = 1 ) {
2000-06-16 22:27:28 +08:00
/* We start up this process-wide thread here and not in zend_startup(), because if Zend
* is initialized inside a DllMain ( ) , you ' re not supposed to start threads from it .
*/
zend_init_timeout_thread ( ) ;
}
2008-03-19 23:30:49 +08:00
PostThreadMessage ( timeout_thread_id , WM_REGISTER_ZEND_TIMEOUT , ( WPARAM ) GetCurrentThreadId ( ) , ( LPARAM ) seconds ) ;
2000-06-16 09:54:56 +08:00
# else
# ifdef HAVE_SETITIMER
2000-06-16 10:49:21 +08:00
{
struct itimerval t_r ; /* timeout requested */
2000-07-04 00:53:39 +08:00
sigset_t sigset ;
2000-06-16 09:54:56 +08:00
2008-03-19 23:22:17 +08:00
if ( seconds ) {
t_r . it_value . tv_sec = seconds ;
t_r . it_value . tv_usec = t_r . it_interval . tv_sec = t_r . it_interval . tv_usec = 0 ;
2000-06-16 09:54:56 +08:00
2005-07-12 14:52:59 +08:00
# ifdef __CYGWIN__
2008-03-19 23:22:17 +08:00
setitimer ( ITIMER_REAL , & t_r , NULL ) ;
}
2008-03-19 05:42:50 +08:00
if ( reset_signals ) {
signal ( SIGALRM , zend_timeout ) ;
sigemptyset ( & sigset ) ;
sigaddset ( & sigset , SIGALRM ) ;
}
2005-07-12 14:52:59 +08:00
# else
2008-03-19 23:22:17 +08:00
setitimer ( ITIMER_PROF , & t_r , NULL ) ;
}
2008-03-19 05:42:50 +08:00
if ( reset_signals ) {
signal ( SIGPROF , zend_timeout ) ;
sigemptyset ( & sigset ) ;
sigaddset ( & sigset , SIGPROF ) ;
}
2005-07-12 14:52:59 +08:00
# endif
2008-03-19 05:42:50 +08:00
if ( reset_signals ) {
sigprocmask ( SIG_UNBLOCK , & sigset , NULL ) ;
}
2000-06-16 10:49:21 +08:00
}
2000-06-16 09:54:56 +08:00
# endif
# endif
}
2007-11-03 03:40:39 +08:00
/* }}} */
2000-06-16 09:54:56 +08:00
2007-11-03 03:40:39 +08:00
void zend_unset_timeout ( TSRMLS_D ) /* { { { */
2000-06-16 09:54:56 +08:00
{
# ifdef ZEND_WIN32
2006-11-10 19:49:35 +08:00
if ( timeout_thread_initialized ) {
PostThreadMessage ( timeout_thread_id , WM_UNREGISTER_ZEND_TIMEOUT , ( WPARAM ) GetCurrentThreadId ( ) , ( LPARAM ) 0 ) ;
}
2000-06-16 09:54:56 +08:00
# else
# ifdef HAVE_SETITIMER
2000-06-16 10:49:21 +08:00
{
struct itimerval no_timeout ;
2000-06-16 09:54:56 +08:00
2000-06-16 10:49:21 +08:00
no_timeout . it_value . tv_sec = no_timeout . it_value . tv_usec = no_timeout . it_interval . tv_sec = no_timeout . it_interval . tv_usec = 0 ;
2000-06-16 09:54:56 +08:00
2005-08-03 01:01:17 +08:00
# ifdef __CYGWIN__
setitimer ( ITIMER_REAL , & no_timeout , NULL ) ;
# else
2000-06-16 10:49:21 +08:00
setitimer ( ITIMER_PROF , & no_timeout , NULL ) ;
2005-08-03 01:01:17 +08:00
# endif
2000-06-16 10:49:21 +08:00
}
2000-06-16 09:54:56 +08:00
# endif
# endif
}
2007-11-03 03:40:39 +08:00
/* }}} */
2003-02-01 09:49:15 +08:00
2007-11-03 03:40:39 +08:00
zend_class_entry * zend_fetch_class ( const char * class_name , uint class_name_len , int fetch_type TSRMLS_DC ) /* { { { */
2003-08-03 16:21:08 +08:00
{
zend_class_entry * * pce ;
2005-09-09 14:48:49 +08:00
int use_autoload = ( fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD ) = = 0 ;
2007-11-03 03:40:39 +08:00
int rt_ns_check = ( fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK ) ? 1 : 0 ;
2007-10-03 18:33:02 +08:00
int silent = ( fetch_type & ZEND_FETCH_CLASS_SILENT ) ! = 0 ;
2003-08-03 16:21:08 +08:00
2007-10-03 18:33:02 +08:00
fetch_type & = ZEND_FETCH_CLASS_MASK ;
2007-11-03 03:40:39 +08:00
2003-08-03 16:21:08 +08:00
check_fetch_type :
switch ( fetch_type ) {
case ZEND_FETCH_CLASS_SELF :
if ( ! EG ( scope ) ) {
zend_error ( E_ERROR , " Cannot access self:: when no class scope is active " ) ;
}
return EG ( scope ) ;
case ZEND_FETCH_CLASS_PARENT :
if ( ! EG ( scope ) ) {
zend_error ( E_ERROR , " Cannot access parent:: when no class scope is active " ) ;
}
if ( ! EG ( scope ) - > parent ) {
zend_error ( E_ERROR , " Cannot access parent:: when current class scope has no parent " ) ;
}
return EG ( scope ) - > parent ;
2007-09-29 15:28:34 +08:00
case ZEND_FETCH_CLASS_STATIC :
if ( ! EG ( called_scope ) ) {
zend_error ( E_ERROR , " Cannot access static:: when no class scope is active " ) ;
}
return EG ( called_scope ) ;
2003-08-03 16:21:08 +08:00
case ZEND_FETCH_CLASS_AUTO : {
fetch_type = zend_get_class_fetch_type ( class_name , class_name_len ) ;
if ( fetch_type ! = ZEND_FETCH_CLASS_DEFAULT ) {
goto check_fetch_type ;
}
}
break ;
}
2007-11-03 03:40:39 +08:00
if ( zend_lookup_class_ex ( class_name , class_name_len , ( ! rt_ns_check & use_autoload ) , & pce TSRMLS_CC ) = = FAILURE ) {
2007-09-29 03:52:53 +08:00
if ( rt_ns_check ) {
/* Check if we have internal class with the same name */
char * php_name ;
uint php_name_len ;
2007-11-03 03:40:39 +08:00
2007-09-29 03:52:53 +08:00
php_name = zend_memrchr ( class_name , ' : ' , class_name_len ) ;
if ( php_name ) {
php_name + + ;
2007-11-03 03:40:39 +08:00
php_name_len = class_name_len - ( php_name - class_name ) ;
2007-09-29 03:52:53 +08:00
php_name = zend_str_tolower_dup ( php_name , php_name_len ) ;
2007-11-03 03:40:39 +08:00
if ( zend_hash_find ( EG ( class_table ) , php_name , php_name_len + 1 , ( void * * ) & pce ) = = SUCCESS & &
( * pce ) - > type = = ZEND_INTERNAL_CLASS
) {
efree ( php_name ) ;
2007-09-29 03:52:53 +08:00
return * pce ;
}
2007-11-03 03:40:39 +08:00
efree ( php_name ) ;
2007-09-29 03:52:53 +08:00
}
}
2005-09-09 14:48:49 +08:00
if ( use_autoload ) {
2007-11-03 03:40:39 +08:00
if ( rt_ns_check & & zend_lookup_class_ex ( class_name , class_name_len , 1 , & pce TSRMLS_CC ) = = SUCCESS ) {
2007-09-29 03:52:53 +08:00
return * pce ;
}
2007-10-03 18:33:02 +08:00
if ( ! silent ) {
if ( fetch_type = = ZEND_FETCH_CLASS_INTERFACE ) {
zend_error ( E_ERROR , " Interface '%s' not found " , class_name ) ;
} else {
zend_error ( E_ERROR , " Class '%s' not found " , class_name ) ;
}
2005-09-09 14:48:49 +08:00
}
2005-06-24 16:45:17 +08:00
}
2005-09-09 14:48:49 +08:00
return NULL ;
2003-08-03 16:21:08 +08:00
}
return * pce ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
2004-02-03 20:17:09 +08:00
2004-02-05 00:30:15 +08:00
# define MAX_ABSTRACT_INFO_CNT 3
# define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
# define DISPLAY_ABSTRACT_FN(idx) \
ai . afn [ idx ] ? ZEND_FN_SCOPE_NAME ( ai . afn [ idx ] ) : " " , \
ai . afn [ idx ] ? " :: " : " " , \
ai . afn [ idx ] ? ai . afn [ idx ] - > common . function_name : " " , \
2007-11-03 03:40:39 +08:00
ai . afn [ idx ] & & ai . afn [ idx + 1 ] ? " , " : ( ai . afn [ idx ] & & ai . cnt > MAX_ABSTRACT_INFO_CNT ? " , ... " : " " )
2004-02-05 00:30:15 +08:00
typedef struct _zend_abstract_info {
2007-11-03 03:40:39 +08:00
zend_function * afn [ MAX_ABSTRACT_INFO_CNT + 1 ] ;
2004-02-05 00:30:15 +08:00
int cnt ;
2008-01-29 19:12:57 +08:00
int ctor ;
2004-02-05 00:30:15 +08:00
} zend_abstract_info ;
2007-11-03 03:40:39 +08:00
static int zend_verify_abstract_class_function ( zend_function * fn , zend_abstract_info * ai TSRMLS_DC ) /* { { { */
2004-02-05 00:30:15 +08:00
{
if ( fn - > common . fn_flags & ZEND_ACC_ABSTRACT ) {
if ( ai - > cnt < MAX_ABSTRACT_INFO_CNT ) {
ai - > afn [ ai - > cnt ] = fn ;
}
2008-01-29 19:12:57 +08:00
if ( fn - > common . fn_flags & ZEND_ACC_CTOR ) {
if ( ! ai - > ctor ) {
ai - > cnt + + ;
ai - > ctor = 1 ;
} else {
ai - > afn [ ai - > cnt ] = NULL ;
}
} else {
ai - > cnt + + ;
}
2004-02-05 00:30:15 +08:00
}
return 0 ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
2004-02-05 00:30:15 +08:00
2007-11-03 03:40:39 +08:00
void zend_verify_abstract_class ( zend_class_entry * ce TSRMLS_DC ) /* { { { */
2004-02-05 00:30:15 +08:00
{
zend_abstract_info ai ;
2004-03-10 00:38:37 +08:00
if ( ( ce - > ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS ) & & ! ( ce - > ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS ) ) {
2004-02-05 00:30:15 +08:00
memset ( & ai , 0 , sizeof ( ai ) ) ;
zend_hash_apply_with_argument ( & ce - > function_table , ( apply_func_arg_t ) zend_verify_abstract_class_function , & ai TSRMLS_CC ) ;
2004-03-09 00:52:59 +08:00
2006-05-10 07:53:23 +08:00
if ( ai . cnt ) {
zend_error ( E_ERROR , " Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods ( " MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT " ) " ,
ce - > name , ai . cnt ,
2005-05-02 23:55:05 +08:00
ai . cnt > 1 ? " s " : " " ,
2004-03-09 00:52:59 +08:00
DISPLAY_ABSTRACT_FN ( 0 ) ,
DISPLAY_ABSTRACT_FN ( 1 ) ,
DISPLAY_ABSTRACT_FN ( 2 )
) ;
}
2004-02-05 00:30:15 +08:00
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
2004-02-05 00:30:15 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API void zend_reset_all_cv ( HashTable * symbol_table TSRMLS_DC ) /* { { { */
2005-07-04 18:01:10 +08:00
{
zend_execute_data * ex ;
int i ;
for ( ex = EG ( current_execute_data ) ; ex ; ex = ex - > prev_execute_data ) {
2005-10-28 03:25:52 +08:00
if ( ex - > op_array & & ex - > symbol_table = = symbol_table ) {
2005-07-04 18:01:10 +08:00
for ( i = 0 ; i < ex - > op_array - > last_var ; i + + ) {
ex - > CVs [ i ] = NULL ;
}
}
}
}
2007-11-03 03:40:39 +08:00
/* }}} */
2005-07-04 18:01:10 +08:00
2007-11-03 03:40:39 +08:00
ZEND_API int zend_delete_global_variable ( char * name , int name_len TSRMLS_DC ) /* { { { */
2004-10-05 03:54:35 +08:00
{
zend_execute_data * ex ;
2007-11-03 03:40:39 +08:00
ulong hash_value = zend_inline_hash_func ( name , name_len + 1 ) ;
2004-10-05 03:54:35 +08:00
2007-11-03 03:40:39 +08:00
if ( zend_hash_quick_exists ( & EG ( symbol_table ) , name , name_len + 1 , hash_value ) ) {
2004-10-05 03:54:35 +08:00
for ( ex = EG ( current_execute_data ) ; ex ; ex = ex - > prev_execute_data ) {
2005-10-28 03:25:52 +08:00
if ( ex - > op_array & & ex - > symbol_table = = & EG ( symbol_table ) ) {
2004-10-05 03:54:35 +08:00
int i ;
for ( i = 0 ; i < ex - > op_array - > last_var ; i + + ) {
2004-10-05 14:53:39 +08:00
if ( ex - > op_array - > vars [ i ] . hash_value = = hash_value & &
2007-11-03 03:40:39 +08:00
ex - > op_array - > vars [ i ] . name_len = = name_len & &
! memcmp ( ex - > op_array - > vars [ i ] . name , name , name_len )
) {
2004-10-05 03:54:35 +08:00
ex - > CVs [ i ] = NULL ;
break ;
}
}
}
}
2008-04-29 16:15:20 +08:00
return zend_hash_quick_del ( & EG ( symbol_table ) , name , name_len + 1 , hash_value ) ;
2004-10-05 03:54:35 +08:00
}
return FAILURE ;
}
2007-11-03 03:40:39 +08:00
/* }}} */
2004-02-05 00:30:15 +08:00
2008-04-29 16:15:20 +08:00
ZEND_API void zend_rebuild_symbol_table ( TSRMLS_D ) /* { { { */
{
zend_uint i ;
if ( ! EG ( active_symbol_table ) ) {
if ( EG ( symtable_cache_ptr ) > = EG ( symtable_cache ) ) {
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
EG ( active_symbol_table ) = * ( EG ( symtable_cache_ptr ) - - ) ;
} else {
ALLOC_HASHTABLE ( EG ( active_symbol_table ) ) ;
zend_hash_init ( EG ( active_symbol_table ) , 0 , NULL , ZVAL_PTR_DTOR , 0 ) ;
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
}
if ( EG ( current_execute_data ) & & EG ( current_execute_data ) - > op_array ) {
EG ( current_execute_data ) - > symbol_table = EG ( active_symbol_table ) ;
2008-05-07 20:04:39 +08:00
if ( EG ( current_execute_data ) - > op_array - > this_var ! = - 1 & &
! EG ( current_execute_data ) - > CVs [ EG ( current_execute_data ) - > op_array - > this_var ] & &
EG ( This ) ) {
EG ( current_execute_data ) - > CVs [ EG ( current_execute_data ) - > op_array - > this_var ] = ( zval * * ) EG ( current_execute_data ) - > CVs + EG ( current_execute_data ) - > op_array - > last_var + EG ( current_execute_data ) - > op_array - > this_var ;
* EG ( current_execute_data ) - > CVs [ EG ( current_execute_data ) - > op_array - > this_var ] = EG ( This ) ;
}
2008-04-29 16:15:20 +08:00
for ( i = 0 ; i < EG ( current_execute_data ) - > op_array - > last_var ; i + + ) {
if ( EG ( current_execute_data ) - > CVs [ i ] ) {
zend_hash_quick_update ( EG ( active_symbol_table ) ,
EG ( current_execute_data ) - > op_array - > vars [ i ] . name ,
EG ( current_execute_data ) - > op_array - > vars [ i ] . name_len + 1 ,
EG ( current_execute_data ) - > op_array - > vars [ i ] . hash_value ,
( void * * ) EG ( current_execute_data ) - > CVs [ i ] ,
sizeof ( zval * ) ,
( void * * ) & EG ( current_execute_data ) - > CVs [ i ] ) ;
}
}
}
}
}
/* }}} */
2003-02-01 09:49:15 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/