diff options
author | Jani Taskinen <jani@php.net> | 2007-11-02 19:40:39 +0000 |
---|---|---|
committer | Jani Taskinen <jani@php.net> | 2007-11-02 19:40:39 +0000 |
commit | b48925117750da2a7fb7cff629e3852d13917f2f (patch) | |
tree | 44671e4afbcd83803757998784821a6cc19007b5 | |
parent | 0d7479891444f46d1c30cf875037e5099f8f782b (diff) | |
download | php-git-b48925117750da2a7fb7cff629e3852d13917f2f.tar.gz |
- MFH from HEAD:
. Folding tags
. Parameter parsing
. SPL debug info
. array function improvements (not all yet)
. Improvements to function calling with call_user_* functions
. Improvements to debugging info in var_dump/print_r
# I propably forgot already something but this all was pretty close tied
# to each other so it wasn't possible to do it in parts.
-rw-r--r-- | Zend/zend.c | 473 | ||||
-rw-r--r-- | Zend/zend.h | 46 | ||||
-rw-r--r-- | Zend/zend_API.c | 817 | ||||
-rw-r--r-- | Zend/zend_API.h | 137 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 407 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 154 | ||||
-rw-r--r-- | Zend/zend_object_handlers.h | 1 | ||||
-rwxr-xr-x | ext/spl/php_spl.c | 28 | ||||
-rwxr-xr-x | ext/spl/php_spl.h | 2 | ||||
-rwxr-xr-x | ext/spl/spl_array.c | 34 | ||||
-rwxr-xr-x | ext/spl/spl_directory.c | 52 | ||||
-rwxr-xr-x | ext/spl/spl_functions.c | 29 | ||||
-rwxr-xr-x | ext/spl/spl_functions.h | 5 | ||||
-rwxr-xr-x | ext/spl/spl_iterators.c | 29 | ||||
-rwxr-xr-x | ext/spl/spl_observer.c | 38 | ||||
-rw-r--r-- | ext/standard/array.c | 2559 | ||||
-rw-r--r-- | ext/standard/basic_functions.c | 224 | ||||
-rw-r--r-- | ext/standard/basic_functions.h | 7 | ||||
-rw-r--r-- | ext/standard/php_array.h | 11 | ||||
-rw-r--r-- | ext/standard/var.c | 283 |
20 files changed, 2613 insertions, 2723 deletions
diff --git a/Zend/zend.c b/Zend/zend.c index e7767ceadf..30895c5a1a 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -30,15 +30,15 @@ #include "zend_ini.h" #ifdef ZTS -# define GLOBAL_FUNCTION_TABLE global_function_table -# define GLOBAL_CLASS_TABLE global_class_table -# define GLOBAL_CONSTANTS_TABLE global_constants_table -# define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table +# define GLOBAL_FUNCTION_TABLE global_function_table +# define GLOBAL_CLASS_TABLE global_class_table +# define GLOBAL_CONSTANTS_TABLE global_constants_table +# define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table #else -# define GLOBAL_FUNCTION_TABLE CG(function_table) -# define GLOBAL_CLASS_TABLE CG(class_table) -# define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals) -# define GLOBAL_CONSTANTS_TABLE EG(zend_constants) +# define GLOBAL_FUNCTION_TABLE CG(function_table) +# define GLOBAL_CLASS_TABLE CG(class_table) +# define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals) +# define GLOBAL_CONSTANTS_TABLE EG(zend_constants) #endif #if defined(ZEND_WIN32) && ZEND_DEBUG @@ -63,8 +63,7 @@ void (*zend_on_timeout)(int seconds TSRMLS_DC); static void (*zend_message_dispatcher_p)(long message, void *data); static int (*zend_get_configuration_directive_p)(char *name, uint name_length, zval *contents); - -static ZEND_INI_MH(OnUpdateErrorReporting) +static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */ { if (!new_value) { EG(error_reporting) = E_ALL & ~E_NOTICE & ~E_STRICT; @@ -73,7 +72,7 @@ static ZEND_INI_MH(OnUpdateErrorReporting) } return SUCCESS; } - +/* }}} */ ZEND_INI_BEGIN() ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting) @@ -87,10 +86,10 @@ ZEND_INI_END() #ifdef ZTS ZEND_API int compiler_globals_id; ZEND_API int executor_globals_id; -HashTable *global_function_table; -HashTable *global_class_table; -HashTable *global_constants_table; -HashTable *global_auto_globals_table; +static HashTable *global_function_table = NULL; +static HashTable *global_class_table = NULL; +static HashTable *global_constants_table = NULL; +static HashTable *global_auto_globals_table = NULL; static HashTable *global_persistent_list = NULL; #endif @@ -102,11 +101,9 @@ ZEND_API zval zval_used_for_init; /* True global variable */ static char *zend_version_info; static uint zend_version_info_length; #define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2007 Zend Technologies\n" - - #define PRINT_ZVAL_INDENT 4 -static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent, zend_bool is_object TSRMLS_DC) +static void print_hash(HashTable *ht, int indent, zend_bool is_object TSRMLS_DC) /* {{{ */ { zval **tmp; char *string_key; @@ -115,116 +112,116 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent, uint str_len; int i; - for (i=0; i<indent; i++) { - ZEND_PUTS_EX(" "); + for (i = 0; i < indent; i++) { + ZEND_PUTS(" "); } - ZEND_PUTS_EX("(\n"); + ZEND_PUTS("(\n"); indent += PRINT_ZVAL_INDENT; zend_hash_internal_pointer_reset_ex(ht, &iterator); while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) { - for (i=0; i<indent; i++) { - ZEND_PUTS_EX(" "); + for (i = 0; i < indent; i++) { + ZEND_PUTS(" "); } - ZEND_PUTS_EX("["); + ZEND_PUTS("["); switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) { case HASH_KEY_IS_STRING: if (is_object) { char *prop_name, *class_name; + int mangled = zend_unmangle_property_name(string_key, str_len - 1, &class_name, &prop_name); - int mangled = zend_unmangle_property_name(string_key, str_len-1, &class_name, &prop_name); - ZEND_PUTS_EX(prop_name); if (class_name && mangled == SUCCESS) { if (class_name[0]=='*') { - ZEND_PUTS_EX(":protected"); + zend_printf("%s:protected", prop_name); } else { - ZEND_PUTS_EX(":private"); + zend_printf("%s:%s:private", prop_name, class_name); } + } else { + zend_printf("%s", prop_name); } } else { - ZEND_WRITE_EX(string_key, str_len-1); + zend_printf("%s", string_key); } break; case HASH_KEY_IS_LONG: - { - char key[25]; - snprintf(key, sizeof(key), "%ld", num_key); - ZEND_PUTS_EX(key); - } + zend_printf("%ld", num_key); break; } - ZEND_PUTS_EX("] => "); - zend_print_zval_r_ex(write_func, *tmp, indent+PRINT_ZVAL_INDENT TSRMLS_CC); - ZEND_PUTS_EX("\n"); + ZEND_PUTS("] => "); + zend_print_zval_r(*tmp, indent+PRINT_ZVAL_INDENT TSRMLS_CC); + ZEND_PUTS("\n"); zend_hash_move_forward_ex(ht, &iterator); } indent -= PRINT_ZVAL_INDENT; - for (i=0; i<indent; i++) { - ZEND_PUTS_EX(" "); + for (i = 0; i < indent; i++) { + ZEND_PUTS(" "); } - ZEND_PUTS_EX(")\n"); + ZEND_PUTS(")\n"); } +/* }}} */ -static void print_flat_hash(HashTable *ht TSRMLS_DC) +static void print_flat_hash(HashTable *ht TSRMLS_DC) /* {{{ */ { - zval **tmp; - char *string_key; - HashPosition iterator; - ulong num_key; - uint str_len; - int i = 0; - - zend_hash_internal_pointer_reset_ex(ht, &iterator); - while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) { - if (i++ > 0) { - ZEND_PUTS(","); - } - ZEND_PUTS("["); - switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) { - case HASH_KEY_IS_STRING: - ZEND_PUTS(string_key); - break; - case HASH_KEY_IS_LONG: - zend_printf("%ld", num_key); - break; + zval **tmp; + char *string_key; + HashPosition iterator; + ulong num_key; + uint str_len; + int i = 0; + + zend_hash_internal_pointer_reset_ex(ht, &iterator); + while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) { + if (i++ > 0) { + ZEND_PUTS(","); + } + ZEND_PUTS("["); + switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) { + case HASH_KEY_IS_STRING: + ZEND_PUTS(string_key); + break; + case HASH_KEY_IS_LONG: + zend_printf("%ld", num_key); + break; + } + ZEND_PUTS("] => "); + zend_print_flat_zval_r(*tmp TSRMLS_CC); + zend_hash_move_forward_ex(ht, &iterator); } - ZEND_PUTS("] => "); - zend_print_flat_zval_r(*tmp TSRMLS_CC); - zend_hash_move_forward_ex(ht, &iterator); - } } +/* }}} */ -ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy) +ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy) /* {{{ */ { - if (expr->type==IS_STRING) { + if (Z_TYPE_P(expr)==IS_STRING) { *use_copy = 0; return; } - switch (expr->type) { + switch (Z_TYPE_P(expr)) { case IS_NULL: - expr_copy->value.str.len = 0; - expr_copy->value.str.val = STR_EMPTY_ALLOC(); + Z_STRLEN_P(expr_copy) = 0; + Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC(); break; case IS_BOOL: - if (expr->value.lval) { - expr_copy->value.str.len = 1; - expr_copy->value.str.val = estrndup("1", 1); + if (Z_LVAL_P(expr)) { + Z_STRLEN_P(expr_copy) = 1; + Z_STRVAL_P(expr_copy) = estrndup("1", 1); } else { - expr_copy->value.str.len = 0; - expr_copy->value.str.val = STR_EMPTY_ALLOC(); + Z_STRLEN_P(expr_copy) = 0; + Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC(); } break; case IS_RESOURCE: - expr_copy->value.str.len = zend_spprintf(&expr_copy->value.str.val, 0, "Resource id #%ld", expr->value.lval); + Z_STRVAL_P(expr_copy) = (char *) emalloc(sizeof("Resource id #") - 1 + MAX_LENGTH_OF_LONG); + Z_STRLEN_P(expr_copy) = sprintf(Z_STRVAL_P(expr_copy), "Resource id #%ld", Z_LVAL_P(expr)); break; case IS_ARRAY: - expr_copy->value.str.len = sizeof("Array")-1; - expr_copy->value.str.val = estrndup("Array", expr_copy->value.str.len); + Z_STRLEN_P(expr_copy) = sizeof("Array") - 1; + Z_STRVAL_P(expr_copy) = estrndup("Array", Z_STRLEN_P(expr_copy)); break; case IS_OBJECT: { TSRMLS_FETCH(); - if(Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) { + if (Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) { break; } /* Standard PHP objects */ @@ -237,7 +234,7 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC); Z_ADDREF_P(z); - if(Z_TYPE_P(z) != IS_OBJECT) { + if (Z_TYPE_P(z) != IS_OBJECT) { zend_make_printable_zval(z, expr_copy, use_copy); if (*use_copy) { zval_ptr_dtor(&z); @@ -250,8 +247,8 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop zval_ptr_dtor(&z); } zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name); - expr_copy->value.str.len = 0; - expr_copy->value.str.val = STR_EMPTY_ALLOC(); + Z_STRLEN_P(expr_copy) = 0; + Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC(); } break; case IS_DOUBLE: @@ -265,18 +262,18 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop convert_to_string(expr_copy); break; } - expr_copy->type = IS_STRING; + Z_TYPE_P(expr_copy) = IS_STRING; *use_copy = 1; } +/* }}} */ - -ZEND_API int zend_print_zval(zval *expr, int indent) +ZEND_API int zend_print_zval(zval *expr, int indent) /* {{{ */ { return zend_print_zval_ex(zend_write, expr, indent); } +/* }}} */ - -ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent) +ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent) /* {{{ */ { zval expr_copy; int use_copy; @@ -285,35 +282,36 @@ ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int in if (use_copy) { expr = &expr_copy; } - if (expr->value.str.len==0) { /* optimize away empty strings */ + if (Z_STRLEN_P(expr) == 0) { /* optimize away empty strings */ if (use_copy) { zval_dtor(expr); } return 0; } - write_func(expr->value.str.val, expr->value.str.len); + write_func(Z_STRVAL_P(expr), Z_STRLEN_P(expr)); if (use_copy) { zval_dtor(expr); } - return expr->value.str.len; + return Z_STRLEN_P(expr); } +/* }}} */ -ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) +ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) /* {{{ */ { - switch (expr->type) { - case IS_ARRAY: - ZEND_PUTS("Array ("); - if (++expr->value.ht->nApplyCount>1) { - ZEND_PUTS(" *RECURSION*"); - expr->value.ht->nApplyCount--; - return; - } - print_flat_hash(expr->value.ht TSRMLS_CC); - ZEND_PUTS(")"); - expr->value.ht->nApplyCount--; - break; - case IS_OBJECT: - { + switch (Z_TYPE_P(expr)) { + case IS_ARRAY: + ZEND_PUTS("Array ("); + if (++Z_ARRVAL_P(expr)->nApplyCount>1) { + ZEND_PUTS(" *RECURSION*"); + Z_ARRVAL_P(expr)->nApplyCount--; + return; + } + print_flat_hash(Z_ARRVAL_P(expr) TSRMLS_CC); + ZEND_PUTS(")"); + Z_ARRVAL_P(expr)->nApplyCount--; + break; + case IS_OBJECT: + { HashTable *properties = NULL; char *class_name = NULL; zend_uint clen; @@ -321,7 +319,11 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) if (Z_OBJ_HANDLER_P(expr, get_class_name)) { Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC); } - zend_printf("%s Object (", class_name?class_name:"Unknown Class"); + if (class_name) { + zend_printf("%s Object (", class_name); + } else { + zend_printf("%s Object (", "Unknown Class"); + } if (class_name) { efree(class_name); } @@ -339,31 +341,32 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) } ZEND_PUTS(")"); break; - } - default: - zend_print_variable(expr); - break; - } + } + default: + zend_print_variable(expr); + break; + } } +/* }}} */ -ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC) +ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC) /* {{{ */ { zend_print_zval_r_ex(zend_write, expr, indent TSRMLS_CC); } +/* }}} */ - -ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC) +ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC) /* {{{ */ { - switch (expr->type) { + switch (Z_TYPE_P(expr)) { case IS_ARRAY: - ZEND_PUTS_EX("Array\n"); - if (++expr->value.ht->nApplyCount>1) { - ZEND_PUTS_EX(" *RECURSION*"); - expr->value.ht->nApplyCount--; + ZEND_PUTS("Array\n"); + if (++Z_ARRVAL_P(expr)->nApplyCount>1) { + ZEND_PUTS(" *RECURSION*"); + Z_ARRVAL_P(expr)->nApplyCount--; return; } - print_hash(write_func, expr->value.ht, indent, 0 TSRMLS_CC); - expr->value.ht->nApplyCount--; + print_hash(Z_ARRVAL_P(expr), indent, 0 TSRMLS_CC); + Z_ARRVAL_P(expr)->nApplyCount--; break; case IS_OBJECT: { @@ -376,11 +379,10 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC); } if (class_name) { - ZEND_PUTS_EX(class_name); + zend_printf("%s Object\n", class_name); } else { - ZEND_PUTS_EX("Unknown Class"); + zend_printf("%s Object\n", "Unknown class"); } - ZEND_PUTS_EX(" Object\n"); if (class_name) { efree(class_name); } @@ -388,11 +390,11 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int break; } if (++properties->nApplyCount>1) { - ZEND_PUTS_EX(" *RECURSION*"); + ZEND_PUTS(" *RECURSION*"); properties->nApplyCount--; return; } - print_hash(write_func, properties, indent, 1 TSRMLS_CC); + print_hash(properties, indent, 1 TSRMLS_CC); properties->nApplyCount--; if (is_temp) { zend_hash_destroy(properties); @@ -401,22 +403,22 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int break; } default: - zend_print_zval_ex(write_func, expr, indent); + zend_print_variable(expr); break; } } +/* }}} */ - -static FILE *zend_fopen_wrapper(const char *filename, char **opened_path) +static FILE *zend_fopen_wrapper(const char *filename, char **opened_path) /* {{{ */ { if (opened_path) { *opened_path = estrdup(filename); } return fopen(filename, "rb"); } +/* }}} */ - -static void register_standard_class(TSRMLS_D) +static void register_standard_class(TSRMLS_D) /* {{{ */ { zend_standard_class_def = calloc(1, sizeof(zend_class_entry)); @@ -427,20 +429,21 @@ static void register_standard_class(TSRMLS_D) zend_hash_add(CG(class_table), "stdclass", sizeof("stdclass"), &zend_standard_class_def, sizeof(zend_class_entry *), NULL); } +/* }}} */ #ifdef ZTS -static zend_bool asp_tags_default = 0; -static zend_bool short_tags_default = 1; -static zend_bool ct_pass_ref_default = 1; -static zend_bool extended_info_default = 0; +static zend_bool asp_tags_default = 0; +static zend_bool short_tags_default = 1; +static zend_bool ct_pass_ref_default = 1; +static zend_bool extended_info_default = 0; #else -# define asp_tags_default 0 -# define short_tags_default 1 -# define ct_pass_ref_default 1 -# define extended_info_default 0 +# define asp_tags_default 0 +# define short_tags_default 1 +# define ct_pass_ref_default 1 +# define extended_info_default 0 #endif -static void zend_set_default_compile_time_values(TSRMLS_D) +static void zend_set_default_compile_time_values(TSRMLS_D) /* {{{ */ { /* default compile-time values */ CG(asp_tags) = asp_tags_default; @@ -448,10 +451,10 @@ static void zend_set_default_compile_time_values(TSRMLS_D) CG(allow_call_time_pass_reference) = ct_pass_ref_default; CG(extended_info) = extended_info_default; } - +/* }}} */ #ifdef ZTS -static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS_DC) +static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS_DC) /* {{{ */ { zend_function tmp_func; zend_class_entry *tmp_class; @@ -459,12 +462,12 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS compiler_globals->compiled_filename = NULL; compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init_ex(compiler_globals->function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0); - zend_hash_copy(compiler_globals->function_table, global_function_table, NULL, &tmp_func, sizeof(zend_function)); + zend_hash_init_ex(compiler_globals->function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0); + zend_hash_copy(compiler_globals->function_table, global_function_table, NULL, &tmp_func, sizeof(zend_function)); - compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0); - zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry *)); + compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable)); + zend_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0); + zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry *)); zend_set_default_compile_time_values(TSRMLS_C); @@ -481,9 +484,9 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS compiler_globals->static_members = NULL; } } +/* }}} */ - -static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS_DC) +static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS_DC) /* {{{ */ { if (compiler_globals->function_table != GLOBAL_FUNCTION_TABLE) { zend_hash_destroy(compiler_globals->function_table); @@ -502,14 +505,14 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS } compiler_globals->last_static_member = 0; } +/* }}} */ - -static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS_DC) +static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS_DC) /* {{{ */ { zend_startup_constants(TSRMLS_C); zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE); zend_init_rsrc_plist(TSRMLS_C); - EG(lambda_count)=0; + EG(lambda_count) = 0; EG(user_error_handler) = NULL; EG(user_exception_handler) = NULL; EG(in_execution) = 0; @@ -519,9 +522,9 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS EG(exit_status) = 0; EG(active) = 0; } +/* }}} */ - -static void executor_globals_dtor(zend_executor_globals *executor_globals TSRMLS_DC) +static void executor_globals_dtor(zend_executor_globals *executor_globals TSRMLS_DC) /* {{{ */ { zend_ini_shutdown(TSRMLS_C); if (&executor_globals->persistent_list != global_persistent_list) { @@ -532,14 +535,15 @@ static void executor_globals_dtor(zend_executor_globals *executor_globals TSRMLS free(executor_globals->zend_constants); } } +/* }}} */ - -static void zend_new_thread_end_handler(THREAD_T thread_id TSRMLS_DC) +static void zend_new_thread_end_handler(THREAD_T thread_id TSRMLS_DC) /* {{{ */ { if (zend_copy_ini_directives(TSRMLS_C) == SUCCESS) { zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP TSRMLS_CC); } } +/* }}} */ #endif #if defined(__FreeBSD__) || defined(__DragonFly__) @@ -547,8 +551,7 @@ static void zend_new_thread_end_handler(THREAD_T thread_id TSRMLS_DC) #include <floatingpoint.h> #endif - -static void scanner_globals_ctor(zend_scanner_globals *scanner_globals_p TSRMLS_DC) +static void scanner_globals_ctor(zend_scanner_globals *scanner_globals_p TSRMLS_DC) /* {{{ */ { scanner_globals_p->c_buf_p = (char *) 0; scanner_globals_p->init = 1; @@ -562,10 +565,11 @@ static void scanner_globals_ctor(zend_scanner_globals *scanner_globals_p TSRMLS_ scanner_globals_p->yy_start_stack_depth = 0; scanner_globals_p->yy_start_stack = 0; } +/* }}} */ void zend_init_opcodes_handlers(void); -int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions) +int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions) /* {{{ */ { #ifdef ZTS zend_compiler_globals *compiler_globals; @@ -616,29 +620,27 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i /* set up version */ zend_version_info = strdup(ZEND_CORE_VERSION_INFO); - zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO)-1; + zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO) - 1; + + GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable)); + GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable)); + GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable)); + GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable)); - GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable)); - GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable)); - GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable)); -#ifdef ZTS - GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable)); -#endif zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0); zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0); + zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0); + zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0); zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0); zend_init_rsrc_list_dtors(); - /* This zval can be used to initialize allocate zval's to an uninit'ed value */ Z_UNSET_ISREF(zval_used_for_init); Z_SET_REFCOUNT(zval_used_for_init, 1); - zval_used_for_init.type = IS_NULL; + Z_TYPE(zval_used_for_init) = IS_NULL; #ifdef ZTS - zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0); - zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0); ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor); ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor); ts_allocate_id(&language_scanner_globals_id, sizeof(zend_scanner_globals), (ts_allocate_ctor) scanner_globals_ctor, NULL); @@ -659,17 +661,15 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i zend_hash_destroy(executor_globals->zend_constants); *executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE; #else - zend_hash_init_ex(CG(auto_globals), 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0); scanner_globals_ctor(&ini_scanner_globals TSRMLS_CC); scanner_globals_ctor(&language_scanner_globals TSRMLS_CC); - zend_startup_constants(); zend_set_default_compile_time_values(TSRMLS_C); EG(user_error_handler) = NULL; EG(user_exception_handler) = NULL; #endif register_standard_class(TSRMLS_C); zend_register_standard_constants(TSRMLS_C); - zend_register_auto_global("GLOBALS", sizeof("GLOBALS")-1, NULL TSRMLS_CC); + zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, NULL TSRMLS_CC); #ifndef ZTS zend_init_rsrc_plist(TSRMLS_C); @@ -687,22 +687,22 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i return SUCCESS; } +/* }}} */ - -void zend_register_standard_ini_entries(TSRMLS_D) +void zend_register_standard_ini_entries(TSRMLS_D) /* {{{ */ { int module_number = 0; REGISTER_INI_ENTRIES(); } +/* }}} */ - -#ifdef ZTS /* Unlink the global (r/o) copies of the class, function and constant tables, * and use a fresh r/w copy for the startup thread */ -void zend_post_startup(TSRMLS_D) +void zend_post_startup(TSRMLS_D) /* {{{ */ { +#ifdef ZTS zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id); zend_executor_globals *executor_globals = ts_resource(executor_globals_id); @@ -723,11 +723,11 @@ void zend_post_startup(TSRMLS_D) executor_globals_ctor(executor_globals, tsrm_ls); global_persistent_list = &EG(persistent_list); zend_copy_ini_directives(TSRMLS_C); -} #endif +} +/* }}} */ - -void zend_shutdown(TSRMLS_D) +void zend_shutdown(TSRMLS_D) /* {{{ */ { #ifdef ZEND_WIN32 zend_shutdown_timeout_thread(); @@ -749,8 +749,8 @@ void zend_shutdown(TSRMLS_D) zend_hash_destroy(GLOBAL_CONSTANTS_TABLE); free(GLOBAL_CONSTANTS_TABLE); - zend_shutdown_strtod(); + #ifdef ZTS GLOBAL_FUNCTION_TABLE = NULL; GLOBAL_CLASS_TABLE = NULL; @@ -759,24 +759,24 @@ void zend_shutdown(TSRMLS_D) #endif zend_destroy_rsrc_list_dtors(); } +/* }}} */ - -void zend_set_utility_values(zend_utility_values *utility_values) +void zend_set_utility_values(zend_utility_values *utility_values) /* {{{ */ { zend_uv = *utility_values; zend_uv.import_use_extension_length = strlen(zend_uv.import_use_extension); } - +/* }}} */ /* this should be compatible with the standard zenderror */ -void zenderror(char *error) +void zenderror(char *error) /* {{{ */ { zend_error(E_PARSE, "%s", error); } - +/* }}} */ BEGIN_EXTERN_C() -ZEND_API void _zend_bailout(char *filename, uint lineno) +ZEND_API void _zend_bailout(char *filename, uint lineno) /* {{{ */ { TSRMLS_FETCH(); @@ -789,10 +789,10 @@ ZEND_API void _zend_bailout(char *filename, uint lineno) EG(current_execute_data) = NULL; longjmp(*EG(bailout), FAILURE); } +/* }}} */ END_EXTERN_C() - -void zend_append_version_info(zend_extension *extension) +void zend_append_version_info(zend_extension *extension) /* {{{ */ { char *new_info; uint new_info_length; @@ -803,37 +803,38 @@ void zend_append_version_info(zend_extension *extension) + strlen(extension->copyright) + strlen(extension->author); - new_info = (char *) malloc(new_info_length+1); + new_info = (char *) malloc(new_info_length + 1); sprintf(new_info, " with %s v%s, %s, by %s\n", extension->name, extension->version, extension->copyright, extension->author); - zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length+1); + zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length + 1); strcat(zend_version_info, new_info); zend_version_info_length += new_info_length; free(new_info); } +/* }}} */ - -ZEND_API char *get_zend_version(void) +ZEND_API char *get_zend_version(void) /* {{{ */ { return zend_version_info; } +/* }}} */ - -void zend_activate(TSRMLS_D) +void zend_activate(TSRMLS_D) /* {{{ */ { init_compiler(TSRMLS_C); init_executor(TSRMLS_C); startup_scanner(TSRMLS_C); } +/* }}} */ - -void zend_activate_modules(TSRMLS_D) +void zend_activate_modules(TSRMLS_D) /* {{{ */ { zend_hash_apply(&module_registry, (apply_func_t) module_registry_request_startup TSRMLS_CC); } +/* }}} */ -void zend_deactivate_modules(TSRMLS_D) +void zend_deactivate_modules(TSRMLS_D) /* {{{ */ { EG(opline_ptr) = NULL; /* we're no longer executing anything */ @@ -841,15 +842,17 @@ void zend_deactivate_modules(TSRMLS_D) zend_hash_apply(&module_registry, (apply_func_t) module_registry_cleanup TSRMLS_CC); } zend_end_try(); } +/* }}} */ -void zend_call_destructors(TSRMLS_D) +void zend_call_destructors(TSRMLS_D) /* {{{ */ { zend_try { shutdown_destructors(TSRMLS_C); } zend_end_try(); } +/* }}} */ -void zend_deactivate(TSRMLS_D) +void zend_deactivate(TSRMLS_D) /* {{{ */ { /* we're no longer executing anything */ EG(opline_ptr) = NULL; @@ -872,35 +875,35 @@ void zend_deactivate(TSRMLS_D) zend_ini_deactivate(TSRMLS_C); } zend_end_try(); } +/* }}} */ - -static int exec_done_cb(zend_module_entry *module TSRMLS_DC) +static int exec_done_cb(zend_module_entry *module TSRMLS_DC) /* {{{ */ { if (module->post_deactivate_func) { module->post_deactivate_func(); } return 0; } +/* }}} */ - -void zend_post_deactivate_modules(TSRMLS_D) +void zend_post_deactivate_modules(TSRMLS_D) /* {{{ */ { zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC); zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_unload_temp TSRMLS_CC); } - +/* }}} */ BEGIN_EXTERN_C() -ZEND_API void zend_message_dispatcher(long message, void *data) +ZEND_API void zend_message_dispatcher(long message, void *data) /* {{{ */ { if (zend_message_dispatcher_p) { zend_message_dispatcher_p(message, data); } } +/* }}} */ END_EXTERN_C() - -ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval *contents) +ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval *contents) /* {{{ */ { if (zend_get_configuration_directive_p) { return zend_get_configuration_directive_p(name, name_length, contents); @@ -908,9 +911,9 @@ ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval return FAILURE; } } +/* }}} */ - -ZEND_API void zend_error(int type, const char *format, ...) +ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ { va_list args; va_list usr_copy; @@ -998,26 +1001,24 @@ ZEND_API void zend_error(int type, const char *format, ...) # endif #endif va_copy(usr_copy, args); - z_error_message->value.str.len = zend_vspprintf(&z_error_message->value.str.val, 0, format, usr_copy); + Z_STRLEN_P(z_error_message) = zend_vspprintf(&Z_STRVAL_P(z_error_message), 0, format, usr_copy); #ifdef va_copy va_end(usr_copy); #endif - z_error_message->type = IS_STRING; + Z_TYPE_P(z_error_message) = IS_STRING; - z_error_type->value.lval = type; - z_error_type->type = IS_LONG; + Z_LVAL_P(z_error_type) = type; + Z_TYPE_P(z_error_type) = IS_LONG; if (error_filename) { - z_error_filename->value.str.len = strlen(error_filename); - z_error_filename->value.str.val = estrndup(error_filename, z_error_filename->value.str.len); - z_error_filename->type = IS_STRING; + ZVAL_STRING(z_error_filename, error_filename, 1); } - z_error_lineno->value.lval = error_lineno; - z_error_lineno->type = IS_LONG; + Z_LVAL_P(z_error_lineno) = error_lineno; + Z_TYPE_P(z_error_lineno) = IS_LONG; - z_context->value.ht = EG(active_symbol_table); - z_context->type = IS_ARRAY; + Z_ARRVAL_P(z_context) = EG(active_symbol_table); + Z_TYPE_P(z_context) = IS_ARRAY; zval_copy_ctor(z_context); params = (zval ***) emalloc(sizeof(zval **)*5); @@ -1041,7 +1042,7 @@ ZEND_API void zend_error(int type, const char *format, ...) CG(active_class_entry) = NULL; } - if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC)==SUCCESS) { + if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC) == SUCCESS) { if (retval) { if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) { zend_error_cb(type, error_filename, error_lineno, format, args); @@ -1080,12 +1081,13 @@ ZEND_API void zend_error(int type, const char *format, ...) zend_init_compiler_data_structures(TSRMLS_C); } } +/* }}} */ #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__) void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((alias("zend_error"),noreturn)); #endif -ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...) +ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...) /* {{{ */ { #if ZEND_DEBUG va_list args; @@ -1109,27 +1111,27 @@ ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, .. va_end(args); #endif } +/* }}} */ - -ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) +ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) /* {{{ */ { va_list files; int i; zend_file_handle *file_handle; zend_op_array *orig_op_array = EG(active_op_array); zval **orig_retval_ptr_ptr = EG(return_value_ptr_ptr); - zval *local_retval=NULL; + zval *local_retval = NULL; va_start(files, file_count); - for (i=0; i<file_count; i++) { + for (i = 0; i < file_count; i++) { file_handle = va_arg(files, zend_file_handle *); if (!file_handle) { continue; } EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC); - if(file_handle->opened_path) { - int dummy=1; - zend_hash_add(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path)+1, (void *)&dummy, sizeof(int), NULL); + if (file_handle->opened_path) { + int dummy = 1; + zend_hash_add(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path) + 1, (void *)&dummy, sizeof(int), NULL); } zend_destroy_file_handle(file_handle TSRMLS_CC); if (EG(active_op_array)) { @@ -1186,10 +1188,11 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co return SUCCESS; } +/* }}} */ #define COMPILED_STRING_DESCRIPTION_FORMAT "%s(%d) : %s" -ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC) +ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC) /* {{{ */ { char *cur_filename; int cur_lineno; @@ -1209,13 +1212,13 @@ ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC) zend_spprintf(&compiled_string_description, 0, COMPILED_STRING_DESCRIPTION_FORMAT, cur_filename, cur_lineno, name); return compiled_string_description; } +/* }}} */ - -void free_estring(char **str_p) +void free_estring(char **str_p) /* {{{ */ { efree(*str_p); } - +/* }}} */ /* * Local variables: diff --git a/Zend/zend.h b/Zend/zend.h index 5c869495c3..0b92c5dc75 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -54,7 +54,6 @@ # define ZEND_PATHS_SEPARATOR ':' #endif - #ifdef ZEND_WIN32 /* Only use this macro if you know for sure that all of the switches values are covered by its case statements */ @@ -177,7 +176,6 @@ char *alloca (); # define ZEND_ATTRIBUTE_PTR_FORMAT(type, idx, first) #endif - #if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(ZEND_WIN32)) && !(defined(ZTS) && defined(NETWARE)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN) # define do_alloca(p) alloca(p) # define free_alloca(p) @@ -242,7 +240,6 @@ char *alloca (); #define SUCCESS 0 #define FAILURE -1 /* this MUST stay a negative number, or it may affect functions! */ - #include "zend_hash.h" #include "zend_ts_hash.h" #include "zend_llist.h" @@ -291,7 +288,6 @@ typedef union _zvalue_value { zend_object_value obj; } zvalue_value; - struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ @@ -362,6 +358,7 @@ static always_inline zend_bool zval_set_isref_p(zval* pz) { static always_inline zend_bool zval_unset_isref_p(zval* pz) { return pz->is_ref__gc = 0; } + static always_inline zend_bool zval_set_isref_to_p(zval* pz, zend_bool isref) { return pz->is_ref__gc = isref; } @@ -451,17 +448,14 @@ typedef struct _zend_utility_functions { char *(*getenv_function)(char *name, size_t name_len TSRMLS_DC); } zend_utility_functions; - typedef struct _zend_utility_values { char *import_use_extension; uint import_use_extension_length; zend_bool html_errors; } zend_utility_values; - typedef int (*zend_write_func_t)(const char *str, uint str_length); - #undef MIN #undef MAX #define MAX(a, b) (((a)>(b))?(a):(b)) @@ -473,8 +467,6 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length); #define ZEND_TRUTH(x) ((x) ? 1 : 0) #define ZEND_LOG_XOR(a, b) (ZEND_TRUTH(a) ^ ZEND_TRUTH(b)) - - /* data types */ /* All data types <= IS_BOOL have their constructor/destructors skipped */ #define IS_NULL 0 @@ -493,20 +485,15 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length); #define IS_CONSTANT_RT_NS_CHECK 0x10 #define IS_CONSTANT_INDEX 0x80 - /* overloaded elements data types */ -#define OE_IS_ARRAY (1<<0) +#define OE_IS_ARRAY (1<<0) #define OE_IS_OBJECT (1<<1) #define OE_IS_METHOD (1<<2) int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions); void zend_shutdown(TSRMLS_D); void zend_register_standard_ini_entries(TSRMLS_D); - -#ifdef ZTS void zend_post_startup(TSRMLS_D); -#endif - void zend_set_utility_values(zend_utility_values *utility_values); BEGIN_EXTERN_C() @@ -529,7 +516,7 @@ END_EXTERN_C() } \ EG(bailout) = __orig_bailout; \ } -#define zend_first_try EG(bailout)=NULL; zend_try +#define zend_first_try EG(bailout)=NULL; zend_try BEGIN_EXTERN_C() ZEND_API char *get_zend_version(void); @@ -571,12 +558,9 @@ END_EXTERN_C() /* output support */ #define ZEND_WRITE(str, str_len) zend_write((str), (str_len)) -#define ZEND_WRITE_EX(str, str_len) write_func((str), (str_len)) #define ZEND_PUTS(str) zend_write((str), strlen((str))) -#define ZEND_PUTS_EX(str) write_func((str), strlen((str))) #define ZEND_PUTC(c) zend_write(&(c), 1), (c) - BEGIN_EXTERN_C() extern ZEND_API int (*zend_printf)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2); extern ZEND_API zend_write_func_t zend_write; @@ -590,7 +574,6 @@ extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap); extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC); - ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); void zenderror(char *error); @@ -605,7 +588,6 @@ END_EXTERN_C() #define ZEND_UV(name) (zend_uv.name) - #define HANDLE_BLOCK_INTERRUPTIONS() if (zend_block_interruptions) { zend_block_interruptions(); } #define HANDLE_UNBLOCK_INTERRUPTIONS() if (zend_unblock_interruptions) { zend_unblock_interruptions(); } @@ -615,7 +597,6 @@ ZEND_API void zend_message_dispatcher(long message, void *data); ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval *contents); END_EXTERN_C() - /* Messages for applications of Zend */ #define ZMSG_FAILED_INCLUDE_FOPEN 1L #define ZMSG_FAILED_REQUIRE_FOPEN 2L @@ -626,7 +607,7 @@ END_EXTERN_C() #define ZMSG_MEMORY_LEAKS_GRAND_TOTAL 7L #define INIT_PZVAL(z) \ - (z)->refcount__gc = 1; \ + (z)->refcount__gc = 1; \ (z)->is_ref__gc = 0; #define INIT_ZVAL(z) z = zval_used_for_init; @@ -645,13 +626,13 @@ END_EXTERN_C() { \ zval *orig_ptr = *(ppzv); \ \ - if (Z_REFCOUNT_P(orig_ptr)>1) { \ + if (Z_REFCOUNT_P(orig_ptr) > 1) { \ Z_DELREF_P(orig_ptr); \ ALLOC_ZVAL(*(ppzv)); \ **(ppzv) = *orig_ptr; \ zval_copy_ctor(*(ppzv)); \ - Z_SET_REFCOUNT_PP(ppzv, 1); \ - Z_UNSET_ISREF_PP(ppzv); \ + Z_SET_REFCOUNT_PP(ppzv, 1); \ + Z_UNSET_ISREF_PP((ppzv)); \ } \ } @@ -663,14 +644,14 @@ END_EXTERN_C() #define SEPARATE_ZVAL_TO_MAKE_IS_REF(ppzv) \ if (!PZVAL_IS_REF(*ppzv)) { \ SEPARATE_ZVAL(ppzv); \ - Z_SET_ISREF_PP(ppzv); \ + Z_SET_ISREF_PP((ppzv)); \ } #define COPY_PZVAL_TO_ZVAL(zv, pzv) \ (zv) = *(pzv); \ if (Z_REFCOUNT_P(pzv)>1) { \ zval_copy_ctor(&(zv)); \ - Z_DELREF_P(pzv); \ + Z_DELREF_P((pzv)); \ } else { \ FREE_ZVAL(pzv); \ } \ @@ -681,14 +662,14 @@ END_EXTERN_C() \ SEPARATE_ZVAL_IF_NOT_REF(ppzv_dest); \ is_ref = Z_ISREF_PP(ppzv_dest); \ - refcount = Z_REFCOUNT_PP(ppzv_dest); \ + refcount = Z_REFCOUNT_PP(ppzv_dest); \ zval_dtor(*ppzv_dest); \ **ppzv_dest = *pzv_src; \ if (copy) { \ zval_copy_ctor(*ppzv_dest); \ } \ - Z_SET_ISREF_TO_PP(ppzv_dest, is_ref); \ - Z_SET_REFCOUNT_PP(ppzv_dest, refcount); \ + Z_SET_ISREF_TO_PP(ppzv_dest, is_ref); \ + Z_SET_REFCOUNT_PP(ppzv_dest, refcount); \ } #define SEPARATE_ARG_IF_REF(varptr) \ @@ -696,7 +677,7 @@ END_EXTERN_C() zval *original_var = varptr; \ ALLOC_ZVAL(varptr); \ varptr->value = original_var->value; \ - varptr->type = original_var->type; \ + Z_TYPE_P(varptr) = Z_TYPE_P(original_var); \ Z_UNSET_ISREF_P(varptr); \ Z_SET_REFCOUNT_P(varptr, 1); \ zval_copy_ctor(varptr); \ @@ -709,7 +690,6 @@ END_EXTERN_C() (Z_TYPE_P(zv) != IS_OBJECT || \ zend_objects_store_get_refcount(zv TSRMLS_CC) == 1)) - #define ZEND_MAX_RESERVED_RESOURCES 4 #include "zend_operators.h" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 02530aad71..97b86f3f34 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -35,7 +35,7 @@ static int module_count=0; ZEND_API HashTable module_registry; /* this function doesn't check for too many parameters */ -ZEND_API int zend_get_parameters(int ht, int param_count, ...) +ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */ { void **p; int arg_count; @@ -55,7 +55,7 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) while (param_count-->0) { param = va_arg(ptr, zval **); param_ptr = *(p-arg_count); - if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr)>1) { + if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) { zval *new_tmp; ALLOC_ZVAL(new_tmp); @@ -73,9 +73,9 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) return SUCCESS; } +/* }}} */ - -ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC) +ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC) /* {{{ */ { void **p; int arg_count; @@ -90,7 +90,7 @@ ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument while (param_count-->0) { param_ptr = *(p-arg_count); - if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr)>1) { + if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) { zval *new_tmp; ALLOC_ZVAL(new_tmp); @@ -107,13 +107,11 @@ ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument return SUCCESS; } - - - +/* }}} */ /* Zend-optimized Extended functions */ /* this function doesn't check for too many parameters */ -ZEND_API int zend_get_parameters_ex(int param_count, ...) +ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */ { void **p; int arg_count; @@ -137,9 +135,9 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) return SUCCESS; } +/* }}} */ - -ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC) +ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC) /* {{{ */ { void **p; int arg_count; @@ -155,13 +153,14 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr zval **value = (zval**)(p-arg_count); if (EG(ze1_compatibility_mode) && - Z_TYPE_PP(value) == IS_OBJECT && - !Z_ISREF_PP(value)) { + Z_TYPE_PP(value) == IS_OBJECT && + !Z_ISREF_PP(value) + ) { zval *value_ptr; char *class_name; zend_uint class_name_len; int dup; - + dup = zend_get_object_classname(*value, &class_name, &class_name_len TSRMLS_CC); ALLOC_ZVAL(value_ptr); @@ -181,9 +180,9 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr return SUCCESS; } +/* }}} */ - -ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) +ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */ { void **p; int arg_count; @@ -203,20 +202,19 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TS return SUCCESS; } +/* }}} */ - -ZEND_API void zend_wrong_param_count(TSRMLS_D) +ZEND_API void zend_wrong_param_count(TSRMLS_D) /* {{{ */ { char *space; char *class_name = get_active_class_name(&space TSRMLS_CC); - + zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C)); } - +/* }}} */ /* Argument parsing API -- andrei */ - -ZEND_API char *zend_get_type_by_const(int type) +ZEND_API char *zend_get_type_by_const(int type) /* {{{ */ { switch(type) { case IS_BOOL: @@ -239,13 +237,15 @@ ZEND_API char *zend_get_type_by_const(int type) return "unknown"; } } +/* }}} */ -ZEND_API char *zend_zval_type_name(zval *arg) +ZEND_API char *zend_zval_type_name(zval *arg) /* {{{ */ { return zend_get_type_by_const(Z_TYPE_P(arg)); } +/* }}} */ -ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC) +ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC) /* {{{ */ { if (Z_OBJ_HT_P(zobject)->get_class_entry) { return Z_OBJ_HT_P(zobject)->get_class_entry(zobject TSRMLS_CC); @@ -254,9 +254,10 @@ ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC) return NULL; } } +/* }}} */ /* returns 1 if you need to copy result, 0 if it's already a copy */ -ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) +ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) /* {{{ */ { if (Z_OBJ_HT_P(object)->get_class_name == NULL || Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) { @@ -268,8 +269,9 @@ ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uin } return 0; } +/* }}} */ -static int parse_arg_object_to_string(zval **arg, char **p, int *pl, int type TSRMLS_DC) +static int parse_arg_object_to_string(zval **arg, char **p, int *pl, int type TSRMLS_DC) /* {{{ */ { if (Z_OBJ_HANDLER_PP(arg, cast_object)) { SEPARATE_ZVAL_IF_NOT_REF(arg); @@ -307,18 +309,24 @@ static int parse_arg_object_to_string(zval **arg, char **p, int *pl, int type TS } return FAILURE; } +/* }}} */ -static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec TSRMLS_DC) +static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec TSRMLS_DC) /* {{{ */ { char *spec_walk = *spec; char c = *spec_walk++; int return_null = 0; - while (*spec_walk == '/' || *spec_walk == '!') { + /* scan through modifiers */ + while (1) { if (*spec_walk == '/') { SEPARATE_ZVAL_IF_NOT_REF(arg); - } else if (*spec_walk == '!' && Z_TYPE_PP(arg) == IS_NULL) { - return_null = 1; + } else if (*spec_walk == '!') { + if (Z_TYPE_PP(arg) == IS_NULL) { + return_null = 1; + } + } else { + break; } spec_walk++; } @@ -452,14 +460,14 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp case 'r': { zval **p = va_arg(*va, zval **); - if (Z_TYPE_PP(arg) != IS_RESOURCE) { - if (Z_TYPE_PP(arg) == IS_NULL && return_null) { - *p = NULL; - } else { - return "resource"; - } - } else { + if (return_null) { + *p = NULL; + break; + } + if (Z_TYPE_PP(arg) == IS_RESOURCE) { *p = *arg; + } else { + return "resource"; } } break; @@ -467,14 +475,14 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp case 'a': { zval **p = va_arg(*va, zval **); - if (Z_TYPE_PP(arg) != IS_ARRAY) { - if (Z_TYPE_PP(arg) == IS_NULL && return_null) { - *p = NULL; - } else { - return "array"; - } - } else { + if (return_null) { + *p = NULL; + break; + } + if (Z_TYPE_PP(arg) == IS_ARRAY) { *p = *arg; + } else { + return "array"; } } break; @@ -482,14 +490,14 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp case 'h': { HashTable **p = va_arg(*va, HashTable **); - if (Z_TYPE_PP(arg) != IS_ARRAY) { - if (Z_TYPE_PP(arg) == IS_NULL && return_null) { - *p = NULL; - } else { - return "array"; - } - } else { + if (return_null) { + *p = NULL; + break; + } + if (Z_TYPE_PP(arg) == IS_ARRAY) { *p = Z_ARRVAL_PP(arg); + } else { + return "array"; } } break; @@ -497,14 +505,14 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp case 'o': { zval **p = va_arg(*va, zval **); - if (Z_TYPE_PP(arg) != IS_OBJECT) { - if (Z_TYPE_PP(arg) == IS_NULL && return_null) { - *p = NULL; - } else { - return "object"; - } - } else { + if (return_null) { + *p = NULL; + break; + } + if (Z_TYPE_PP(arg) == IS_OBJECT) { *p = *arg; + } else { + return "object"; } } break; @@ -514,13 +522,15 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp zval **p = va_arg(*va, zval **); zend_class_entry *ce = va_arg(*va, zend_class_entry *); + if (return_null) { + *p = NULL; + break; + } if (Z_TYPE_PP(arg) == IS_OBJECT && (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) { *p = *arg; } else { - if (Z_TYPE_PP(arg) == IS_NULL && return_null) { - *p = NULL; - } else if (ce) { + if (ce) { return ce->name; } else { return "object"; @@ -534,7 +544,7 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **); zend_class_entry *ce_base = *pce; - if (return_null && Z_TYPE_PP(arg) == IS_NULL) { + if (return_null) { *pce = NULL; break; } @@ -545,12 +555,12 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp *pce = *lookup; } if (ce_base) { - if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC)) && !return_null) { + if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) { char *space; char *class_name = get_active_class_name(&space TSRMLS_CC); zend_error(E_WARNING, "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given", - class_name, space, get_active_function_name(TSRMLS_C), - arg_num, ce_base->name, Z_STRVAL_PP(arg)); + class_name, space, get_active_function_name(TSRMLS_C), + arg_num, ce_base->name, Z_STRVAL_PP(arg)); *pce = NULL; return ""; } @@ -559,8 +569,8 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp char *space; char *class_name = get_active_class_name(&space TSRMLS_CC); zend_error(E_WARNING, "%s%s%s() expects parameter %d to be a valid class name, '%s' given", - class_name, space, get_active_function_name(TSRMLS_C), - arg_num, Z_STRVAL_PP(arg)); + class_name, space, get_active_function_name(TSRMLS_C), + arg_num, Z_STRVAL_PP(arg)); return ""; } break; @@ -570,40 +580,44 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp case 'f': { - zend_fcall_info *fci = va_arg(*va, zend_fcall_info *); + zend_fcall_info *fci = va_arg(*va, zend_fcall_info *); zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *); - if (zend_fcall_info_init(*arg, fci, fcc TSRMLS_CC) == SUCCESS) { - break; - } else if (return_null) { + if (return_null) { fci->size = 0; fcc->initialized = 0; break; + } + + if (zend_fcall_info_init(*arg, fci, fcc, NULL TSRMLS_CC) == SUCCESS) { + break; } else { - return "function"; + return "valid callback"; } } case 'z': { zval **p = va_arg(*va, zval **); - if (Z_TYPE_PP(arg) == IS_NULL && return_null) { + if (return_null) { *p = NULL; } else { *p = *arg; } } break; + case 'Z': { zval ***p = va_arg(*va, zval ***); - if (Z_TYPE_PP(arg) == IS_NULL && return_null) { + if (return_null) { *p = NULL; } else { *p = arg; } } break; + default: return "unknown"; } @@ -612,8 +626,9 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp return NULL; } +/* }}} */ -static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) +static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) /* {{{ */ { char *expected_type = NULL; @@ -632,8 +647,9 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int return SUCCESS; } +/* }}} */ -static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC) +static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */ { char *spec_walk; int c, i; @@ -641,10 +657,11 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl int max_num_args = 0; int post_varargs = 0; zval **arg; - void **p; int arg_count; int quiet = flags & ZEND_PARSE_PARAMS_QUIET; zend_bool have_varargs = 0; + zval ****varargs = NULL; + int *n_varargs = NULL; for (spec_walk = type_spec; *spec_walk; spec_walk++) { c = *spec_walk; @@ -681,7 +698,6 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl } return FAILURE; } - have_varargs = 1; /* we expect at least one parameter in varargs */ if (c == '+') { @@ -695,7 +711,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl if (!quiet) { zend_function *active_function = EG(function_state_ptr)->function; char *class_name = active_function->common.scope ? active_function->common.scope->name : ""; - zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters", + zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters", class_name, class_name[0] ? "::" : "", get_active_function_name(TSRMLS_C)); @@ -714,7 +730,6 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl max_num_args = -1; } - if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) { if (!quiet) { zend_function *active_function = EG(function_state_ptr)->function; @@ -731,8 +746,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl return FAILURE; } - p = EG(argument_stack).top_element-2; - arg_count = (int)(zend_uintptr_t) *p; + arg_count = (int)(zend_uintptr_t) *(EG(argument_stack).top_element-2); if (num_args > arg_count) { zend_error(E_WARNING, "%s(): could not obtain parameters for parsing", @@ -742,7 +756,6 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl i = 0; while (num_args-- > 0) { - arg = (zval **) p - (arg_count-i); if (*type_spec == '|') { type_spec++; } @@ -751,8 +764,8 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl int num_varargs = num_args + 1 - post_varargs; /* eat up the passed in storage even if it won't be filled in with varargs */ - zval ****varargs = (zval ****)va_arg(*va, zval ****); - int *n_varargs = (int *) va_arg(*va, int *); + varargs = va_arg(*va, zval ****); + n_varargs = va_arg(*va, int *); type_spec++; if (num_varargs > 0) { @@ -780,6 +793,11 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl arg = (zval **) (EG(argument_stack).top_element - 2 - (arg_count-i)); if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) { + /* clean up varargs array if it was used */ + if (varargs && *varargs) { + efree(*varargs); + *varargs = NULL; + } return FAILURE; } i++; @@ -787,21 +805,22 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl return SUCCESS; } +/* }}} */ -#define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \ +#define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \ int __num_args = (num_args); \ + \ if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \ char *__space; \ char * __class_name = get_active_class_name(&__space TSRMLS_CC); \ zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \ - __class_name, __space, \ - get_active_function_name(TSRMLS_C), __num_args); \ + __class_name, __space, \ + get_active_function_name(TSRMLS_C), __num_args); \ return FAILURE; \ }\ } - -ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) +ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */ { va_list va; int retval; @@ -814,8 +833,9 @@ ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *t return retval; } +/* }}} */ -ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) +ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */ { va_list va; int retval; @@ -828,8 +848,9 @@ ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) return retval; } +/* }}} */ -ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) +ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */ { va_list va; int retval; @@ -862,9 +883,9 @@ ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr } return retval; } +/* }}} */ - -ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) +ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */ { va_list va; int retval; @@ -901,22 +922,20 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, } return retval; } - +/* }}} */ /* Argument parsing API -- andrei */ - - -ZEND_API int _array_init(zval *arg ZEND_FILE_LINE_DC) +ZEND_API int _array_init(zval *arg ZEND_FILE_LINE_DC) /* {{{ */ { - ALLOC_HASHTABLE_REL(arg->value.ht); + ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg)); - _zend_hash_init(arg->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC); - arg->type = IS_ARRAY; + _zend_hash_init(Z_ARRVAL_P(arg), 0, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC); + Z_TYPE_P(arg) = IS_ARRAY; return SUCCESS; } +/* }}} */ - -static int zend_merge_property(zval **value, int num_args, va_list args, zend_hash_key *hash_key) +static int zend_merge_property(zval **value, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { /* which name should a numeric property have ? */ if (hash_key->nKeyLength) { @@ -932,11 +951,11 @@ static int zend_merge_property(zval **value, int num_args, va_list args, zend_ha } return ZEND_HASH_APPLY_KEEP; } - +/* }}} */ /* This function should be called after the constructor has been called * because it may call __set from the uninitialized object otherwise. */ -ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) +ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) /* {{{ */ { zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj); zend_class_entry *old_scope = EG(scope); @@ -950,9 +969,9 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro FREE_HASHTABLE(properties); } } +/* }}} */ - -ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) +ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ { if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) { zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); @@ -985,10 +1004,11 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos); if (Z_ISREF_PP(p) && - class_type->parent && - zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS && - *p == *q && - zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS) { + class_type->parent && + zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS && + *p == *q && + zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS + ) { Z_ADDREF_PP(q); Z_SET_ISREF_PP(q); zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL); @@ -1010,13 +1030,13 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC class_type->constants_updated = 1; } } - +/* }}} */ /* This function requires 'properties' to contain all props declared in the * class and all props being public. If only a subset is given or the class * has protected members then you need to merge the properties seperately by * calling zend_merge_properties(). */ -ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) +ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */ { zval *tmp; zend_object *object; @@ -1043,26 +1063,28 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type } return SUCCESS; } +/* }}} */ -ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) +ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */ { return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC); } +/* }}} */ -ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) +ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */ { return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC); } +/* }}} */ - -ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) +ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) /* {{{ */ { zend_error(E_WARNING, "add_assoc_function() is no longer supported"); return FAILURE; } +/* }}} */ - -ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) +ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */ { zval *tmp; @@ -1071,8 +1093,9 @@ ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ -ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) +ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */ { zval *tmp; @@ -1081,8 +1104,9 @@ ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ -ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) +ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */ { zval *tmp; @@ -1091,8 +1115,9 @@ ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ -ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) +ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) /* {{{ */ { zval *tmp; @@ -1101,9 +1126,9 @@ ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) +ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */ { zval *tmp; @@ -1112,9 +1137,9 @@ ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, doubl return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) +ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) /* {{{ */ { zval *tmp; @@ -1123,9 +1148,9 @@ ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate) +ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate) /* {{{ */ { zval *tmp; @@ -1134,14 +1159,15 @@ ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ -ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) +ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) /* {{{ */ { return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_index_long(zval *arg, ulong index, long n) +ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */ { zval *tmp; @@ -1150,9 +1176,9 @@ ZEND_API int add_index_long(zval *arg, ulong index, long n) return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_index_null(zval *arg, ulong index) +ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */ { zval *tmp; @@ -1161,8 +1187,9 @@ ZEND_API int add_index_null(zval *arg, ulong index) return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ -ZEND_API int add_index_bool(zval *arg, ulong index, int b) +ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */ { zval *tmp; @@ -1171,9 +1198,9 @@ ZEND_API int add_index_bool(zval *arg, ulong index, int b) return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_index_resource(zval *arg, ulong index, int r) +ZEND_API int add_index_resource(zval *arg, ulong index, int r) /* {{{ */ { zval *tmp; @@ -1182,9 +1209,9 @@ ZEND_API int add_index_resource(zval *arg, ulong index, int r) return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_index_double(zval *arg, ulong index, double d) +ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */ { zval *tmp; @@ -1193,9 +1220,9 @@ ZEND_API int add_index_double(zval *arg, ulong index, double d) return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) +ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */ { zval *tmp; @@ -1204,26 +1231,26 @@ ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int dupli return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) +ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) /* {{{ */ { zval *tmp; MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); - + return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) +ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) /* {{{ */ { return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &value, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_next_index_long(zval *arg, long n) +ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */ { zval *tmp; @@ -1232,9 +1259,9 @@ ZEND_API int add_next_index_long(zval *arg, long n) return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_next_index_null(zval *arg) +ZEND_API int add_next_index_null(zval *arg) /* {{{ */ { zval *tmp; @@ -1243,9 +1270,9 @@ ZEND_API int add_next_index_null(zval *arg) return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_next_index_bool(zval *arg, int b) +ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */ { zval *tmp; @@ -1254,9 +1281,9 @@ ZEND_API int add_next_index_bool(zval *arg, int b) return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_next_index_resource(zval *arg, int r) +ZEND_API int add_next_index_resource(zval *arg, int r) /* {{{ */ { zval *tmp; @@ -1265,9 +1292,9 @@ ZEND_API int add_next_index_resource(zval *arg, int r) return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_next_index_double(zval *arg, double d) +ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */ { zval *tmp; @@ -1276,9 +1303,9 @@ ZEND_API int add_next_index_double(zval *arg, double d) return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) +ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) /* {{{ */ { zval *tmp; @@ -1287,9 +1314,9 @@ ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) +ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) /* {{{ */ { zval *tmp; @@ -1298,15 +1325,15 @@ ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_next_index_zval(zval *arg, zval *value) +ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */ { return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL); } +/* }}} */ - -ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) +ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */ { zval *tmp; @@ -1315,9 +1342,9 @@ ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, c return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest); } +/* }}} */ - -ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, void **dest, int duplicate) +ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, void **dest, int duplicate) /* {{{ */ { zval *tmp; @@ -1326,9 +1353,9 @@ ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest); } +/* }}} */ - -ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) +ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) /* {{{ */ { zval *tmp; @@ -1337,9 +1364,9 @@ ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest); } +/* }}} */ - -ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) +ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) /* {{{ */ { zval *tmp; @@ -1348,38 +1375,38 @@ ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest); } +/* }}} */ - -ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) +ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) /* {{{ */ { zval *tmp; MAKE_STD_ZVAL(tmp); ZVAL_STRING(tmp, str, duplicate); - + return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest); } +/* }}} */ - -ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) +ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) /* {{{ */ { zval *tmp; - + MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); - + return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest); } +/* }}} */ - -ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC) +ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC) /* {{{ */ { zval *tmp; zval *z_key; MAKE_STD_ZVAL(tmp); ZVAL_LONG(tmp, n); - + MAKE_STD_ZVAL(z_key); ZVAL_STRINGL(z_key, key, key_len-1, 1); @@ -1388,8 +1415,9 @@ ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long n TSR zval_ptr_dtor(&z_key); return SUCCESS; } +/* }}} */ -ZEND_API int add_property_bool_ex(zval *arg, char *key, uint key_len, int b TSRMLS_DC) +ZEND_API int add_property_bool_ex(zval *arg, char *key, uint key_len, int b TSRMLS_DC) /* {{{ */ { zval *tmp; zval *z_key; @@ -1405,15 +1433,16 @@ ZEND_API int add_property_bool_ex(zval *arg, char *key, uint key_len, int b TSRM zval_ptr_dtor(&z_key); return SUCCESS; } +/* }}} */ -ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len TSRMLS_DC) +ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len TSRMLS_DC) /* {{{ */ { zval *tmp; zval *z_key; - + MAKE_STD_ZVAL(tmp); ZVAL_NULL(tmp); - + MAKE_STD_ZVAL(z_key); ZVAL_STRINGL(z_key, key, key_len-1, 1); @@ -1422,12 +1451,13 @@ ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len TSRMLS_DC) zval_ptr_dtor(&z_key); return SUCCESS; } +/* }}} */ -ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC) +ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC) /* {{{ */ { zval *tmp; zval *z_key; - + MAKE_STD_ZVAL(tmp); ZVAL_RESOURCE(tmp, n); @@ -1439,16 +1469,16 @@ ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long n zval_ptr_dtor(&z_key); return SUCCESS; } +/* }}} */ - -ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d TSRMLS_DC) +ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d TSRMLS_DC) /* {{{ */ { zval *tmp; zval *z_key; MAKE_STD_ZVAL(tmp); ZVAL_DOUBLE(tmp, d); - + MAKE_STD_ZVAL(z_key); ZVAL_STRINGL(z_key, key, key_len-1, 1); @@ -1457,9 +1487,9 @@ ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d zval_ptr_dtor(&z_key); return SUCCESS; } +/* }}} */ - -ZEND_API int add_property_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate TSRMLS_DC) +ZEND_API int add_property_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate TSRMLS_DC) /* {{{ */ { zval *tmp; zval *z_key; @@ -1475,8 +1505,9 @@ ZEND_API int add_property_string_ex(zval *arg, char *key, uint key_len, char *st zval_ptr_dtor(&z_key); return SUCCESS; } +/* }}} */ -ZEND_API int add_property_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC) +ZEND_API int add_property_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC) /* {{{ */ { zval *tmp; zval *z_key; @@ -1492,8 +1523,9 @@ ZEND_API int add_property_stringl_ex(zval *arg, char *key, uint key_len, char *s zval_ptr_dtor(&z_key); return SUCCESS; } +/* }}} */ -ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *value TSRMLS_DC) +ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *value TSRMLS_DC) /* {{{ */ { zval *z_key; @@ -1504,8 +1536,9 @@ ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *valu zval_ptr_dtor(&z_key); return SUCCESS; } +/* }}} */ -ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) +ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */ { int name_len; char *lcname; @@ -1526,8 +1559,7 @@ ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) name_len = strlen(dep->name); lcname = zend_str_tolower_dup(dep->name, name_len); - if (zend_hash_find(&module_registry, lcname, name_len+1, (void**)&req_mod) == FAILURE || - !req_mod->module_started) { + if (zend_hash_find(&module_registry, lcname, name_len+1, (void**)&req_mod) == FAILURE || !req_mod->module_started) { efree(lcname); /* TODO: Check version relationship */ zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name); @@ -1562,8 +1594,9 @@ ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) } return SUCCESS; } +/* }}} */ -static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) +static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) /* {{{ */ { Bucket **b1 = base; Bucket **b2; @@ -1582,7 +1615,7 @@ try_again: while (b2 < end) { r = (zend_module_entry*)(*b2)->pData; if (strcasecmp(dep->name, r->name) == 0) { - tmp = *b1; + tmp = *b1; *b1 = *b2; *b2 = tmp; goto try_again; @@ -1596,15 +1629,17 @@ try_again: b1++; } } +/* }}} */ -ZEND_API int zend_startup_modules(TSRMLS_D) +ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */ { zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC); zend_hash_apply(&module_registry, (apply_func_t)zend_startup_module_ex TSRMLS_CC); return SUCCESS; } +/* }}} */ -ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) +ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */ { int name_len; char *lcname; @@ -1615,7 +1650,7 @@ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TS } #if 0 - zend_printf("%s: Registering module %d\n", module->name, module->module_number); + zend_printf("%s: Registering module %d\n", module->name, module->module_number); #endif /* Check module dependencies */ @@ -1653,27 +1688,29 @@ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TS if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { EG(current_module) = NULL; - zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name); + zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name); return NULL; } EG(current_module) = NULL; return module; } +/* }}} */ -ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module TSRMLS_DC) +ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module TSRMLS_DC) /* {{{ */ { module->module_number = zend_next_free_module(); module->type = MODULE_PERSISTENT; return zend_register_module_ex(module TSRMLS_CC); } +/* }}} */ -ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC) +ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */ { char lcname[16]; int name_len; - /* we don't care if the function name is longer, in fact lowercasing only + /* we don't care if the function name is longer, in fact lowercasing only * the beginning of the name speeds up the check process */ name_len = strlen(fptr->common.function_name); zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1)); @@ -1714,20 +1751,23 @@ ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_ zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALL_FUNC_NAME); } } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 && - !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)) { + !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) + ) { if (fptr->common.num_args != 2) { zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALLSTATIC_FUNC_NAME); } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) { zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALLSTATIC_FUNC_NAME); } } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 && - !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0) { + !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0 + ) { zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name, ZEND_TOSTRING_FUNC_NAME); } } +/* }}} */ /* registers all functions in *library_functions in the function hash */ -ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) +ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */ { const zend_function_entry *ptr = functions; zend_function function, *reg_function; @@ -1752,7 +1792,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } internal_function->type = ZEND_INTERNAL_FUNCTION; internal_function->module = EG(current_module); - + if (scope) { class_name_len = strlen(scope->name); lc_class_name = zend_str_tolower_dup(scope->name, class_name_len); @@ -1962,11 +2002,12 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } return SUCCESS; } +/* }}} */ /* count=-1 means erase all functions, otherwise, * erase the first count functions */ -ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC) +ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC) /* {{{ */ { const zend_function_entry *ptr = functions; int i=0; @@ -1987,29 +2028,28 @@ ZEND_API void zend_unregister_functions(const zend_function_entry *functions, in i++; } } +/* }}} */ - -ZEND_API int zend_startup_module(zend_module_entry *module) +ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */ { TSRMLS_FETCH(); - if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && - zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) { + if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) { return SUCCESS; } return FAILURE; } +/* }}} */ - -ZEND_API int zend_get_module_started(char *module_name) +ZEND_API int zend_get_module_started(char *module_name) /* {{{ */ { zend_module_entry *module; return (zend_hash_find(&module_registry, module_name, strlen(module_name)+1, (void**)&module) == SUCCESS && module->module_started) ? SUCCESS : FAILURE; } +/* }}} */ - -void module_destructor(zend_module_entry *module) +void module_destructor(zend_module_entry *module) /* {{{ */ { TSRMLS_FETCH(); @@ -2020,11 +2060,11 @@ void module_destructor(zend_module_entry *module) if (module->module_started && module->module_shutdown_func) { #if 0 - zend_printf("%s: Module shutdown\n", module->name); + zend_printf("%s: Module shutdown\n", module->name); #endif module->module_shutdown_func(module->type, module->module_number TSRMLS_CC); } - + /* Deinitilaise module globals */ if (module->globals_size) { #ifdef ZTS @@ -2049,14 +2089,14 @@ void module_destructor(zend_module_entry *module) #endif #endif } - +/* }}} */ /* call request startup for all modules */ -int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) +int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) /* {{{ */ { if (module->request_startup_func) { #if 0 - zend_printf("%s: Request startup\n", module->name); + zend_printf("%s: Request startup\n", module->name); #endif if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) { zend_error(E_WARNING, "request_startup() for %s module failed", module->name); @@ -2065,33 +2105,35 @@ int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) } return 0; } - +/* }}} */ /* call request shutdown for all modules */ -int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) +int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */ { if (module->request_shutdown_func) { #if 0 - zend_printf("%s: Request shutdown\n", module->name); + zend_printf("%s: Request shutdown\n", module->name); #endif module->request_shutdown_func(module->type, module->module_number TSRMLS_CC); } return 0; } +/* }}} */ -int module_registry_unload_temp(zend_module_entry *module TSRMLS_DC) +int module_registry_unload_temp(zend_module_entry *module TSRMLS_DC) /* {{{ */ { return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP; } - +/* }}} */ /* return the next free module number */ -int zend_next_free_module(void) +int zend_next_free_module(void) /* {{{ */ { return ++module_count; } +/* }}} */ -static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) +static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */ { zend_class_entry *class_entry = malloc(sizeof(zend_class_entry)); char *lowercase_name = malloc(orig_class_entry->name_length + 1); @@ -2111,13 +2153,14 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class free(lowercase_name); return class_entry; } +/* }}} */ /* If parent_ce is not NULL then it inherits from parent_ce * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it * If both parent_ce and parent_name are NULL it does a regular class registration * If parent_name is specified but not found NULL is returned */ -ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC) +ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC) /* {{{ */ { zend_class_entry *register_class; @@ -2137,8 +2180,9 @@ ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *cla } return register_class; } +/* }}} */ -ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) +ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) /* {{{ */ { zend_class_entry *interface_entry; va_list interface_list; @@ -2148,27 +2192,29 @@ ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int interface_entry = va_arg(interface_list, zend_class_entry *); zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC); } - + va_end(interface_list); } +/* }}} */ /* A class that contains at least one abstract method automatically becomes an abstract class. */ -ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) +ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */ { return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC); } +/* }}} */ -ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC) +ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */ { return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length, - zend_bool is_ref, int num_symbol_tables, ...) +ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */ { - HashTable *symbol_table; - va_list symbol_table_list; + HashTable *symbol_table; + va_list symbol_table_list; if (num_symbol_tables <= 0) return FAILURE; @@ -2183,25 +2229,24 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length, va_end(symbol_table_list); return SUCCESS; } - - - +/* }}} */ /* Disabled functions support */ +/* {{{ proto void display_disabled_function(void) +Dummy function which displays an error when a disabled function is called. */ ZEND_API ZEND_FUNCTION(display_disabled_function) { zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C)); } +/* }}} */ - -static zend_function_entry disabled_function[] = { +static zend_function_entry disabled_function[] = { ZEND_FE(display_disabled_function, NULL) { NULL, NULL, NULL } }; - -ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC) +ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC) /* {{{ */ { if (zend_hash_del(CG(function_table), function_name, function_name_length+1)==FAILURE) { return FAILURE; @@ -2209,8 +2254,9 @@ ZEND_API int zend_disable_function(char *function_name, uint function_name_lengt disabled_function[0].fname = function_name; return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); } +/* }}} */ -static zend_object_value display_disabled_class(zend_class_entry *class_type TSRMLS_DC) +static zend_object_value display_disabled_class(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ { zend_object_value retval; zend_object *intern; @@ -2220,12 +2266,13 @@ static zend_object_value display_disabled_class(zend_class_entry *class_type TSR zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name); return retval; } +/* }}} */ -static const zend_function_entry disabled_class_new[] = { +static const zend_function_entry disabled_class_new[] = { { NULL, NULL, NULL } }; -ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC) +ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC) /* {{{ */ { zend_class_entry disabled_class; @@ -2233,14 +2280,15 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_ if (zend_hash_del(CG(class_table), class_name, class_name_length+1)==FAILURE) { return FAILURE; } - INIT_CLASS_ENTRY(disabled_class, class_name, disabled_class_new); + INIT_OVERLOADED_CLASS_ENTRY_EX(disabled_class, class_name, class_name_length, disabled_class_new, NULL, NULL, NULL, NULL, NULL); disabled_class.create_object = display_disabled_class; disabled_class.name_length = class_name_length; zend_register_internal_class(&disabled_class TSRMLS_CC); return SUCCESS; } +/* }}} */ -static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_function **fptr_ptr TSRMLS_DC) +static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_function **fptr_ptr TSRMLS_DC) /* {{{ */ { int retval; char *lmname, *colon; @@ -2251,11 +2299,11 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze *ce_ptr = NULL; *fptr_ptr = NULL; - if (!ce_org) { /* Skip leading :: */ if (Z_STRVAL_P(callable)[0] == ':' && - Z_STRVAL_P(callable)[1] == ':') { + Z_STRVAL_P(callable)[1] == ':' + ) { mlen = Z_STRLEN_P(callable) - 2; lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + 2, mlen); } else { @@ -2263,7 +2311,7 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen); } /* Check if function with given name exists. - This may be a compound name that includes namespace name */ + * This may be a compound name that includes namespace name */ if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fptr) == SUCCESS) { *fptr_ptr = fptr; efree(lmname); @@ -2274,8 +2322,9 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze /* Split name into class/namespace and method/function names */ if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL && - colon > Z_STRVAL_P(callable) && - *(colon-1) == ':') { + colon > Z_STRVAL_P(callable) && + *(colon-1) == ':' + ) { colon--; clen = colon - Z_STRVAL_P(callable); mlen = Z_STRLEN_P(callable) - clen - 2; @@ -2283,7 +2332,7 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze } if (colon != NULL) { /* This is a compound name. - Try to fetch class and then find static method. */ + * Try to fetch class and then find static method. */ *ce_ptr = zend_fetch_class(Z_STRVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); if (!*ce_ptr) { return 0; @@ -2345,11 +2394,11 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze efree(lmname); return retval; } +/* }}} */ -ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval ***zobj_ptr_ptr TSRMLS_DC) +ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval ***zobj_ptr_ptr TSRMLS_DC) /* {{{ */ { char *lcname; - zend_bool retval = 0; int callable_name_len_local; zend_class_entry *ce_local, **pce; zend_function *fptr_local; @@ -2383,9 +2432,8 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { return 1; } - - retval = zend_is_callable_check_func(check_flags|IS_CALLABLE_CHECK_IS_STATIC, zobj_ptr_ptr, NULL, callable, ce_ptr, fptr_ptr TSRMLS_CC); - break; + + return zend_is_callable_check_func(check_flags|IS_CALLABLE_CHECK_IS_STATIC, zobj_ptr_ptr, NULL, callable, ce_ptr, fptr_ptr TSRMLS_CC); case IS_ARRAY: { @@ -2396,7 +2444,8 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2 && zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj) == SUCCESS && zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method) == SUCCESS && - (Z_TYPE_PP(obj) == IS_OBJECT || Z_TYPE_PP(obj) == IS_STRING) && + (Z_TYPE_PP(obj) == IS_OBJECT || + Z_TYPE_PP(obj) == IS_STRING) && Z_TYPE_PP(method) == IS_STRING) { if (Z_TYPE_PP(obj) == IS_STRING) { @@ -2421,8 +2470,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** ce = EG(active_op_array)->scope; } else if (Z_STRLEN_PP(obj) == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent")-1) == 0 && EG(active_op_array) && EG(active_op_array)->scope) { ce = EG(active_op_array)->scope->parent; - } else if (Z_STRLEN_PP(obj) == sizeof("static")-1 && - !memcmp(lcname, "static", sizeof("static")-1)) { + } else if (Z_STRLEN_PP(obj) == sizeof("static")-1 && !memcmp(lcname, "static", sizeof("static")-1)) { ce = EG(called_scope); } else if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) { ce = *pce; @@ -2452,7 +2500,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** } if (ce) { - retval = zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fptr_ptr TSRMLS_CC); + return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fptr_ptr TSRMLS_CC); } } else if (callable_name) { *callable_name = estrndup("Array", sizeof("Array")-1); @@ -2460,7 +2508,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** } *ce_ptr = ce; } - break; + return 0; default: if (callable_name) { @@ -2472,22 +2520,20 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** *callable_name_len = Z_STRLEN(expr_copy); zval_dtor(&expr_copy); } - break; + return 0; } - - return retval; } +/* }}} */ - -ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name) +ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name) /* {{{ */ { TSRMLS_FETCH(); return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL, NULL TSRMLS_CC); } +/* }}} */ - -ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) +ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) /* {{{ */ { zend_class_entry *ce; zend_function *fptr; @@ -2504,16 +2550,17 @@ ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRML } return 0; } +/* }}} */ - -ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc TSRMLS_DC) +ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char **callable_name TSRMLS_DC) /* {{{ */ { - int len; + int lc_len; + char *lcname; zend_class_entry *ce; - zend_function *func; - zval **obj; + zend_function *func; + zval **obj; - if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, NULL, NULL, &ce, &func, &obj TSRMLS_CC)) { + if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, &ce, &func, &obj TSRMLS_CC)) { return FAILURE; } @@ -2527,11 +2574,11 @@ ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fca fci->no_separation = 1; fci->symbol_table = NULL; - len = strlen(func->common.function_name); - if ((len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && - !memcmp(func->common.function_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1)) || - (len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 && - !memcmp(func->common.function_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) { + lc_len = strlen(func->common.function_name); + lcname = zend_str_tolower_dup(func->common.function_name, lc_len); + if ((lc_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) || + (lc_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1)) + ) { fcc->initialized = 0; fcc->function_handler = NULL; fcc->calling_scope = NULL; @@ -2542,12 +2589,13 @@ ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fca fcc->calling_scope = ce; fcc->object_pp = obj; } + efree(lcname); return SUCCESS; } +/* }}} */ - -ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) +ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */ { if (fci->params) { while (fci->param_count) { @@ -2560,26 +2608,29 @@ ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) } fci->param_count = 0; } +/* }}} */ -ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) +ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) /* {{{ */ { *param_count = fci->param_count; *params = fci->params; fci->param_count = 0; fci->params = NULL; } +/* }}} */ -ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) +ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) /* {{{ */ { zend_fcall_info_args_clear(fci, 1); fci->param_count = param_count; fci->params = params; } +/* }}} */ -ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) +ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */ { HashPosition pos; - zval **arg, ***params; + zval **arg, ***params; zend_fcall_info_args_clear(fci, !args); @@ -2592,22 +2643,86 @@ ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) } fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args)); - fci->params = params = (zval***)safe_emalloc(sizeof(zval**), fci->param_count, 0); + fci->params = params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos); - while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) &arg, &pos) == SUCCESS) { + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void *) &arg, &pos) == SUCCESS) { *params++ = arg; - Z_ADDREF_PP(arg); + Z_ADDREF_P(*arg); zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos); } + + return SUCCESS; +} +/* }}} */ + +ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */ +{ + int i; + + if (argc < 0) { + return FAILURE; + } + + zend_fcall_info_args_clear(fci, !argc); + + if (argc) { + fci->param_count = argc; + fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); + + for (i = 0; i < argc; ++i) { + Z_ADDREF_P(*(argv[i])); + fci->params[i] = argv[i]; + } + } + + return SUCCESS; +} +/* }}} */ + +ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) /* {{{ */ +{ + int i; + zval **arg; + + if (argc < 0) { + return FAILURE; + } + + zend_fcall_info_args_clear(fci, !argc); + + if (argc) { + fci->param_count = argc; + fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); + + for (i = 0; i < argc; ++i) { + arg = va_arg(*argv, zval **); + Z_ADDREF_P(*arg); + fci->params[i] = arg; + } + } + return SUCCESS; } +/* }}} */ + +ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) /* {{{ */ +{ + int ret; + va_list argv; + va_start(argv, argc); + ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv); + va_end(argv); + + return ret; +} +/* }}} */ -ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) +ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) /* {{{ */ { zval *retval, ***org_params = NULL; - int result, org_count = 0; + int result, org_count = 0; fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval; if (args) { @@ -2615,7 +2730,7 @@ ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *f zend_fcall_info_args(fci, args TSRMLS_CC); } result = zend_call_function(fci, fcc TSRMLS_CC); - + if (!retval_ptr_ptr && retval) { zval_ptr_dtor(&retval); } @@ -2624,31 +2739,25 @@ ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *f } return result; } +/* }}} */ - -ZEND_API const char *zend_get_module_version(const char *module_name) +ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */ { char *lname; int name_len = strlen(module_name); zend_module_entry *module; lname = zend_str_tolower_dup(module_name, name_len); - if (zend_hash_find(&module_registry, lname, name_len + 1, - (void**)&module) == FAILURE) { + if (zend_hash_find(&module_registry, lname, name_len + 1, (void**)&module) == FAILURE) { efree(lname); return NULL; } efree(lname); return module->version; } +/* }}} */ - -ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC) -{ - return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC); -} - -ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) +ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */ { zend_property_info property_info; HashTable *target_symbol_table; @@ -2720,8 +2829,15 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name return SUCCESS; } +/* }}} */ + +ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */ +{ + return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC); +} +/* }}} */ -ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC) +ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */ { zval *property; @@ -2733,8 +2849,9 @@ ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int na INIT_ZVAL(*property); return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) +ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */ { zval *property; @@ -2747,8 +2864,9 @@ ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int na ZVAL_BOOL(property, value); return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) +ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */ { zval *property; @@ -2761,8 +2879,9 @@ ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int na ZVAL_LONG(property, value); return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC) +ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */ { zval *property; @@ -2775,8 +2894,9 @@ ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int ZVAL_DOUBLE(property, value); return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC) +ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC) /* {{{ */ { zval *property; int len = strlen(value); @@ -2791,8 +2911,9 @@ ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int INIT_PZVAL(property); return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC) +ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */ { zval *property; @@ -2806,13 +2927,15 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int INIT_PZVAL(property); return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_class_constant(zend_class_entry *ce, char *name, size_t name_length, zval *value TSRMLS_DC) +ZEND_API int zend_declare_class_constant(zend_class_entry *ce, char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */ { return zend_hash_update(&ce->constants_table, name, name_length+1, &value, sizeof(zval *), NULL); } +/* }}} */ -ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, char *name, size_t name_length TSRMLS_DC) +ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, char *name, size_t name_length TSRMLS_DC) /* {{{ */ { zval *constant; @@ -2825,8 +2948,9 @@ ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, char *name, INIT_PZVAL(constant); return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, char *name, size_t name_length, long value TSRMLS_DC) +ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */ { zval *constant; @@ -2839,8 +2963,9 @@ ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, char *name, INIT_PZVAL(constant); return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, char *name, size_t name_length, zend_bool value TSRMLS_DC) +ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, char *name, size_t name_length, zend_bool value TSRMLS_DC) /* {{{ */ { zval *constant; @@ -2853,8 +2978,9 @@ ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, char *name, INIT_PZVAL(constant); return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, char *name, size_t name_length, double value TSRMLS_DC) +ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */ { zval *constant; @@ -2867,8 +2993,9 @@ ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, char *name INIT_PZVAL(constant); return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, char *name, size_t name_length, char *value, size_t value_length TSRMLS_DC) +ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, char *name, size_t name_length, char *value, size_t value_length TSRMLS_DC) /* {{{ */ { zval *constant; @@ -2882,13 +3009,15 @@ ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, char *nam INIT_PZVAL(constant); return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, char *name, size_t name_length, char *value TSRMLS_DC) +ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, char *name, size_t name_length, char *value TSRMLS_DC) /* {{{ */ { return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC); } +/* }}} */ -ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC) +ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */ { zval *property; zend_class_entry *old_scope = EG(scope); @@ -2910,8 +3039,9 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char * EG(scope) = old_scope; } +/* }}} */ -ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC) +ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -2921,8 +3051,9 @@ ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, c ZVAL_NULL(tmp); zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) +ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -2932,8 +3063,9 @@ ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, c ZVAL_BOOL(tmp, value); zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) +ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -2943,8 +3075,9 @@ ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, c ZVAL_LONG(tmp, value); zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC) +ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -2954,8 +3087,9 @@ ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, ZVAL_DOUBLE(tmp, value); zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, char *value TSRMLS_DC) +ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, char *value TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -2965,8 +3099,9 @@ ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, ZVAL_STRING(tmp, value, 1); zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC) +ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -2976,8 +3111,9 @@ ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object ZVAL_STRINGL(tmp, value, value_len, 1); zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC) +ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */ { zval **property; zend_class_entry *old_scope = EG(scope); @@ -3010,8 +3146,9 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, in return SUCCESS; } } +/* }}} */ -ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC) +ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -3021,8 +3158,9 @@ ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *nam ZVAL_NULL(tmp); return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) +ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -3032,8 +3170,9 @@ ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *nam ZVAL_BOOL(tmp, value); return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) +ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -3043,8 +3182,9 @@ ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *nam ZVAL_LONG(tmp, value); return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC) +ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -3054,8 +3194,9 @@ ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *n ZVAL_DOUBLE(tmp, value); return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC) +ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -3065,8 +3206,9 @@ ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *n ZVAL_STRING(tmp, value, 1); return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_len TSRMLS_DC) +ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_len TSRMLS_DC) /* {{{ */ { zval *tmp; @@ -3076,8 +3218,9 @@ ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char * ZVAL_STRINGL(tmp, value, value_len, 1); return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC); } +/* }}} */ -ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC) +ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */ { zval *property, *value; zend_class_entry *old_scope = EG(scope); @@ -3100,8 +3243,9 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n EG(scope) = old_scope; return value; } +/* }}} */ -ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC) +ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */ { zval **property; zend_class_entry *old_scope = EG(scope); @@ -3112,6 +3256,7 @@ ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, in return property?*property:NULL; } +/* }}} */ /* * Local variables: diff --git a/Zend/zend_API.h b/Zend/zend_API.h index c0db612c10..ea88ca86dd 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -5,7 +5,7 @@ | Copyright (c) 1998-2007 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | + | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend license and are unable to | @@ -124,12 +124,17 @@ typedef struct _zend_function_entry { #endif -#define INIT_CLASS_ENTRY(class_container, class_name, functions) INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL) +#define INIT_CLASS_ENTRY(class_container, class_name, functions) \ + INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL) -#define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \ +#define INIT_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions) \ + INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, NULL, NULL, NULL, NULL, NULL) + +#define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \ { \ - class_container.name = strdup(class_name); \ - class_container.name_length = sizeof(class_name) - 1; \ + int _len = class_name_len; \ + class_container.name = zend_strndup(class_name, _len); \ + class_container.name_length = _len; \ class_container.builtin_functions = functions; \ class_container.constructor = NULL; \ class_container.destructor = NULL; \ @@ -140,7 +145,7 @@ typedef struct _zend_function_entry { class_container.interface_gets_implemented = NULL; \ class_container.get_static_method = NULL; \ class_container.__call = handle_fcall; \ - class_container.__callstatic = handle_fcall; \ + class_container.__callstatic = NULL; \ class_container.__tostring = NULL; \ class_container.__get = handle_propget; \ class_container.__set = handle_propset; \ @@ -159,7 +164,7 @@ typedef struct _zend_function_entry { } #define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) \ - INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset, NULL, NULL) + INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, sizeof(class_name)-1, functions, handle_fcall, handle_propget, handle_propset, NULL, NULL) #ifdef ZTS # define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members:CG(static_members)[(zend_intptr_t)(ce)->static_members]) @@ -167,6 +172,8 @@ typedef struct _zend_function_entry { # define CE_STATIC_MEMBERS(ce) ((ce)->static_members) #endif +#define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0) + int zend_next_free_module(void); BEGIN_EXTERN_C() @@ -391,6 +398,7 @@ typedef struct _zend_fcall_info_cache { } zend_fcall_info_cache; BEGIN_EXTERN_C() +ZEND_API extern zend_fcall_info empty_fcall_info; ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache; /** Build zend_call_info/cache from a zval* @@ -400,14 +408,47 @@ ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache; * In order to pass parameters the following members need to be set: * fci->param_count = 0; * fci->params = NULL; + * The callable_name argument may be NULL. + */ +ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char **callable_name TSRMLS_DC); + +/** Clear argumens connected with zend_fcall_info *fci + * If free_mem is not zero then the params array gets free'd as well + */ +ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem); + +/** Save current arguments from zend_fcall_info *fci + * params array will be set to NULL + */ +ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params); + +/** Free arguments connected with zend_fcall_info *fci andset back saved ones. */ -ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc TSRMLS_DC); +ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params); /** Set or clear the arguments in the zend_call_info struct taking care of * refcount. If args is NULL and arguments are set then those are cleared. */ ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC); +/** Set arguments in the zend_fcall_info struct taking care of refcount. + * If argc is 0 the arguments which are set will be cleared, else pass + * a variable amount of zval** arguments. + */ +ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv); + +/** Set arguments in the zend_fcall_info struct taking care of refcount. + * If argc is 0 the arguments which are set will be cleared, else pass + * a variable amount of zval** arguments. + */ +ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv); + +/** Set arguments in the zend_fcall_info struct taking care of refcount. + * If argc is 0 the arguments which are set will be cleared, else pass + * a variable amount of zval** arguments. + */ +ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...); + /** Call a function using information created by zend_fcall_info_init()/args(). * If args is given then those replace the arguement info in fci is temporarily. */ @@ -415,9 +456,7 @@ ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *f ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); - -ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length, - zend_bool is_ref, int num_symbol_tables, ...); +ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...); ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC); @@ -431,9 +470,9 @@ END_EXTERN_C() #if ZEND_DEBUG #define CHECK_ZVAL_STRING(z) \ - if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s)", (z)->value.str.val); } + if (Z_STRVAL_P(z)[ Z_STRLEN_P(z) ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s)", Z_STRVAL_P(z)); } #define CHECK_ZVAL_STRING_REL(z) \ - if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s) (source: %s:%d)", (z)->value.str.val ZEND_FILE_LINE_RELAY_CC); } + if (Z_STRVAL_P(z)[ Z_STRLEN_P(z) ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s) (source: %s:%d)", Z_STRVAL_P(z) ZEND_FILE_LINE_RELAY_CC); } #else #define CHECK_ZVAL_STRING(z) #define CHECK_ZVAL_STRING_REL(z) @@ -464,41 +503,41 @@ END_EXTERN_C() } #define ZVAL_STRING(z, s, duplicate) { \ - const char *__s=(s); \ - (z)->value.str.len = strlen(__s); \ - (z)->value.str.val = (duplicate?estrndup(__s, (z)->value.str.len):(char*)__s); \ - (z)->type = IS_STRING; \ + const char *__s=(s); \ + Z_STRLEN_P(z) = strlen(__s); \ + Z_STRVAL_P(z) = (duplicate?estrndup(__s, Z_STRLEN_P(z)):(char*)__s);\ + Z_TYPE_P(z) = IS_STRING; \ } #define ZVAL_STRINGL(z, s, l, duplicate) { \ - const char *__s=(s); int __l=l;\ - (z)->value.str.len = __l; \ - (z)->value.str.val = (duplicate?estrndup(__s, __l):(char*)__s); \ - (z)->type = IS_STRING; \ + const char *__s=(s); int __l=l; \ + Z_STRLEN_P(z) = __l; \ + Z_STRVAL_P(z) = (duplicate?estrndup(__s, __l):(char*)__s);\ + Z_TYPE_P(z) = IS_STRING; \ } -#define ZVAL_EMPTY_STRING(z) { \ - (z)->value.str.len = 0; \ - (z)->value.str.val = STR_EMPTY_ALLOC(); \ - (z)->type = IS_STRING; \ +#define ZVAL_EMPTY_STRING(z) { \ + Z_STRLEN_P(z) = 0; \ + Z_STRVAL_P(z) = STR_EMPTY_ALLOC();\ + Z_TYPE_P(z) = IS_STRING; \ } -#define ZVAL_ZVAL(z, zv, copy, dtor) { \ - int is_ref, refcount; \ - is_ref = Z_ISREF_P(z); \ - refcount = Z_REFCOUNT_P(z); \ - *(z) = *(zv); \ - if (copy) { \ - zval_copy_ctor(z); \ - } \ - if (dtor) { \ - if (!copy) { \ - ZVAL_NULL(zv); \ - } \ - zval_ptr_dtor(&zv); \ - } \ - Z_SET_ISREF_TO_P(z, is_ref); \ - Z_SET_REFCOUNT_P(z, refcount); \ +#define ZVAL_ZVAL(z, zv, copy, dtor) { \ + int is_ref, refcount; \ + is_ref = Z_ISREF_P(z); \ + refcount = Z_REFCOUNT_P(z); \ + *(z) = *(zv); \ + if (copy) { \ + zval_copy_ctor(z); \ + } \ + if (dtor) { \ + if (!copy) { \ + ZVAL_NULL(zv); \ + } \ + zval_ptr_dtor(&zv); \ + } \ + Z_SET_ISREF_TO_P(z, is_ref); \ + Z_SET_REFCOUNT_P(z, refcount); \ } #define ZVAL_FALSE(z) ZVAL_BOOL(z, 0) @@ -578,19 +617,19 @@ END_EXTERN_C() \ if (zend_hash_find(symtable, (name), (name_length), (void **) &orig_var)==SUCCESS \ && PZVAL_IS_REF(*orig_var)) { \ - Z_SET_REFCOUNT_P(var, Z_REFCOUNT_PP(orig_var)); \ - Z_SET_ISREF_P(var); \ + Z_SET_REFCOUNT_P(var, Z_REFCOUNT_PP(orig_var)); \ + Z_SET_ISREF_P(var); \ \ if (_refcount) { \ - Z_SET_REFCOUNT_P(var, Z_REFCOUNT_P(var) + _refcount-1); \ + Z_SET_REFCOUNT_P(var, Z_REFCOUNT_P(var) + _refcount - 1); \ } \ zval_dtor(*orig_var); \ **orig_var = *(var); \ - FREE_ZVAL(var); \ + FREE_ZVAL(var); \ } else { \ - Z_SET_ISREF_TO_P(var, _is_ref); \ + Z_SET_ISREF_TO_P(var, _is_ref); \ if (_refcount) { \ - Z_SET_REFCOUNT_P(var, _refcount); \ + Z_SET_REFCOUNT_P(var, _refcount); \ } \ zend_hash_update(symtable, (name), (name_length), &(var), sizeof(zval *), NULL); \ } \ @@ -600,10 +639,10 @@ END_EXTERN_C() #define ZEND_SET_GLOBAL_VAR(name, var) \ ZEND_SET_SYMBOL(&EG(symbol_table), name, var) -#define ZEND_SET_GLOBAL_VAR_WITH_LENGTH(name, name_length, var, _refcount, _is_ref) \ +#define ZEND_SET_GLOBAL_VAR_WITH_LENGTH(name, name_length, var, _refcount, _is_ref) \ ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), name, name_length, var, _refcount, _is_ref) -#define ZEND_DEFINE_PROPERTY(class_ptr, name, value, mask) \ +#define ZEND_DEFINE_PROPERTY(class_ptr, name, value, mask) \ { \ char *_name = (name); \ int namelen = strlen(_name); \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 8993c1bf4e..f5b984f5e7 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -39,6 +39,7 @@ ZEND_API void (*zend_execute)(zend_op_array *op_array TSRMLS_DC); ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); /* true globals */ +ZEND_API zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 }; ZEND_API zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL }; #ifdef ZEND_WIN32 @@ -53,11 +54,11 @@ static int timeout_thread_initialized=0; #if 0&&ZEND_DEBUG static void (*original_sigsegv_handler)(int); -static void zend_handle_sigsegv(int dummy) +static void zend_handle_sigsegv(int dummy) /* {{{ */ { fflush(stdout); fflush(stderr); - if (original_sigsegv_handler==zend_handle_sigsegv) { + if (original_sigsegv_handler == zend_handle_sigsegv) { signal(SIGSEGV, original_sigsegv_handler); } else { signal(SIGSEGV, SIG_DFL); @@ -76,53 +77,53 @@ static void zend_handle_sigsegv(int dummy) original_sigsegv_handler(dummy); } } +/* }}} */ #endif - -static void zend_extension_activator(zend_extension *extension TSRMLS_DC) +static void zend_extension_activator(zend_extension *extension TSRMLS_DC) /* {{{ */ { if (extension->activate) { extension->activate(); } } +/* }}} */ - -static void zend_extension_deactivator(zend_extension *extension TSRMLS_DC) +static void zend_extension_deactivator(zend_extension *extension TSRMLS_DC) /* {{{ */ { if (extension->deactivate) { extension->deactivate(); } } +/* }}} */ - -static int clean_non_persistent_function(zend_function *function TSRMLS_DC) +static int clean_non_persistent_function(zend_function *function TSRMLS_DC) /* {{{ */ { return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE; } +/* }}} */ - -static int clean_non_persistent_function_full(zend_function *function TSRMLS_DC) +static int clean_non_persistent_function_full(zend_function *function TSRMLS_DC) /* {{{ */ { return (function->type != ZEND_INTERNAL_FUNCTION); } +/* }}} */ - -static int clean_non_persistent_class(zend_class_entry **ce TSRMLS_DC) +static int clean_non_persistent_class(zend_class_entry **ce TSRMLS_DC) /* {{{ */ { return ((*ce)->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE; } +/* }}} */ - -static int clean_non_persistent_class_full(zend_class_entry **ce TSRMLS_DC) +static int clean_non_persistent_class_full(zend_class_entry **ce TSRMLS_DC) /* {{{ */ { return ((*ce)->type != ZEND_INTERNAL_CLASS); } +/* }}} */ - -void init_executor(TSRMLS_D) +void init_executor(TSRMLS_D) /* {{{ */ { INIT_ZVAL(EG(uninitialized_zval)); - /* trick to make uninitialized_zval never be modified, passed by ref, etc. */ + /* trick to make uninitialized_zval never be modified, passed by ref, etc. */ Z_ADDREF(EG(uninitialized_zval)); INIT_ZVAL(EG(error_zval)); EG(uninitialized_zval_ptr)=&EG(uninitialized_zval); @@ -134,9 +135,9 @@ void init_executor(TSRMLS_D) #endif EG(return_value_ptr_ptr) = NULL; - EG(symtable_cache_ptr) = EG(symtable_cache)-1; - EG(symtable_cache_limit)=EG(symtable_cache)+SYMTABLE_CACHE_SIZE-1; - EG(no_extensions)=0; + EG(symtable_cache_ptr) = EG(symtable_cache) - 1; + EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE - 1; + EG(no_extensions) = 0; EG(function_table) = CG(function_table); EG(class_table) = CG(class_table); @@ -189,13 +190,14 @@ void init_executor(TSRMLS_D) EG(called_scope) = NULL; EG(This) = NULL; - + EG(active_op_array) = NULL; EG(active) = 1; } +/* }}} */ -static int zval_call_destructor(zval **zv TSRMLS_DC) +static int zval_call_destructor(zval **zv TSRMLS_DC) /* {{{ */ { if (Z_TYPE_PP(zv) == IS_OBJECT && Z_REFCOUNT_PP(zv) == 1) { return ZEND_HASH_APPLY_REMOVE; @@ -203,8 +205,10 @@ static int zval_call_destructor(zval **zv TSRMLS_DC) return ZEND_HASH_APPLY_KEEP; } } +/* }}} */ -void shutdown_destructors(TSRMLS_D) { +void shutdown_destructors(TSRMLS_D) /* {{{ */ +{ zend_try { int symbols; do { @@ -217,10 +221,12 @@ void shutdown_destructors(TSRMLS_D) { zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC); } zend_end_try(); } +/* }}} */ -void shutdown_executor(TSRMLS_D) +void shutdown_executor(TSRMLS_D) /* {{{ */ { zend_try { + /* 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. @@ -243,7 +249,7 @@ void shutdown_executor(TSRMLS_D) zend_try { zval *zeh; /* remove error handlers before destroying classes and functions, - so that if handler used some class, crash would not happen */ + * so that if handler used some class, crash would not happen */ if (EG(user_error_handler)) { zeh = EG(user_error_handler); EG(user_error_handler) = NULL; @@ -266,14 +272,14 @@ void shutdown_executor(TSRMLS_D) zend_try { /* Cleanup static data for functions and arrays. - 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 */ + * 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 */ if (EG(full_tables_cleanup)) { zend_hash_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC); } else { @@ -323,10 +329,10 @@ void shutdown_executor(TSRMLS_D) } zend_end_try(); EG(active) = 0; } - +/* }}} */ /* return class name and "::" or "". */ -ZEND_API char *get_active_class_name(char **space TSRMLS_DC) +ZEND_API char *get_active_class_name(char **space TSRMLS_DC) /* {{{ */ { if (!zend_is_executing(TSRMLS_C)) { if (space) { @@ -352,9 +358,9 @@ ZEND_API char *get_active_class_name(char **space TSRMLS_DC) return ""; } } +/* }}} */ - -ZEND_API char *get_active_function_name(TSRMLS_D) +ZEND_API char *get_active_function_name(TSRMLS_D) /* {{{ */ { if (!zend_is_executing(TSRMLS_C)) { return NULL; @@ -377,9 +383,9 @@ ZEND_API char *get_active_function_name(TSRMLS_D) return NULL; } } +/* }}} */ - -ZEND_API char *zend_get_executed_filename(TSRMLS_D) +ZEND_API char *zend_get_executed_filename(TSRMLS_D) /* {{{ */ { if (EG(active_op_array)) { return EG(active_op_array)->filename; @@ -387,9 +393,9 @@ ZEND_API char *zend_get_executed_filename(TSRMLS_D) return "[no active file]"; } } +/* }}} */ - -ZEND_API uint zend_get_executed_lineno(TSRMLS_D) +ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */ { if (EG(opline_ptr)) { return active_opline->lineno; @@ -397,21 +403,21 @@ ZEND_API uint zend_get_executed_lineno(TSRMLS_D) return 0; } } +/* }}} */ - -ZEND_API zend_bool zend_is_executing(TSRMLS_D) +ZEND_API zend_bool zend_is_executing(TSRMLS_D) /* {{{ */ { return EG(in_execution); } +/* }}} */ - -ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) +ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */ { #if DEBUG_ZEND>=2 - printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr)-1); + printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1); #endif Z_DELREF_PP(zval_ptr); - if (Z_REFCOUNT_PP(zval_ptr)==0) { + if (Z_REFCOUNT_PP(zval_ptr) == 0) { zval_dtor(*zval_ptr); safe_free_zval_ptr_rel(*zval_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC); } else if (Z_REFCOUNT_PP(zval_ptr) == 1) { @@ -425,36 +431,37 @@ ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) Z_UNSET_ISREF_PP(zval_ptr); } } +/* }}} */ - -ZEND_API void _zval_internal_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) +ZEND_API void _zval_internal_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */ { #if DEBUG_ZEND>=2 - printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr)-1); + printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1); #endif Z_DELREF_PP(zval_ptr); - if (Z_REFCOUNT_PP(zval_ptr)==0) { + if (Z_REFCOUNT_PP(zval_ptr) == 0) { zval_internal_dtor(*zval_ptr); free(*zval_ptr); } else if (Z_REFCOUNT_PP(zval_ptr) == 1) { Z_UNSET_ISREF_PP(zval_ptr); } } +/* }}} */ - -ZEND_API int zend_is_true(zval *op) +ZEND_API int zend_is_true(zval *op) /* {{{ */ { return i_zend_is_true(op); } +/* }}} */ #include "../TSRM/tsrm_strtok_r.h" -#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 +#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 -ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC) +ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC) /* {{{ */ { zval *p = *pp; zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg; @@ -479,16 +486,14 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco if ((colon = memchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p))) && colon[1] == ':') { zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p)); } - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", - p->value.str.val, - p->value.str.val); + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", Z_STRVAL_P(p), Z_STRVAL_P(p)); p->type = IS_STRING; if (!inline_change) { zval_copy_ctor(p); } } else { if (inline_change) { - STR_FREE(p->value.str.val); + STR_FREE(Z_STRVAL_P(p)); } *p = const_value; } @@ -507,18 +512,18 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco /* First go over the array and see if there are any constant indices */ zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); - while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element)==SUCCESS) { + while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) { if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) { zend_hash_move_forward(Z_ARRVAL_P(p)); continue; } Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX; - if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL)!=HASH_KEY_IS_STRING) { + if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) { zend_hash_move_forward(Z_ARRVAL_P(p)); continue; } - if (!zend_get_constant_ex(str_index, str_index_len-3, &const_value, scope, str_index[str_index_len-2] TSRMLS_CC)) { - if ((colon = memchr(str_index, ':', str_index_len-3)) && colon[1] == ':') { + if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) { + if ((colon = memchr(str_index, ':', str_index_len - 3)) && colon[1] == ':') { zend_error(E_ERROR, "Undefined class constant '%s'", str_index); } zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index); @@ -540,7 +545,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco switch (Z_TYPE(const_value)) { case IS_STRING: - zend_symtable_update_current_key(Z_ARRVAL_P(p), const_value.value.str.val, const_value.value.str.len+1); + zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1); break; case IS_BOOL: case IS_LONG: @@ -561,13 +566,15 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco } return 0; } +/* }}} */ -ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) +ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) /* {{{ */ { return zval_update_constant_ex(pp, arg, NULL TSRMLS_CC); } +/* }}} */ -int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC) +int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC) /* {{{ */ { zval ***params_array; zend_uint i; @@ -593,9 +600,9 @@ int call_user_function(HashTable *function_table, zval **object_pp, zval *functi } return ex_retval; } +/* }}} */ - -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) +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) /* {{{ */ { zend_fcall_info fci; @@ -611,9 +618,9 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun return zend_call_function(&fci, NULL TSRMLS_CC); } +/* }}} */ - -int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) +int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) /* {{{ */ { zend_uint i; zval **original_return_value; @@ -630,9 +637,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zval *method_name; zval *params_array; int call_via_handler = 0; - char *fname, *colon; + unsigned int clen; int fname_len; - char *lcname; + char *colon, *fname, *cname, *lcname; *fci->retval_ptr_ptr = NULL; @@ -657,7 +664,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS execute_data = *EG(current_execute_data); EX(op_array) = NULL; EX(opline) = NULL; - EX(object) = NULL; + EX(object) = NULL; } else { /* This only happens when we're called outside any execute()'s * It shouldn't be strictly necessary to NULL execute_data out, @@ -667,13 +674,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } if (!fci_cache || !fci_cache->initialized) { - if (Z_TYPE_P(fci->function_name)==IS_ARRAY) { /* assume array($obj, $name) couple */ + if (Z_TYPE_P(fci->function_name) == IS_ARRAY) { /* assume array($obj, $name) couple */ zval **tmp_object_ptr, **tmp_real_function_name; - if (zend_hash_index_find(Z_ARRVAL_P(fci->function_name), 0, (void **) &tmp_object_ptr)==FAILURE) { + if (zend_hash_index_find(Z_ARRVAL_P(fci->function_name), 0, (void **) &tmp_object_ptr) == FAILURE) { return FAILURE; } - if (zend_hash_index_find(Z_ARRVAL_P(fci->function_name), 1, (void **) &tmp_real_function_name)==FAILURE) { + if (zend_hash_index_find(Z_ARRVAL_P(fci->function_name), 1, (void **) &tmp_real_function_name) == FAILURE) { return FAILURE; } fci->function_name = *tmp_real_function_name; @@ -700,7 +707,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS calling_scope = Z_OBJCE_PP(fci->object_pp); fci->function_table = &calling_scope->function_table; - EX(object) = *fci->object_pp; + EX(object) = *fci->object_pp; } else if (Z_TYPE_PP(fci->object_pp) == IS_STRING) { zend_class_entry **ce; int found = FAILURE; @@ -725,8 +732,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); - } else if (Z_STRLEN_PP(fci->object_pp) == sizeof("static")-1 && - !memcmp(Z_STRVAL_PP(fci->object_pp), "static", sizeof("static")-1)) { + } else if (Z_STRLEN_PP(fci->object_pp) == sizeof("static") - 1 && + !memcmp(Z_STRVAL_PP(fci->object_pp), "static", sizeof("static") - 1) + ) { if (!EG(called_scope)) { zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); } @@ -766,7 +774,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } } - if (fci->function_name->type!=IS_STRING) { + if (Z_TYPE_P(fci->function_name) != IS_STRING) { return FAILURE; } @@ -776,51 +784,66 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS fname += 2; fname_len -=2; } - lcname = zend_str_tolower_dup(fname, fname_len); EX(function_state).function = NULL; + lcname = zend_str_tolower_dup(fname, fname_len); + if (!fci->object_pp && - zend_hash_find(fci->function_table, lcname, fname_len+1, (void**)&EX(function_state).function) == SUCCESS) { + zend_hash_find(fci->function_table, lcname, fname_len + 1, (void **)&EX(function_state).function) == SUCCESS + ) { efree(lcname); } else { + efree(lcname); + + cname = fname; + if ((colon = zend_memrchr(fname, ':', fname_len)) != NULL && - colon > fname && - *(colon-1) == ':') { - int clen = colon - fname - 1; - int mlen = fname_len - clen - 2; + colon > fname && + *(colon - 1) == ':' + ) { + clen = colon - fname - 1; + fname_len -= (clen + 2); + fname = colon + 1; + } + if (colon != NULL) { zend_class_entry **pce, *ce_child = NULL; - - if (calling_scope && clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) { + + lcname = zend_str_tolower_dup(cname, clen); + /* caution: lcname is not '\0' terminated */ + if (calling_scope && clen == sizeof("self") - 1 && + memcmp(lcname, "self", sizeof("self") - 1) == 0 + ) { ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL; - } else if (calling_scope && clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) { + } else if (calling_scope && clen == sizeof("parent") - 1 && + memcmp(lcname, "parent", sizeof("parent") - 1) == 0 + ) { ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL; - } else if (clen == sizeof("static") - 1 && - !memcmp(lcname, "static", sizeof("static")-1)) { + } else if (clen == sizeof("static") - 1 && + memcmp(lcname, "static", sizeof("static") - 1) + ) { ce_child = EG(called_scope); - } else if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) { + } else if (zend_lookup_class(lcname, clen, &pce TSRMLS_CC) == SUCCESS) { ce_child = *pce; } - + efree(lcname); + if (!ce_child) { - zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname); + zend_error(E_ERROR, "Cannot call method %s() or method does not exist", Z_STRVAL_P(fci->function_name)); return FAILURE; } check_scope_or_static = calling_scope; fci->function_table = &ce_child->function_table; calling_scope = ce_child; - fname = fname + clen + 2; - fname_len = mlen; } - efree(lcname); if (fci->object_pp) { if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) { zend_error(E_ERROR, "Object does not support method calls"); } - EX(function_state).function = - Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, fname, fname_len TSRMLS_CC); + EX(function_state).function = + Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, fname, fname_len TSRMLS_CC); if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) { char *function_name_lc = zend_str_tolower_dup(fname, fname_len); - if (zend_hash_find(&calling_scope->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) { + if (zend_hash_find(&calling_scope->function_table, function_name_lc, fname_len + 1, (void **) &EX(function_state).function) == FAILURE) { efree(function_name_lc); zend_error(E_ERROR, "Cannot call method %s::%s() or method does not exist", calling_scope->name, fname); } @@ -830,29 +853,28 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS char *function_name_lc = zend_str_tolower_dup(fname, fname_len); if (calling_scope->get_static_method) { - EX(function_state).function = - calling_scope->get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC); + EX(function_state).function = calling_scope->get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC); } else { - EX(function_state).function = - zend_std_get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC); + EX(function_state).function = zend_std_get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC); } efree(function_name_lc); + if (check_scope_or_static && EX(function_state).function && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC) && !instanceof_function(check_scope_or_static, calling_scope TSRMLS_CC)) { - zend_error(E_ERROR, "Cannot call method %s() of class %s which is not a derived from %s", fname, calling_scope->name, check_scope_or_static->name); + zend_error(E_ERROR, "Cannot call method %s() of class %s which is not a derived from %s", Z_STRVAL_P(fci->function_name), calling_scope->name, check_scope_or_static->name); return FAILURE; } } } - if (EX(function_state).function == NULL) { + if (EX(function_state).function == NULL) { /* try calling __call */ if (calling_scope && calling_scope->__call) { EX(function_state).function = calling_scope->__call; /* prepare params */ ALLOC_INIT_ZVAL(method_name); - ZVAL_STRINGL(method_name, Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name), 0); + ZVAL_STRINGL(method_name, fname, fname_len, 0); ALLOC_INIT_ZVAL(params_array); array_init(params_array); @@ -862,8 +884,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } } if (fci_cache && - (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION || - ((zend_internal_function*)EX(function_state).function)->handler != zend_std_call_user_call)) { + (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION || + ((zend_internal_function*)EX(function_state).function)->handler != zend_std_call_user_call) + ) { fci_cache->function_handler = EX(function_state).function; fci_cache->object_pp = fci->object_pp; fci_cache->calling_scope = calling_scope; @@ -895,9 +918,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS for (i=0; i<fci->param_count; i++) { zval *param; - if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i+1) + if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1) && !PZVAL_IS_REF(*fci->params[i])) { - if (Z_REFCOUNT_PP(fci->params[i])>1) { + if (Z_REFCOUNT_PP(fci->params[i]) > 1) { zval *new_zval; if (fci->no_separation) { @@ -960,7 +983,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) { EG(called_scope) = NULL; } - + if (fci->object_pp) { if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) { EG(This) = NULL; @@ -1024,8 +1047,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS if (EX(function_state).function->common.scope) { EG(scope) = EX(function_state).function->common.scope; } - ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, EX(function_state).function->common.return_reference?fci->retval_ptr_ptr:NULL, (fci->object_pp?*fci->object_pp:NULL), 1 TSRMLS_CC); - INIT_PZVAL(*fci->retval_ptr_ptr); + ((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); + /* 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); + }*/ } zend_ptr_stack_clear_multiple(TSRMLS_C); if (call_via_handler) { @@ -1047,9 +1075,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } return SUCCESS; } +/* }}} */ - -ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC) +ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ { zval **args[1]; zval autoload_function; @@ -1066,7 +1094,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut if (name == NULL || !name_length) { return FAILURE; } - + lc_free = lc_name = do_alloca(name_length + 1); zend_str_tolower_copy(lc_name, name, name_length); @@ -1075,7 +1103,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut name_length -= 2; } - if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) { + if (zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce) == SUCCESS) { free_alloca(lc_free); return SUCCESS; } @@ -1090,20 +1118,20 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut if (EG(in_autoload) == NULL) { ALLOC_HASHTABLE(EG(in_autoload)); - zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0); + zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0); } - - if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) { + + if (zend_hash_add(EG(in_autoload), lc_name, name_length + 1, (void**)&dummy, sizeof(char), NULL) == FAILURE) { free_alloca(lc_free); return FAILURE; } - ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1, 0); + ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1, 0); ALLOC_ZVAL(class_name_ptr); INIT_PZVAL(class_name_ptr); ZVAL_STRINGL(class_name_ptr, name, name_length, 1); - + args[0] = &class_name_ptr; fcall_info.size = sizeof(fcall_info); @@ -1128,7 +1156,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut zval_ptr_dtor(&class_name_ptr); - zend_hash_del(EG(in_autoload), lc_name, name_length+1); + zend_hash_del(EG(in_autoload), lc_name, name_length + 1); if (retval == FAILURE) { EG(exception) = exception; @@ -1152,13 +1180,15 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut free_alloca(lc_free); return retval; } +/* }}} */ -ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) +ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ { return zend_lookup_class_ex(name, name_length, 1, ce TSRMLS_CC); } +/* }}} */ -ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC) +ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */ { zval pv; zend_op_array *new_op_array; @@ -1169,18 +1199,18 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR if (retval_ptr) { int l = strlen(str); - Z_STRLEN(pv) = l+sizeof("return ;")-1; + Z_STRLEN(pv) = l + sizeof("return ;") - 1; Z_STRVAL(pv) = emalloc(Z_STRLEN(pv) + 1); - 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] = ';'; + 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] = ';'; Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0'; } else { - pv.value.str.len = strlen(str); - pv.value.str.val = estrndup(str, pv.value.str.len); + Z_STRLEN(pv) = strlen(str); + Z_STRVAL(pv) = estrndup(str, Z_STRLEN(pv)); } - pv.type = IS_STRING; + Z_TYPE(pv) = IS_STRING; /*printf("Evaluating '%s'\n", pv.value.str.val);*/ @@ -1226,9 +1256,9 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR zval_dtor(&pv); return retval; } +/* }}} */ - -ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) +ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */ { int result; @@ -1239,9 +1269,9 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, } return result; } +/* }}} */ - -void execute_new_code(TSRMLS_D) +void execute_new_code(TSRMLS_D) /* {{{ */ { zend_op *opline, *end; zend_op *ret_opline; @@ -1270,11 +1300,11 @@ void execute_new_code(TSRMLS_D) end=CG(active_op_array)->opcodes+CG(active_op_array)->last; while (opline<end) { - if (opline->op1.op_type==IS_CONST) { + if (opline->op1.op_type == IS_CONST) { Z_SET_ISREF(opline->op1.u.constant); Z_SET_REFCOUNT(opline->op1.u.constant, 2); /* Make sure is_ref won't be reset */ } - if (opline->op2.op_type==IS_CONST) { + if (opline->op2.op_type == IS_CONST) { Z_SET_ISREF(opline->op2.u.constant); Z_SET_REFCOUNT(opline->op2.u.constant, 2); } @@ -1307,9 +1337,9 @@ void execute_new_code(TSRMLS_D) CG(active_op_array)->last -= 2; /* get rid of that ZEND_RETURN and ZEND_HANDLE_EXCEPTION */ CG(active_op_array)->start_op = CG(active_op_array)->opcodes+CG(active_op_array)->last; } +/* }}} */ - -ZEND_API void zend_timeout(int dummy) +ZEND_API void zend_timeout(int dummy) /* {{{ */ { TSRMLS_FETCH(); @@ -1317,12 +1347,12 @@ ZEND_API void zend_timeout(int dummy) zend_on_timeout(EG(timeout_seconds) TSRMLS_CC); } - zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", - EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); + zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); } +/* }}} */ #ifdef ZEND_WIN32 -static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /* {{{ */ { switch (message) { case WM_DESTROY: @@ -1330,7 +1360,7 @@ static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wPa break; case WM_REGISTER_ZEND_TIMEOUT: /* wParam is the thread id pointer, lParam is the timeout amount in seconds */ - if (lParam==0) { + if (lParam == 0) { KillTimer(timeout_window, wParam); } else { #ifdef ZTS @@ -1370,10 +1400,9 @@ static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wPa } return 0; } +/* }}} */ - - -static unsigned __stdcall timeout_thread_proc(void *pArgs) +static unsigned __stdcall timeout_thread_proc(void *pArgs) /* {{{ */ { MSG message; @@ -1403,18 +1432,18 @@ static unsigned __stdcall timeout_thread_proc(void *pArgs) SetEvent(timeout_thread_handle); return 0; } +/* }}} */ - -void zend_init_timeout_thread(void) +void zend_init_timeout_thread(void) /* {{{ */ { timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL); timeout_thread_handle = CreateEvent(NULL, FALSE, FALSE, NULL); _beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id); WaitForSingleObject(timeout_thread_event, INFINITE); } +/* }}} */ - -void zend_shutdown_timeout_thread(void) +void zend_shutdown_timeout_thread(void) /* {{{ */ { if (!timeout_thread_initialized) { return; @@ -1426,6 +1455,7 @@ void zend_shutdown_timeout_thread(void) CloseHandle(timeout_thread_handle); timeout_thread_initialized = 0; } +/* }}} */ #endif @@ -1434,7 +1464,7 @@ void zend_shutdown_timeout_thread(void) #define SIGPROF 27 #endif -void zend_set_timeout(long seconds) +void zend_set_timeout(long seconds) /* {{{ */ { TSRMLS_FETCH(); @@ -1443,7 +1473,7 @@ void zend_set_timeout(long seconds) return; } #ifdef ZEND_WIN32 - if (timeout_thread_initialized==0 && InterlockedIncrement(&timeout_thread_initialized)==1) { + if (timeout_thread_initialized == 0 && InterlockedIncrement(&timeout_thread_initialized) == 1) { /* 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. */ @@ -1475,9 +1505,9 @@ void zend_set_timeout(long seconds) # endif #endif } +/* }}} */ - -void zend_unset_timeout(TSRMLS_D) +void zend_unset_timeout(TSRMLS_D) /* {{{ */ { #ifdef ZEND_WIN32 if(timeout_thread_initialized) { @@ -1499,16 +1529,17 @@ void zend_unset_timeout(TSRMLS_D) # endif #endif } +/* }}} */ - -zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC) +zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC) /* {{{ */ { zend_class_entry **pce; int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0; - int rt_ns_check = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK) ? 1 : 0; + int rt_ns_check = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK) ? 1 : 0; int silent = (fetch_type & ZEND_FETCH_CLASS_SILENT) != 0; fetch_type &= ZEND_FETCH_CLASS_MASK; + check_fetch_type: switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: @@ -1538,28 +1569,28 @@ check_fetch_type: break; } - if (zend_lookup_class_ex(class_name, class_name_len, (!rt_ns_check & use_autoload), &pce TSRMLS_CC)==FAILURE) { + if (zend_lookup_class_ex(class_name, class_name_len, (!rt_ns_check & use_autoload), &pce TSRMLS_CC) == FAILURE) { if (rt_ns_check) { /* Check if we have internal class with the same name */ char *php_name; uint php_name_len; - + php_name = zend_memrchr(class_name, ':', class_name_len); if (php_name) { php_name++; - php_name_len = class_name_len-(php_name-class_name); + php_name_len = class_name_len - (php_name - class_name); php_name = zend_str_tolower_dup(php_name, php_name_len); - if (zend_hash_find(EG(class_table), php_name, php_name_len+1, (void **) &pce) == SUCCESS && - (*pce)->type == ZEND_INTERNAL_CLASS) { - efree(php_name); + if (zend_hash_find(EG(class_table), php_name, php_name_len + 1, (void **) &pce) == SUCCESS && + (*pce)->type == ZEND_INTERNAL_CLASS + ) { + efree(php_name); return *pce; } - efree(php_name); + efree(php_name); } } if (use_autoload) { - if (rt_ns_check && - zend_lookup_class_ex(class_name, class_name_len, 1, &pce TSRMLS_CC)==SUCCESS) { + if (rt_ns_check && zend_lookup_class_ex(class_name, class_name_len, 1, &pce TSRMLS_CC) == SUCCESS) { return *pce; } if (!silent) { @@ -1574,8 +1605,7 @@ check_fetch_type: } return *pce; } - - +/* }}} */ #define MAX_ABSTRACT_INFO_CNT 3 #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" @@ -1583,15 +1613,14 @@ check_fetch_type: ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ ai.afn[idx] ? "::" : "", \ ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \ - ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "") + ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "") typedef struct _zend_abstract_info { - zend_function *afn[MAX_ABSTRACT_INFO_CNT+1]; + zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1]; int cnt; } zend_abstract_info; - -static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) +static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) /* {{{ */ { if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { @@ -1601,9 +1630,9 @@ static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_ } return 0; } +/* }}} */ - -void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) +void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { zend_abstract_info ai; @@ -1623,8 +1652,9 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) } } } +/* }}} */ -ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) +ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) /* {{{ */ { zend_execute_data *ex; int i; @@ -1637,30 +1667,33 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) } } } +/* }}} */ -ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC) +ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC) /* {{{ */ { zend_execute_data *ex; - ulong hash_value = zend_inline_hash_func(name, name_len+1); + ulong hash_value = zend_inline_hash_func(name, name_len + 1); - if (zend_hash_quick_exists(&EG(symbol_table), name, name_len+1, hash_value)) { + if (zend_hash_quick_exists(&EG(symbol_table), name, name_len + 1, hash_value)) { for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { if (ex->op_array && ex->symbol_table == &EG(symbol_table)) { int i; for (i = 0; i < ex->op_array->last_var; i++) { if (ex->op_array->vars[i].hash_value == hash_value && - ex->op_array->vars[i].name_len == name_len && - !memcmp(ex->op_array->vars[i].name, name, name_len)) { + ex->op_array->vars[i].name_len == name_len && + !memcmp(ex->op_array->vars[i].name, name, name_len) + ) { ex->CVs[i] = NULL; break; } } } } - return zend_hash_del(&EG(symbol_table), name, name_len+1); + return zend_hash_del(&EG(symbol_table), name, name_len + 1); } return FAILURE; } +/* }}} */ /* * Local variables: diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 794d78fd27..ef8ebad697 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -49,14 +49,22 @@ called, we cal __call handler. */ -ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) +ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) /* {{{ */ { zend_object *zobj; zobj = Z_OBJ_P(object); return zobj->properties; } +/* }}} */ + +ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 0; + return zend_std_get_properties(object TSRMLS_CC); +} +/* }}} */ -static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) +static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) /* {{{ */ { zval *retval = NULL; zend_class_entry *ce = Z_OBJCE_P(object); @@ -79,8 +87,9 @@ static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) return retval; } +/* }}} */ -static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_DC) +static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */ { zval *retval = NULL; int result; @@ -108,8 +117,9 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D return FAILURE; } } +/* }}} */ -static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) +static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); @@ -123,8 +133,9 @@ static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) zval_ptr_dtor(&member); } +/* }}} */ -static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) +static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) /* {{{ */ { zval *retval = NULL; zend_class_entry *ce = Z_OBJCE_P(object); @@ -143,8 +154,9 @@ static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) return retval; } +/* }}} */ -static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) +static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) /* {{{ */ { switch (property_info->flags & ZEND_ACC_PPP_MASK) { case ZEND_ACC_PUBLIC: @@ -161,8 +173,9 @@ static int zend_verify_property_access(zend_property_info *property_info, zend_c } return 0; } +/* }}} */ -static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) +static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */ { child_class = child_class->parent; while (child_class) { @@ -174,8 +187,9 @@ static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_cla return 0; } +/* }}} */ -ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) +ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) /* {{{ */ { zend_property_info *property_info = NULL; zend_property_info *scope_property_info; @@ -243,9 +257,9 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce } return property_info; } +/* }}} */ - -ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name, int prop_info_name_len TSRMLS_DC) +ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name, int prop_info_name_len TSRMLS_DC) /* {{{ */ { zend_property_info *property_info; char *class_name, *prop_name; @@ -257,7 +271,7 @@ ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name, if (!property_info) { return FAILURE; } - if (prop_info_name[0] == '\0' && prop_info_name[1] != '*') { + if (class_name && class_name[0] != '*') { if (!(property_info->flags & ZEND_ACC_PRIVATE)) { /* we we're looking for a private prop but found a non private one of the same name */ return FAILURE; @@ -268,8 +282,9 @@ ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name, } return zend_verify_property_access(property_info, zobj->ce TSRMLS_CC) ? SUCCESS : FAILURE; } +/* }}} */ -static int zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member, zend_guard **pguard) +static int zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member, zend_guard **pguard) /* {{{ */ { zend_property_info info; zend_guard stub; @@ -292,8 +307,9 @@ static int zend_get_property_guard(zend_object *zobj, zend_property_info *proper stub.in_isset = 0; return zend_hash_quick_add(zobj->guards, property_info->name, property_info->name_length+1, property_info->h, (void**)&stub, sizeof(stub), (void**) pguard); } +/* }}} */ -zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) +zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */ { zend_object *zobj; zval *tmp_member = NULL; @@ -305,7 +321,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) silent = (type == BP_VAR_IS); zobj = Z_OBJ_P(object); - if (member->type != IS_STRING) { + if (Z_TYPE_P(member) != IS_STRING) { ALLOC_ZVAL(tmp_member); *tmp_member = *member; INIT_PZVAL(tmp_member); @@ -366,9 +382,9 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) } return *retval; } +/* }}} */ - -static void zend_std_write_property(zval *object, zval *member, zval *value TSRMLS_DC) +static void zend_std_write_property(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */ { zend_object *zobj; zval *tmp_member = NULL; @@ -377,7 +393,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM zobj = Z_OBJ_P(object); - if (member->type != IS_STRING) { + if (Z_TYPE_P(member) != IS_STRING) { ALLOC_ZVAL(tmp_member); *tmp_member = *member; INIT_PZVAL(tmp_member); @@ -397,9 +413,9 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM zval garbage = **variable_ptr; /* old value should be destroyed */ /* To check: can't *variable_ptr be some system variable like error_zval here? */ - (*variable_ptr)->type = value->type; + Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value); (*variable_ptr)->value = value->value; - if (Z_REFCOUNT_P(value)>0) { + if (Z_REFCOUNT_P(value) > 0) { zval_copy_ctor(*variable_ptr); } zval_dtor(&garbage); @@ -445,8 +461,9 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM zval_ptr_dtor(&tmp_member); } } +/* }}} */ -zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) +zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); zval *retval; @@ -478,9 +495,9 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) return 0; } } +/* }}} */ - -static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) +static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); @@ -496,9 +513,9 @@ static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSR zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name); } } +/* }}} */ - -static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) +static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); zval *retval; @@ -527,9 +544,9 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS } return result; } +/* }}} */ - -static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) +static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */ { zend_object *zobj; zval tmp_member; @@ -538,7 +555,7 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC zobj = Z_OBJ_P(object); - if (member->type != IS_STRING) { + if (Z_TYPE_P(member) != IS_STRING) { tmp_member = *member; zval_copy_ctor(&tmp_member); convert_to_string(&tmp_member); @@ -574,9 +591,9 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC } return retval; } +/* }}} */ - -static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) +static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{ */ { zend_object *zobj; zval *tmp_member = NULL; @@ -584,7 +601,7 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) zobj = Z_OBJ_P(object); - if (member->type != IS_STRING) { + if (Z_TYPE_P(member) != IS_STRING) { ALLOC_ZVAL(tmp_member); *tmp_member = *member; INIT_PZVAL(tmp_member); @@ -612,9 +629,9 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) zval_ptr_dtor(&tmp_member); } } +/* }}} */ - -static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) +static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); @@ -626,9 +643,9 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name); } } +/* }}} */ - -ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) +ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { zend_internal_function *func = (zend_internal_function *)EG(function_state_ptr)->function; zval *method_name_ptr, *method_args_ptr; @@ -671,12 +688,13 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* destruct the function also, then - we have allocated it in get_method */ efree(func); } +/* }}} */ /* Ensures that we're allowed to call a private method. * Returns the function address that should be called, or NULL * if no such function exists. */ -static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) +static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) /* {{{ */ { if (!ce) { return 0; @@ -709,17 +727,17 @@ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_cla } return NULL; } +/* }}} */ - -ZEND_API int zend_check_private(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) +ZEND_API int zend_check_private(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) /* {{{ */ { return zend_check_private_int(fbc, ce, function_name_strval, function_name_strlen TSRMLS_CC) != NULL; } - +/* }}} */ /* Ensures that we're allowed to call a protected method. */ -ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) +ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) /* {{{ */ { zend_class_entry *fbc_scope = ce; @@ -744,15 +762,15 @@ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) } return 0; } +/* }}} */ - -static inline zend_class_entry * zend_get_function_root_class(zend_function *fbc) +static inline zend_class_entry * zend_get_function_root_class(zend_function *fbc) /* {{{ */ { return fbc->common.prototype ? fbc->common.prototype->common.scope : fbc->common.scope; } +/* }}} */ - -static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC) +static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC) /* {{{ */ { zend_object *zobj; zend_function *fbc; @@ -823,6 +841,7 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method free_alloca(lc_method_name); return fbc; } +/* }}} */ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { @@ -869,7 +888,8 @@ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ /* }}} */ /* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */ -ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) + +ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) /* {{{ */ { zend_function *fbc; @@ -893,6 +913,14 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f zend_error(E_ERROR, "Call to undefined method %s::%s()", ce->name ? ce->name : "", function_name_strval); } } + +#if MBO_0 + /* right now this function is used for non static method lookup too */ + /* Is the function static */ + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + zend_error(E_ERROR, "Cannot call non static method %s::%s() without object", ZEND_FN_SCOPE_NAME(fbc), fbc->common.function_name); + } +#endif if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) { /* No further checks necessary, most common case */ } else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { @@ -915,16 +943,16 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f return fbc; } +/* }}} */ - -ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent TSRMLS_DC) +ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent TSRMLS_DC) /* {{{ */ { zval **retval = NULL; zend_class_entry *tmp_ce = ce; zend_property_info *property_info; zend_property_info std_property_info; - if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) { + if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE) { std_property_info.flags = ZEND_ACC_PUBLIC; std_property_info.name = property_name; std_property_info.name_length = property_name_len; @@ -958,16 +986,16 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert return retval; } +/* }}} */ - -ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC) +ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC) /* {{{ */ { zend_error(E_ERROR, "Attempt to unset static property %s::$%s", ce->name, property_name); return 0; } +/* }}} */ - -ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC) +ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC) /* {{{ */ { zend_object *zobj = Z_OBJ_P(object); zend_function *constructor = zobj->ce->constructor; @@ -987,6 +1015,8 @@ ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC) } } else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. + * Constructors only have prototype if they are defined by an interface but + * it is the compilers responsibility to take care of the prototype. */ if (!zend_check_protected(zend_get_function_root_class(constructor), EG(scope))) { if (EG(scope)) { @@ -1000,12 +1030,11 @@ ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC) return constructor; } - +/* }}} */ int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC); - -static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) +static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */ { zend_object *zobj1, *zobj2; @@ -1017,8 +1046,9 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) } return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC); } +/* }}} */ -static int zend_std_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC) +static int zend_std_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC) /* {{{ */ { zend_object *zobj; int result; @@ -1028,7 +1058,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists zobj = Z_OBJ_P(object); - if (member->type != IS_STRING) { + if (Z_TYPE_P(member) != IS_STRING) { ALLOC_ZVAL(tmp_member); *tmp_member = *member; INIT_PZVAL(tmp_member); @@ -1091,17 +1121,18 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists } return result; } +/* }}} */ - -zend_class_entry *zend_std_object_get_class(zval *object TSRMLS_DC) +zend_class_entry *zend_std_object_get_class(zval *object TSRMLS_DC) /* {{{ */ { zend_object *zobj; zobj = Z_OBJ_P(object); return zobj->ce; } +/* }}} */ -int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) +int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) /* {{{ */ { zend_object *zobj; zend_class_entry *ce; @@ -1120,8 +1151,9 @@ int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *c *class_name = estrndup(ce->name, ce->name_length); return SUCCESS; } +/* }}} */ -ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC) +ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* {{{ */ { zval *retval; zend_class_entry *ce; @@ -1175,7 +1207,7 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty } return FAILURE; } - +/* }}} */ ZEND_API zend_object_handlers std_object_handlers = { zend_objects_store_add_ref, /* add_ref */ diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 83dd72356c..757d5177e3 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -145,7 +145,6 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC); ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC); ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC); - ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC); ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC); ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC); diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index cc88d91906..b4cd28144b 100755 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -19,7 +19,7 @@ /* $Id$ */ #ifdef HAVE_CONFIG_H - #include "config.h" +#include "config.h" #endif #include "php.h" @@ -153,7 +153,7 @@ PHP_FUNCTION(class_implements) /* }}} */ #define SPL_ADD_CLASS(class_name, z_list, sub, allow, ce_flags) \ - spl_add_classes(&spl_ce_ ## class_name, z_list, sub, allow, ce_flags TSRMLS_CC) + spl_add_classes(spl_ce_ ## class_name, z_list, sub, allow, ce_flags TSRMLS_CC) #define SPL_LIST_CLASSES(z_list, sub, allow, ce_flags) \ SPL_ADD_CLASS(AppendIterator, z_list, sub, allow, ce_flags); \ @@ -607,26 +607,36 @@ PHP_FUNCTION(spl_autoload_functions) PHP_FUNCTION(spl_object_hash) { zval *obj; - int len; - char *hash; - char md5str[33]; - PHP_MD5_CTX context; - unsigned char digest[16]; + char* md5str; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) { return; } + + md5str = emalloc(33); + php_spl_object_hash(obj, md5str TSRMLS_CC); + + RETVAL_STRING(md5str, 0); +} +/* }}} */ + +PHPAPI void php_spl_object_hash(zval *obj, char *md5str TSRMLS_DC) /* {{{*/ +{ + int len; + char *hash; + PHP_MD5_CTX context; + unsigned char digest[16]; len = spprintf(&hash, 0, "%p:%d", Z_OBJ_HT_P(obj), Z_OBJ_HANDLE_P(obj)); - + md5str[0] = '\0'; PHP_MD5Init(&context); PHP_MD5Update(&context, (unsigned char*)hash, len); PHP_MD5Final(digest, &context); make_digest(md5str, digest); - RETVAL_STRING(md5str, 1); efree(hash); } +/* }}} */ int spl_build_class_list_string(zval **entry, char **list TSRMLS_DC) /* {{{ */ { diff --git a/ext/spl/php_spl.h b/ext/spl/php_spl.h index 7c44f58550..e28578dcc1 100755 --- a/ext/spl/php_spl.h +++ b/ext/spl/php_spl.h @@ -74,6 +74,8 @@ PHP_FUNCTION(spl_classes); PHP_FUNCTION(class_parents); PHP_FUNCTION(class_implements); +PHPAPI void php_spl_object_hash(zval *obj, char* md5str TSRMLS_DC); + #endif /* PHP_SPL_H */ /* diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index d9d7cd7e27..74e0999687 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -614,6 +614,39 @@ static HashTable *spl_array_get_properties(zval *object TSRMLS_DC) /* {{{ */ return spl_array_get_hash_table(intern, 1 TSRMLS_CC); } /* }}} */ +static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ +{ + spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(obj TSRMLS_CC); + HashTable *rv; + zval *tmp, *storage; + int name_len; + char *zname; + zend_class_entry *base; + + if (HASH_OF(intern->array) == intern->std.properties) { + *is_temp = 0; + return intern->std.properties; + } else { + *is_temp = 1; + + ALLOC_HASHTABLE(rv); + ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 1, 0); + + zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + + storage = intern->array; + zval_add_ref(&storage); + + base = (Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator) ? spl_ce_ArrayIterator : spl_ce_ArrayObject; + zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1, &name_len TSRMLS_CC); + zend_symtable_update(rv, zname, name_len+1, &storage, sizeof(zval *), NULL); + efree(zname); + + return rv; + } +} +/* }}} */ + static zval *spl_array_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */ { spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); @@ -1514,6 +1547,7 @@ PHP_MINIT_FUNCTION(spl_array) spl_handler_ArrayObject.count_elements = spl_array_object_count_elements; spl_handler_ArrayObject.get_properties = spl_array_get_properties; + spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info; spl_handler_ArrayObject.read_property = spl_array_read_property; spl_handler_ArrayObject.write_property = spl_array_write_property; spl_handler_ArrayObject.get_property_ptr_ptr = spl_array_get_property_ptr_ptr; diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index bf3eb83f5a..6ee18d335c 100755 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -459,6 +459,57 @@ static int spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */ } /* }}} */ +static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */ +{ + spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(obj TSRMLS_CC); + HashTable *rv; + zval *tmp, zrv; + char *pnstr; + int pnlen; + char stmp[2]; + + *is_temp = 1; + + ALLOC_HASHTABLE(rv); + ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0); + + INIT_PZVAL(&zrv); + Z_ARRVAL(zrv) = rv; + + zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + + pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1, &pnlen TSRMLS_CC); + add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->path, intern->path_len, 1); + efree(pnstr); + if (intern->file_name) { + pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1, &pnlen TSRMLS_CC); + add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->file_name, intern->file_name_len, 1); + efree(pnstr); + } + if (intern->type == SPL_FS_DIR && intern->u.dir.sub_path) { + pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "subPathName", sizeof("subPathName")-1, &pnlen TSRMLS_CC); + add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->u.dir.sub_path, intern->u.dir.sub_path_len, 1); + efree(pnstr); + } + if (intern->type == SPL_FS_FILE) { + pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "openMode", sizeof("openMode")-1, &pnlen TSRMLS_CC); + add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->u.file.open_mode, intern->u.file.open_mode_len, 1); + efree(pnstr); + stmp[1] = '\0'; + stmp[0] = intern->u.file.delimiter; + pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "delimiter", sizeof("delimiter")-1, &pnlen TSRMLS_CC); + add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, stmp, 1, 1); + efree(pnstr); + stmp[0] = intern->u.file.enclosure; + pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "enclosure", sizeof("enclosure")-1, &pnlen TSRMLS_CC); + add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, stmp, 1, 1); + efree(pnstr); + } + + return rv; +} +/* }}}} */ + /* {{{ proto void DirectoryIterator::__construct(string path) Cronstructs a new dir iterator from a path. */ SPL_METHOD(DirectoryIterator, __construct) @@ -2349,6 +2400,7 @@ PHP_MINIT_FUNCTION(spl_directory) memcpy(&spl_filesystem_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone; spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast; + spl_filesystem_object_handlers.get_debug_info = spl_filesystem_object_get_debug_info; REGISTER_SPL_SUB_CLASS_EX(DirectoryIterator, SplFileInfo, spl_filesystem_object_new, spl_DirectoryIterator_functions); zend_class_implements(spl_ce_DirectoryIterator TSRMLS_CC, 1, zend_ce_iterator); diff --git a/ext/spl/spl_functions.c b/ext/spl/spl_functions.c index 31acfee436..16bda2fcec 100755 --- a/ext/spl/spl_functions.c +++ b/ext/spl/spl_functions.c @@ -40,8 +40,7 @@ void spl_register_interface(zend_class_entry ** ppce, char * class_name, const z { zend_class_entry ce; - INIT_CLASS_ENTRY(ce, class_name, functions); - ce.name_length = strlen(class_name); + INIT_CLASS_ENTRY_EX(ce, class_name, strlen(class_name), functions); *ppce = zend_register_internal_interface(&ce TSRMLS_CC); } /* }}} */ @@ -51,8 +50,7 @@ PHPAPI void spl_register_std_class(zend_class_entry ** ppce, char * class_name, { zend_class_entry ce; - INIT_CLASS_ENTRY(ce, class_name, function_list); - ce.name_length = strlen(class_name); + INIT_CLASS_ENTRY_EX(ce, class_name, strlen(class_name), function_list); *ppce = zend_register_internal_class(&ce TSRMLS_CC); /* entries changed by initialize */ @@ -67,8 +65,7 @@ PHPAPI void spl_register_sub_class(zend_class_entry ** ppce, zend_class_entry * { zend_class_entry ce; - INIT_CLASS_ENTRY(ce, class_name, function_list); - ce.name_length = strlen(class_name); + INIT_CLASS_ENTRY_EX(ce, class_name, strlen(class_name), function_list); *ppce = zend_register_internal_class_ex(&ce, parent_ce, NULL TSRMLS_CC); /* entries changed by initialize */ @@ -105,12 +102,12 @@ void spl_register_property( zend_class_entry * class_entry, char *prop_name, int void spl_add_class_name(zval *list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC) { if (!allow || (allow > 0 && pce->ce_flags & ce_flags) || (allow < 0 && !(pce->ce_flags & ce_flags))) { - size_t len = strlen(pce->name); + size_t len = pce->name_length; zval *tmp; if (zend_hash_find(Z_ARRVAL_P(list), pce->name, len+1, (void*)&tmp) == FAILURE) { MAKE_STD_ZVAL(tmp); - ZVAL_STRING(tmp, pce->name, 1); + ZVAL_STRINGL(tmp, pce->name, pce->name_length, 1); zend_hash_add(Z_ARRVAL_P(list), pce->name, len+1, &tmp, sizeof(zval *), NULL); } } @@ -129,10 +126,8 @@ void spl_add_interfaces(zval *list, zend_class_entry * pce, int allow, int ce_fl /* }}} */ /* {{{ spl_add_classes */ -int spl_add_classes(zend_class_entry ** ppce, zval *list, int sub, int allow, int ce_flags TSRMLS_DC) +int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags TSRMLS_DC) { - zend_class_entry *pce = *ppce; - if (!pce) { return 0; } @@ -141,13 +136,23 @@ int spl_add_classes(zend_class_entry ** ppce, zval *list, int sub, int allow, in spl_add_interfaces(list, pce, allow, ce_flags TSRMLS_CC); while (pce->parent) { pce = pce->parent; - spl_add_classes(&pce, list, sub, allow, ce_flags TSRMLS_CC); + spl_add_classes(pce, list, sub, allow, ce_flags TSRMLS_CC); } } return 0; } /* }}} */ +char * spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, int prop_len, int *name_len TSRMLS_DC) /* {{{ */ +{ + char *rv; + + zend_mangle_property_name(&rv, name_len, ce->name, ce->name_length, prop_name, prop_len, 0); + + return rv; +} +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/ext/spl/spl_functions.h b/ext/spl/spl_functions.h index 0db207b754..5eab7f9f7c 100755 --- a/ext/spl/spl_functions.h +++ b/ext/spl/spl_functions.h @@ -73,7 +73,10 @@ void spl_register_property( zend_class_entry * class_entry, char *prop_name, int */ void spl_add_class_name(zval * list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC); void spl_add_interfaces(zval * list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC); -int spl_add_classes(zend_class_entry ** ppce, zval *list, int sub, int allow, int ce_flags TSRMLS_DC); +int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags TSRMLS_DC); + +/* caller must efree(return) */ +char * spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, int prop_len, int *name_len TSRMLS_DC); #define SPL_ME(class_name, function_name, arg_info, flags) \ PHP_ME( spl_ ## class_name, function_name, arg_info, flags) diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 58bf8144f6..d806642132 100755 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -517,10 +517,16 @@ SPL_METHOD(RecursiveIteratorIterator, key) char *str_key; uint str_key_len; ulong int_key; - if (iterator->funcs->get_current_key(iterator, &str_key, &str_key_len, &int_key TSRMLS_CC) == HASH_KEY_IS_LONG) { - RETURN_LONG(int_key); - } else { - RETURN_STRINGL(str_key, str_key_len-1, 0); + + switch (iterator->funcs->get_current_key(iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) { + case HASH_KEY_IS_LONG: + RETURN_LONG(int_key); + break; + case HASH_KEY_IS_STRING: + RETURN_STRINGL(str_key, str_key_len-1, 0); + break; + default: + RETURN_NULL(); } } else { RETURN_NULL(); @@ -1126,7 +1132,7 @@ static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more T intern->inner.iterator->funcs->get_current_data(intern->inner.iterator, &data TSRMLS_CC); if (data && *data) { intern->current.data = *data; - Z_ADDREF_P(intern->current.data); + Z_ADDREF_P(intern->current.data); } if (intern->inner.iterator->funcs->get_current_key) { intern->current.key_type = intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &intern->current.str_key, &intern->current.str_key_len, &intern->current.int_key TSRMLS_CC); @@ -2364,10 +2370,15 @@ SPL_METHOD(NoRewindIterator, key) char *str_key; uint str_key_len; ulong int_key; - if (intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &str_key, &str_key_len, &int_key TSRMLS_CC) == HASH_KEY_IS_LONG) { - RETURN_LONG(int_key); - } else { - RETURN_STRINGL(str_key, str_key_len-1, 0); + switch (intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) { + case HASH_KEY_IS_LONG: + RETURN_LONG(int_key); + break; + case HASH_KEY_IS_STRING: + RETURN_STRINGL(str_key, str_key_len-1, 0); + break; + default: + RETURN_NULL(); } } else { RETURN_NULL(); diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index eeaac42bb8..f96e42b7e4 100755 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -116,6 +116,43 @@ static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, } /* }}} */ +static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ +{ + spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC); + HashTable *rv, *props; + HashPosition pos; + zval *tmp, *storage, **entry; + char md5str[33]; + int name_len; + char *zname; + + *is_temp = 1; + + props = Z_OBJPROP_P(obj); + ALLOC_HASHTABLE(rv); + ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(props) + 1, 0); + + zend_hash_copy(rv, props, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + + MAKE_STD_ZVAL(storage); + array_init(storage); + + zend_hash_internal_pointer_reset_ex(&intern->storage, &pos); + while (zend_hash_get_current_data_ex(&intern->storage, (void **)&entry, &pos) == SUCCESS) { + php_spl_object_hash(*entry, md5str TSRMLS_CC); + zval_add_ref(entry); + add_assoc_zval_ex(storage, md5str, 33, *entry); + zend_hash_move_forward_ex(&intern->storage, &pos); + } + + zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1, &name_len TSRMLS_CC); + zend_symtable_update(rv, zname, name_len+1, &storage, sizeof(zval *), NULL); + efree(zname); + + return rv; +} +/* }}} */ + /* {{{ spl_array_object_new */ static zend_object_value spl_SplObjectStorage_new(zend_class_entry *class_type TSRMLS_DC) { @@ -437,6 +474,7 @@ PHP_MINIT_FUNCTION(spl_observer) REGISTER_SPL_STD_CLASS_EX(SplObjectStorage, spl_SplObjectStorage_new, spl_funcs_SplObjectStorage); memcpy(&spl_handler_SplObjectStorage, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_handler_SplObjectStorage.get_debug_info = spl_object_storage_debug_info; REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Countable); REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Iterator); diff --git a/ext/standard/array.c b/ext/standard/array.c index 259fb7f180..f620209605 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -61,14 +61,6 @@ #define EXTR_REFS 0x100 -#define SORT_REGULAR 0 -#define SORT_NUMERIC 1 -#define SORT_STRING 2 -#define SORT_LOCALE_STRING 5 - -#define SORT_DESC 3 -#define SORT_ASC 4 - #define CASE_LOWER 0 #define CASE_UPPER 1 @@ -99,7 +91,7 @@ ZEND_DECLARE_MODULE_GLOBALS(array) /* {{{ php_array_init_globals - */ +*/ static void php_array_init_globals(zend_array_globals *array_globals) { memset(array_globals, 0, sizeof(array_globals)); @@ -108,7 +100,7 @@ static void php_array_init_globals(zend_array_globals *array_globals) PHP_MINIT_FUNCTION(array) /* {{{ */ { - ZEND_INIT_MODULE_GLOBALS(array, php_array_init_globals, NULL); + ZEND_INIT_MODULE_GLOBALS(array, php_array_init_globals, NULL); REGISTER_LONG_CONSTANT("EXTR_OVERWRITE", EXTR_OVERWRITE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("EXTR_SKIP", EXTR_SKIP, CONST_CS | CONST_PERSISTENT); @@ -118,21 +110,21 @@ PHP_MINIT_FUNCTION(array) /* {{{ */ REGISTER_LONG_CONSTANT("EXTR_PREFIX_IF_EXISTS", EXTR_PREFIX_IF_EXISTS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("EXTR_IF_EXISTS", EXTR_IF_EXISTS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("EXTR_REFS", EXTR_REFS, CONST_CS | CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("SORT_ASC", SORT_ASC, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SORT_DESC", SORT_DESC, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SORT_REGULAR", SORT_REGULAR, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SORT_NUMERIC", SORT_NUMERIC, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SORT_STRING", SORT_STRING, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_ASC", PHP_SORT_ASC, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_DESC", PHP_SORT_DESC, CONST_CS | CONST_PERSISTENT); + + REGISTER_LONG_CONSTANT("SORT_REGULAR", PHP_SORT_REGULAR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_NUMERIC", PHP_SORT_NUMERIC, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_STRING", PHP_SORT_STRING, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CASE_LOWER", CASE_LOWER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CASE_UPPER", CASE_UPPER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("COUNT_NORMAL", COUNT_NORMAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("COUNT_RECURSIVE", COUNT_RECURSIVE, CONST_CS | CONST_PERSISTENT); - + return SUCCESS; } /* }}} */ @@ -147,24 +139,24 @@ PHP_MSHUTDOWN_FUNCTION(array) /* {{{ */ } /* }}} */ -static void set_compare_func(int sort_type TSRMLS_DC) /* {{{ */ +static void php_set_compare_func(int sort_type TSRMLS_DC) /* {{{ */ { switch (sort_type) { - case SORT_NUMERIC: + case PHP_SORT_NUMERIC: ARRAYG(compare_func) = numeric_compare_function; break; - case SORT_STRING: + case PHP_SORT_STRING: ARRAYG(compare_func) = string_compare_function; break; #if HAVE_STRCOLL - case SORT_LOCALE_STRING: + case PHP_SORT_LOCALE_STRING: ARRAYG(compare_func) = string_locale_compare_function; break; #endif - case SORT_REGULAR: + case PHP_SORT_REGULAR: default: ARRAYG(compare_func) = compare_function; break; @@ -172,14 +164,14 @@ static void set_compare_func(int sort_type TSRMLS_DC) /* {{{ */ } /* }}} */ -static int array_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int php_array_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { Bucket *f; Bucket *s; zval result; zval first; zval second; - + f = *((Bucket **) a); s = *((Bucket **) b); @@ -189,7 +181,7 @@ static int array_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ } else { Z_TYPE(first) = IS_STRING; Z_STRVAL(first) = f->arKey; - Z_STRLEN(first) = f->nKeyLength-1; + Z_STRLEN(first) = f->nKeyLength - 1; } if (s->nKeyLength == 0) { @@ -198,12 +190,12 @@ static int array_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ } else { Z_TYPE(second) = IS_STRING; Z_STRVAL(second) = s->arKey; - Z_STRLEN(second) = s->nKeyLength-1; + Z_STRLEN(second) = s->nKeyLength - 1; } - + if (ARRAYG(compare_func)(&result, &first, &second TSRMLS_CC) == FAILURE) { return 0; - } + } if (Z_TYPE(result) == IS_DOUBLE) { if (Z_DVAL(result) < 0) { @@ -221,15 +213,15 @@ static int array_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ return -1; } else if (Z_LVAL(result) > 0) { return 1; - } + } return 0; } /* }}} */ -static int array_reverse_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int php_array_reverse_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { - return array_key_compare(a, b TSRMLS_CC) * -1; + return php_array_key_compare(a, b TSRMLS_CC) * -1; } /* }}} */ @@ -238,17 +230,17 @@ static int array_reverse_key_compare(const void *a, const void *b TSRMLS_DC) /* PHP_FUNCTION(krsort) { zval *array; - long sort_type = SORT_REGULAR; + long sort_type = PHP_SORT_REGULAR; HashTable *target_hash; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { RETURN_FALSE; } - + target_hash = HASH_OF(array); - set_compare_func(sort_type TSRMLS_CC); - - if (zend_hash_sort(target_hash, zend_qsort, array_reverse_key_compare, 0 TSRMLS_CC) == FAILURE) { + php_set_compare_func(sort_type TSRMLS_CC); + + if (zend_hash_sort(target_hash, zend_qsort, php_array_reverse_key_compare, 0 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } RETURN_TRUE; @@ -260,7 +252,7 @@ PHP_FUNCTION(krsort) PHP_FUNCTION(ksort) { zval *array; - long sort_type = SORT_REGULAR; + long sort_type = PHP_SORT_REGULAR; HashTable *target_hash; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { @@ -268,9 +260,9 @@ PHP_FUNCTION(ksort) } target_hash = HASH_OF(array); - set_compare_func(sort_type TSRMLS_CC); - - if (zend_hash_sort(target_hash, zend_qsort, array_key_compare, 0 TSRMLS_CC) == FAILURE) { + php_set_compare_func(sort_type TSRMLS_CC); + + if (zend_hash_sort(target_hash, zend_qsort, php_array_key_compare, 0 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } RETURN_TRUE; @@ -288,8 +280,9 @@ static int php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */ HashPosition pos; for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); - zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **) &element, &pos) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)) { + zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **) &element, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos) + ) { cnt += php_count_recursive(*element, COUNT_RECURSIVE TSRMLS_CC); } } @@ -305,10 +298,11 @@ PHP_FUNCTION(count) { zval *array; long mode = COUNT_NORMAL; - - if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &mode) == FAILURE) + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &mode) == FAILURE) { return; - + } + switch (Z_TYPE_P(array)) { case IS_NULL: RETURN_LONG(0); @@ -352,23 +346,23 @@ PHP_FUNCTION(count) * * This is not correct any more, depends on what compare_func is set to. */ -static int array_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int php_array_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { Bucket *f; Bucket *s; zval result; zval *first; zval *second; - + f = *((Bucket **) a); s = *((Bucket **) b); - + first = *((zval **) f->pData); second = *((zval **) s->pData); if (ARRAYG(compare_func)(&result, first, second TSRMLS_CC) == FAILURE) { return 0; - } + } if (Z_TYPE(result) == IS_DOUBLE) { if (Z_DVAL(result) < 0) { @@ -386,36 +380,38 @@ static int array_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ return -1; } else if (Z_LVAL(result) > 0) { return 1; - } + } return 0; } /* }}} */ -static int array_reverse_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int php_array_reverse_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { - return array_data_compare(a, b TSRMLS_CC)*-1; + return php_array_data_compare(a, b TSRMLS_CC) * -1; } /* }}} */ -static int array_natural_general_compare(const void *a, const void *b, int fold_case) /* {{{ */ +static int php_array_natural_general_compare(const void *a, const void *b, int fold_case) /* {{{ */ { Bucket *f, *s; zval *fval, *sval; zval first, second; int result; - + f = *((Bucket **) a); s = *((Bucket **) b); - + fval = *((zval **) f->pData); sval = *((zval **) s->pData); first = *fval; second = *sval; + if (Z_TYPE_P(fval) != IS_STRING) { zval_copy_ctor(&first); convert_to_string(&first); } + if (Z_TYPE_P(sval) != IS_STRING) { zval_copy_ctor(&second); convert_to_string(&second); @@ -423,48 +419,51 @@ static int array_natural_general_compare(const void *a, const void *b, int fold_ result = strnatcmp_ex(Z_STRVAL(first), Z_STRLEN(first), Z_STRVAL(second), Z_STRLEN(second), fold_case); - if (Z_TYPE_P(fval) != IS_STRING) + if (Z_TYPE_P(fval) != IS_STRING) { zval_dtor(&first); - if (Z_TYPE_P(sval) != IS_STRING) + } + + if (Z_TYPE_P(sval) != IS_STRING) { zval_dtor(&second); - + } + return result; } /* }}} */ -static int array_natural_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int php_array_natural_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { - return array_natural_general_compare(a, b, 0); + return php_array_natural_general_compare(a, b, 0); } /* }}} */ -static int array_natural_case_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int php_array_natural_case_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { - return array_natural_general_compare(a, b, 1); + return php_array_natural_general_compare(a, b, 1); } /* }}} */ static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case) /* {{{ */ { - zval **array; + zval *array; HashTable *target_hash; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &array) == FAILURE) { + return; } - target_hash = HASH_OF(*array); + target_hash = HASH_OF(array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); return; } if (fold_case) { - if (zend_hash_sort(target_hash, zend_qsort, array_natural_case_compare, 0 TSRMLS_CC) == FAILURE) { + if (zend_hash_sort(target_hash, zend_qsort, php_array_natural_case_compare, 0 TSRMLS_CC) == FAILURE) { return; } } else { - if (zend_hash_sort(target_hash, zend_qsort, array_natural_compare, 0 TSRMLS_CC) == FAILURE) { + if (zend_hash_sort(target_hash, zend_qsort, php_array_natural_compare, 0 TSRMLS_CC) == FAILURE) { return; } } @@ -494,17 +493,17 @@ PHP_FUNCTION(natcasesort) PHP_FUNCTION(asort) { zval *array; - long sort_type = SORT_REGULAR; + long sort_type = PHP_SORT_REGULAR; HashTable *target_hash; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { RETURN_FALSE; } - + target_hash = HASH_OF(array); - set_compare_func(sort_type TSRMLS_CC); - - if (zend_hash_sort(target_hash, zend_qsort, array_data_compare, 0 TSRMLS_CC) == FAILURE) { + php_set_compare_func(sort_type TSRMLS_CC); + + if (zend_hash_sort(target_hash, zend_qsort, php_array_data_compare, 0 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } RETURN_TRUE; @@ -516,17 +515,17 @@ PHP_FUNCTION(asort) PHP_FUNCTION(arsort) { zval *array; - long sort_type = SORT_REGULAR; + long sort_type = PHP_SORT_REGULAR; HashTable *target_hash; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { RETURN_FALSE; } - + target_hash = HASH_OF(array); - set_compare_func(sort_type TSRMLS_CC); - - if (zend_hash_sort(target_hash, zend_qsort, array_reverse_data_compare, 0 TSRMLS_CC) == FAILURE) { + php_set_compare_func(sort_type TSRMLS_CC); + + if (zend_hash_sort(target_hash, zend_qsort, php_array_reverse_data_compare, 0 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } RETURN_TRUE; @@ -538,17 +537,17 @@ PHP_FUNCTION(arsort) PHP_FUNCTION(sort) { zval *array; - long sort_type = SORT_REGULAR; + long sort_type = PHP_SORT_REGULAR; HashTable *target_hash; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { RETURN_FALSE; } - + target_hash = HASH_OF(array); - set_compare_func(sort_type TSRMLS_CC); - - if (zend_hash_sort(target_hash, zend_qsort, array_data_compare, 1 TSRMLS_CC) == FAILURE) { + php_set_compare_func(sort_type TSRMLS_CC); + + if (zend_hash_sort(target_hash, zend_qsort, php_array_data_compare, 1 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } RETURN_TRUE; @@ -560,30 +559,29 @@ PHP_FUNCTION(sort) PHP_FUNCTION(rsort) { zval *array; - long sort_type = SORT_REGULAR; + long sort_type = PHP_SORT_REGULAR; HashTable *target_hash; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { RETURN_FALSE; } - + target_hash = HASH_OF(array); - set_compare_func(sort_type TSRMLS_CC); - - if (zend_hash_sort(target_hash, zend_qsort, array_reverse_data_compare, 1 TSRMLS_CC) == FAILURE) { + php_set_compare_func(sort_type TSRMLS_CC); + + if (zend_hash_sort(target_hash, zend_qsort, php_array_reverse_data_compare, 1 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } RETURN_TRUE; } /* }}} */ -static int array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int php_array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { Bucket *f; Bucket *s; zval **args[2]; - zval *retval_ptr; - zend_fcall_info fci; + zval *retval_ptr = NULL; f = *((Bucket **) a); s = *((Bucket **) b); @@ -591,24 +589,17 @@ static int array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ args[0] = (zval **) f->pData; args[1] = (zval **) s->pData; - fci.size = sizeof(fci); - fci.function_table = EG(function_table); - fci.function_name = *BG(user_compare_func_name); - fci.symbol_table = NULL; - fci.object_pp = NULL; - fci.retval_ptr_ptr = &retval_ptr; - fci.param_count = 2; - fci.params = args; - fci.no_separation = 0; - - if (zend_call_function(&fci, &BG(user_compare_fci_cache) TSRMLS_CC)== SUCCESS - && retval_ptr) { + BG(user_compare_fci).param_count = 2; + BG(user_compare_fci).params = args; + BG(user_compare_fci).retval_ptr_ptr = &retval_ptr; + BG(user_compare_fci).no_separation = 0; + if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) { long retval; convert_to_long_ex(&retval_ptr); retval = Z_LVAL_P(retval_ptr); zval_ptr_dtor(&retval_ptr); - return retval < 0 ? -1 : retval > 0 ? 1 : 0;; + return retval < 0 ? -1 : retval > 0 ? 1 : 0; } else { return 0; } @@ -619,57 +610,49 @@ static int array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ #define PHP_ARRAY_CMP_FUNC_CHECK(func_name) \ if (!zend_is_callable(*func_name, 0, NULL)) { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid comparison function"); \ - BG(user_compare_fci_cache) = old_user_compare_fci_cache; \ - BG(user_compare_func_name) = old_compare_func; \ + BG(user_compare_fci) = old_user_compare_fci; \ + BG(user_compare_fci_cache) = old_user_compare_fci_cache; \ RETURN_FALSE; \ } \ - /* clear FCI cache otherwise : for example the same or other array with - (partly) the same key values has been sorted with uasort() or - other sorting function the comparison is cached, however the the name - of the function for comparison is not respected. see bug #28739 AND #33295 - - following defines will assist in backup / restore values. - */ + /* Clear FCI cache otherwise : for example the same or other array with + * (partly) the same key values has been sorted with uasort() or + * other sorting function the comparison is cached, however the the name + * of the function for comparison is not respected. see bug #28739 AND #33295 + * + * Following defines will assist in backup / restore values. */ #define PHP_ARRAY_CMP_FUNC_VARS \ - zval **old_compare_func; \ - zend_fcall_info_cache old_user_compare_fci_cache \ + zend_fcall_info old_user_compare_fci; \ + zend_fcall_info_cache old_user_compare_fci_cache \ #define PHP_ARRAY_CMP_FUNC_BACKUP() \ - old_compare_func = BG(user_compare_func_name); \ - old_user_compare_fci_cache = BG(user_compare_fci_cache); \ - BG(user_compare_fci_cache) = empty_fcall_info_cache; \ + old_user_compare_fci = BG(user_compare_fci); \ + old_user_compare_fci_cache = BG(user_compare_fci_cache); \ + BG(user_compare_fci_cache) = empty_fcall_info_cache; \ #define PHP_ARRAY_CMP_FUNC_RESTORE() \ - BG(user_compare_fci_cache) = old_user_compare_fci_cache; \ - BG(user_compare_func_name) = old_compare_func; \ + BG(user_compare_fci) = old_user_compare_fci; \ + BG(user_compare_fci_cache) = old_user_compare_fci_cache; \ /* {{{ proto bool usort(array array_arg, string cmp_function) Sort an array by values using a user-defined comparison function */ PHP_FUNCTION(usort) { - zval **array; + zval *array; HashTable *target_hash; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); - - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); - PHP_ARRAY_CMP_FUNC_RESTORE(); - RETURN_FALSE; + return; } - PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name)) - - if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 1 TSRMLS_CC) == FAILURE) { + target_hash = HASH_OF(array); + + if (zend_hash_sort(target_hash, zend_qsort, php_array_user_compare, 1 TSRMLS_CC) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_FALSE; } @@ -682,80 +665,78 @@ PHP_FUNCTION(usort) Sort an array with a user-defined comparison function and maintain index association */ PHP_FUNCTION(uasort) { - zval **array; + zval *array; HashTable *target_hash; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); - PHP_ARRAY_CMP_FUNC_RESTORE(); - RETURN_FALSE; + return; } - PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name)) + target_hash = HASH_OF(array); - if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 0 TSRMLS_CC) == FAILURE) { + if (zend_hash_sort(target_hash, zend_qsort, php_array_user_compare, 0 TSRMLS_CC) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_FALSE; } PHP_ARRAY_CMP_FUNC_RESTORE(); - RETURN_TRUE; } /* }}} */ -static int array_user_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int php_array_user_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { Bucket *f; Bucket *s; zval *key1, *key2; - zval *args[2]; - zval retval; - int status; + zval **args[2]; + zval *retval_ptr = NULL; + long result; ALLOC_INIT_ZVAL(key1); ALLOC_INIT_ZVAL(key2); - args[0] = key1; - args[1] = key2; - + args[0] = &key1; + args[1] = &key2; + f = *((Bucket **) a); s = *((Bucket **) b); - if (f->nKeyLength) { - Z_STRVAL_P(key1) = estrndup(f->arKey, f->nKeyLength-1); - Z_STRLEN_P(key1) = f->nKeyLength-1; - Z_TYPE_P(key1) = IS_STRING; - } else { + if (f->nKeyLength == 0) { Z_LVAL_P(key1) = f->h; Z_TYPE_P(key1) = IS_LONG; - } - if (s->nKeyLength) { - Z_STRVAL_P(key2) = estrndup(s->arKey, s->nKeyLength-1); - Z_STRLEN_P(key2) = s->nKeyLength-1; - Z_TYPE_P(key2) = IS_STRING; } else { + Z_STRVAL_P(key1) = estrndup(f->arKey, f->nKeyLength - 1); + Z_STRLEN_P(key1) = f->nKeyLength - 1; + Z_TYPE_P(key1) = IS_STRING; + } + if (s->nKeyLength == 0) { Z_LVAL_P(key2) = s->h; Z_TYPE_P(key2) = IS_LONG; + } else { + Z_STRVAL_P(key2) = estrndup(s->arKey, s->nKeyLength - 1); + Z_STRLEN_P(key2) = s->nKeyLength - 1; + Z_TYPE_P(key2) = IS_STRING; } - status = call_user_function(EG(function_table), NULL, *BG(user_compare_func_name), &retval, 2, args TSRMLS_CC); - - zval_ptr_dtor(&key1); - zval_ptr_dtor(&key2); - - if (status == SUCCESS) { - convert_to_long(&retval); - return Z_LVAL(retval); + BG(user_compare_fci).param_count = 2; + BG(user_compare_fci).params = args; + BG(user_compare_fci).retval_ptr_ptr = &retval_ptr; + BG(user_compare_fci).no_separation = 0; + if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) { + convert_to_long_ex(&retval_ptr); + result = Z_LVAL_P(retval_ptr); + zval_ptr_dtor(&retval_ptr); } else { - return 0; + result = 0; } + + zval_ptr_dtor(&key1); + zval_ptr_dtor(&key2); + + return result; } /* }}} */ @@ -763,28 +744,20 @@ static int array_user_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ Sort an array by keys using a user-defined comparison function */ PHP_FUNCTION(uksort) { - zval **array; + zval *array; HashTable *target_hash; PHP_ARRAY_CMP_FUNC_VARS; - PHP_ARRAY_CMP_FUNC_BACKUP(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); - PHP_ARRAY_CMP_FUNC_RESTORE(); - - RETURN_FALSE; + return; } - PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name)) + target_hash = HASH_OF(array); - if (zend_hash_sort(target_hash, zend_qsort, array_user_key_compare, 0 TSRMLS_CC) == FAILURE) { + if (zend_hash_sort(target_hash, zend_qsort, php_array_user_key_compare, 0 TSRMLS_CC) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_FALSE; @@ -799,20 +772,17 @@ PHP_FUNCTION(uksort) Advances array argument's internal pointer to the last element and return it */ PHP_FUNCTION(end) { - zval **array, **entry; + zval *array, **entry; HashTable *target_hash; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + return; } + + target_hash = HASH_OF(array); zend_hash_internal_pointer_end(target_hash); - if (return_value_used) { + if (return_value_used) { if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } @@ -826,24 +796,21 @@ PHP_FUNCTION(end) Move array argument's internal pointer to the previous element and return it */ PHP_FUNCTION(prev) { - zval **array, **entry; + zval *array, **entry; HashTable *target_hash; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + return; } + + target_hash = HASH_OF(array); zend_hash_move_backwards(target_hash); - if (return_value_used) { + if (return_value_used) { if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } - + RETURN_ZVAL(*entry, 1, 0); } } @@ -853,17 +820,14 @@ PHP_FUNCTION(prev) Move array argument's internal pointer to the next element and return it */ PHP_FUNCTION(next) { - zval **array, **entry; + zval *array, **entry; HashTable *target_hash; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + return; } + + target_hash = HASH_OF(array); zend_hash_move_forward(target_hash); if (return_value_used) { @@ -877,23 +841,20 @@ PHP_FUNCTION(next) /* }}} */ /* {{{ proto mixed reset(array array_arg) - Set array argument's internal pointer to the first element and return it */ + Set array argument's internal pointer to the first element and return it */ PHP_FUNCTION(reset) { - zval **array, **entry; + zval *array, **entry; HashTable *target_hash; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + return; } + + target_hash = HASH_OF(array); zend_hash_internal_pointer_reset(target_hash); - if (return_value_used) { + if (return_value_used) { if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } @@ -907,17 +868,14 @@ PHP_FUNCTION(reset) Return the element currently pointed to by the internal array pointer */ PHP_FUNCTION(current) { - zval **array, **entry; + zval *array, **entry; HashTable *target_hash; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + return; } + + target_hash = HASH_OF(array); if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } @@ -929,20 +887,17 @@ PHP_FUNCTION(current) Return the key of the element currently pointed to by the internal array pointer */ PHP_FUNCTION(key) { - zval **array; + zval *array; char *string_key; uint string_length; ulong num_key; HashTable *target_hash; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + return; } + + target_hash = HASH_OF(array); switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_length, &num_key, 0, NULL)) { case HASH_KEY_IS_STRING: RETVAL_STRINGL(string_key, string_length - 1, 1); @@ -967,14 +922,14 @@ PHP_FUNCTION(min) php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one value should be passed"); RETURN_NULL(); } - set_compare_func(SORT_REGULAR TSRMLS_CC); + php_set_compare_func(PHP_SORT_REGULAR TSRMLS_CC); if (argc == 1) { zval **arr; if (zend_get_parameters_ex(1, &arr) == FAILURE || Z_TYPE_PP(arr) != IS_ARRAY) { WRONG_PARAM_COUNT; } - if (zend_hash_minmax(Z_ARRVAL_PP(arr), array_data_compare, 0, (void **) &result TSRMLS_CC) == SUCCESS) { + if (zend_hash_minmax(Z_ARRVAL_PP(arr), php_array_data_compare, 0, (void **) &result TSRMLS_CC) == SUCCESS) { RETVAL_ZVAL(*result, 1, 0); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain at least one element"); @@ -1017,14 +972,14 @@ PHP_FUNCTION(max) php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one value should be passed"); RETURN_NULL(); } - set_compare_func(SORT_REGULAR TSRMLS_CC); + php_set_compare_func(PHP_SORT_REGULAR TSRMLS_CC); if (argc == 1) { zval **arr; if (zend_get_parameters_ex(1, &arr) == FAILURE || Z_TYPE_PP(arr) != IS_ARRAY) { WRONG_PARAM_COUNT; } - if (zend_hash_minmax(Z_ARRVAL_PP(arr), array_data_compare, 1, (void **) &result TSRMLS_CC) == SUCCESS) { + if (zend_hash_minmax(Z_ARRVAL_PP(arr), php_array_data_compare, 1, (void **) &result TSRMLS_CC) == SUCCESS) { RETVAL_ZVAL(*result, 1, 0); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain at least one element"); @@ -1058,13 +1013,12 @@ PHP_FUNCTION(max) static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive TSRMLS_DC) /* {{{ */ { zval **args[3], /* Arguments to userland function */ - *retval_ptr, /* Return value - unused */ - *key=NULL; /* Entry key */ + *retval_ptr, /* Return value - unused */ + *key=NULL; /* Entry key */ char *string_key; uint string_key_len; ulong num_key; HashPosition pos; - zend_fcall_info_cache array_walk_fci_cache = empty_fcall_info_cache; /* Set up known arguments */ args[1] = &key; @@ -1072,62 +1026,61 @@ static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive zend_hash_internal_pointer_reset_ex(target_hash, &pos); + BG(array_walk_fci).retval_ptr_ptr = &retval_ptr; + BG(array_walk_fci).param_count = userdata ? 3 : 2; + BG(array_walk_fci).params = args; + BG(array_walk_fci).no_separation = 0; + /* Iterate through hash */ while (!EG(exception) && zend_hash_get_current_data_ex(target_hash, (void **)&args[0], &pos) == SUCCESS) { if (recursive && Z_TYPE_PP(args[0]) == IS_ARRAY) { HashTable *thash; - + zend_fcall_info orig_array_walk_fci; + zend_fcall_info_cache orig_array_walk_fci_cache; + SEPARATE_ZVAL_TO_MAKE_IS_REF(args[0]); thash = HASH_OF(*(args[0])); if (thash->nApplyCount > 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected"); return 0; } + + /* backup the fcall info and cache */ + orig_array_walk_fci = BG(array_walk_fci); + orig_array_walk_fci_cache = BG(array_walk_fci_cache); + thash->nApplyCount++; php_array_walk(thash, userdata, recursive TSRMLS_CC); thash->nApplyCount--; - } else { - zend_fcall_info fci; + /* restore the fcall info and cache */ + BG(array_walk_fci) = orig_array_walk_fci; + BG(array_walk_fci_cache) = orig_array_walk_fci_cache; + } else { /* Allocate space for key */ MAKE_STD_ZVAL(key); /* Set up the key */ - if (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, &pos) == HASH_KEY_IS_LONG) { - Z_TYPE_P(key) = IS_LONG; - Z_LVAL_P(key) = num_key; - } else { - ZVAL_STRINGL(key, string_key, string_key_len-1, 1); + switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, &pos)) { + case HASH_KEY_IS_LONG: + Z_TYPE_P(key) = IS_LONG; + Z_LVAL_P(key) = num_key; + break; + case HASH_KEY_IS_STRING: + ZVAL_STRINGL(key, string_key, string_key_len - 1, 1); + break; } - fci.size = sizeof(fci); - fci.function_table = EG(function_table); - fci.function_name = *BG(array_walk_func_name); - fci.symbol_table = NULL; - fci.object_pp = NULL; - fci.retval_ptr_ptr = &retval_ptr; - fci.param_count = userdata ? 3 : 2; - fci.params = args; - fci.no_separation = 0; - /* Call the userland function */ - if (zend_call_function(&fci, &array_walk_fci_cache TSRMLS_CC) == SUCCESS) { + if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) { if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } } else { - char *func_name; - - if (zend_is_callable(*BG(array_walk_func_name), 0, &func_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s()", func_name); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s() - function does not exist", func_name); - } if (key) { zval_ptr_dtor(&key); key = NULL; } - efree(func_name); break; } } @@ -1138,7 +1091,7 @@ static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive } zend_hash_move_forward_ex(target_hash, &pos); } - + return 0; } /* }}} */ @@ -1148,28 +1101,31 @@ static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive PHP_FUNCTION(array_walk) { zval *array, - *userdata = NULL, - *tmp, - **old_walk_func_name; + *userdata = NULL; + zend_fcall_info orig_array_walk_fci; + zend_fcall_info_cache orig_array_walk_fci_cache; HashTable *target_hash; - old_walk_func_name = BG(array_walk_func_name); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz/|z/", &array, &tmp, &userdata) == FAILURE) { + orig_array_walk_fci = BG(array_walk_fci); + orig_array_walk_fci_cache = BG(array_walk_fci_cache); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zf|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) { + BG(array_walk_fci) = orig_array_walk_fci; + BG(array_walk_fci_cache) = orig_array_walk_fci_cache; return; } + target_hash = HASH_OF(array); if (!target_hash) { + BG(array_walk_fci) = orig_array_walk_fci; + BG(array_walk_fci_cache) = orig_array_walk_fci_cache; php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); RETURN_FALSE; } - if (Z_TYPE_P(tmp) != IS_ARRAY && Z_TYPE_P(tmp) != IS_STRING) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong syntax for function name"); - RETURN_FALSE; - } else { - BG(array_walk_func_name) = &tmp; - } - php_array_walk(target_hash, userdata ? &userdata: NULL, 0 TSRMLS_CC); - BG(array_walk_func_name) = old_walk_func_name; + + php_array_walk(target_hash, userdata ? &userdata : NULL, 0 TSRMLS_CC); + BG(array_walk_fci) = orig_array_walk_fci; + BG(array_walk_fci_cache) = orig_array_walk_fci_cache; RETURN_TRUE; } /* }}} */ @@ -1179,80 +1135,73 @@ PHP_FUNCTION(array_walk) PHP_FUNCTION(array_walk_recursive) { zval *array, - *userdata = NULL, - *tmp, - **old_walk_func_name; + *userdata = NULL; + zend_fcall_info orig_array_walk_fci; + zend_fcall_info_cache orig_array_walk_fci_cache; HashTable *target_hash; - old_walk_func_name = BG(array_walk_func_name); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz/|z/", &array, &tmp, &userdata) == FAILURE) { + orig_array_walk_fci = BG(array_walk_fci); + orig_array_walk_fci_cache = BG(array_walk_fci_cache); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zf|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) { + BG(array_walk_fci) = orig_array_walk_fci; + BG(array_walk_fci_cache) = orig_array_walk_fci_cache; return; } + target_hash = HASH_OF(array); if (!target_hash) { + BG(array_walk_fci) = orig_array_walk_fci; + BG(array_walk_fci_cache) = orig_array_walk_fci_cache; php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); RETURN_FALSE; } - if (Z_TYPE_P(tmp) != IS_ARRAY && Z_TYPE_P(tmp) != IS_STRING) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong syntax for function name"); - RETURN_FALSE; - } else { - BG(array_walk_func_name) = &tmp; - } - php_array_walk(target_hash, userdata ? &userdata : NULL, 1 TSRMLS_CC); - BG(array_walk_func_name) = old_walk_func_name; + + php_array_walk(HASH_OF(array), userdata ? &userdata : NULL, 1 TSRMLS_CC); + BG(array_walk_fci) = orig_array_walk_fci; + BG(array_walk_fci_cache) = orig_array_walk_fci_cache; RETURN_TRUE; } /* }}} */ -/* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) {{{ - * 0 = return boolean - * 1 = return key +/* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) + * 0 = return boolean + * 1 = return key */ -static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) +static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */ { - zval **value, /* value to check for */ - **array, /* array to check in */ - **strict, /* strict comparison or not */ + zval *value, /* value to check for */ + *array, /* array to check in */ **entry, /* pointer to array entry */ res; /* comparison result */ HashTable *target_hash; /* array hashtable */ HashPosition pos; /* hash iterator */ - ulong num_key; + zend_bool strict = 0; /* strict comparison or not */ + ulong num_key; uint str_key_len; - char *string_key; + char *string_key; int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function; - if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3 || - zend_get_parameters_ex(ZEND_NUM_ARGS(), &value, &array, &strict) == FAILURE) { - WRONG_PARAM_COUNT; - } - - - if (Z_TYPE_PP(array) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong datatype for second argument"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) { + return; } - if (ZEND_NUM_ARGS() == 3) { - convert_to_boolean_ex(strict); - if (Z_LVAL_PP(strict)) { - is_equal_func = is_identical_function; - } + if (strict) { + is_equal_func = is_identical_function; } - target_hash = HASH_OF(*array); + target_hash = HASH_OF(array); zend_hash_internal_pointer_reset_ex(target_hash, &pos); while (zend_hash_get_current_data_ex(target_hash, (void **)&entry, &pos) == SUCCESS) { - is_equal_func(&res, *value, *entry TSRMLS_CC); + is_equal_func(&res, value, *entry TSRMLS_CC); if (Z_LVAL(res)) { - if (behavior == 0) { + if (behavior == 0) { RETURN_TRUE; } else { /* Return current key */ switch (zend_hash_get_current_key_ex(target_hash, &string_key, &str_key_len, &num_key, 0, &pos)) { case HASH_KEY_IS_STRING: - RETURN_STRINGL(string_key, str_key_len-1, 1); + RETURN_STRINGL(string_key, str_key_len - 1, 1); break; case HASH_KEY_IS_LONG: RETURN_LONG(num_key); @@ -1260,7 +1209,6 @@ static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) } } } - zend_hash_move_forward_ex(target_hash, &pos); } @@ -1284,13 +1232,14 @@ PHP_FUNCTION(array_search) } /* }}} */ -static int php_valid_var_name(char *var_name, int len) /* {{{ */ +static int php_valid_var_name(char *var_name, int var_name_len) /* {{{ */ { int i, ch; - - if (!var_name) - return 0; + if (!var_name || !var_name_len) { + return 0; + } + /* These are allowed as first char: [a-zA-Z_\x7f-\xff] */ ch = (int)((unsigned char *)var_name)[0]; if (var_name[0] != '_' && @@ -1302,15 +1251,15 @@ static int php_valid_var_name(char *var_name, int len) /* {{{ */ } /* And these as the rest: [a-zA-Z0-9_\x7f-\xff] */ - if (len > 1) { - for (i = 1; i < len; i++) { + if (var_name_len > 1) { + for (i = 1; i < var_name_len; i++) { ch = (int)((unsigned char *)var_name)[i]; if (var_name[i] != '_' && (ch < 48 /* 0 */ || /* 9 */ ch > 57) && (ch < 65 /* A */ || /* Z */ ch > 90) && (ch < 97 /* a */ || /* z */ ch > 122) && (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255) - ) { + ) { return 0; } } @@ -1387,10 +1336,7 @@ PHP_FUNCTION(extract) if (key_type == HASH_KEY_IS_STRING) { var_name_len--; var_exists = zend_hash_exists(EG(active_symbol_table), var_name, var_name_len + 1); - } else if (key_type == HASH_KEY_IS_LONG && - (extract_type == EXTR_PREFIX_ALL || - extract_type == EXTR_PREFIX_INVALID) - ) { + } else if (key_type == HASH_KEY_IS_LONG && (extract_type == EXTR_PREFIX_ALL || extract_type == EXTR_PREFIX_INVALID)) { zval num; ZVAL_LONG(&num, num_key); @@ -1401,7 +1347,7 @@ PHP_FUNCTION(extract) zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos); continue; } - + switch (extract_type) { case EXTR_IF_EXISTS: if (!var_exists) break; @@ -1409,10 +1355,7 @@ PHP_FUNCTION(extract) case EXTR_OVERWRITE: /* GLOBALS protection */ - if (var_exists && - var_name_len == sizeof("GLOBALS") && - !strcmp(var_name, "GLOBALS") - ) { + if (var_exists && var_name_len == sizeof("GLOBALS") && !strcmp(var_name, "GLOBALS")) { break; } ZVAL_STRINGL(&final_name, var_name, var_name_len, 1); @@ -1460,9 +1403,7 @@ PHP_FUNCTION(extract) if (zend_hash_find(EG(active_symbol_table), Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, (void **) &orig_var) == SUCCESS) { SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); zval_add_ref(entry); - zval_ptr_dtor(orig_var); - *orig_var = *entry; } else { if (Z_REFCOUNT_P(var_array) > 1 || *entry == EG(uninitialized_zval_ptr)) { @@ -1494,18 +1435,16 @@ PHP_FUNCTION(extract) static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_value, zval *entry) /* {{{ */ { zval **value_ptr, *value, *data; - + if (Z_TYPE_P(entry) == IS_STRING) { - if (zend_hash_find(eg_active_symbol_table, Z_STRVAL_P(entry), - Z_STRLEN_P(entry)+1, (void **)&value_ptr) != FAILURE) { + if (zend_hash_find(eg_active_symbol_table, Z_STRVAL_P(entry), Z_STRLEN_P(entry) + 1, (void **)&value_ptr) != FAILURE) { value = *value_ptr; ALLOC_ZVAL(data); *data = *value; zval_copy_ctor(data); INIT_PZVAL(data); - - zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(entry), - Z_STRLEN_P(entry)+1, &data, sizeof(zval *), NULL); + + zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(entry), Z_STRLEN_P(entry) + 1, &data, sizeof(zval *), NULL); } } else if (Z_TYPE_P(entry) == IS_ARRAY) { @@ -1528,23 +1467,23 @@ PHP_FUNCTION(compact) { zval ***args; /* function arguments array */ int i; - + if (ZEND_NUM_ARGS() < 1) { WRONG_PARAM_COUNT; } args = (zval ***)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval **), 0); - + if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } array_init(return_value); - + for (i=0; i<ZEND_NUM_ARGS(); i++) { php_compact_var(EG(active_symbol_table), return_value, *args[i]); } - + efree(args); } /* }}} */ @@ -1553,45 +1492,28 @@ PHP_FUNCTION(compact) Create an array containing num elements starting with index start_key each initialized to val */ PHP_FUNCTION(array_fill) { - zval **start_key, **num, **val, *newval; - long i; + zval *val; + long start_key, num; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &start_key, &num, &val) == FAILURE) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llz", &start_key, &num, &val) == FAILURE) { + return; } - switch (Z_TYPE_PP(start_key)) { - case IS_STRING: - case IS_LONG: - case IS_DOUBLE: - /* allocate an array for return */ - array_init(return_value); - - if (PZVAL_IS_REF(*val)) { - SEPARATE_ZVAL(val); - } - convert_to_long_ex(start_key); - zval_add_ref(val); - zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(start_key), val, sizeof(val), NULL); - break; - default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong data type for start key"); - RETURN_FALSE; - break; - } - - convert_to_long_ex(num); - i = Z_LVAL_PP(num) - 1; - if (i < 0) { - zend_hash_destroy(Z_ARRVAL_P(return_value)); - efree(Z_ARRVAL_P(return_value)); + num--; + if (num < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements must be positive"); RETURN_FALSE; } - newval = *val; - while (i--) { - zval_add_ref(&newval); - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &newval, sizeof(zval *), NULL); + + /* allocate an array for return */ + array_init(return_value); + + zval_add_ref(&val); + zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, &val, sizeof(zval *), NULL); + + while (num--) { + zval_add_ref(&val); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &val, sizeof(zval *), NULL); } } /* }}} */ @@ -1652,7 +1574,9 @@ PHP_FUNCTION(range) } if (zstep) { - if (Z_TYPE_P(zstep) == IS_DOUBLE || (Z_TYPE_P(zstep) == IS_STRING && is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0) == IS_DOUBLE)) { + if (Z_TYPE_P(zstep) == IS_DOUBLE || + (Z_TYPE_P(zstep) == IS_STRING && is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0) == IS_DOUBLE) + ) { is_step_double = 1; } @@ -1663,7 +1587,7 @@ PHP_FUNCTION(range) if (step < 0.0) { step *= -1; } - } + } /* Initialize the return_value as an array. */ array_init(return_value); @@ -1676,13 +1600,13 @@ PHP_FUNCTION(range) type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, 0); type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, 0); - + if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) { goto double_str; } else if (type1 == IS_LONG || type2 == IS_LONG) { goto long_str; } - + convert_to_string(zlow); convert_to_string(zhigh); low = (unsigned char *)Z_STRVAL_P(zlow); @@ -1716,12 +1640,12 @@ PHP_FUNCTION(range) } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) { double low, high; -double_str: +double_str: convert_to_double(zlow); convert_to_double(zhigh); low = Z_DVAL_P(zlow); high = Z_DVAL_P(zhigh); - + if (low > high) { /* Negative steps */ if (low - high < step || step <= 0) { err = 1; @@ -1729,7 +1653,7 @@ double_str: } for (; low >= (high - DOUBLE_DRIFT_FIX); low -= step) { add_next_index_double(return_value, low); - } + } } else if (high > low) { /* Positive steps */ if (high - low < step || step <= 0) { err = 1; @@ -1737,7 +1661,7 @@ double_str: } for (; low <= (high + DOUBLE_DRIFT_FIX); low += step) { add_next_index_double(return_value, low); - } + } } else { add_next_index_double(return_value, low); } @@ -1750,7 +1674,7 @@ long_str: low = Z_DVAL_P(zlow); high = Z_DVAL_P(zhigh); lstep = (long) step; - + if (low > high) { /* Negative steps */ if (low - high < lstep || lstep <= 0) { err = 1; @@ -1758,15 +1682,15 @@ long_str: } for (; low >= high; low -= lstep) { add_next_index_long(return_value, (long)low); - } - } else if (high > low) { /* Positive steps */ + } + } else if (high > low) { /* Positive steps */ if (high - low < lstep || lstep <= 0) { err = 1; goto err; } for (; low <= high; low += lstep) { add_next_index_long(return_value, (long)low); - } + } } else { add_next_index_long(return_value, (long)low); } @@ -1776,18 +1700,18 @@ err: php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range"); zval_dtor(return_value); RETURN_FALSE; - } + } } /* }}} */ -static void array_data_shuffle(zval *array TSRMLS_DC) /* {{{ */ +static void php_array_data_shuffle(zval *array TSRMLS_DC) /* {{{ */ { Bucket **elems, *temp; HashTable *hash; int j, n_elems, rnd_idx, n_left; n_elems = zend_hash_num_elements(Z_ARRVAL_P(array)); - + if (n_elems < 1) { return; } @@ -1846,13 +1770,13 @@ PHP_FUNCTION(shuffle) RETURN_FALSE; } - array_data_shuffle(array TSRMLS_CC); + php_array_data_shuffle(array TSRMLS_CC); RETURN_TRUE; } /* }}} */ -HashTable* php_splice(HashTable *in_hash, int offset, int length, zval ***list, int list_count, HashTable **removed) /* {{{ */ +PHPAPI HashTable* php_splice(HashTable *in_hash, int offset, int length, zval ***list, int list_count, HashTable **removed) /* {{{ */ { HashTable *out_hash = NULL; /* Output hashtable */ int num_in, /* Number of entries in the input hashtable */ @@ -1860,20 +1784,22 @@ HashTable* php_splice(HashTable *in_hash, int offset, int length, zval ***list, i; /* Loop counter */ Bucket *p; /* Pointer to hash bucket */ zval *entry; /* Hash entry */ - + /* If input hash doesn't exist, we have nothing to do */ - if (!in_hash) + if (!in_hash) { return NULL; - + } + /* Get number of entries in the input hash */ num_in = zend_hash_num_elements(in_hash); - + /* Clamp the offset.. */ - if (offset > num_in) + if (offset > num_in) { offset = num_in; - else if (offset < 0 && (offset = (num_in + offset)) < 0) + } else if (offset < 0 && (offset = (num_in + offset)) < 0) { offset = 0; - + } + /* ..and the length */ if (length < 0) { length = num_in - offset + length; @@ -1884,51 +1810,55 @@ HashTable* php_splice(HashTable *in_hash, int offset, int length, zval ***list, /* Create and initialize output hash */ ALLOC_HASHTABLE(out_hash); zend_hash_init(out_hash, 0, NULL, ZVAL_PTR_DTOR, 0); - + /* Start at the beginning of the input hash and copy entries to output hash until offset is reached */ - for (pos=0, p=in_hash->pListHead; pos<offset && p ; pos++, p=p->pListNext) { + for (pos = 0, p = in_hash->pListHead; pos < offset && p ; pos++, p = p->pListNext) { /* Get entry and increase reference count */ entry = *((zval **)p->pData); Z_ADDREF_P(entry); - + /* Update output hash depending on key type */ - if (p->nKeyLength) - zend_hash_quick_update(out_hash, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL); - else + if (p->nKeyLength == 0) { zend_hash_next_index_insert(out_hash, &entry, sizeof(zval *), NULL); + } else { + zend_hash_quick_update(out_hash, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL); + } } - + /* If hash for removed entries exists, go until offset+length and copy the entries to it */ if (removed != NULL) { - for ( ; pos<offset+length && p; pos++, p=p->pListNext) { + for ( ; pos < offset + length && p; pos++, p = p->pListNext) { entry = *((zval **)p->pData); Z_ADDREF_P(entry); - if (p->nKeyLength) - zend_hash_quick_update(*removed, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL); - else + if (p->nKeyLength == 0) { zend_hash_next_index_insert(*removed, &entry, sizeof(zval *), NULL); + } else { + zend_hash_quick_update(*removed, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL); + } } - } else /* otherwise just skip those entries */ - for ( ; pos<offset+length && p; pos++, p=p->pListNext); - + } else { /* otherwise just skip those entries */ + for ( ; pos < offset + length && p; pos++, p = p->pListNext); + } + /* If there are entries to insert.. */ if (list != NULL) { /* ..for each one, create a new zval, copy entry into it and copy it into the output hash */ - for (i=0; i<list_count; i++) { + for (i = 0; i < list_count; i++) { entry = *list[i]; Z_ADDREF_P(entry); zend_hash_next_index_insert(out_hash, &entry, sizeof(zval *), NULL); } } - + /* Copy the remaining input hash entries to the output hash */ - for ( ; p ; p=p->pListNext) { + for ( ; p ; p = p->pListNext) { entry = *((zval **)p->pData); Z_ADDREF_P(entry); - if (p->nKeyLength) - zend_hash_quick_update(out_hash, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL); - else + if (p->nKeyLength == 0) { zend_hash_next_index_insert(out_hash, &entry, sizeof(zval *), NULL); + } else { + zend_hash_quick_update(out_hash, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL); + } } zend_hash_internal_pointer_reset(out_hash); @@ -1940,18 +1870,18 @@ HashTable* php_splice(HashTable *in_hash, int offset, int length, zval ***list, Pushes elements onto the end of the array */ PHP_FUNCTION(array_push) { - zval ***args, /* Function arguments array */ - *stack, /* Input array */ - *new_var; /* Variable to be pushed */ - int i, /* Loop counter */ - argc; /* Number of function arguments */ + zval ***args, /* Function arguments array */ + *stack, /* Input array */ + *new_var; /* Variable to be pushed */ + int i, /* Loop counter */ + argc; /* Number of function arguments */ /* Get the argument count and check it */ argc = ZEND_NUM_ARGS(); if (argc < 2) { WRONG_PARAM_COUNT; } - + /* Allocate arguments array and get the arguments, checking for errors. */ args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (zend_get_parameters_array_ex(argc, args) == FAILURE) { @@ -1959,7 +1889,7 @@ PHP_FUNCTION(array_push) WRONG_PARAM_COUNT; } - /* Get first argument and check that it's an array */ + /* Get first argument and check that it's an array */ stack = *args[0]; if (Z_TYPE_P(stack) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argument should be an array"); @@ -1971,64 +1901,59 @@ PHP_FUNCTION(array_push) for (i=1; i<argc; i++) { new_var = *args[i]; Z_ADDREF_P(new_var); - + if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var, sizeof(zval *), NULL) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to the array as the next element is already occupied"); efree(args); RETURN_FALSE; } } - + /* Clean up and return the number of values in the stack */ efree(args); RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack))); } /* }}} */ -/* {{{ void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int which_end) */ +/* {{{ void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) */ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) { - zval **stack, /* Input stack */ - **val; /* Value to be popped */ + zval *stack, /* Input stack */ + **val; /* Value to be popped */ char *key = NULL; - int key_len = 0; + uint key_len = 0; ulong index; - - /* Get the arguments and do error-checking */ - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &stack) == FAILURE) { - WRONG_PARAM_COUNT; - } - - if (Z_TYPE_PP(stack) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &stack) == FAILURE) { return; } - if (zend_hash_num_elements(Z_ARRVAL_PP(stack)) == 0) { + if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) { return; } - + /* Get the first or last value and copy it into the return value */ - if (off_the_end) - zend_hash_internal_pointer_end(Z_ARRVAL_PP(stack)); - else - zend_hash_internal_pointer_reset(Z_ARRVAL_PP(stack)); - zend_hash_get_current_data(Z_ARRVAL_PP(stack), (void **)&val); + if (off_the_end) { + zend_hash_internal_pointer_end(Z_ARRVAL_P(stack)); + } else { + zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); + } + zend_hash_get_current_data(Z_ARRVAL_P(stack), (void **)&val); RETVAL_ZVAL(*val, 1, 0); - + /* Delete the first or last value */ - zend_hash_get_current_key_ex(Z_ARRVAL_PP(stack), &key, &key_len, &index, 0, NULL); - if (key && Z_ARRVAL_PP(stack) == &EG(symbol_table)) { - zend_delete_global_variable(key, key_len-1 TSRMLS_CC); + zend_hash_get_current_key_ex(Z_ARRVAL_P(stack), &key, &key_len, &index, 0, NULL); + if (key && Z_ARRVAL_P(stack) == &EG(symbol_table)) { + zend_delete_global_variable(key, key_len - 1 TSRMLS_CC); } else { - zend_hash_del_key_or_index(Z_ARRVAL_PP(stack), key, key_len, index, (key) ? HASH_DEL_KEY : HASH_DEL_INDEX); + zend_hash_del_key_or_index(Z_ARRVAL_P(stack), key, key_len, index, (key) ? HASH_DEL_KEY : HASH_DEL_INDEX); } - + /* If we did a shift... re-index like it did before */ if (!off_the_end) { unsigned int k = 0; int should_rehash = 0; - Bucket *p = Z_ARRVAL_PP(stack)->pListHead; + Bucket *p = Z_ARRVAL_P(stack)->pListHead; while (p != NULL) { if (p->nKeyLength == 0) { if (p->h != k) { @@ -2040,15 +1965,15 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) } p = p->pListNext; } - Z_ARRVAL_PP(stack)->nNextFreeElement = k; + Z_ARRVAL_P(stack)->nNextFreeElement = k; if (should_rehash) { - zend_hash_rehash(Z_ARRVAL_PP(stack)); + zend_hash_rehash(Z_ARRVAL_P(stack)); } - } else if (!key_len && index >= Z_ARRVAL_PP(stack)->nNextFreeElement-1) { - Z_ARRVAL_PP(stack)->nNextFreeElement = Z_ARRVAL_PP(stack)->nNextFreeElement - 1; + } else if (!key_len && index >= Z_ARRVAL_P(stack)->nNextFreeElement - 1) { + Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1; } - zend_hash_internal_pointer_reset(Z_ARRVAL_PP(stack)); + zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); } /* }}} */ @@ -2072,25 +1997,24 @@ PHP_FUNCTION(array_shift) Pushes elements onto the beginning of the array */ PHP_FUNCTION(array_unshift) { - zval ***args, /* Function arguments array */ - *stack; /* Input stack */ - HashTable *new_hash; /* New hashtable for the stack */ - int argc; /* Number of function arguments */ - + zval ***args, /* Function arguments array */ + *stack; /* Input stack */ + HashTable *new_hash; /* New hashtable for the stack */ + int argc; /* Number of function arguments */ - /* Get the argument count and check it */ + /* Get the argument count and check it */ argc = ZEND_NUM_ARGS(); if (argc < 2) { WRONG_PARAM_COUNT; } - + /* Allocate arguments array and get the arguments, checking for errors. */ args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (zend_get_parameters_array_ex(argc, args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } - + /* Get first argument and check that it's an array */ stack = *args[0]; if (Z_TYPE_P(stack) != IS_ARRAY) { @@ -2100,8 +2024,8 @@ PHP_FUNCTION(array_unshift) } /* Use splice to insert the elements at the beginning. Destroy old - hashtable and replace it with new one */ - new_hash = php_splice(Z_ARRVAL_P(stack), 0, 0, &args[1], argc-1, NULL); + * hashtable and replace it with new one */ + new_hash = php_splice(Z_ARRVAL_P(stack), 0, 0, &args[1], argc - 1, NULL); zend_hash_destroy(Z_ARRVAL_P(stack)); if (Z_ARRVAL_P(stack) == &EG(symbol_table)) { zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC); @@ -2119,67 +2043,42 @@ PHP_FUNCTION(array_unshift) Removes the elements designated by offset and length and replace them with supplied array */ PHP_FUNCTION(array_splice) { - zval ***args, /* Function arguments array */ - *array, /* Input array */ - ***repl = NULL; /* Replacement elements */ - HashTable *new_hash = NULL; /* Output array's hash */ - Bucket *p; /* Bucket used for traversing hash */ - int argc, /* Number of function arguments */ - i, - offset, - length, - repl_num = 0; /* Number of replacement elements */ - - /* Get the argument count and check it */ - argc = ZEND_NUM_ARGS(); - if (argc < 2 || argc > 4) { - WRONG_PARAM_COUNT; - } - - /* Allocate arguments array and get the arguments, checking for errors. */ - args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); - if (zend_get_parameters_array_ex(argc, args) == FAILURE) { - efree(args); - WRONG_PARAM_COUNT; - } - - /* Get first argument and check that it's an array */ - array = *args[0]; - if (Z_TYPE_P(array) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be an array"); - efree(args); + zval *array, /* Input array */ + *repl_array, /* Replacement array */ + ***repl = NULL; /* Replacement elements */ + HashTable *new_hash = NULL; /* Output array's hash */ + Bucket *p; /* Bucket used for traversing hash */ + long i, + offset, + length, + repl_num = 0; /* Number of replacement elements */ + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|lz/", &array, &offset, &length, &repl_array) == FAILURE) { return; } - - /* Get the next two arguments. If length is omitted, it's assumed to be until the end of the array */ - convert_to_long_ex(args[1]); - offset = Z_LVAL_PP(args[1]); - if (argc > 2) { - convert_to_long_ex(args[2]); - length = Z_LVAL_PP(args[2]); - } else + + if (ZEND_NUM_ARGS() < 3) { length = zend_hash_num_elements(Z_ARRVAL_P(array)); + } - if (argc == 4) { + if (ZEND_NUM_ARGS() == 4) { /* Make sure the last argument, if passed, is an array */ - convert_to_array_ex(args[3]); - + convert_to_array(repl_array); + /* Create the array of replacement elements */ - repl_num = zend_hash_num_elements(Z_ARRVAL_PP(args[3])); + repl_num = zend_hash_num_elements(Z_ARRVAL_P(repl_array)); repl = (zval ***)safe_emalloc(repl_num, sizeof(zval **), 0); - for (p=Z_ARRVAL_PP(args[3])->pListHead, i=0; p; p=p->pListNext, i++) { + for (p = Z_ARRVAL_P(repl_array)->pListHead, i = 0; p; p = p->pListNext, i++) { repl[i] = ((zval **)p->pData); } } - + /* Initialize return value */ array_init(return_value); - + /* Perform splice */ - new_hash = php_splice(Z_ARRVAL_P(array), offset, length, - repl, repl_num, - &Z_ARRVAL_P(return_value)); - + new_hash = php_splice(Z_ARRVAL_P(array), offset, length, repl, repl_num, &Z_ARRVAL_P(return_value)); + /* Replace input array's hashtable with the new one */ zend_hash_destroy(Z_ARRVAL_P(array)); if (Z_ARRVAL_P(array) == &EG(symbol_table)) { @@ -2187,11 +2086,11 @@ PHP_FUNCTION(array_splice) } *Z_ARRVAL_P(array) = *new_hash; FREE_HASHTABLE(new_hash); - + /* Clean up */ - if (argc == 4) + if (ZEND_NUM_ARGS() == 4) { efree(repl); - efree(args); + } } /* }}} */ @@ -2199,103 +2098,82 @@ PHP_FUNCTION(array_splice) Returns elements specified by offset and length */ PHP_FUNCTION(array_slice) { - zval **input, /* Input array */ - **offset, /* Offset to get elements from */ - **length, /* How many elements to get */ - **entry, /* An array entry */ - **z_preserve_keys; /* Whether to preserve keys while copying to the new array or not */ - int offset_val, /* Value of the offset argument */ - length_val, /* Value of the length argument */ - num_in, /* Number of elements in the input array */ - pos, /* Current position in the array */ - argc; /* Number of function arguments */ - + zval *input, /* Input array */ + **entry; /* An array entry */ + long offset, /* Offset to get elements from */ + length; /* How many elements to get */ + zend_bool preserve_keys = 0; /* Whether to preserve keys while copying to the new array or not */ + int num_in, /* Number of elements in the input array */ + pos; /* Current position in the array */ + zval *length_param; char *string_key; uint string_key_len; ulong num_key; HashPosition hpos; - zend_bool preserve_keys = 0; - /* Get the arguments and do error-checking */ - argc = ZEND_NUM_ARGS(); - if (argc < 2 || argc > 4 || zend_get_parameters_ex(argc, &input, &offset, &length, &z_preserve_keys)) { - WRONG_PARAM_COUNT; - } - - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be an array"); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|zb", &input, &offset, &length_param, &preserve_keys) == FAILURE) { return; } - - /* Make sure offset and length are integers and assume - we want all entries from offset to the end if length - is not passed */ - convert_to_long_ex(offset); - offset_val = Z_LVAL_PP(offset); - if (argc >= 3 && Z_TYPE_PP(length) != IS_NULL) { - convert_to_long_ex(length); - length_val = Z_LVAL_PP(length); - } else { - length_val = zend_hash_num_elements(Z_ARRVAL_PP(input)); - } - if (ZEND_NUM_ARGS() > 3) { - convert_to_boolean_ex(z_preserve_keys); - preserve_keys = Z_BVAL_PP(z_preserve_keys); + /* Get number of entries in the input hash */ + num_in = zend_hash_num_elements(Z_ARRVAL_P(input)); + + /* We want all entries from offset to the end if length is not passed or is null */ + if (ZEND_NUM_ARGS() >= 3 && Z_TYPE_P(length_param) != IS_NULL) { + length = Z_LVAL_P(length_param); + } else { + length = num_in; } /* Initialize returned array */ array_init(return_value); - - /* Get number of entries in the input hash */ - num_in = zend_hash_num_elements(Z_ARRVAL_PP(input)); - + /* Clamp the offset.. */ - if (offset_val > num_in) + if (offset > num_in) { return; - else if (offset_val < 0 && (offset_val = (num_in + offset_val)) < 0) - offset_val = 0; - + } else if (offset < 0 && (offset = (num_in + offset)) < 0) { + offset = 0; + } + /* ..and the length */ - if (length_val < 0) { - length_val = num_in - offset_val + length_val; - } else if (((unsigned)offset_val + (unsigned)length_val) > (unsigned)num_in) { - length_val = num_in - offset_val; + if (length < 0) { + length = num_in - offset + length; + } else if (((unsigned) offset + (unsigned) length) > (unsigned) num_in) { + length = num_in - offset; } - - if (length_val == 0) + + if (length == 0) { return; - + } + /* Start at the beginning and go until we hit offset */ pos = 0; - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &hpos); - while (pos < offset_val && zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &hpos) == SUCCESS) { + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &hpos); + while (pos < offset && zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &hpos) == SUCCESS) { pos++; - zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &hpos); + zend_hash_move_forward_ex(Z_ARRVAL_P(input), &hpos); } - + /* Copy elements from input array to the one that's returned */ - while (pos < offset_val+length_val && zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &hpos) == SUCCESS) { - - Z_ADDREF_PP(entry); + while (pos < offset + length && zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &hpos) == SUCCESS) { + + zval_add_ref(entry); - switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(input), &string_key, &string_key_len, &num_key, 0, &hpos)) { + switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &hpos)) { case HASH_KEY_IS_STRING: - zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, - entry, sizeof(zval *), NULL); + zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL); break; - + case HASH_KEY_IS_LONG: - if (preserve_keys) - zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, - entry, sizeof(zval *), NULL); - else - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), - entry, sizeof(zval *), NULL); + if (preserve_keys) { + zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(zval *), NULL); + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL); + } break; } pos++; - zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &hpos); + zend_hash_move_forward_ex(Z_ARRVAL_P(input), &hpos); } } /* }}} */ @@ -2312,25 +2190,22 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) { switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) { case HASH_KEY_IS_STRING: - if (recursive && - zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS) { + if (recursive && zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS) { if (*src_entry == *dest_entry && (Z_REFCOUNT_PP(dest_entry) % 2)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected"); return 0; } SEPARATE_ZVAL(dest_entry); SEPARATE_ZVAL(src_entry); - + convert_to_array_ex(dest_entry); convert_to_array_ex(src_entry); - if (!php_array_merge(Z_ARRVAL_PP(dest_entry), - Z_ARRVAL_PP(src_entry), recursive TSRMLS_CC)) + if (!php_array_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry), recursive TSRMLS_CC)) { return 0; + } } else { Z_ADDREF_PP(src_entry); - - zend_hash_update(dest, string_key, string_key_len, - src_entry, sizeof(zval *), NULL); + zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL); } break; @@ -2339,10 +2214,8 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS zend_hash_next_index_insert(dest, src_entry, sizeof(zval *), NULL); break; } - zend_hash_move_forward_ex(src, &pos); } - return 1; } /* }}} */ @@ -2352,12 +2225,12 @@ static void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive) zval ***args = NULL; int argc, i, params_ok = 1; - /* Get the argument count and check it */ + /* Get the argument count and check it */ argc = ZEND_NUM_ARGS(); if (argc < 1) { WRONG_PARAM_COUNT; } - + /* Allocate arguments array and get the arguments, checking for errors. */ args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (zend_get_parameters_array_ex(argc, args) == FAILURE) { @@ -2367,7 +2240,7 @@ static void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive) for (i = 0; i < argc; i++) { if (Z_TYPE_PP(args[i]) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i+1); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1); params_ok = 0; } } @@ -2377,13 +2250,13 @@ static void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive) } array_init(return_value); - + for (i=0; i<argc; i++) { SEPARATE_ZVAL(args[i]); convert_to_array_ex(args[i]); php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), recursive TSRMLS_CC); } - + efree(args); } /* }}} */ @@ -2408,73 +2281,57 @@ PHP_FUNCTION(array_merge_recursive) Return just the keys from the input array, optionally only for the specified search_value */ PHP_FUNCTION(array_keys) { - zval **input, /* Input array */ - **search_value, /* Value to search for */ - **entry, /* An entry in the input array */ - res, /* Result of comparison */ - **strict, /* be strict */ - *new_val; /* New value */ - int add_key; /* Flag to indicate whether a key should be added */ - char *string_key; /* String key */ + zval *input, /* Input array */ + *search_value = NULL, /* Value to search for */ + **entry, /* An entry in the input array */ + res, /* Result of comparison */ + *new_val; /* New value */ + int add_key; /* Flag to indicate whether a key should be added */ + char *string_key; /* String key */ uint string_key_len; - ulong num_key; /* Numeric key */ + ulong num_key; /* Numeric key */ + zend_bool strict = 0; /* do strict comparison */ HashPosition pos; int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function; - - search_value = NULL; - - /* Get arguments and do error-checking */ - if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 3 || - zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &search_value, &strict) == FAILURE) { - WRONG_PARAM_COUNT; - } - - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be an array"); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zb", &input, &search_value, &strict) == FAILURE) { return; } - if (ZEND_NUM_ARGS() == 3) { - convert_to_boolean_ex(strict); - if (Z_LVAL_PP(strict)) { - is_equal_func = is_identical_function; - } + + if (strict) { + is_equal_func = is_identical_function; } - + /* Initialize return array */ array_init(return_value); add_key = 1; - + /* Go through input array and add keys to the return array */ - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos); - while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &pos) == SUCCESS) { + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos); + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) { if (search_value != NULL) { - is_equal_func(&res, *search_value, *entry TSRMLS_CC); + is_equal_func(&res, search_value, *entry TSRMLS_CC); add_key = zval_is_true(&res); } - - if (add_key) { + + if (add_key) { MAKE_STD_ZVAL(new_val); - switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(input), &string_key, &string_key_len, &num_key, 1, &pos)) { + switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 1, &pos)) { case HASH_KEY_IS_STRING: - Z_TYPE_P(new_val) = IS_STRING; - Z_STRVAL_P(new_val) = string_key; - Z_STRLEN_P(new_val) = string_key_len-1; - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, - sizeof(zval *), NULL); + ZVAL_STRINGL(new_val, string_key, string_key_len - 1, 0); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL); break; case HASH_KEY_IS_LONG: Z_TYPE_P(new_val) = IS_LONG; Z_LVAL_P(new_val) = num_key; - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, - sizeof(zval *), NULL); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL); break; } } - zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos); + zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos); } } /* }}} */ @@ -2483,32 +2340,23 @@ PHP_FUNCTION(array_keys) Return just the values from the input array */ PHP_FUNCTION(array_values) { - zval **input, /* Input array */ - **entry; /* An entry in the input array */ + zval *input, /* Input array */ + **entry; /* An entry in the input array */ HashPosition pos; - - /* Get arguments and do error-checking */ - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &input) == FAILURE) { - WRONG_PARAM_COUNT; - } - - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) { return; } - + /* Initialize return array */ array_init(return_value); - /* Go through input array and add values to the return array */ - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos); - while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &pos) == SUCCESS) { - - Z_ADDREF_PP(entry); - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, - sizeof(zval *), NULL); - - zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos); + /* Go through input array and add values to the return array */ + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos); + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) { + zval_add_ref(entry); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL); + zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos); } } /* }}} */ @@ -2517,33 +2365,25 @@ PHP_FUNCTION(array_values) Return the value as key and the frequency of that value in input as value */ PHP_FUNCTION(array_count_values) { - zval **input, /* Input array */ - **entry, /* An entry in the input array */ - **tmp; + zval *input, /* Input array */ + **entry, /* An entry in the input array */ + **tmp; HashTable *myht; HashPosition pos; - - /* Get arguments and do error-checking */ - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &input) == FAILURE) { - WRONG_PARAM_COUNT; - } - - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) { return; } - + /* Initialize return array */ array_init(return_value); - /* Go through input array and add values to the return array */ - myht = Z_ARRVAL_PP(input); + /* Go through input array and add values to the return array */ + myht = Z_ARRVAL_P(input); zend_hash_internal_pointer_reset_ex(myht, &pos); while (zend_hash_get_current_data_ex(myht, (void **)&entry, &pos) == SUCCESS) { if (Z_TYPE_PP(entry) == IS_LONG) { - if (zend_hash_index_find(Z_ARRVAL_P(return_value), - Z_LVAL_PP(entry), - (void**)&tmp) == FAILURE) { + if (zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), (void **)&tmp) == FAILURE) { zval *data; MAKE_STD_ZVAL(data); ZVAL_LONG(data, 1); @@ -2573,38 +2413,26 @@ PHP_FUNCTION(array_count_values) Return input as a new array with the order of the entries reversed */ PHP_FUNCTION(array_reverse) { - zval **input, /* Input array */ - **z_preserve_keys, /* Flag: whether to preserve keys */ - **entry; /* An entry in the input array */ + zval *input, /* Input array */ + **entry; /* An entry in the input array */ char *string_key; uint string_key_len; ulong num_key; - zend_bool preserve_keys = 0; + zend_bool preserve_keys = 0; /* whether to preserve keys */ HashPosition pos; - - /* Get arguments and do error-checking */ - if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &z_preserve_keys) == FAILURE) { - WRONG_PARAM_COUNT; - } - - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &input, &preserve_keys) == FAILURE) { return; } - if (ZEND_NUM_ARGS() > 1) { - convert_to_boolean_ex(z_preserve_keys); - preserve_keys = Z_BVAL_PP(z_preserve_keys); - } - /* Initialize return array */ array_init(return_value); - - zend_hash_internal_pointer_end_ex(Z_ARRVAL_PP(input), &pos); - while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &pos) == SUCCESS) { - Z_ADDREF_PP(entry); - - switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(input), &string_key, &string_key_len, &num_key, 0, &pos)) { + + zend_hash_internal_pointer_end_ex(Z_ARRVAL_P(input), &pos); + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) { + zval_add_ref(entry); + + switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &pos)) { case HASH_KEY_IS_STRING: zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL); break; @@ -2617,8 +2445,8 @@ PHP_FUNCTION(array_reverse) } break; } - - zend_hash_move_backwards_ex(Z_ARRVAL_PP(input), &pos); + + zend_hash_move_backwards_ex(Z_ARRVAL_P(input), &pos); } } /* }}} */ @@ -2627,37 +2455,29 @@ PHP_FUNCTION(array_reverse) Returns a copy of input array padded with pad_value to size pad_size */ PHP_FUNCTION(array_pad) { - zval **input; /* Input array */ - zval **pad_size; /* Size to pad to */ - zval **pad_value; /* Padding value obviously */ + zval *input; /* Input array */ + zval *pad_value; /* Padding value obviously */ zval ***pads; /* Array to pass to splice */ - HashTable *new_hash; /* Return value from splice */ - int input_size; /* Size of the input array */ - int pad_size_abs; /* Absolute value of pad_size */ - int num_pads; /* How many pads do we need */ - int do_pad; /* Whether we should do padding at all */ + HashTable *new_hash;/* Return value from splice */ + long pad_size; /* Size to pad to */ + long pad_size_abs; /* Absolute value of pad_size */ + int input_size; /* Size of the input array */ + int num_pads; /* How many pads do we need */ + int do_pad; /* Whether we should do padding at all */ int i; - - /* Get arguments and do error-checking */ - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &input, &pad_size, &pad_value) == FAILURE) { - WRONG_PARAM_COUNT; - } - - /* Make sure arguments are of the proper type */ - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "alz", &input, &pad_size, &pad_value) == FAILURE) { return; } - convert_to_long_ex(pad_size); - + /* Do some initial calculations */ - input_size = zend_hash_num_elements(Z_ARRVAL_PP(input)); - pad_size_abs = abs(Z_LVAL_PP(pad_size)); + input_size = zend_hash_num_elements(Z_ARRVAL_P(input)); + pad_size_abs = abs(pad_size); do_pad = (input_size >= pad_size_abs) ? 0 : 1; - + /* Copy the original array */ - RETVAL_ZVAL(*input, 1, 0); - + RETVAL_ZVAL(input, 1, 0); + /* If no need to pad, no need to continue */ if (!do_pad) { return; @@ -2665,18 +2485,18 @@ PHP_FUNCTION(array_pad) /* Populate the pads array */ num_pads = pad_size_abs - input_size; - if(num_pads > 1048576) { + if (num_pads > 1048576) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "You may only pad up to 1048576 elements at a time"); zval_dtor(return_value); RETURN_FALSE; } pads = (zval ***)safe_emalloc(num_pads, sizeof(zval **), 0); for (i = 0; i < num_pads; i++) { - pads[i] = pad_value; + pads[i] = &pad_value; } /* Pad on the right or on the left */ - if (Z_LVAL_PP(pad_size) > 0) { + if (pad_size > 0) { new_hash = php_splice(Z_ARRVAL_P(return_value), input_size, 0, pads, num_pads, NULL); } else { new_hash = php_splice(Z_ARRVAL_P(return_value), 0, 0, pads, num_pads, NULL); @@ -2689,7 +2509,7 @@ PHP_FUNCTION(array_pad) } *Z_ARRVAL_P(return_value) = *new_hash; FREE_HASHTABLE(new_hash); - + /* Clean up */ efree(pads); } @@ -2699,23 +2519,18 @@ PHP_FUNCTION(array_pad) Return array with key <-> value flipped */ PHP_FUNCTION(array_flip) { - zval **array, **entry, *data; + zval *array, **entry, *data; HashTable *target_hash; char *string_key; uint str_key_len; ulong num_key; HashPosition pos; - - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; - } - target_hash = HASH_OF(*array); - if (!target_hash) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + return; } - + + target_hash = HASH_OF(array); array_init(return_value); zend_hash_internal_pointer_reset_ex(target_hash, &pos); @@ -2723,9 +2538,7 @@ PHP_FUNCTION(array_flip) MAKE_STD_ZVAL(data); switch (zend_hash_get_current_key_ex(target_hash, &string_key, &str_key_len, &num_key, 1, &pos)) { case HASH_KEY_IS_STRING: - Z_STRVAL_P(data) = string_key; - Z_STRLEN_P(data) = str_key_len-1; - Z_TYPE_P(data) = IS_STRING; + ZVAL_STRINGL(data, string_key, str_key_len - 1, 0); break; case HASH_KEY_IS_LONG: Z_TYPE_P(data) = IS_LONG; @@ -2741,7 +2554,7 @@ PHP_FUNCTION(array_flip) zval_ptr_dtor(&data); /* will free also zval structure */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only flip STRING and INTEGER values!"); } - + zend_hash_move_forward_ex(target_hash, &pos); } } @@ -2751,52 +2564,41 @@ PHP_FUNCTION(array_flip) Retuns an array with all string keys lowercased [or uppercased] */ PHP_FUNCTION(array_change_key_case) { - zval **array, **entry, **to_upper; + zval *array, **entry; char *string_key; char *new_key; uint str_key_len; ulong num_key; - ulong change_to_upper=0; - + long change_to_upper=0; HashPosition pos; - - if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || - zend_get_parameters_ex(ZEND_NUM_ARGS(), &array, &to_upper) == FAILURE) { - WRONG_PARAM_COUNT; - } - if (ZEND_NUM_ARGS() > 1) { - convert_to_long_ex(to_upper); - change_to_upper = Z_LVAL_PP(to_upper); - } - - if (Z_TYPE_PP(array) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &change_to_upper) == FAILURE) { + return; } array_init(return_value); - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(array), &pos); - while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(array), (void **)&entry, &pos) == SUCCESS) { - Z_ADDREF_PP(entry); + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) { + zval_add_ref(entry); - switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(array), &string_key, &str_key_len, &num_key, 0, &pos)) { + switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) { case HASH_KEY_IS_LONG: zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(entry), NULL); break; case HASH_KEY_IS_STRING: - new_key=estrndup(string_key,str_key_len - 1); - if (change_to_upper) + new_key = estrndup(string_key, str_key_len - 1); + if (change_to_upper) { php_strtoupper(new_key, str_key_len - 1); - else + } else { php_strtolower(new_key, str_key_len - 1); + } zend_hash_update(Z_ARRVAL_P(return_value), new_key, str_key_len, entry, sizeof(entry), NULL); efree(new_key); break; } - zend_hash_move_forward_ex(Z_ARRVAL_PP(array), &pos); + zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos); } } /* }}} */ @@ -2815,9 +2617,10 @@ PHP_FUNCTION(array_unique) struct bucketindex *arTmp, *cmpdata, *lastkept; unsigned int i; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &array) == FAILURE) { + return; } + target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); @@ -2834,6 +2637,7 @@ PHP_FUNCTION(array_unique) /* create and sort array with pointers to the target_hash buckets */ arTmp = (struct bucketindex *) pemalloc((target_hash->nNumOfElements + 1) * sizeof(struct bucketindex), target_hash->persistent); if (!arTmp) { + zval_dtor(return_value); RETURN_FALSE; } for (i = 0, p = target_hash->pListHead; p; i++, p = p->pListNext) { @@ -2841,13 +2645,13 @@ PHP_FUNCTION(array_unique) arTmp[i].i = i; } arTmp[i].b = NULL; - set_compare_func(SORT_STRING TSRMLS_CC); - zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), array_data_compare TSRMLS_CC); + php_set_compare_func(PHP_SORT_STRING TSRMLS_CC); + zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), php_array_data_compare TSRMLS_CC); /* go through the sorted array and delete duplicates from the copy */ lastkept = arTmp; for (cmpdata = arTmp + 1; cmpdata->b; cmpdata++) { - if (array_data_compare(lastkept, cmpdata TSRMLS_CC)) { + if (php_array_data_compare(lastkept, cmpdata TSRMLS_CC)) { lastkept = cmpdata; } else { if (lastkept->i > cmpdata->i) { @@ -2856,14 +2660,14 @@ PHP_FUNCTION(array_unique) } else { p = cmpdata->b; } - if (p->nKeyLength) { + if (p->nKeyLength == 0) { + zend_hash_index_del(Z_ARRVAL_P(return_value), p->h); + } else { if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) { - zend_delete_global_variable(p->arKey, p->nKeyLength-1 TSRMLS_CC); + zend_delete_global_variable(p->arKey, p->nKeyLength - 1 TSRMLS_CC); } else { zend_hash_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength); } - } else { - zend_hash_index_del(Z_ARRVAL_P(return_value), p->h); } } } @@ -2876,13 +2680,13 @@ static int zval_compare(zval **a, zval **b TSRMLS_DC) /* {{{ */ zval result; zval *first; zval *second; - + first = *((zval **) a); second = *((zval **) b); if (string_compare_function(&result, first, second TSRMLS_CC) == FAILURE) { return 0; - } + } if (Z_TYPE(result) == IS_DOUBLE) { if (Z_DVAL(result) < 0) { @@ -2900,7 +2704,7 @@ static int zval_compare(zval **a, zval **b TSRMLS_DC) /* {{{ */ return -1; } else if (Z_LVAL(result) > 0) { return 1; - } + } return 0; } @@ -2910,23 +2714,16 @@ static int zval_user_compare(zval **a, zval **b TSRMLS_DC) /* {{{ */ { zval **args[2]; zval *retval_ptr; - zend_fcall_info fci; args[0] = (zval **) a; args[1] = (zval **) b; - fci.size = sizeof(fci); - fci.function_table = EG(function_table); - fci.function_name = *BG(user_compare_func_name); - fci.symbol_table = NULL; - fci.object_pp = NULL; - fci.retval_ptr_ptr = &retval_ptr; - fci.param_count = 2; - fci.params = args; - fci.no_separation = 0; + BG(user_compare_fci).param_count = 2; + BG(user_compare_fci).params = args; + BG(user_compare_fci).retval_ptr_ptr = &retval_ptr; + BG(user_compare_fci).no_separation = 0; - if (zend_call_function(&fci, &BG(user_compare_fci_cache) TSRMLS_CC)== SUCCESS - && retval_ptr) { + if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) { long retval; convert_to_long_ex(&retval_ptr); @@ -2950,31 +2747,18 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa /* Get the argument count */ argc = ZEND_NUM_ARGS(); - /* Allocate arguments array and get the arguments, checking for errors. */ - args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); - if (argc < 2 || zend_get_parameters_array_ex(argc, args) == FAILURE) { - efree(args); - WRONG_PARAM_COUNT; - } if (data_compare_type == INTERSECT_COMP_DATA_USER) { - char *callback_name; - - if (argc < 3) { - efree(args); - WRONG_PARAM_COUNT; - } - argc--; - if (!zend_is_callable(*args[argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); + if (argc < 3 || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { return; - } - efree(callback_name); + } intersect_data_compare_func = zval_user_compare; - BG(user_compare_func_name) = args[argc]; - } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) { - intersect_data_compare_func = zval_compare; + } else { + if (argc < 2 || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) { + return; + } + if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) { + intersect_data_compare_func = zval_compare; + } } array_init(return_value); @@ -2984,8 +2768,9 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa ok = 1; for (i = 1; i < argc; i++) { if (zend_hash_index_find(Z_ARRVAL_PP(args[i]), p->h, (void**)&data) == FAILURE || - (intersect_data_compare_func && - intersect_data_compare_func((zval**)p->pData, data TSRMLS_CC) != 0)) { + (intersect_data_compare_func && + intersect_data_compare_func((zval**)p->pData, data TSRMLS_CC) != 0) + ) { ok = 0; break; } @@ -2998,8 +2783,9 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa ok = 1; for (i = 1; i < argc; i++) { if (zend_hash_quick_find(Z_ARRVAL_PP(args[i]), p->arKey, p->nKeyLength, p->h, (void**)&data) == FAILURE || - (intersect_data_compare_func && - intersect_data_compare_func((zval**)p->pData, data TSRMLS_CC) != 0)) { + (intersect_data_compare_func && + intersect_data_compare_func((zval**)p->pData, data TSRMLS_CC) != 0) + ) { ok = 0; break; } @@ -3018,171 +2804,133 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int { zval ***args = NULL; HashTable *hash; - int argc, arr_argc, i, c = 0; + int arr_argc, i, c = 0; Bucket ***lists, **list, ***ptrs, *p; - - char *callback_name; + int req_args; + char *param_spec; + zend_fcall_info fci1, fci2; + zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache; + zend_fcall_info *fci_key, *fci_data; + zend_fcall_info_cache *fci_key_cache, *fci_data_cache; PHP_ARRAY_CMP_FUNC_VARS; - int (*intersect_key_compare_func)(const void *, const void * TSRMLS_DC); int (*intersect_data_compare_func)(const void *, const void * TSRMLS_DC); - /* Get the argument count */ - argc = ZEND_NUM_ARGS(); - /* Allocate arguments array and get the arguments, checking for errors. */ - args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); - if (zend_get_parameters_array_ex(argc, args) == FAILURE) { - efree(args); - WRONG_PARAM_COUNT; - } - - PHP_ARRAY_CMP_FUNC_BACKUP(); - if (behavior == INTERSECT_NORMAL) { - intersect_key_compare_func = array_key_compare; + intersect_key_compare_func = php_array_key_compare; + if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) { /* array_intersect() */ - - if (argc < 2) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc; - intersect_data_compare_func = array_data_compare; + req_args = 2; + param_spec = "+"; + intersect_data_compare_func = php_array_data_compare; } else if (data_compare_type == INTERSECT_COMP_DATA_USER) { /* array_uintersect() */ - if (argc < 3) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc - 1; - intersect_data_compare_func = array_user_compare; - if (!zend_is_callable(*args[arr_argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - - BG(user_compare_func_name) = args[arr_argc]; + req_args = 3; + param_spec = "+f"; + intersect_data_compare_func = php_array_user_compare; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type); return; } + + if (ZEND_NUM_ARGS() < req_args) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); + return; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) { + return; + } + fci_data = &fci1; + fci_data_cache = &fci1_cache; + } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */ - /* - INTERSECT_KEY is subset of INTERSECT_ASSOC. When having the former - no comparison of the data is done (part of INTERSECT_ASSOC) - */ - intersect_key_compare_func = array_key_compare; - if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL - && - key_compare_type == INTERSECT_COMP_KEY_INTERNAL) { + /* INTERSECT_KEY is subset of INTERSECT_ASSOC. When having the former + * no comparison of the data is done (part of INTERSECT_ASSOC) */ + intersect_key_compare_func = php_array_key_compare; + + if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) { /* array_intersect_assoc() or array_intersect_key() */ - - if (argc < 2) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc; - intersect_key_compare_func = array_key_compare; - intersect_data_compare_func = array_data_compare; - } else if (data_compare_type == INTERSECT_COMP_DATA_USER - && - key_compare_type == INTERSECT_COMP_KEY_INTERNAL) { + req_args = 2; + param_spec = "+"; + intersect_key_compare_func = php_array_key_compare; + intersect_data_compare_func = php_array_data_compare; + } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) { /* array_uintersect_assoc() */ - - if (argc < 3) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc - 1; - if (!zend_is_callable(*args[arr_argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - intersect_key_compare_func = array_key_compare; - intersect_data_compare_func = array_user_compare; - } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL - && - key_compare_type == INTERSECT_COMP_KEY_USER) { - /* array_intersect_uassoc() or array_intersect_ukey() */ - - if (argc < 3) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc - 1; - if (!zend_is_callable(*args[arr_argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - intersect_key_compare_func = array_user_key_compare; - intersect_data_compare_func = array_data_compare; - BG(user_compare_func_name) = args[arr_argc]; - } else if (data_compare_type == INTERSECT_COMP_DATA_USER - && - key_compare_type == INTERSECT_COMP_KEY_USER) { - /* array_uintersect_uassoc() */ - - if (argc < 4) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc - 2; - if (!zend_is_callable(*args[arr_argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - if (!zend_is_callable(*args[arr_argc + 1], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - intersect_key_compare_func = array_user_key_compare; - intersect_data_compare_func = array_user_compare; - BG(user_compare_func_name) = args[arr_argc + 1];/* data - key */ + req_args = 3; + param_spec = "+f"; + intersect_key_compare_func = php_array_key_compare; + intersect_data_compare_func = php_array_user_compare; + fci_data = &fci1; + fci_data_cache = &fci1_cache; + } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_USER) { + /* array_intersect_uassoc() or array_intersect_ukey() */ + req_args = 3; + param_spec = "+f"; + intersect_key_compare_func = php_array_user_key_compare; + intersect_data_compare_func = php_array_data_compare; + fci_key = &fci1; + fci_key_cache = &fci1_cache; + } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_USER) { + /* array_uintersect_uassoc() */ + req_args = 4; + param_spec = "+ff"; + intersect_key_compare_func = php_array_user_key_compare; + intersect_data_compare_func = php_array_user_compare; + fci_data = &fci1; + fci_data_cache = &fci1_cache; + fci_key = &fci2; + fci_key_cache = &fci2_cache; } else { - efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type); return; - } + } + + if (ZEND_NUM_ARGS() < req_args) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); + return; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) { + return; + } + } else { - efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior); return; } + PHP_ARRAY_CMP_FUNC_BACKUP(); /* for each argument, create and sort list with pointers to the hash buckets */ lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0); ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0); - set_compare_func(SORT_STRING TSRMLS_CC); + php_set_compare_func(PHP_SORT_STRING TSRMLS_CC); + + if (behavior == INTERSECT_NORMAL && data_compare_type == INTERSECT_COMP_DATA_USER) { + BG(user_compare_fci) = *fci_data; + BG(user_compare_fci_cache) = *fci_data_cache; + } else if (behavior & INTERSECT_ASSOC && key_compare_type == INTERSECT_COMP_KEY_USER) { + BG(user_compare_fci) = *fci_key; + BG(user_compare_fci_cache) = *fci_key_cache; + } + for (i = 0; i < arr_argc; i++) { if (Z_TYPE_PP(args[i]) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i+1); - arr_argc = i; /* only free up to i-1 */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1); + arr_argc = i; /* only free up to i - 1 */ goto out; } hash = HASH_OF(*args[i]); list = (Bucket **) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket *), hash->persistent); if (!list) { - efree(args); - efree(lists); + PHP_ARRAY_CMP_FUNC_RESTORE(); + efree(ptrs); + efree(lists); + efree(args); RETURN_FALSE; } lists[i] = list; @@ -3207,21 +2955,17 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int ALLOC_HASHTABLE(ht); zend_hash_init(ht, zend_hash_num_elements(return_value->value.ht), NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(ht, return_value->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - return_value->value.ht = ht; + return_value->value.ht = ht; } - if ((behavior & INTERSECT_NORMAL) && data_compare_type == INTERSECT_COMP_DATA_USER) { - /* array_uintersect() */ - BG(user_compare_func_name) = args[arr_argc]; - } - /* go through the lists and look for common values */ while (*ptrs[0]) { if ((behavior & INTERSECT_ASSOC) /* triggered also when INTERSECT_KEY */ - && + && key_compare_type == INTERSECT_COMP_KEY_USER) { - BG(user_compare_func_name) = args[argc - 1]; + BG(user_compare_fci) = *fci_key; + BG(user_compare_fci_cache) = *fci_key_cache; } for (i = 1; i < arr_argc; i++) { @@ -3234,26 +2978,25 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int ptrs[i]++; } if ((!c && *ptrs[i]) && (behavior == INTERSECT_ASSOC)) { /* only when INTERSECT_ASSOC */ - /* - this means that ptrs[i] is not NULL so we can compare - and "c==0" is from last operation - in this branch of code we enter only when INTERSECT_ASSOC - since when we have INTERSECT_KEY compare of data is not - wanted. - */ + /* this means that ptrs[i] is not NULL so we can compare + * and "c==0" is from last operation + * in this branch of code we enter only when INTERSECT_ASSOC + * since when we have INTERSECT_KEY compare of data is not wanted. */ if (data_compare_type == INTERSECT_COMP_DATA_USER) { - BG(user_compare_func_name) = args[arr_argc]; + BG(user_compare_fci) = *fci_data; + BG(user_compare_fci_cache) = *fci_data_cache; + } + if (intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC) != 0) { + c = 1; + if (key_compare_type == INTERSECT_COMP_KEY_USER) { + BG(user_compare_fci) = *fci_key; + BG(user_compare_fci_cache) = *fci_key_cache; + /* When KEY_USER, the last parameter is always the callback */ + } + /* we are going to the break */ + } else { + /* continue looping */ } - if (intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC) != 0) { - c = 1; - if (key_compare_type == INTERSECT_COMP_KEY_USER) { - BG(user_compare_func_name) = args[argc - 1]; - /* When KEY_USER, the last parameter is always the callback */ - } - /* we are going to the break */ - } else { - /* continue looping */ - } } } if (!*ptrs[i]) { @@ -3265,10 +3008,10 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int if (!p) { goto out; } - if (p->nKeyLength) { - zend_hash_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength); - } else { + if (p->nKeyLength == 0) { zend_hash_index_del(Z_ARRVAL_P(return_value), p->h); + } else { + zend_hash_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength); } } } @@ -3281,12 +3024,12 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int /* with value < value of ptrs[i] */ for (;;) { p = *ptrs[0]; - if (p->nKeyLength) { - zend_hash_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength); + if (p->nKeyLength == 0) { + zend_hash_index_del(Z_ARRVAL_P(return_value), p->h); } else { - zend_hash_index_del(Z_ARRVAL_P(return_value), p->h); + zend_hash_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength); } - if (!*++ptrs[0]) { + if (!*++ptrs[0]) { goto out; } if (behavior == INTERSECT_NORMAL) { @@ -3306,7 +3049,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int goto out; } if (behavior == INTERSECT_NORMAL) { - if (intersect_data_compare_func(ptrs[0]-1, ptrs[0] TSRMLS_CC)) { + if (intersect_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) { break; } } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */ @@ -3321,10 +3064,9 @@ out: hash = HASH_OF(*args[i]); pefree(lists[i], hash->persistent); } - + PHP_ARRAY_CMP_FUNC_RESTORE(); - efree(ptrs); efree(lists); efree(args); @@ -3343,8 +3085,7 @@ PHP_FUNCTION(array_intersect_key) Returns the entries of arr1 that have keys which are present in all the other arguments. Kind of equivalent to array_diff(array_keys($arr1), array_keys($arr2)[,array_keys(...)]). The comparison of the keys is performed by a user supplied function. Equivalent of array_intersect_uassoc() but does not do compare of the data. */ PHP_FUNCTION(array_intersect_ukey) { - php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY, - INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER); + php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER); } /* }}} */ @@ -3352,8 +3093,7 @@ PHP_FUNCTION(array_intersect_ukey) Returns the entries of arr1 that have values which are present in all the other arguments */ PHP_FUNCTION(array_intersect) { - php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, - INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_INTERNAL); + php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_INTERNAL); } /* }}} */ @@ -3361,8 +3101,7 @@ PHP_FUNCTION(array_intersect) Returns the entries of arr1 that have values which are present in all the other arguments. Data is compared by using an user-supplied callback. */ PHP_FUNCTION(array_uintersect) { - php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, - INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_INTERNAL); + php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_INTERNAL); } /* }}} */ @@ -3374,20 +3113,19 @@ PHP_FUNCTION(array_intersect_assoc) } /* }}} */ -/* {{{ proto array array_uintersect_assoc(array arr1, array arr2 [, array ...], callback data_compare_func) - Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Data is compared by using an user-supplied callback. */ -PHP_FUNCTION(array_uintersect_assoc) +/* {{{ proto array array_intersect_uassoc(array arr1, array arr2 [, array ...], callback key_compare_func) U + Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check and they are compared by using an user-supplied callback. */ +PHP_FUNCTION(array_intersect_uassoc) { - php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_USER); + php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER); } /* }}} */ -/* {{{ proto array array_intersect_uassoc(array arr1, array arr2 [, array ...], callback key_compare_func) - Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check and they are compared by using an user-supplied callback. */ -PHP_FUNCTION(array_intersect_uassoc) +/* {{{ proto array array_uintersect_assoc(array arr1, array arr2 [, array ...], callback data_compare_func) U + Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Data is compared by using an user-supplied callback. */ +PHP_FUNCTION(array_uintersect_assoc) { - php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, - INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER); + php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_USER); } /* }}} */ @@ -3395,8 +3133,7 @@ PHP_FUNCTION(array_intersect_uassoc) Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Both data and keys are compared by using user-supplied callbacks. */ PHP_FUNCTION(array_uintersect_uassoc) { - php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, - INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_USER); + php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_USER); } /* }}} */ @@ -3411,31 +3148,18 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty /* Get the argument count */ argc = ZEND_NUM_ARGS(); - /* Allocate arguments array and get the arguments, checking for errors. */ - args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); - if (argc < 2 || zend_get_parameters_array_ex(argc, args) == FAILURE) { - efree(args); - WRONG_PARAM_COUNT; - } if (data_compare_type == DIFF_COMP_DATA_USER) { - char *callback_name; - - if (argc < 3) { - efree(args); - WRONG_PARAM_COUNT; - } - argc--; - if (!zend_is_callable(*args[argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); + if (argc < 3 || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { return; - } - efree(callback_name); + } diff_data_compare_func = zval_user_compare; - BG(user_compare_func_name) = args[argc]; - } else if (data_compare_type == DIFF_COMP_DATA_INTERNAL) { - diff_data_compare_func = zval_compare; + } else { + if (argc < 2 || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) { + return; + } + if (data_compare_type == DIFF_COMP_DATA_INTERNAL) { + diff_data_compare_func = zval_compare; + } } array_init(return_value); @@ -3445,8 +3169,9 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty ok = 1; for (i = 1; i < argc; i++) { if (zend_hash_index_find(Z_ARRVAL_PP(args[i]), p->h, (void**)&data) == SUCCESS && - (!diff_data_compare_func || - diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0)) { + (!diff_data_compare_func || + diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0) + ) { ok = 0; break; } @@ -3459,8 +3184,9 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty ok = 1; for (i = 1; i < argc; i++) { if (zend_hash_quick_find(Z_ARRVAL_PP(args[i]), p->arKey, p->nKeyLength, p->h, (void**)&data) == SUCCESS && - (!diff_data_compare_func || - diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0)) { + (!diff_data_compare_func || + diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0) + ) { ok = 0; break; } @@ -3479,171 +3205,133 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ { zval ***args = NULL; HashTable *hash; - int argc, arr_argc, i, c; + int arr_argc, i, c; Bucket ***lists, **list, ***ptrs, *p; - char *callback_name; - + int req_args; + char *param_spec; + zend_fcall_info fci1, fci2; + zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache; + zend_fcall_info *fci_key, *fci_data; + zend_fcall_info_cache *fci_key_cache, *fci_data_cache; PHP_ARRAY_CMP_FUNC_VARS; int (*diff_key_compare_func)(const void *, const void * TSRMLS_DC); int (*diff_data_compare_func)(const void *, const void * TSRMLS_DC); - - - /* Get the argument count */ - argc = ZEND_NUM_ARGS(); - /* Allocate arguments array and get the arguments, checking for errors. */ - args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); - if (zend_get_parameters_array_ex(argc, args) == FAILURE) { - efree(args); - WRONG_PARAM_COUNT; - } - - PHP_ARRAY_CMP_FUNC_BACKUP(); if (behavior == DIFF_NORMAL) { - diff_key_compare_func = array_key_compare; + diff_key_compare_func = php_array_key_compare; + if (data_compare_type == DIFF_COMP_DATA_INTERNAL) { /* array_diff */ - - if (argc < 2) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc; - diff_data_compare_func = array_data_compare; + req_args = 2; + param_spec = "+"; + diff_data_compare_func = php_array_data_compare; } else if (data_compare_type == DIFF_COMP_DATA_USER) { /* array_udiff */ - if (argc < 3) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc - 1; - diff_data_compare_func = array_user_compare; - if (!zend_is_callable(*args[arr_argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - - BG(user_compare_func_name) = args[arr_argc]; + req_args = 3; + param_spec = "+f"; + diff_data_compare_func = php_array_user_compare; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type); - return; + return; } + + if (ZEND_NUM_ARGS() < req_args) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); + return; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) { + return; + } + fci_data = &fci1; + fci_data_cache = &fci1_cache; + } else if (behavior & DIFF_ASSOC) { /* triggered also if DIFF_KEY */ - /* - DIFF_KEY is subset of DIFF_ASSOC. When having the former - no comparison of the data is done (part of DIFF_ASSOC) - */ - diff_key_compare_func = array_key_compare; - if (data_compare_type == DIFF_COMP_DATA_INTERNAL - && - key_compare_type == DIFF_COMP_KEY_INTERNAL) { + /* DIFF_KEY is subset of DIFF_ASSOC. When having the former + * no comparison of the data is done (part of DIFF_ASSOC) */ + diff_key_compare_func = php_array_key_compare; + + if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_INTERNAL) { /* array_diff_assoc() or array_diff_key() */ - - if (argc < 2) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc; - diff_key_compare_func = array_key_compare; - diff_data_compare_func = array_data_compare; - } else if (data_compare_type == DIFF_COMP_DATA_USER - && - key_compare_type == DIFF_COMP_KEY_INTERNAL) { + req_args = 2; + param_spec = "+"; + diff_key_compare_func = php_array_key_compare; + diff_data_compare_func = php_array_data_compare; + } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_INTERNAL) { /* array_udiff_assoc() */ - - if (argc < 3) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc - 1; - if (!zend_is_callable(*args[arr_argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - diff_key_compare_func = array_key_compare; - diff_data_compare_func = array_user_compare; - } else if (data_compare_type == DIFF_COMP_DATA_INTERNAL - && - key_compare_type == DIFF_COMP_KEY_USER) { + req_args = 3; + param_spec = "+f"; + diff_key_compare_func = php_array_key_compare; + diff_data_compare_func = php_array_user_compare; + fci_data = &fci1; + fci_data_cache = &fci1_cache; + } else if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_USER) { /* array_diff_uassoc() or array_diff_ukey() */ - - if (argc < 3) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc - 1; - if (!zend_is_callable(*args[arr_argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - diff_key_compare_func = array_user_key_compare; - diff_data_compare_func = array_data_compare; - BG(user_compare_func_name) = args[arr_argc]; - } else if (data_compare_type == DIFF_COMP_DATA_USER - && - key_compare_type == DIFF_COMP_KEY_USER) { + req_args = 3; + param_spec = "+f"; + diff_key_compare_func = php_array_user_key_compare; + diff_data_compare_func = php_array_data_compare; + fci_key = &fci1; + fci_key_cache = &fci1_cache; + } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_USER) { /* array_udiff_uassoc() */ - - if (argc < 4) { - efree(args); - WRONG_PARAM_COUNT; - } - arr_argc = argc - 2; - if (!zend_is_callable(*args[arr_argc], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - if (!zend_is_callable(*args[arr_argc + 1], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback %s", callback_name); - efree(callback_name); - efree(args); - return; - } - efree(callback_name); - diff_key_compare_func = array_user_key_compare; - diff_data_compare_func = array_user_compare; - BG(user_compare_func_name) = args[arr_argc + 1];/* data - key*/ + req_args = 4; + param_spec = "+ff"; + diff_key_compare_func = php_array_user_key_compare; + diff_data_compare_func = php_array_user_compare; + fci_data = &fci1; + fci_data_cache = &fci1_cache; + fci_key = &fci2; + fci_key_cache = &fci2_cache; } else { - efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type); - return; - } + return; + } + + if (ZEND_NUM_ARGS() < req_args) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); + return; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) { + return; + } + } else { - efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior); - return; + return; } - + PHP_ARRAY_CMP_FUNC_BACKUP(); + /* for each argument, create and sort list with pointers to the hash buckets */ lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0); ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0); - set_compare_func(SORT_STRING TSRMLS_CC); + php_set_compare_func(PHP_SORT_STRING TSRMLS_CC); + + if (behavior == DIFF_NORMAL && data_compare_type == DIFF_COMP_DATA_USER) { + BG(user_compare_fci) = *fci_data; + BG(user_compare_fci_cache) = *fci_data_cache; + } else if (behavior & DIFF_ASSOC && key_compare_type == DIFF_COMP_KEY_USER) { + BG(user_compare_fci) = *fci_key; + BG(user_compare_fci_cache) = *fci_key_cache; + } + for (i = 0; i < arr_argc; i++) { if (Z_TYPE_PP(args[i]) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1); - arr_argc = i; /* only free up to i-1 */ + arr_argc = i; /* only free up to i - 1 */ goto out; } hash = HASH_OF(*args[i]); list = (Bucket **) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket *), hash->persistent); if (!list) { - efree(args); + PHP_ARRAY_CMP_FUNC_RESTORE(); + efree(ptrs); efree(lists); + efree(args); RETURN_FALSE; } lists[i] = list; @@ -3668,21 +3356,17 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ ALLOC_HASHTABLE(ht); zend_hash_init(ht, zend_hash_num_elements(return_value->value.ht), NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(ht, return_value->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - return_value->value.ht = ht; + return_value->value.ht = ht; } - if (behavior == DIFF_NORMAL && data_compare_type == DIFF_COMP_DATA_USER) { - /* array_udiff() */ - BG(user_compare_func_name) = args[arr_argc]; - } - /* go through the lists and look for values of ptr[0] that are not in the others */ while (*ptrs[0]) { if ((behavior & DIFF_ASSOC) /* triggered also when DIFF_KEY */ - && - key_compare_type == DIFF_COMP_KEY_USER) { - - BG(user_compare_func_name) = args[argc - 1]; + && + key_compare_type == DIFF_COMP_KEY_USER + ) { + BG(user_compare_fci) = *fci_key; + BG(user_compare_fci_cache) = *fci_key_cache; } c = 1; for (i = 1; i < arr_argc; i++) { @@ -3702,35 +3386,31 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ } break; } else if (behavior == DIFF_ASSOC) { /* only when DIFF_ASSOC */ - /* - In this branch is execute only when DIFF_ASSOC. If behavior == DIFF_KEY - data comparison is not needed - skipped. - */ + /* In this branch is execute only when DIFF_ASSOC. If behavior == DIFF_KEY + * data comparison is not needed - skipped. */ if (*ptrs[i]) { if (data_compare_type == DIFF_COMP_DATA_USER) { - BG(user_compare_func_name) = args[arr_argc]; + BG(user_compare_fci) = *fci_data; + BG(user_compare_fci_cache) = *fci_data_cache; } if (diff_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC) != 0) { /* the data is not the same */ c = -1; if (key_compare_type == DIFF_COMP_KEY_USER) { - BG(user_compare_func_name) = args[argc - 1]; + BG(user_compare_fci) = *fci_key; + BG(user_compare_fci_cache) = *fci_key_cache; } } else { break; - /* - we have found the element in other arrays thus we don't want it - in the return_value -> delete from there - */ + /* we have found the element in other arrays thus we don't want it + * in the return_value -> delete from there */ } } } else if (behavior == DIFF_KEY) { /* only when DIFF_KEY */ - /* - the behavior here differs from INTERSECT_KEY in php_intersect - since in the "diff" case we have to remove the entry from - return_value while when doing intersection the entry must not - be deleted. - */ + /* the behavior here differs from INTERSECT_KEY in php_intersect + * since in the "diff" case we have to remove the entry from + * return_value while when doing intersection the entry must not + * be deleted. */ break; /* remove the key */ } } @@ -3740,10 +3420,10 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ /* delete all entries with value as ptrs[0] */ for (;;) { p = *ptrs[0]; - if (p->nKeyLength) { - zend_hash_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength); - } else { + if (p->nKeyLength == 0) { zend_hash_index_del(Z_ARRVAL_P(return_value), p->h); + } else { + zend_hash_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength); } if (!*++ptrs[0]) { goto out; @@ -3765,7 +3445,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ goto out; } if (behavior == DIFF_NORMAL) { - if (diff_data_compare_func(ptrs[0]-1, ptrs[0] TSRMLS_CC)) { + if (diff_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) { break; } } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */ @@ -3783,7 +3463,6 @@ out: PHP_ARRAY_CMP_FUNC_RESTORE(); - efree(ptrs); efree(lists); efree(args); @@ -3802,8 +3481,7 @@ PHP_FUNCTION(array_diff_key) Returns the entries of arr1 that have keys which are not present in any of the others arguments. User supplied function is used for comparing the keys. This function is like array_udiff() but works on the keys instead of the values. The associativity is preserved. */ PHP_FUNCTION(array_diff_ukey) { - php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_KEY, - DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER); + php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_KEY, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER); } /* }}} */ @@ -3811,8 +3489,7 @@ PHP_FUNCTION(array_diff_ukey) Returns the entries of arr1 that have values which are not present in any of the others arguments. */ PHP_FUNCTION(array_diff) { - php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, - DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_INTERNAL); + php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_INTERNAL); } /* }}} */ @@ -3820,8 +3497,7 @@ PHP_FUNCTION(array_diff) Returns the entries of arr1 that have values which are not present in any of the others arguments. Elements are compared by user supplied function. */ PHP_FUNCTION(array_udiff) { - php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, - DIFF_COMP_DATA_USER, DIFF_COMP_KEY_INTERNAL); + php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, DIFF_COMP_DATA_USER, DIFF_COMP_KEY_INTERNAL); } /* }}} */ @@ -3837,8 +3513,7 @@ PHP_FUNCTION(array_diff_assoc) Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Elements are compared by user supplied function. */ PHP_FUNCTION(array_diff_uassoc) { - php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, - DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER); + php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER); } /* }}} */ @@ -3854,8 +3529,7 @@ PHP_FUNCTION(array_udiff_assoc) Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Keys and elements are compared by user supplied functions. */ PHP_FUNCTION(array_udiff_uassoc) { - php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, - DIFF_COMP_DATA_USER, DIFF_COMP_KEY_USER); + php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_USER, DIFF_COMP_KEY_USER); } /* }}} */ @@ -3863,17 +3537,17 @@ PHP_FUNCTION(array_udiff_uassoc) #define MULTISORT_TYPE 1 #define MULTISORT_LAST 2 -int multisort_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ +PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */ { Bucket **ab = *(Bucket ***)a; Bucket **bb = *(Bucket ***)b; - int r; - int result = 0; - zval temp; - + int r; + int result = 0; + zval temp; + r = 0; do { - set_compare_func(ARRAYG(multisort_flags)[MULTISORT_TYPE][r] TSRMLS_CC); + php_set_compare_func(ARRAYG(multisort_flags)[MULTISORT_TYPE][r] TSRMLS_CC); ARRAYG(compare_func)(&temp, *((zval **)ab[r]->pData), *((zval **)bb[r]->pData) TSRMLS_CC); result = ARRAYG(multisort_flags)[MULTISORT_ORDER][r] * Z_LVAL(temp); @@ -3906,17 +3580,17 @@ PHP_FUNCTION(array_multisort) int argc; int array_size; int num_arrays = 0; - int parse_state[MULTISORT_LAST]; /* 0 - flag not allowed 1 - flag allowed */ - int sort_order = SORT_ASC; - int sort_type = SORT_REGULAR; + int parse_state[MULTISORT_LAST]; /* 0 - flag not allowed 1 - flag allowed */ + int sort_order = PHP_SORT_ASC; + int sort_type = PHP_SORT_REGULAR; int i, k; - + /* Get the argument count and check it */ argc = ZEND_NUM_ARGS(); if (argc < 1) { WRONG_PARAM_COUNT; } - + /* Allocate arguments array and get the arguments, checking for errors. */ args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (zend_get_parameters_array_ex(argc, args) == FAILURE) { @@ -3925,7 +3599,7 @@ PHP_FUNCTION(array_multisort) } /* Allocate space for storing pointers to input arrays and sort flags. */ - arrays = (zval ***)ecalloc(argc, sizeof(zval **)); + arrays = (zval ***)ecalloc(argc, sizeof(zval **)); for (i = 0; i < MULTISORT_LAST; i++) { parse_state[i] = 0; ARRAYG(multisort_flags)[i] = (int *)ecalloc(argc, sizeof(int)); @@ -3933,19 +3607,18 @@ PHP_FUNCTION(array_multisort) /* Here we go through the input arguments and parse them. Each one can * be either an array or a sort flag which follows an array. If not - * specified, the sort flags defaults to SORT_ASC and SORT_REGULAR + * specified, the sort flags defaults to PHP_SORT_ASC and PHP_SORT_REGULAR * accordingly. There can't be two sort flags of the same type after an - * array, and the very first argument has to be an array. - */ + * array, and the very first argument has to be an array. */ for (i = 0; i < argc; i++) { if (Z_TYPE_PP(args[i]) == IS_ARRAY) { /* We see the next array, so we update the sort flags of - the previous array and reset the sort flags. */ + * the previous array and reset the sort flags. */ if (i > 0) { - ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays-1] = sort_order; - ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays-1] = sort_type; - sort_order = SORT_ASC; - sort_type = SORT_REGULAR; + ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays - 1] = sort_order; + ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays - 1] = sort_type; + sort_order = PHP_SORT_ASC; + sort_type = PHP_SORT_REGULAR; } arrays[num_arrays++] = args[i]; @@ -3955,22 +3628,25 @@ PHP_FUNCTION(array_multisort) } } else if (Z_TYPE_PP(args[i]) == IS_LONG) { switch (Z_LVAL_PP(args[i])) { - case SORT_ASC: - case SORT_DESC: + case PHP_SORT_ASC: + case PHP_SORT_DESC: /* flag allowed here */ if (parse_state[MULTISORT_ORDER] == 1) { /* Save the flag and make sure then next arg is not the current flag. */ - sort_order = Z_LVAL_PP(args[i]) == SORT_DESC ? -1 : 1; + sort_order = Z_LVAL_PP(args[i]) == PHP_SORT_DESC ? -1 : 1; parse_state[MULTISORT_ORDER] = 0; } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i+1); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1); MULTISORT_ABORT; } break; - case SORT_REGULAR: - case SORT_NUMERIC: - case SORT_STRING: + case PHP_SORT_REGULAR: + case PHP_SORT_NUMERIC: + case PHP_SORT_STRING: +#if HAVE_STRCOLL + case PHP_SORT_LOCALE_STRING: +#endif /* flag allowed here */ if (parse_state[MULTISORT_TYPE] == 1) { /* Save the flag and make sure then next arg is not the current flag. */ @@ -3994,9 +3670,9 @@ PHP_FUNCTION(array_multisort) } } /* Take care of the last array sort flags. */ - ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays-1] = sort_order; - ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays-1] = sort_type; - + ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays - 1] = sort_order; + ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays - 1] = sort_type; + /* Make sure the arrays are of the same size. */ array_size = zend_hash_num_elements(Z_ARRVAL_PP(arrays[0])); for (i = 0; i < num_arrays; i++) { @@ -4008,34 +3684,35 @@ PHP_FUNCTION(array_multisort) /* If all arrays are empty or have only one entry, we don't need to do anything. */ if (array_size < 1) { - for (k = 0; k < MULTISORT_LAST; k++) + for (k = 0; k < MULTISORT_LAST; k++) { efree(ARRAYG(multisort_flags)[k]); + } efree(arrays); efree(args); RETURN_TRUE; } - /* Create the indirection array. This array is of size MxN, where + /* Create the indirection array. This array is of size MxN, where * M is the number of entries in each input array and N is the number * of the input arrays + 1. The last column is NULL to indicate the end - * of the row. - */ + * of the row. */ indirect = (Bucket ***)safe_emalloc(array_size, sizeof(Bucket **), 0); - for (i = 0; i < array_size; i++) - indirect[i] = (Bucket **)safe_emalloc((num_arrays+1), sizeof(Bucket *), 0); - + for (i = 0; i < array_size; i++) { + indirect[i] = (Bucket **)safe_emalloc((num_arrays + 1), sizeof(Bucket *), 0); + } for (i = 0; i < num_arrays; i++) { k = 0; for (p = Z_ARRVAL_PP(arrays[i])->pListHead; p; p = p->pListNext, k++) { indirect[k][i] = p; } } - for (k = 0; k < array_size; k++) + for (k = 0; k < array_size; k++) { indirect[k][num_arrays] = NULL; + } /* Do the actual sort magic - bada-bim, bada-boom. */ - zend_qsort(indirect, array_size, sizeof(Bucket **), multisort_compare TSRMLS_CC); - + zend_qsort(indirect, array_size, sizeof(Bucket **), php_multisort_compare TSRMLS_CC); + /* Restructure the arrays based on sorted indirect - this is mostly taken from zend_hash_sort() function. */ HANDLE_BLOCK_INTERRUPTIONS(); for (i = 0; i < num_arrays; i++) { @@ -4052,7 +3729,7 @@ PHP_FUNCTION(array_multisort) indirect[k][i]->pListNext = NULL; hash->pListTail = indirect[k][i]; } - + p = hash->pListHead; k = 0; while (p != NULL) { @@ -4064,13 +3741,15 @@ PHP_FUNCTION(array_multisort) zend_hash_rehash(hash); } HANDLE_UNBLOCK_INTERRUPTIONS(); - - /* Clean up. */ - for (i = 0; i < array_size; i++) + + /* Clean up. */ + for (i = 0; i < array_size; i++) { efree(indirect[i]); + } efree(indirect); - for (k = 0; k < MULTISORT_LAST; k++) + for (k = 0; k < MULTISORT_LAST; k++) { efree(ARRAYG(multisort_flags)[k]); + } efree(arrays); efree(args); RETURN_TRUE; @@ -4081,70 +3760,62 @@ PHP_FUNCTION(array_multisort) Return key/keys for random entry/entries in the array */ PHP_FUNCTION(array_rand) { - zval **input, **num_req; - long randval; - int num_req_val, num_avail, key_type; + zval *input; + long randval, num_req = 1; + int num_avail, key_type; char *string_key; uint string_key_len; ulong num_key; HashPosition pos; - if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || - zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &num_req) == FAILURE) { - WRONG_PARAM_COUNT; - } - - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argument has to be an array"); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &input, &num_req) == FAILURE) { return; } - num_avail = zend_hash_num_elements(Z_ARRVAL_PP(input)); + num_avail = zend_hash_num_elements(Z_ARRVAL_P(input)); if (ZEND_NUM_ARGS() > 1) { - convert_to_long_ex(num_req); - num_req_val = Z_LVAL_PP(num_req); - if (num_req_val <= 0 || num_req_val > num_avail) { + if (num_req <= 0 || num_req > num_avail) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second argument has to be between 1 and the number of elements in the array"); return; } - } else - num_req_val = 1; + } /* Make the return value an array only if we need to pass back more than one result. */ - if (num_req_val > 1) { + if (num_req > 1) { array_init(return_value); } /* We can't use zend_hash_index_find() because the array may have string keys or gaps. */ - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos); - while (num_req_val && (key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(input), &string_key, &string_key_len, &num_key, 0, &pos)) != HASH_KEY_NON_EXISTANT) { + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos); + while (num_req && (key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &pos)) != HASH_KEY_NON_EXISTANT) { randval = php_rand(TSRMLS_C); - if ((double)(randval/(PHP_RAND_MAX+1.0)) < (double)num_req_val/(double)num_avail) { + if ((double) (randval / (PHP_RAND_MAX + 1.0)) < (double) num_req / (double) num_avail) { /* If we are returning a single result, just do it. */ if (Z_TYPE_P(return_value) != IS_ARRAY) { if (key_type == HASH_KEY_IS_STRING) { - RETURN_STRINGL(string_key, string_key_len-1, 1); + RETURN_STRINGL(string_key, string_key_len - 1, 1); } else { RETURN_LONG(num_key); } } else { /* Append the result to the return value. */ - if (key_type == HASH_KEY_IS_STRING) - add_next_index_stringl(return_value, string_key, string_key_len-1, 1); - else + if (key_type == HASH_KEY_IS_STRING) { + add_next_index_stringl(return_value, string_key, string_key_len - 1, 1); + } else { add_next_index_long(return_value, num_key); + } } - num_req_val--; + num_req--; } num_avail--; - zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos); + zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos); } - if (num_req_val == num_avail) { - array_data_shuffle(return_value TSRMLS_CC); + if (num_req == num_avail) { + php_array_data_shuffle(return_value TSRMLS_CC); } } /* }}} */ @@ -4153,31 +3824,25 @@ PHP_FUNCTION(array_rand) Returns the sum of the array entries */ PHP_FUNCTION(array_sum) { - zval **input, + zval *input, **entry, entry_n; - int argc = ZEND_NUM_ARGS(); HashPosition pos; double dval; - - if (argc != 1 || zend_get_parameters_ex(argc, &input) == FAILURE) { - WRONG_PARAM_COUNT; - } - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) { return; } ZVAL_LONG(return_value, 0); - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos); - zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &pos) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos)) { - - if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT) + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos) + ) { + if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT) { continue; - + } entry_n = **entry; zval_copy_ctor(&entry_n); convert_scalar_to_number(&entry_n TSRMLS_CC); @@ -4200,34 +3865,28 @@ PHP_FUNCTION(array_sum) Returns the product of the array entries */ PHP_FUNCTION(array_product) { - zval **input, + zval *input, **entry, entry_n; - int argc = ZEND_NUM_ARGS(); HashPosition pos; double dval; - - if (argc != 1 || zend_get_parameters_ex(argc, &input) == FAILURE) { - WRONG_PARAM_COUNT; - } - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) { return; } - - if (!zend_hash_num_elements(Z_ARRVAL_PP(input))) { + + if (!zend_hash_num_elements(Z_ARRVAL_P(input))) { RETURN_LONG(0); } ZVAL_LONG(return_value, 1); - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos); - zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &pos) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos)) { - - if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT) + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos) + ) { + if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT) { continue; - + } entry_n = **entry; zval_copy_ctor(&entry_n); convert_scalar_to_number(&entry_n TSRMLS_CC); @@ -4250,39 +3909,25 @@ PHP_FUNCTION(array_product) Iteratively reduce the array to a single value via the callback. */ PHP_FUNCTION(array_reduce) { - zval **input, **callback, **initial; + zval *input; zval **args[2]; zval **operand; zval *result = NULL; zval *retval; + zend_fcall_info fci; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; - char *callback_name; + long initial; HashPosition pos; HashTable *htbl; - - if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3 || - zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &callback, &initial) == FAILURE) { - WRONG_PARAM_COUNT; - } - - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be an array"); - return; - } - if (!zend_is_callable(*callback, 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument, '%s', should be a valid callback", callback_name); - efree(callback_name); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af|l", &input, &fci, &fci_cache, &initial) == FAILURE) { return; } - efree(callback_name); if (ZEND_NUM_ARGS() > 2) { ALLOC_ZVAL(result); - *result = **initial; - zval_copy_ctor(result); - convert_to_long(result); INIT_PZVAL(result); + ZVAL_LONG(result, initial); } else { MAKE_STD_ZVAL(result); ZVAL_NULL(result); @@ -4291,9 +3936,8 @@ PHP_FUNCTION(array_reduce) /* (zval **)input points to an element of argument stack * the base pointer of which is subject to change. * thus we need to keep the pointer to the hashtable for safety */ + htbl = Z_ARRVAL_P(input); - htbl = Z_ARRVAL_PP(input); - if (zend_hash_num_elements(htbl) == 0) { if (result) { RETVAL_ZVAL(result, 1, 1); @@ -4301,21 +3945,17 @@ PHP_FUNCTION(array_reduce) return; } + fci.retval_ptr_ptr = &retval; + fci.param_count = 2; + fci.no_separation = 0; + zend_hash_internal_pointer_reset_ex(htbl, &pos); while (zend_hash_get_current_data_ex(htbl, (void **)&operand, &pos) == SUCCESS) { + if (result) { - zend_fcall_info fci; args[0] = &result; args[1] = operand; - fci.size = sizeof(fci); - fci.function_table = EG(function_table); - fci.function_name = *callback; - fci.symbol_table = NULL; - fci.object_pp = NULL; - fci.retval_ptr_ptr = &retval; - fci.param_count = 2; fci.params = args; - fci.no_separation = 0; if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) { zval_ptr_dtor(&result); @@ -4328,10 +3968,8 @@ PHP_FUNCTION(array_reduce) result = *operand; zval_add_ref(&result); } - zend_hash_move_forward_ex(htbl, &pos); } - RETVAL_ZVAL(result, 1, 1); } /* }}} */ @@ -4340,62 +3978,41 @@ PHP_FUNCTION(array_reduce) Filters elements from the array via the callback. */ PHP_FUNCTION(array_filter) { - zval **input, **callback = NULL; - zval *array, *func = NULL; + zval *array; zval **operand; zval **args[1]; zval *retval = NULL; - char *callback_name; + zend_bool have_callback = 0; char *string_key; + zend_fcall_info fci; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; uint string_key_len; ulong num_key; HashPosition pos; - - if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || - zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &callback) == FAILURE) { - WRONG_PARAM_COUNT; - } - if (Z_TYPE_PP(input) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be an array"); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|f", &array, &fci, &fci_cache) == FAILURE) { return; } - array = *input; - - if (ZEND_NUM_ARGS() > 1) { - func = *callback; - if (!zend_is_callable(func, 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument, '%s', should be a valid callback", callback_name); - efree(callback_name); - return; - } - efree(callback_name); - } array_init(return_value); if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) { return; } - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); - zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&operand, &pos) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)) { - - if (func) { - zend_fcall_info fci; + if (ZEND_NUM_ARGS() > 1) { + have_callback = 1; + fci.no_separation = 0; + fci.retval_ptr_ptr = &retval; + fci.param_count = 1; + } + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&operand, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos) + ) { + if (have_callback) { args[0] = operand; - - fci.size = sizeof(fci); - fci.function_table = EG(function_table); - fci.function_name = func; - fci.symbol_table = NULL; - fci.object_pp = NULL; - fci.retval_ptr_ptr = &retval; - fci.param_count = 1; fci.params = args; - fci.no_separation = 0; if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) { if (!zend_is_true(retval)) { @@ -4430,68 +4047,50 @@ PHP_FUNCTION(array_filter) Applies the callback to the elements in given arrays. */ PHP_FUNCTION(array_map) { - zval ***pargs = NULL; + zval ***arrays = NULL; + int n_arrays = 0; zval ***params; - zval *callback; zval *result, *null; HashPosition *array_pos; zval **args; - char *callback_name; + zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; int i, k, maxlen = 0; int *array_len; - if (ZEND_NUM_ARGS() < 2) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f!+", &fci, &fci_cache, &arrays, &n_arrays) == FAILURE) { + return; } RETVAL_NULL(); - pargs = (zval ***)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval **), 0); - if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), pargs) == FAILURE) { - efree(pargs); - WRONG_PARAM_COUNT; - } - - callback = *pargs[0]; + args = (zval **)safe_emalloc(n_arrays, sizeof(zval *), 0); + array_len = (int *)safe_emalloc(n_arrays, sizeof(int), 0); + array_pos = (HashPosition *)safe_emalloc(n_arrays, sizeof(HashPosition), 0); - if (Z_TYPE_P(callback) != IS_NULL) { - if (!zend_is_callable(callback, 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument, '%s', should be either NULL or a valid callback", callback_name); - efree(callback_name); - efree(pargs); - return; - } - efree(callback_name); - } - - args = (zval **)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval *), 0); - array_len = (int *)safe_emalloc(ZEND_NUM_ARGS(), sizeof(int), 0); - array_pos = (HashPosition *)safe_emalloc(ZEND_NUM_ARGS(), sizeof(HashPosition), 0); - - for (i = 1; i < ZEND_NUM_ARGS(); i++) { - if (Z_TYPE_PP(pargs[i]) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d should be an array", i + 1); - efree(pargs); + for (i = 0; i < n_arrays; i++) { + if (Z_TYPE_PP(arrays[i]) != IS_ARRAY) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d should be an array", i + 2); + efree(arrays); efree(args); efree(array_len); efree(array_pos); return; } - SEPARATE_ZVAL_IF_NOT_REF(pargs[i]); - args[i] = *pargs[i]; - array_len[i] = zend_hash_num_elements(Z_ARRVAL_PP(pargs[i])); + SEPARATE_ZVAL_IF_NOT_REF(arrays[i]); + args[i] = *arrays[i]; + array_len[i] = zend_hash_num_elements(Z_ARRVAL_PP(arrays[i])); if (array_len[i] > maxlen) { maxlen = array_len[i]; } - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(pargs[i]), &array_pos[i]); + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arrays[i]), &array_pos[i]); } - efree(pargs); + efree(arrays); /* Short-circuit: if no callback and only one array, just return it. */ - if (Z_TYPE_P(callback) == IS_NULL && ZEND_NUM_ARGS() == 2) { - RETVAL_ZVAL(args[1], 1, 0); + if (!ZEND_FCI_INITIALIZED(fci) && n_arrays == 1) { + RETVAL_ZVAL(args[0], 1, 0); efree(array_len); efree(array_pos); efree(args); @@ -4499,7 +4098,7 @@ PHP_FUNCTION(array_map) } array_init(return_value); - params = (zval ***)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval **), 0); + params = (zval ***)safe_emalloc(n_arrays, sizeof(zval **), 0); MAKE_STD_ZVAL(null); ZVAL_NULL(null); @@ -4510,53 +4109,39 @@ PHP_FUNCTION(array_map) char *str_key; int key_type = 0; - /* - * If no callback, the result will be an array, consisting of current - * entries from all arrays. - */ - if (Z_TYPE_P(callback) == IS_NULL) { + /* If no callback, the result will be an array, consisting of current + * entries from all arrays. */ + if (!ZEND_FCI_INITIALIZED(fci)) { MAKE_STD_ZVAL(result); array_init(result); } - for (i = 1; i < ZEND_NUM_ARGS(); i++) { - /* - * If this array still hash elements, add the current one to the - * parameter list, otherwise use null value. - */ + for (i = 0; i < n_arrays; i++) { + /* If this array still has elements, add the current one to the + * parameter list, otherwise use null value. */ if (k < array_len[i]) { zend_hash_get_current_data_ex(Z_ARRVAL_P(args[i]), (void **)¶ms[i], &array_pos[i]); - /* - * It is safe to store only last value of key type, because - * this loop will run just once if there is only 1 array. - */ - if (ZEND_NUM_ARGS() == 2) { - key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(args[1]), &str_key, &str_key_len, &num_key, 0, &array_pos[i]); + /* It is safe to store only last value of key type, because + * this loop will run just once if there is only 1 array. */ + if (n_arrays == 1) { + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(args[0]), &str_key, &str_key_len, &num_key, 0, &array_pos[i]); } - zend_hash_move_forward_ex(Z_ARRVAL_P(args[i]), &array_pos[i]); } else { params[i] = &null; } - if (Z_TYPE_P(callback) == IS_NULL) { + if (!ZEND_FCI_INITIALIZED(fci)) { zval_add_ref(params[i]); add_next_index_zval(result, *params[i]); } } - if (Z_TYPE_P(callback) != IS_NULL) { - zend_fcall_info fci; - - fci.size = sizeof(fci); - fci.function_table = EG(function_table); - fci.function_name = callback; - fci.symbol_table = NULL; - fci.object_pp = NULL; + if (ZEND_FCI_INITIALIZED(fci)) { fci.retval_ptr_ptr = &result; - fci.param_count = ZEND_NUM_ARGS()-1; - fci.params = ¶ms[1]; + fci.param_count = n_arrays; + fci.params = params; fci.no_separation = 0; if (zend_call_function(&fci, &fci_cache TSRMLS_CC) != SUCCESS || !result) { @@ -4571,7 +4156,7 @@ PHP_FUNCTION(array_map) } } - if (ZEND_NUM_ARGS() > 2) { + if (n_arrays > 1) { add_next_index_zval(return_value, result); } else { if (key_type == HASH_KEY_IS_STRING) { @@ -4581,7 +4166,7 @@ PHP_FUNCTION(array_map) } } } - + zval_ptr_dtor(&null); efree(params); efree(array_len); @@ -4594,32 +4179,31 @@ PHP_FUNCTION(array_map) Checks if the given key or index exists in the array */ PHP_FUNCTION(array_key_exists) { - zval **key, /* key to check for */ - **array; /* array to check in */ + zval *key, /* key to check for */ + *array; /* array to check in */ - if (ZEND_NUM_ARGS() != 2 || - zend_get_parameters_ex(ZEND_NUM_ARGS(), &key, &array) == FAILURE) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &key, &array) == FAILURE) { + return; } - if (Z_TYPE_PP(array) != IS_ARRAY && Z_TYPE_PP(array) != IS_OBJECT) { + if (Z_TYPE_P(array) != IS_ARRAY && Z_TYPE_P(array) != IS_OBJECT) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument should be either an array or an object"); RETURN_FALSE; } - switch (Z_TYPE_PP(key)) { + switch (Z_TYPE_P(key)) { case IS_STRING: - if (zend_symtable_exists(HASH_OF(*array), Z_STRVAL_PP(key), Z_STRLEN_PP(key)+1)) { + if (zend_symtable_exists(HASH_OF(array), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1)) { RETURN_TRUE; } RETURN_FALSE; case IS_LONG: - if (zend_hash_index_exists(HASH_OF(*array), Z_LVAL_PP(key))) { + if (zend_hash_index_exists(HASH_OF(array), Z_LVAL_P(key))) { RETURN_TRUE; } RETURN_FALSE; case IS_NULL: - if (zend_hash_exists(HASH_OF(*array), "", 1)) { + if (zend_hash_exists(HASH_OF(array), "", 1)) { RETURN_TRUE; } RETURN_FALSE; @@ -4628,7 +4212,6 @@ PHP_FUNCTION(array_key_exists) php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be either a string or an integer"); RETURN_FALSE; } - } /* }}} */ @@ -4670,21 +4253,21 @@ PHP_FUNCTION(array_chunk) zval_add_ref(entry); if (preserve_keys) { - key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &str_key, - &str_key_len, &num_key, 0, &pos); - if (key_type == HASH_KEY_IS_STRING) { - add_assoc_zval_ex(chunk, str_key, str_key_len, *entry); - } else { - add_index_zval(chunk, num_key, *entry); + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &str_key, &str_key_len, &num_key, 0, &pos); + switch (key_type) { + case HASH_KEY_IS_STRING: + add_assoc_zval_ex(chunk, str_key, str_key_len, *entry); + break; + default: + add_index_zval(chunk, num_key, *entry); + break; } } else { add_next_index_zval(chunk, *entry); } - /* - * If reached the chunk size, add it to the result array, and reset the - * pointer. - */ + /* If reached the chunk size, add it to the result array, and reset the + * pointer. */ if (!(++current % size)) { add_next_index_zval(return_value, chunk); chunk = NULL; @@ -4707,45 +4290,53 @@ PHP_FUNCTION(array_combine) zval *values, *keys; HashPosition pos_values, pos_keys; zval **entry_keys, **entry_values; - + int num_keys, num_values; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &keys, &values) == FAILURE) { return; } - if (zend_hash_num_elements(Z_ARRVAL_P(keys)) != zend_hash_num_elements(Z_ARRVAL_P(values))) { + num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys)); + num_values = zend_hash_num_elements(Z_ARRVAL_P(values)); + + if (num_keys != num_values) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have an equal number of elements"); RETURN_FALSE; } - if (!zend_hash_num_elements(Z_ARRVAL_P(keys))) { + if (!num_keys) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have at least 1 element"); RETURN_FALSE; } array_init(return_value); - + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos_keys); zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos_values); while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&entry_keys, &pos_keys) == SUCCESS && - zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&entry_values, &pos_values) == SUCCESS) { - if (Z_TYPE_PP(entry_keys) == IS_STRING) { - zval_add_ref(entry_values); - add_assoc_zval_ex(return_value, Z_STRVAL_PP(entry_keys), Z_STRLEN_PP(entry_keys)+1, *entry_values); - } else if (Z_TYPE_PP(entry_keys) == IS_LONG) { + zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&entry_values, &pos_values) == SUCCESS + ) { + if (Z_TYPE_PP(entry_keys) == IS_LONG) { zval_add_ref(entry_values); add_index_zval(return_value, Z_LVAL_PP(entry_keys), *entry_values); } else { - zval key; + zval key, *key_ptr = *entry_keys; - key = **entry_keys; - zval_copy_ctor(&key); - convert_to_string(&key); + if (Z_TYPE_PP(entry_keys) != IS_STRING) { + key = **entry_keys; + zval_copy_ctor(&key); + convert_to_string(&key); + key_ptr = &key; + } zval_add_ref(entry_values); - add_assoc_zval_ex(return_value, Z_STRVAL(key), Z_STRLEN(key)+1, *entry_values); + add_assoc_zval_ex(return_value, Z_STRVAL_P(key_ptr), Z_STRLEN_P(key_ptr) + 1, *entry_values); - zval_dtor(&key); + if (key_ptr != *entry_keys) { + zval_dtor(&key); + } } + zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos_keys); zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos_values); } diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 81e1208f56..516f0c2492 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -53,7 +53,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; #include <time.h> #include <stdio.h> -#ifndef PHP_WIN32 +#ifndef PHP_WIN32 #include <sys/types.h> #include <sys/stat.h> #endif @@ -789,7 +789,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_call_user_func, 0, 0, 1) ZEND_END_ARG_INFO() static -ZEND_BEGIN_ARG_INFO(arginfo_call_user_func_array, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_call_user_func_array, 0, 0, 2) ZEND_ARG_INFO(0, function_name) ZEND_ARG_INFO(0, parameters) /* ARRAY_INFO(0, parameters, 1) */ ZEND_END_ARG_INFO() @@ -3858,7 +3858,6 @@ static void basic_globals_ctor(php_basic_globals *basic_globals_p TSRMLS_DC) /* BG(left) = -1; BG(user_tick_functions) = NULL; BG(user_filter_map) = NULL; - BG(user_compare_fci_cache) = empty_fcall_info_cache; zend_hash_init(&BG(sm_protected_env_vars), 5, NULL, NULL, 1); BG(sm_allowed_env_vars) = NULL; @@ -4088,8 +4087,10 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */ BG(strtok_string) = NULL; BG(strtok_zval) = NULL; BG(locale_string) = NULL; - BG(user_compare_func_name) = NULL; - BG(array_walk_func_name) = NULL; + BG(array_walk_fci) = empty_fcall_info; + BG(array_walk_fci_cache) = empty_fcall_info_cache; + BG(user_compare_fci) = empty_fcall_info; + BG(user_compare_fci_cache) = empty_fcall_info_cache; BG(page_uid) = -1; BG(page_gid) = -1; BG(page_inode) = -1; @@ -4107,7 +4108,7 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */ #endif PHP_RINIT(dir)(INIT_FUNC_ARGS_PASSTHRU); PHP_RINIT(url_scanner_ex)(INIT_FUNC_ARGS_PASSTHRU); - + /* Reset magic_quotes_runtime */ PG(magic_quotes_runtime) = INI_BOOL("magic_quotes_runtime"); @@ -4439,11 +4440,11 @@ PHP_FUNCTION(putenv) if (!p) { /* no '=' means we want to unset it */ unsetenv(pe.putenv_string); } - if (!p || putenv(pe.putenv_string) == 0) { /* success */ + if (!p || putenv(pe.putenv_string) == 0) { /* success */ #else - if (putenv(pe.putenv_string) == 0) { /* success */ + if (putenv(pe.putenv_string) == 0) { /* success */ #endif - zend_hash_add(&BG(putenv_ht), pe.key, pe.key_len+1, (void **) &pe, sizeof(putenv_entry), NULL); + zend_hash_add(&BG(putenv_ht), pe.key, pe.key_len + 1, (void **) &pe, sizeof(putenv_entry), NULL); #ifdef HAVE_TZSET if (!strncmp(pe.key, "TZ", pe.key_len)) { tzset(); @@ -4607,12 +4608,12 @@ PHP_FUNCTION(getopt) opts->need_param = 0; opts->opt_name = estrdup(Z_STRVAL_PP(arg)); len = strlen(opts->opt_name); - if ((len > 0) && (opts->opt_name[len-1] == ':')) { + if ((len > 0) && (opts->opt_name[len - 1] == ':')) { opts->need_param++; - opts->opt_name[len-1] = '\0'; - if ((len > 1) && (opts->opt_name[len-2] == ':')) { + opts->opt_name[len - 1] = '\0'; + if ((len > 1) && (opts->opt_name[len - 2] == ':')) { opts->need_param++; - opts->opt_name[len-2] = '\0'; + opts->opt_name[len - 2] = '\0'; } } opts->opt_char = 0; @@ -4670,7 +4671,7 @@ PHP_FUNCTION(getopt) if (Z_TYPE_PP(args) != IS_ARRAY) { convert_to_array_ex(args); } - zend_hash_next_index_insert(HASH_OF(*args), (void *)&val, sizeof(zval *), NULL); + zend_hash_next_index_insert(HASH_OF(*args), (void *)&val, sizeof(zval *), NULL); } else { zend_hash_index_update(HASH_OF(return_value), optname_int, &val, sizeof(zval *), NULL); } @@ -4680,7 +4681,7 @@ PHP_FUNCTION(getopt) if (Z_TYPE_PP(args) != IS_ARRAY) { convert_to_array_ex(args); } - zend_hash_next_index_insert(HASH_OF(*args), (void *)&val, sizeof(zval *), NULL); + zend_hash_next_index_insert(HASH_OF(*args), (void *)&val, sizeof(zval *), NULL); } else { zend_hash_add(HASH_OF(return_value), optname, strlen(optname)+1, (void *)&val, sizeof(zval *), NULL); } @@ -4992,6 +4993,7 @@ PHP_FUNCTION(error_log) if (_php_error_log(opt_err, message, opt, headers TSRMLS_CC) == FAILURE) { RETURN_FALSE; } + RETURN_TRUE; } /* }}} */ @@ -5049,65 +5051,27 @@ PHP_FUNCTION(error_get_last) } /* }}} */ -/* {{{ proto mixed call_user_func(string function_name [, mixed parmeter] [, mixed ...]) +/* {{{ proto mixed call_user_func(mixed function_name [, mixed parmeter] [, mixed ...]) Call a user function which is the first parameter */ PHP_FUNCTION(call_user_func) { - zval ***params; - zval *retval_ptr; - char *name; - int argc = ZEND_NUM_ARGS(); + zval *retval_ptr = NULL; + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; - if (argc < 1) { - WRONG_PARAM_COUNT; - } - - params = safe_emalloc(sizeof(zval **), argc, 0); - - if (zend_get_parameters_array_ex(1, params) == FAILURE) { - efree(params); - RETURN_FALSE; - } - - if (Z_TYPE_PP(params[0]) != IS_STRING && Z_TYPE_PP(params[0]) != IS_ARRAY) { - SEPARATE_ZVAL(params[0]); - convert_to_string_ex(params[0]); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f*", &fci, &fci_cache, &fci.params, &fci.param_count) == FAILURE) { + return; } - if (!zend_is_callable(*params[0], 0, &name)) { - php_error_docref1(NULL TSRMLS_CC, name, E_WARNING, "First argument is expected to be a valid callback"); - efree(name); - efree(params); - RETURN_NULL(); - } + fci.retval_ptr_ptr = &retval_ptr; - if (zend_get_parameters_array_ex(argc, params) == FAILURE) { - efree(params); - RETURN_FALSE; + if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) { + COPY_PZVAL_TO_ZVAL(*return_value, *fci.retval_ptr_ptr); } - if (call_user_function_ex(EG(function_table), NULL, *params[0], &retval_ptr, argc-1, params+1, 0, NULL TSRMLS_CC) == SUCCESS) { - if (retval_ptr) { - COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr); - } - } else { - if (argc > 1) { - SEPARATE_ZVAL(params[1]); - convert_to_string_ex(params[1]); - if (argc > 2) { - SEPARATE_ZVAL(params[2]); - convert_to_string_ex(params[2]); - php_error_docref1(NULL TSRMLS_CC, name, E_WARNING, "Unable to call %s(%s,%s)", name, Z_STRVAL_PP(params[1]), Z_STRVAL_PP(params[2])); - } else { - php_error_docref1(NULL TSRMLS_CC, name, E_WARNING, "Unable to call %s(%s)", name, Z_STRVAL_PP(params[1])); - } - } else { - php_error_docref1(NULL TSRMLS_CC, name, E_WARNING, "Unable to call %s()", name); - } + if (fci.params) { + efree(fci.params); } - - efree(name); - efree(params); } /* }}} */ @@ -5115,59 +5079,22 @@ PHP_FUNCTION(call_user_func) Call a user function which is the first parameter with the arguments contained in array */ PHP_FUNCTION(call_user_func_array) { - zval ***func_params, **func, **params; - zval *retval_ptr; - HashTable *func_params_ht; - char *name; - int count; - int current = 0; - - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &func, ¶ms) == FAILURE) { - WRONG_PARAM_COUNT; - } + zval *params, *retval_ptr = NULL; + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; - SEPARATE_ZVAL(params); - convert_to_array_ex(params); - - if (Z_TYPE_PP(func) != IS_STRING && Z_TYPE_PP(func) != IS_ARRAY) { - SEPARATE_ZVAL(func); - convert_to_string_ex(func); - } - - if (!zend_is_callable(*func, 0, &name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argument is expected to be a valid callback, '%s' was given", name); - efree(name); - RETURN_NULL(); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "fa/", &fci, &fci_cache, ¶ms) == FAILURE) { + return; } - func_params_ht = Z_ARRVAL_PP(params); + zend_fcall_info_args(&fci, params TSRMLS_CC); + fci.retval_ptr_ptr = &retval_ptr; - count = zend_hash_num_elements(func_params_ht); - if (count) { - func_params = safe_emalloc(sizeof(zval **), count, 0); - - for (zend_hash_internal_pointer_reset(func_params_ht); - zend_hash_get_current_data(func_params_ht, (void **) &func_params[current]) == SUCCESS; - zend_hash_move_forward(func_params_ht) - ) { - current++; - } - } else { - func_params = NULL; + if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) { + COPY_PZVAL_TO_ZVAL(*return_value, *fci.retval_ptr_ptr); } - if (call_user_function_ex(EG(function_table), NULL, *func, &retval_ptr, count, func_params, 0, NULL TSRMLS_CC) == SUCCESS) { - if (retval_ptr) { - COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr); - } - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s()", name); - } - - efree(name); - if (func_params) { - efree(func_params); - } + zend_fcall_info_args_clear(&fci, 1); } /* }}} */ @@ -5175,32 +5102,29 @@ PHP_FUNCTION(call_user_func_array) Call a user method on a specific object or class */ PHP_FUNCTION(call_user_method) { - zval ***params; + zval ***params = NULL; + int n_params = 0; zval *retval_ptr; - int arg_count = ZEND_NUM_ARGS(); + zval *callback, *object; - if (arg_count < 2) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z*", &callback, &object, ¶ms, &n_params) == FAILURE) { + return; } - params = (zval ***) safe_emalloc(sizeof(zval **), arg_count, 0); - if (zend_get_parameters_array_ex(arg_count, params) == FAILURE) { - efree(params); - RETURN_FALSE; - } - if (Z_TYPE_PP(params[1]) != IS_OBJECT && Z_TYPE_PP(params[1]) != IS_STRING) { + if (Z_TYPE_P(object) != IS_OBJECT && + Z_TYPE_P(object) != IS_STRING + ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second argument is not an object or class name"); efree(params); RETURN_FALSE; } - SEPARATE_ZVAL(params[0]); - convert_to_string(*params[0]); + convert_to_string(callback); - if (call_user_function_ex(EG(function_table), params[1], *params[0], &retval_ptr, arg_count-2, params+2, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) { + if (call_user_function_ex(EG(function_table), &object, callback, &retval_ptr, n_params, params, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) { COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr); } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s()", Z_STRVAL_PP(params[0])); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s()", Z_STRVAL_P(callback)); } efree(params); } @@ -5210,39 +5134,39 @@ PHP_FUNCTION(call_user_method) Call a user method on a specific object or class using a parameter array */ PHP_FUNCTION(call_user_method_array) { - zval **method_name, **obj, **params, ***method_args = NULL, *retval_ptr; + zval *params, ***method_args = NULL, *retval_ptr; + zval *callback, *object; HashTable *params_ar; int num_elems, element = 0; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &method_name, &obj, ¶ms) == FAILURE) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/za/", &callback, &object, ¶ms) == FAILURE) { + return; } - if (Z_TYPE_PP(obj) != IS_OBJECT && Z_TYPE_PP(obj) != IS_STRING) { + if (Z_TYPE_P(object) != IS_OBJECT && + Z_TYPE_P(object) != IS_STRING + ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second argument is not an object or class name"); RETURN_FALSE; } - SEPARATE_ZVAL(method_name); - SEPARATE_ZVAL(params); - convert_to_string_ex(method_name); - convert_to_array_ex(params); + convert_to_string(callback); - params_ar = HASH_OF(*params); + params_ar = HASH_OF(params); num_elems = zend_hash_num_elements(params_ar); method_args = (zval ***) safe_emalloc(sizeof(zval **), num_elems, 0); for (zend_hash_internal_pointer_reset(params_ar); - zend_hash_get_current_data(params_ar, (void **) &(method_args[element])) == SUCCESS; - zend_hash_move_forward(params_ar) - ) { + zend_hash_get_current_data(params_ar, (void **) &(method_args[element])) == SUCCESS; + zend_hash_move_forward(params_ar) + ) { element++; } - - if (call_user_function_ex(EG(function_table), obj, *method_name, &retval_ptr, num_elems, method_args, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) { + + if (call_user_function_ex(EG(function_table), &object, callback, &retval_ptr, num_elems, method_args, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) { COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr); } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s()", Z_STRVAL_PP(method_name)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s()", Z_STRVAL_P(callback)); } efree(method_args); @@ -5274,14 +5198,18 @@ void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* { static int user_shutdown_function_call(php_shutdown_function_entry *shutdown_function_entry TSRMLS_DC) /* {{{ */ { zval retval; - char *function_name = NULL; + char *function_name; if (!zend_is_callable(shutdown_function_entry->arguments[0], 0, &function_name)) { php_error(E_WARNING, "(Registered shutdown functions) Unable to call %s() - function does not exist", function_name); - efree(function_name); + if (function_name) { + efree(function_name); + } return 0; } - efree(function_name); + if (function_name) { + efree(function_name); + } if (call_user_function(EG(function_table), NULL, shutdown_function_entry->arguments[0], @@ -5320,7 +5248,7 @@ static void user_tick_function_call(user_tick_function_entry *tick_fe TSRMLS_DC) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s() - function does not exist", Z_STRVAL_P(function)); } else if ( Z_TYPE_P(function) == IS_ARRAY && zend_hash_index_find(Z_ARRVAL_P(function), 0, (void **) &obj) == SUCCESS - && zend_hash_index_find(Z_ARRVAL_P(function), 1, (void **) &method) == SUCCESS + && zend_hash_index_find(Z_ARRVAL_P(function), 1, (void **) &method) == SUCCESS && Z_TYPE_PP(obj) == IS_OBJECT && Z_TYPE_PP(method) == IS_STRING) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s::%s() - function does not exist", Z_OBJCE_PP(obj)->name, Z_STRVAL_PP(method)); @@ -5328,6 +5256,7 @@ static void user_tick_function_call(user_tick_function_entry *tick_fe TSRMLS_DC) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call tick function"); } } + tick_fe->calling = 0; } } @@ -5539,7 +5468,7 @@ PHP_FUNCTION(highlight_string) zval **expr; zend_syntax_highlighter_ini syntax_highlighter_ini; char *hicompiled_string_description; - zend_bool i = 0; + zend_bool i = 0; int old_error_reporting = EG(error_reporting); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|b", &expr, &i) == FAILURE) { @@ -5666,7 +5595,7 @@ PHP_FUNCTION(ini_get_all) static int php_ini_check_path(char *option_name, int option_len, char *new_option_name, int new_option_len) /* {{{ */ { - if ( option_len != (new_option_len-1) ) { + if (option_len != (new_option_len - 1)) { return 0; } @@ -6036,7 +5965,7 @@ PHP_FUNCTION(unregister_tick_function) /* }}} */ /* {{{ proto bool is_uploaded_file(string path) - Check if file was created by rfc1867 upload */ + Check if file was created by rfc1867 upload */ PHP_FUNCTION(is_uploaded_file) { char *path; @@ -6337,6 +6266,7 @@ PHP_FUNCTION(import_request_variables) for (p = types; p && *p; p++) { switch (*p) { + case 'g': case 'G': zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]), (apply_func_args_t) copy_request_variable, 1, prefix); diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h index 4a800ae6bb..2c5f66d74e 100644 --- a/ext/standard/basic_functions.h +++ b/ext/standard/basic_functions.h @@ -166,8 +166,9 @@ typedef struct _php_basic_globals { char strtok_table[256]; ulong strtok_len; char str_ebuf[40]; - zval **array_walk_func_name; - zval **user_compare_func_name; + zend_fcall_info array_walk_fci; + zend_fcall_info_cache array_walk_fci_cache; + zend_fcall_info user_compare_fci; zend_fcall_info_cache user_compare_fci_cache; zend_llist *user_tick_functions; @@ -180,7 +181,7 @@ typedef struct _php_basic_globals { long page_uid; long page_gid; long page_inode; - long page_mtime; + time_t page_mtime; /* filestat.c && main/streams/streams.c */ char *CurrentStatFile, *CurrentLStatFile; diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 7ccd6e638c..4b1b9da97f 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -100,9 +100,16 @@ PHP_FUNCTION(array_key_exists); PHP_FUNCTION(array_chunk); PHP_FUNCTION(array_combine); -HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **); +PHPAPI HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **); PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC); -int multisort_compare(const void *a, const void *b TSRMLS_DC); +PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC); + +#define PHP_SORT_REGULAR 0 +#define PHP_SORT_NUMERIC 1 +#define PHP_SORT_STRING 2 +#define PHP_SORT_DESC 3 +#define PHP_SORT_ASC 4 +#define PHP_SORT_LOCALE_STRING 5 ZEND_BEGIN_MODULE_GLOBALS(array) int *multisort_flags[2]; diff --git a/ext/standard/var.c b/ext/standard/var.c index 3a99e5e4ad..cf9fd0145d 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -20,9 +20,8 @@ /* $Id$ */ -/* {{{ includes +/* {{{ includes */ - #include <stdio.h> #include <stdlib.h> #include <errno.h> @@ -34,19 +33,16 @@ #include "php_incomplete_class.h" #define COMMON (Z_ISREF_PP(struc) ? "&" : "") - /* }}} */ -/* {{{ php_var_dump */ - -static int php_array_element_dump(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) +static int php_array_element_dump(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { int level; TSRMLS_FETCH(); level = va_arg(args, int); - if (hash_key->nKeyLength==0) { /* numeric key */ + if (hash_key->nKeyLength == 0) { /* numeric key */ php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h); } else { /* string key */ php_printf("%*c[\"", level + 1, ' '); @@ -56,8 +52,9 @@ static int php_array_element_dump(zval **zv, int num_args, va_list args, zend_ha php_var_dump(zv, level + 2 TSRMLS_CC); return 0; } +/* }}} */ -static int php_object_property_dump(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) +static int php_object_property_dump(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { int level; char *prop_name, *class_name; @@ -65,34 +62,33 @@ static int php_object_property_dump(zval **zv, int num_args, va_list args, zend_ level = va_arg(args, int); - if (hash_key->nKeyLength ==0 ) { /* numeric key */ + if (hash_key->nKeyLength == 0) { /* numeric key */ php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h); } else { /* string key */ - int unmangle = zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength-1, &class_name, &prop_name); + int unmangle = zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name); + php_printf("%*c[", level + 1, ' '); + if (class_name && unmangle == SUCCESS) { - php_printf("%*c[\"%s", level + 1, ' ', prop_name); - if (class_name[0]=='*') { - ZEND_PUTS(":protected"); + if (class_name[0] == '*') { + php_printf("\"%s\":protected", prop_name); } else { - ZEND_PUTS(":private"); + php_printf("\"%s\":\"%s\":private", prop_name, class_name); } } else { - php_printf("%*c[\"", level + 1, ' '); + php_printf("\""); PHPWRITE(hash_key->arKey, hash_key->nKeyLength - 1); -#ifdef ANDREY_0 - ZEND_PUTS(":public"); -#endif + php_printf("\""); } - ZEND_PUTS("\"]=>\n"); + ZEND_PUTS("]=>\n"); } php_var_dump(zv, level + 2 TSRMLS_CC); return 0; } +/* }}} */ - -PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC) +PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC) /* {{{ */ { - HashTable *myht = NULL; + HashTable *myht; char *class_name; zend_uint class_name_len; int (*php_element_dump_func)(zval**, int, va_list, zend_hash_key*); @@ -104,7 +100,7 @@ PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC) switch (Z_TYPE_PP(struc)) { case IS_BOOL: - php_printf("%sbool(%s)\n", COMMON, Z_LVAL_PP(struc)?"true":"false"); + php_printf("%sbool(%s)\n", COMMON, Z_LVAL_PP(struc) ? "true" : "false"); break; case IS_NULL: php_printf("%sNULL\n", COMMON); @@ -166,7 +162,6 @@ head_done: break; } } - /* }}} */ /* {{{ proto void var_dump(mixed var) @@ -176,35 +171,33 @@ PHP_FUNCTION(var_dump) zval ***args; int argc; int i; - + argc = ZEND_NUM_ARGS(); - + args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } - - for (i=0; i<argc; i++) + + for (i = 0; i < argc; i++) { php_var_dump(args[i], 1 TSRMLS_CC); - + } efree(args); } /* }}} */ -/* {{{ debug_zval_dump */ - -static int zval_array_element_dump(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) +static int zval_array_element_dump(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { int level; TSRMLS_FETCH(); level = va_arg(args, int); - if (hash_key->nKeyLength==0) { /* numeric key */ + if (hash_key->nKeyLength == 0) { /* numeric key */ php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h); } else { /* string key */ - /* XXX: perphaps when we are inside the class we should permit access to + /* XXX: perphaps when we are inside the class we should permit access to * private & protected values */ if (va_arg(args, int) && hash_key->arKey[0] == '\0') { @@ -217,8 +210,9 @@ static int zval_array_element_dump(zval **zv, int num_args, va_list args, zend_h php_debug_zval_dump(zv, level + 2 TSRMLS_CC); return 0; } +/* }}} */ -static int zval_object_property_dump(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) +static int zval_object_property_dump(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { int level; char *prop_name, *class_name; @@ -226,30 +220,29 @@ static int zval_object_property_dump(zval **zv, int num_args, va_list args, zend level = va_arg(args, int); - if (hash_key->nKeyLength ==0 ) { /* numeric key */ + if (hash_key->nKeyLength == 0) { /* numeric key */ php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h); } else { /* string key */ - zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength-1, &class_name, &prop_name); + zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name); + php_printf("%*c[", level + 1, ' '); + if (class_name) { - php_printf("%*c[\"%s", level + 1, ' ', prop_name); - if (class_name[0]=='*') { - ZEND_PUTS(":protected"); + if (class_name[0] == '*') { + php_printf("\"%s\":protected", prop_name); } else { - ZEND_PUTS(":private"); + php_printf("\"%s\":\"%s\":private", prop_name, class_name); } } else { - php_printf("%*c[\"%s", level + 1, ' ', hash_key->arKey); -#ifdef ANDREY_0 - ZEND_PUTS(":public"); -#endif + php_printf("\"%s\"", prop_name); } - ZEND_PUTS("\"]=>\n"); + ZEND_PUTS("]=>\n"); } php_debug_zval_dump(zv, level + 2 TSRMLS_CC); return 0; } +/* }}} */ -PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC) +PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC) /* {{{ */ { HashTable *myht = NULL; char *class_name; @@ -309,7 +302,7 @@ head_done: } } if (level > 1) { - php_printf("%*c", level-1, ' '); + php_printf("%*c", level - 1, ' '); } PUTS("}\n"); break; @@ -325,7 +318,6 @@ head_done: break; } } - /* }}} */ /* {{{ proto void debug_zval_dump(mixed var) @@ -335,32 +327,30 @@ PHP_FUNCTION(debug_zval_dump) zval ***args; int argc; int i; - + argc = ZEND_NUM_ARGS(); - + args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } - - for (i=0; i<argc; i++) + + for (i = 0; i < argc; i++) { php_debug_zval_dump(args[i], 1 TSRMLS_CC); - + } efree(args); } /* }}} */ -/* {{{ php_var_export */ - -static int php_array_element_export(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) +static int php_array_element_export(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { int level; TSRMLS_FETCH(); level = va_arg(args, int); - if (hash_key->nKeyLength==0) { /* numeric key */ + if (hash_key->nKeyLength == 0) { /* numeric key */ php_printf("%*c%ld => ", level + 1, ' ', hash_key->h); } else { /* string key */ char *key; @@ -375,8 +365,9 @@ static int php_array_element_export(zval **zv, int num_args, va_list args, zend_ PUTS (",\n"); return 0; } +/* }}} */ -static int php_object_element_export(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) +static int php_object_element_export(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { int level; char *prop_name, *class_name; @@ -386,19 +377,20 @@ static int php_object_element_export(zval **zv, int num_args, va_list args, zend if (hash_key->nKeyLength != 0) { php_printf("%*c", level + 1, ' '); - zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength-1, &class_name, &prop_name); + zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name); php_printf(" '%s' => ", prop_name); php_var_export(zv, level + 2 TSRMLS_CC); PUTS (",\n"); } return 0; } +/* }}} */ -PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC) +PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC) /* {{{ */ { HashTable *myht; - char* tmp_str; - int tmp_len; + char* tmp_str; + int tmp_len; char *class_name; zend_uint class_name_len; @@ -455,7 +447,6 @@ PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC) break; } } - /* }}} */ /* {{{ proto mixed var_export(mixed var [, bool return]) @@ -464,15 +455,15 @@ PHP_FUNCTION(var_export) { zval *var; zend_bool return_output = 0; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &var, &return_output) == FAILURE) { return; } - + if (return_output) { php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); } - + php_var_export(&var, 1 TSRMLS_CC); if (return_output) { @@ -482,19 +473,17 @@ PHP_FUNCTION(var_export) } /* }}} */ -/* {{{ php_var_serialize */ - static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var_hash TSRMLS_DC); -static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old TSRMLS_DC) +static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old TSRMLS_DC) /* {{{ */ { ulong var_no; char id[32], *p; register int len; /* relies on "(long)" being a perfect hash function for data pointers, - however the actual identity of an object has had to be determined - by its object handle and the class entry since 5.0. */ + * however the actual identity of an object has had to be determined + * by its object handle and the class entry since 5.0. */ if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_HT_P(var)->get_class_entry) { p = smart_str_print_long(id + sizeof(id) - 1, (((size_t)Z_OBJCE_P(var) << 5) @@ -510,27 +499,29 @@ static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old if (var_old && zend_hash_find(var_hash, p, len, var_old) == SUCCESS) { if (!Z_ISREF_P(var)) { /* we still need to bump up the counter, since non-refs will - be counted separately by unserializer */ + * be counted separately by unserializer */ var_no = -1; zend_hash_next_index_insert(var_hash, &var_no, sizeof(var_no), NULL); } return FAILURE; } - + /* +1 because otherwise hash will think we are trying to store NULL pointer */ var_no = zend_hash_num_elements(var_hash) + 1; zend_hash_add(var_hash, p, len, &var_no, sizeof(var_no), NULL); return SUCCESS; } +/* }}} */ -static inline void php_var_serialize_long(smart_str *buf, long val) +static inline void php_var_serialize_long(smart_str *buf, long val) /* {{{ */ { smart_str_appendl(buf, "i:", 2); smart_str_append_long(buf, val); smart_str_appendc(buf, ';'); } +/* }}} */ -static inline void php_var_serialize_string(smart_str *buf, char *str, int len) +static inline void php_var_serialize_string(smart_str *buf, char *str, int len) /* {{{ */ { smart_str_appendl(buf, "s:", 2); smart_str_append_long(buf, len); @@ -538,8 +529,9 @@ static inline void php_var_serialize_string(smart_str *buf, char *str, int len) smart_str_appendl(buf, str, len); smart_str_appendl(buf, "\";", 2); } +/* }}} */ -static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval *struc TSRMLS_DC) +static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval *struc TSRMLS_DC) /* {{{ */ { PHP_CLASS_ATTRIBUTES; @@ -552,15 +544,16 @@ static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval *struc PHP_CLEANUP_CLASS_ATTRIBUTES(); return incomplete_class; } +/* }}} */ -static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, HashTable *var_hash TSRMLS_DC) +static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, HashTable *var_hash TSRMLS_DC) /* {{{ */ { int count; - zend_bool incomplete_class; + zend_bool incomplete_class; incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC); /* count after serializing name, since php_var_serialize_class_name - changes the count if the variable is incomplete class */ + * changes the count if the variable is incomplete class */ count = zend_hash_num_elements(HASH_OF(retval_ptr)); if (incomplete_class) { --count; @@ -580,31 +573,27 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt nvalp = &nval; zend_hash_internal_pointer_reset_ex(HASH_OF(retval_ptr), &pos); - + for (;; zend_hash_move_forward_ex(HASH_OF(retval_ptr), &pos)) { - i = zend_hash_get_current_key_ex(HASH_OF(retval_ptr), &key, NULL, - &index, 0, &pos); - - if (i == HASH_KEY_NON_EXISTANT) + i = zend_hash_get_current_key_ex(HASH_OF(retval_ptr), &key, NULL, &index, 0, &pos); + + if (i == HASH_KEY_NON_EXISTANT) { break; + } if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) { continue; } - zend_hash_get_current_data_ex(HASH_OF(retval_ptr), - (void **) &name, &pos); + zend_hash_get_current_data_ex(HASH_OF(retval_ptr), (void **) &name, &pos); if (Z_TYPE_PP(name) != IS_STRING) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only " - "containing the names of instance-variables to " - "serialize."); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize."); /* we should still add element even if it's not OK, - since we already wrote the length of the array before */ + * since we already wrote the length of the array before */ smart_str_appendl(buf,"N;", 2); continue; } - if (zend_hash_find(Z_OBJPROP_P(struc), Z_STRVAL_PP(name), - Z_STRLEN_PP(name) + 1, (void *) &d) == SUCCESS) { + if (zend_hash_find(Z_OBJPROP_P(struc), Z_STRVAL_PP(name), Z_STRLEN_PP(name) + 1, (void *) &d) == SUCCESS) { php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC); } else { @@ -613,20 +602,18 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt if (ce) { char *prot_name, *priv_name; int prop_name_length; - + do { - zend_mangle_property_name(&priv_name, &prop_name_length, ce->name, ce->name_length, - Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS); - if (zend_hash_find(Z_OBJPROP_P(struc), priv_name, prop_name_length+1, (void *) &d) == SUCCESS) { + zend_mangle_property_name(&priv_name, &prop_name_length, ce->name, ce->name_length, Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS); + if (zend_hash_find(Z_OBJPROP_P(struc), priv_name, prop_name_length + 1, (void *) &d) == SUCCESS) { php_var_serialize_string(buf, priv_name, prop_name_length); efree(priv_name); php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC); break; } efree(priv_name); - zend_mangle_property_name(&prot_name, &prop_name_length, "*", 1, - Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS); - if (zend_hash_find(Z_OBJPROP_P(struc), prot_name, prop_name_length+1, (void *) &d) == SUCCESS) { + zend_mangle_property_name(&prot_name, &prop_name_length, "*", 1, Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS); + if (zend_hash_find(Z_OBJPROP_P(struc), prot_name, prop_name_length + 1, (void *) &d) == SUCCESS) { php_var_serialize_string(buf, prot_name, prop_name_length); efree(prot_name); php_var_serialize_intern(buf, *d, var_hash TSRMLS_CC); @@ -646,22 +633,21 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt } smart_str_appendc(buf, '}'); } +/* }}} */ - -static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var_hash TSRMLS_DC) +static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var_hash TSRMLS_DC) /* {{{ */ { int i; ulong *var_already; HashTable *myht; - if (var_hash - && php_add_var_hash(var_hash, struc, (void *) &var_already TSRMLS_CC) == FAILURE) { - if(Z_ISREF_P(struc)) { + if (var_hash && php_add_var_hash(var_hash, struc, (void *) &var_already TSRMLS_CC) == FAILURE) { + if (Z_ISREF_P(struc)) { smart_str_appendl(buf, "R:", 2); smart_str_append_long(buf, *var_already); smart_str_appendc(buf, ';'); return; - } else if(Z_TYPE_P(struc) == IS_OBJECT) { + } else if (Z_TYPE_P(struc) == IS_OBJECT) { smart_str_appendl(buf, "r:", 2); smart_str_append_long(buf, *var_already); smart_str_appendc(buf, ';'); @@ -706,64 +692,59 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var int res; zend_class_entry *ce = NULL; - if(Z_OBJ_HT_P(struc)->get_class_entry) { + if (Z_OBJ_HT_P(struc)->get_class_entry) { ce = Z_OBJCE_P(struc); - } + } - if(ce && ce->serialize != NULL) { + if (ce && ce->serialize != NULL) { /* has custom handler */ unsigned char *serialized_data = NULL; zend_uint serialized_length; - if(ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash TSRMLS_CC) == SUCCESS) { + if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash TSRMLS_CC) == SUCCESS) { smart_str_appendl(buf, "C:", 2); smart_str_append_long(buf, Z_OBJCE_P(struc)->name_length); smart_str_appendl(buf, ":\"", 2); smart_str_appendl(buf, Z_OBJCE_P(struc)->name, Z_OBJCE_P(struc)->name_length); smart_str_appendl(buf, "\":", 2); - + smart_str_append_long(buf, serialized_length); smart_str_appendl(buf, ":{", 2); smart_str_appendl(buf, serialized_data, serialized_length); - smart_str_appendc(buf, '}'); + smart_str_appendc(buf, '}'); } else { smart_str_appendl(buf, "N;", 2); } - if(serialized_data) { + if (serialized_data) { efree(serialized_data); } return; } - - if (ce && ce != PHP_IC_ENTRY && - zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) { + + if (ce && ce != PHP_IC_ENTRY && zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) { INIT_PZVAL(&fname); ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0); - res = call_user_function_ex(CG(function_table), &struc, &fname, - &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); + res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); if (res == SUCCESS && !EG(exception)) { if (retval_ptr) { if (HASH_OF(retval_ptr)) { - php_var_serialize_class(buf, struc, retval_ptr, - var_hash TSRMLS_CC); + php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC); } else { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only " - "containing the names of instance-variables to " - "serialize."); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize"); /* we should still add element even if it's not OK, - since we already wrote the length of the array before */ + * since we already wrote the length of the array before */ smart_str_appendl(buf,"N;", 2); } - zval_ptr_dtor(&retval_ptr); } - return; + return; } } - - if (retval_ptr) + + if (retval_ptr) { zval_ptr_dtor(&retval_ptr); + } /* fall-through */ } case IS_ARRAY: { @@ -776,7 +757,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var myht = Z_OBJPROP_P(struc); } /* count after serializing name, since php_var_serialize_class_name - changes the count if the variable is incomplete class */ + * changes the count if the variable is incomplete class */ i = myht ? zend_hash_num_elements(myht) : 0; if (i > 0 && incomplete_class) { --i; @@ -789,18 +770,17 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var ulong index; uint key_len; HashPosition pos; - + zend_hash_internal_pointer_reset_ex(myht, &pos); for (;; zend_hash_move_forward_ex(myht, &pos)) { - i = zend_hash_get_current_key_ex(myht, &key, &key_len, - &index, 0, &pos); - if (i == HASH_KEY_NON_EXISTANT) + i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos); + if (i == HASH_KEY_NON_EXISTANT) { break; - + } if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) { continue; - } - + } + switch (i) { case HASH_KEY_IS_LONG: php_var_serialize_long(buf, index); @@ -811,10 +791,9 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var } /* we should still add element even if it's not OK, - since we already wrote the length of the array before */ - if (zend_hash_get_current_data_ex(myht, - (void **) &data, &pos) != SUCCESS - || !data + * since we already wrote the length of the array before */ + if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) != SUCCESS + || !data || data == &struc || (Z_TYPE_PP(data) == IS_ARRAY && Z_ARRVAL_PP(data)->nApplyCount > 1) ) { @@ -836,15 +815,15 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var default: smart_str_appendl(buf, "i:0;", 4); return; - } + } } +/* }}} */ -PHPAPI void php_var_serialize(smart_str *buf, zval **struc, HashTable *var_hash TSRMLS_DC) +PHPAPI void php_var_serialize(smart_str *buf, zval **struc, HashTable *var_hash TSRMLS_DC) /* {{{ */ { php_var_serialize_intern(buf, *struc, var_hash TSRMLS_CC); smart_str_0(buf); } - /* }}} */ /* {{{ proto string serialize(mixed variable) @@ -873,20 +852,17 @@ PHP_FUNCTION(serialize) RETURN_NULL(); } } - /* }}} */ /* {{{ proto mixed unserialize(string variable_representation) Takes a string representation of variable and recreates it */ - - PHP_FUNCTION(unserialize) { - char *buf; + char *buf = NULL; int buf_len; const unsigned char *p; php_unserialize_data_t var_hash; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { RETURN_FALSE; } @@ -895,9 +871,9 @@ PHP_FUNCTION(unserialize) RETURN_FALSE; } - p = (const unsigned char*)buf; + p = (const unsigned char*) buf; PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) { + if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) { PHP_VAR_UNSERIALIZE_DESTROY(var_hash); zval_dtor(return_value); php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); @@ -905,24 +881,23 @@ PHP_FUNCTION(unserialize) } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); } - /* }}} */ /* {{{ proto int memory_get_usage([real_usage]) - Returns the allocated by PHP memory */ + Returns the allocated by PHP memory */ PHP_FUNCTION(memory_get_usage) { zend_bool real_usage = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &real_usage) == FAILURE) { RETURN_FALSE; } - + RETURN_LONG(zend_memory_usage(real_usage TSRMLS_CC)); } /* }}} */ /* {{{ proto int memory_get_peak_usage([real_usage]) - Returns the peak allocated by PHP memory */ + Returns the peak allocated by PHP memory */ PHP_FUNCTION(memory_get_peak_usage) { zend_bool real_usage = 0; |