Back to index

php5  5.3.10
zend_builtin_functions.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | Zend Engine                                                          |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 2.00 of the Zend license,     |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.zend.com/license/2_00.txt.                                |
00011    | If you did not receive a copy of the Zend license and are unable to  |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@zend.com so we can mail you a copy immediately.              |
00014    +----------------------------------------------------------------------+
00015    | Authors: Andi Gutmans <andi@zend.com>                                |
00016    |          Zeev Suraski <zeev@zend.com>                                |
00017    +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: zend_builtin_functions.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include "zend.h"
00023 #include "zend_API.h"
00024 #include "zend_builtin_functions.h"
00025 #include "zend_constants.h"
00026 #include "zend_ini.h"
00027 #include "zend_exceptions.h"
00028 #include "zend_extensions.h"
00029 #include "zend_closures.h"
00030 
00031 #undef ZEND_TEST_EXCEPTIONS
00032 
00033 static ZEND_FUNCTION(zend_version);
00034 static ZEND_FUNCTION(func_num_args);
00035 static ZEND_FUNCTION(func_get_arg);
00036 static ZEND_FUNCTION(func_get_args);
00037 static ZEND_FUNCTION(strlen);
00038 static ZEND_FUNCTION(strcmp);
00039 static ZEND_FUNCTION(strncmp);
00040 static ZEND_FUNCTION(strcasecmp);
00041 static ZEND_FUNCTION(strncasecmp);
00042 static ZEND_FUNCTION(each);
00043 static ZEND_FUNCTION(error_reporting);
00044 static ZEND_FUNCTION(define);
00045 static ZEND_FUNCTION(defined);
00046 static ZEND_FUNCTION(get_class);
00047 static ZEND_FUNCTION(get_called_class);
00048 static ZEND_FUNCTION(get_parent_class);
00049 static ZEND_FUNCTION(method_exists);
00050 static ZEND_FUNCTION(property_exists);
00051 static ZEND_FUNCTION(class_exists);
00052 static ZEND_FUNCTION(interface_exists);
00053 static ZEND_FUNCTION(function_exists);
00054 static ZEND_FUNCTION(class_alias);
00055 #if ZEND_DEBUG
00056 static ZEND_FUNCTION(leak);
00057 #ifdef ZEND_TEST_EXCEPTIONS
00058 static ZEND_FUNCTION(crash);
00059 #endif
00060 #endif
00061 static ZEND_FUNCTION(get_included_files);
00062 static ZEND_FUNCTION(is_subclass_of);
00063 static ZEND_FUNCTION(is_a);
00064 static ZEND_FUNCTION(get_class_vars);
00065 static ZEND_FUNCTION(get_object_vars);
00066 static ZEND_FUNCTION(get_class_methods);
00067 static ZEND_FUNCTION(trigger_error);
00068 static ZEND_FUNCTION(set_error_handler);
00069 static ZEND_FUNCTION(restore_error_handler);
00070 static ZEND_FUNCTION(set_exception_handler);
00071 static ZEND_FUNCTION(restore_exception_handler);
00072 static ZEND_FUNCTION(get_declared_classes);
00073 static ZEND_FUNCTION(get_declared_interfaces);
00074 static ZEND_FUNCTION(get_defined_functions);
00075 static ZEND_FUNCTION(get_defined_vars);
00076 static ZEND_FUNCTION(create_function);
00077 static ZEND_FUNCTION(get_resource_type);
00078 static ZEND_FUNCTION(get_loaded_extensions);
00079 static ZEND_FUNCTION(extension_loaded);
00080 static ZEND_FUNCTION(get_extension_funcs);
00081 static ZEND_FUNCTION(get_defined_constants);
00082 static ZEND_FUNCTION(debug_backtrace);
00083 static ZEND_FUNCTION(debug_print_backtrace);
00084 #if ZEND_DEBUG
00085 static ZEND_FUNCTION(zend_test_func);
00086 #ifdef ZTS
00087 static ZEND_FUNCTION(zend_thread_id);
00088 #endif
00089 #endif
00090 static ZEND_FUNCTION(gc_collect_cycles);
00091 static ZEND_FUNCTION(gc_enabled);
00092 static ZEND_FUNCTION(gc_enable);
00093 static ZEND_FUNCTION(gc_disable);
00094 
00095 /* {{{ arginfo */
00096 ZEND_BEGIN_ARG_INFO(arginfo_zend__void, 0)
00097 ZEND_END_ARG_INFO()
00098 
00099 ZEND_BEGIN_ARG_INFO_EX(arginfo_func_get_arg, 0, 0, 1)
00100        ZEND_ARG_INFO(0, arg_num)
00101 ZEND_END_ARG_INFO()
00102 
00103 ZEND_BEGIN_ARG_INFO_EX(arginfo_strlen, 0, 0, 1)
00104        ZEND_ARG_INFO(0, str)
00105 ZEND_END_ARG_INFO()
00106 
00107 ZEND_BEGIN_ARG_INFO_EX(arginfo_strcmp, 0, 0, 2)
00108        ZEND_ARG_INFO(0, str1)
00109        ZEND_ARG_INFO(0, str2)
00110 ZEND_END_ARG_INFO()
00111 
00112 ZEND_BEGIN_ARG_INFO_EX(arginfo_strncmp, 0, 0, 3)
00113        ZEND_ARG_INFO(0, str1)
00114        ZEND_ARG_INFO(0, str2)
00115        ZEND_ARG_INFO(0, len)
00116 ZEND_END_ARG_INFO()
00117 
00118 ZEND_BEGIN_ARG_INFO_EX(arginfo_each, 0, 0, 1)
00119        ZEND_ARG_INFO(1, arr)
00120 ZEND_END_ARG_INFO()
00121 
00122 ZEND_BEGIN_ARG_INFO_EX(arginfo_error_reporting, 0, 0, 0)
00123        ZEND_ARG_INFO(0, new_error_level)
00124 ZEND_END_ARG_INFO()
00125 
00126 ZEND_BEGIN_ARG_INFO_EX(arginfo_define, 0, 0, 3)
00127        ZEND_ARG_INFO(0, constant_name)
00128        ZEND_ARG_INFO(0, value)
00129        ZEND_ARG_INFO(0, case_insensitive)
00130 ZEND_END_ARG_INFO()
00131 
00132 ZEND_BEGIN_ARG_INFO_EX(arginfo_defined, 0, 0, 1)
00133        ZEND_ARG_INFO(0, constant_name)
00134 ZEND_END_ARG_INFO()
00135 
00136 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class, 0, 0, 0)
00137        ZEND_ARG_INFO(0, object)
00138 ZEND_END_ARG_INFO()
00139 
00140 ZEND_BEGIN_ARG_INFO_EX(arginfo_is_subclass_of, 0, 0, 2)
00141        ZEND_ARG_INFO(0, object)
00142        ZEND_ARG_INFO(0, class_name)
00143 ZEND_END_ARG_INFO()
00144 
00145 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_vars, 0, 0, 1)
00146        ZEND_ARG_INFO(0, class_name)
00147 ZEND_END_ARG_INFO()
00148 
00149 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_object_vars, 0, 0, 1)
00150        ZEND_ARG_INFO(0, obj)
00151 ZEND_END_ARG_INFO()
00152 
00153 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_methods, 0, 0, 1)
00154        ZEND_ARG_INFO(0, class)
00155 ZEND_END_ARG_INFO()
00156 
00157 ZEND_BEGIN_ARG_INFO_EX(arginfo_method_exists, 0, 0, 2)
00158        ZEND_ARG_INFO(0, object)
00159        ZEND_ARG_INFO(0, method)
00160 ZEND_END_ARG_INFO()
00161 
00162 ZEND_BEGIN_ARG_INFO_EX(arginfo_property_exists, 0, 0, 2)
00163        ZEND_ARG_INFO(0, object_or_class)
00164        ZEND_ARG_INFO(0, property_name)
00165 ZEND_END_ARG_INFO()
00166 
00167 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_exists, 0, 0, 1)
00168        ZEND_ARG_INFO(0, classname)
00169        ZEND_ARG_INFO(0, autoload)
00170 ZEND_END_ARG_INFO()
00171 
00172 ZEND_BEGIN_ARG_INFO_EX(arginfo_function_exists, 0, 0, 1)
00173        ZEND_ARG_INFO(0, function_name)
00174 ZEND_END_ARG_INFO()
00175 
00176 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2)
00177        ZEND_ARG_INFO(0, user_class_name)
00178        ZEND_ARG_INFO(0, alias_name)
00179        ZEND_ARG_INFO(0, autoload)
00180 ZEND_END_ARG_INFO()
00181 
00182 ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1)
00183        ZEND_ARG_INFO(0, message)
00184        ZEND_ARG_INFO(0, error_type)
00185 ZEND_END_ARG_INFO()
00186 
00187 ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1)
00188        ZEND_ARG_INFO(0, error_handler)
00189        ZEND_ARG_INFO(0, error_types)
00190 ZEND_END_ARG_INFO()
00191 
00192 ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1)
00193        ZEND_ARG_INFO(0, exception_handler)
00194 ZEND_END_ARG_INFO()
00195 
00196 ZEND_BEGIN_ARG_INFO_EX(arginfo_create_function, 0, 0, 2)
00197        ZEND_ARG_INFO(0, args)
00198        ZEND_ARG_INFO(0, code)
00199 ZEND_END_ARG_INFO()
00200 
00201 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1)
00202        ZEND_ARG_INFO(0, res)
00203 ZEND_END_ARG_INFO()
00204 
00205 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_loaded_extensions, 0, 0, 0)
00206        ZEND_ARG_INFO(0, zend_extensions)
00207 ZEND_END_ARG_INFO()
00208 
00209 ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0)
00210        ZEND_ARG_INFO(0, categorize)
00211 ZEND_END_ARG_INFO()
00212 
00213 ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0)
00214        ZEND_ARG_INFO(0, options)
00215 ZEND_END_ARG_INFO()
00216 
00217 ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1)
00218        ZEND_ARG_INFO(0, extension_name)
00219 ZEND_END_ARG_INFO()
00220 /* }}} */
00221 
00222 static const zend_function_entry builtin_functions[] = { /* {{{ */
00223        ZEND_FE(zend_version,              arginfo_zend__void)
00224        ZEND_FE(func_num_args,             arginfo_zend__void)
00225        ZEND_FE(func_get_arg,              arginfo_func_get_arg)
00226        ZEND_FE(func_get_args,             arginfo_zend__void)
00227        ZEND_FE(strlen,                           arginfo_strlen)
00228        ZEND_FE(strcmp,                           arginfo_strcmp)
00229        ZEND_FE(strncmp,                   arginfo_strncmp)
00230        ZEND_FE(strcasecmp,                arginfo_strcmp)
00231        ZEND_FE(strncasecmp,        arginfo_strncmp)
00232        ZEND_FE(each,                      arginfo_each)
00233        ZEND_FE(error_reporting,    arginfo_error_reporting)
00234        ZEND_FE(define,                           arginfo_define)
00235        ZEND_FE(defined,                   arginfo_defined)
00236        ZEND_FE(get_class,                 arginfo_get_class)
00237        ZEND_FE(get_called_class,   arginfo_zend__void)
00238        ZEND_FE(get_parent_class,   arginfo_get_class)
00239        ZEND_FE(method_exists,             arginfo_method_exists)
00240        ZEND_FE(property_exists,    arginfo_property_exists)
00241        ZEND_FE(class_exists,              arginfo_class_exists)
00242        ZEND_FE(interface_exists,   arginfo_class_exists)
00243        ZEND_FE(function_exists,    arginfo_function_exists)
00244        ZEND_FE(class_alias,        arginfo_class_alias)
00245 #if ZEND_DEBUG
00246        ZEND_FE(leak,                      NULL)
00247 #ifdef ZEND_TEST_EXCEPTIONS
00248        ZEND_FE(crash,                            NULL)
00249 #endif
00250 #endif
00251        ZEND_FE(get_included_files, arginfo_zend__void)
00252        ZEND_FALIAS(get_required_files,    get_included_files,         arginfo_zend__void)
00253        ZEND_FE(is_subclass_of,            arginfo_is_subclass_of)
00254        ZEND_FE(is_a,                      arginfo_is_subclass_of)
00255        ZEND_FE(get_class_vars,            arginfo_get_class_vars)
00256        ZEND_FE(get_object_vars,    arginfo_get_object_vars)
00257        ZEND_FE(get_class_methods,  arginfo_get_class_methods)
00258        ZEND_FE(trigger_error,             arginfo_trigger_error)
00259        ZEND_FALIAS(user_error,            trigger_error,              arginfo_trigger_error)
00260        ZEND_FE(set_error_handler,                arginfo_set_error_handler)
00261        ZEND_FE(restore_error_handler,            arginfo_zend__void)
00262        ZEND_FE(set_exception_handler,            arginfo_set_exception_handler)
00263        ZEND_FE(restore_exception_handler, arginfo_zend__void)
00264        ZEND_FE(get_declared_classes,             arginfo_zend__void)
00265        ZEND_FE(get_declared_interfaces,   arginfo_zend__void)
00266        ZEND_FE(get_defined_functions,            arginfo_zend__void)
00267        ZEND_FE(get_defined_vars,                 arginfo_zend__void)
00268        ZEND_FE(create_function,                  arginfo_create_function)
00269        ZEND_FE(get_resource_type,                arginfo_get_resource_type)
00270        ZEND_FE(get_loaded_extensions,            arginfo_get_loaded_extensions)
00271        ZEND_FE(extension_loaded,                 arginfo_extension_loaded)
00272        ZEND_FE(get_extension_funcs,              arginfo_extension_loaded)
00273        ZEND_FE(get_defined_constants,            arginfo_get_defined_constants)
00274        ZEND_FE(debug_backtrace,                  arginfo_debug_backtrace)
00275        ZEND_FE(debug_print_backtrace,            arginfo_debug_backtrace)
00276 #if ZEND_DEBUG
00277        ZEND_FE(zend_test_func,            NULL)
00278 #ifdef ZTS
00279        ZEND_FE(zend_thread_id,            NULL)
00280 #endif
00281 #endif
00282        ZEND_FE(gc_collect_cycles,  arginfo_zend__void)
00283        ZEND_FE(gc_enabled,         arginfo_zend__void)
00284        ZEND_FE(gc_enable,                 arginfo_zend__void)
00285        ZEND_FE(gc_disable,         arginfo_zend__void)
00286        ZEND_FE_END
00287 };
00288 /* }}} */
00289 
00290 ZEND_MINIT_FUNCTION(core) { /* {{{ */
00291        zend_class_entry class_entry;
00292 
00293        INIT_CLASS_ENTRY(class_entry, "stdClass", NULL);
00294        zend_standard_class_def = zend_register_internal_class(&class_entry TSRMLS_CC);
00295 
00296        zend_register_default_classes(TSRMLS_C);
00297 
00298        return SUCCESS;
00299 }
00300 /* }}} */
00301 
00302 zend_module_entry zend_builtin_module = { /* {{{ */
00303     STANDARD_MODULE_HEADER,
00304        "Core",
00305        builtin_functions,
00306        ZEND_MINIT(core),
00307        NULL,
00308        NULL,
00309        NULL,
00310        NULL,
00311        ZEND_VERSION,
00312        STANDARD_MODULE_PROPERTIES
00313 };
00314 /* }}} */
00315 
00316 int zend_startup_builtin_functions(TSRMLS_D) /* {{{ */
00317 {
00318        zend_builtin_module.module_number = 0;
00319        zend_builtin_module.type = MODULE_PERSISTENT;
00320        return (EG(current_module) = zend_register_module_ex(&zend_builtin_module TSRMLS_CC)) == NULL ? FAILURE : SUCCESS;
00321 }
00322 /* }}} */
00323 
00324 /* {{{ proto string zend_version(void)
00325    Get the version of the Zend Engine */
00326 ZEND_FUNCTION(zend_version)
00327 {
00328        RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1, 1);
00329 }
00330 /* }}} */
00331 
00332 /* {{{ proto int gc_collect_cycles(void)
00333    Forces collection of any existing garbage cycles.
00334    Returns number of freed zvals */
00335 ZEND_FUNCTION(gc_collect_cycles)
00336 {
00337        RETURN_LONG(gc_collect_cycles(TSRMLS_C));
00338 }
00339 /* }}} */
00340 
00341 /* {{{ proto void gc_enabled(void)
00342    Returns status of the circular reference collector */
00343 ZEND_FUNCTION(gc_enabled)
00344 {
00345        RETURN_BOOL(GC_G(gc_enabled));
00346 }
00347 /* }}} */
00348 
00349 /* {{{ proto void gc_enable(void)
00350    Activates the circular reference collector */
00351 ZEND_FUNCTION(gc_enable)
00352 {
00353        zend_alter_ini_entry("zend.enable_gc", sizeof("zend.enable_gc"), "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
00354 }
00355 /* }}} */
00356 
00357 /* {{{ proto void gc_disable(void)
00358    Deactivates the circular reference collector */
00359 ZEND_FUNCTION(gc_disable)
00360 {
00361        zend_alter_ini_entry("zend.enable_gc", sizeof("zend.enable_gc"), "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
00362 }
00363 /* }}} */
00364 
00365 /* {{{ proto int func_num_args(void)
00366    Get the number of arguments that were passed to the function */
00367 ZEND_FUNCTION(func_num_args)
00368 {
00369        zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
00370 
00371        if (ex && ex->function_state.arguments) {
00372               RETURN_LONG((long)(zend_uintptr_t)*(ex->function_state.arguments));
00373        } else {
00374               zend_error(E_WARNING, "func_num_args():  Called from the global scope - no function context");
00375               RETURN_LONG(-1);
00376        }
00377 }
00378 /* }}} */
00379 
00380 
00381 /* {{{ proto mixed func_get_arg(int arg_num)
00382    Get the $arg_num'th argument that was passed to the function */
00383 ZEND_FUNCTION(func_get_arg)
00384 {
00385        void **p;
00386        int arg_count;
00387        zval *arg;
00388        long requested_offset;
00389        zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
00390 
00391        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &requested_offset) == FAILURE) {
00392               return;
00393        }
00394 
00395        if (requested_offset < 0) {
00396               zend_error(E_WARNING, "func_get_arg():  The argument number should be >= 0");
00397               RETURN_FALSE;
00398        }
00399 
00400        if (!ex || !ex->function_state.arguments) {
00401               zend_error(E_WARNING, "func_get_arg():  Called from the global scope - no function context");
00402               RETURN_FALSE;
00403        }
00404 
00405        p = ex->function_state.arguments;
00406        arg_count = (int)(zend_uintptr_t) *p;            /* this is the amount of arguments passed to func_get_arg(); */
00407 
00408        if (requested_offset >= arg_count) {
00409               zend_error(E_WARNING, "func_get_arg():  Argument %ld not passed to function", requested_offset);
00410               RETURN_FALSE;
00411        }
00412 
00413        arg = *(p-(arg_count-requested_offset));
00414        *return_value = *arg;
00415        zval_copy_ctor(return_value);
00416        INIT_PZVAL(return_value);
00417 }
00418 /* }}} */
00419 
00420 
00421 /* {{{ proto array func_get_args()
00422    Get an array of the arguments that were passed to the function */
00423 ZEND_FUNCTION(func_get_args)
00424 {
00425        void **p;
00426        int arg_count;
00427        int i;
00428        zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
00429 
00430        if (!ex || !ex->function_state.arguments) {
00431               zend_error(E_WARNING, "func_get_args():  Called from the global scope - no function context");
00432               RETURN_FALSE;
00433        }
00434 
00435        p = ex->function_state.arguments;
00436        arg_count = (int)(zend_uintptr_t) *p;            /* this is the amount of arguments passed to func_get_args(); */
00437 
00438        array_init_size(return_value, arg_count);
00439        for (i=0; i<arg_count; i++) {
00440               zval *element;
00441 
00442               ALLOC_ZVAL(element);
00443               *element = **((zval **) (p-(arg_count-i)));
00444               zval_copy_ctor(element);
00445               INIT_PZVAL(element);
00446               zend_hash_next_index_insert(return_value->value.ht, &element, sizeof(zval *), NULL);
00447        }
00448 }
00449 /* }}} */
00450 
00451 
00452 /* {{{ proto int strlen(string str)
00453    Get string length */
00454 ZEND_FUNCTION(strlen)
00455 {
00456        char *s1;
00457        int s1_len;
00458 
00459        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &s1, &s1_len) == FAILURE) {
00460               return;
00461        }
00462 
00463        RETVAL_LONG(s1_len);
00464 }
00465 /* }}} */
00466 
00467 
00468 /* {{{ proto int strcmp(string str1, string str2)
00469    Binary safe string comparison */
00470 ZEND_FUNCTION(strcmp)
00471 {
00472        char *s1, *s2;
00473        int s1_len, s2_len;
00474        
00475        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &s1_len, &s2, &s2_len) == FAILURE) {
00476               return;
00477        }
00478 
00479        RETURN_LONG(zend_binary_strcmp(s1, s1_len, s2, s2_len));
00480 }
00481 /* }}} */
00482 
00483 
00484 /* {{{ proto int strncmp(string str1, string str2, int len)
00485    Binary safe string comparison */
00486 ZEND_FUNCTION(strncmp)
00487 {
00488        char *s1, *s2;
00489        int s1_len, s2_len;
00490        long len;
00491 
00492        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &s1, &s1_len, &s2, &s2_len, &len) == FAILURE) {
00493               return;
00494        }
00495 
00496        if (len < 0) {
00497               zend_error(E_WARNING, "Length must be greater than or equal to 0");
00498               RETURN_FALSE;
00499        }
00500 
00501        RETURN_LONG(zend_binary_strncmp(s1, s1_len, s2, s2_len, len));
00502 }
00503 /* }}} */
00504 
00505 
00506 /* {{{ proto int strcasecmp(string str1, string str2)
00507    Binary safe case-insensitive string comparison */
00508 ZEND_FUNCTION(strcasecmp)
00509 {
00510        char *s1, *s2;
00511        int s1_len, s2_len;
00512        
00513        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &s1_len, &s2, &s2_len) == FAILURE) {
00514               return;
00515        }
00516 
00517        RETURN_LONG(zend_binary_strcasecmp(s1, s1_len, s2, s2_len));
00518 }
00519 /* }}} */
00520 
00521 
00522 /* {{{ proto int strncasecmp(string str1, string str2, int len)
00523    Binary safe string comparison */
00524 ZEND_FUNCTION(strncasecmp)
00525 {
00526        char *s1, *s2;
00527        int s1_len, s2_len;
00528        long len;
00529 
00530        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &s1, &s1_len, &s2, &s2_len, &len) == FAILURE) {
00531               return;
00532        }
00533 
00534        if (len < 0) {
00535               zend_error(E_WARNING, "Length must be greater than or equal to 0");
00536               RETURN_FALSE;
00537        }
00538 
00539        RETURN_LONG(zend_binary_strncasecmp(s1, s1_len, s2, s2_len, len));
00540 }
00541 /* }}} */
00542 
00543 
00544 /* {{{ proto array each(array arr)
00545    Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element */
00546 ZEND_FUNCTION(each)
00547 {
00548        zval *array, *entry, **entry_ptr, *tmp;
00549        char *string_key;
00550        uint string_key_len;
00551        ulong num_key;
00552        zval **inserted_pointer;
00553        HashTable *target_hash;
00554 
00555        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &array) == FAILURE) {
00556               return;
00557        }
00558 
00559        target_hash = HASH_OF(array);
00560        if (!target_hash) {
00561               zend_error(E_WARNING,"Variable passed to each() is not an array or object");
00562               return;
00563        }
00564        if (zend_hash_get_current_data(target_hash, (void **) &entry_ptr)==FAILURE) {
00565               RETURN_FALSE;
00566        }
00567        array_init(return_value);
00568        entry = *entry_ptr;
00569 
00570        /* add value elements */
00571        if (Z_ISREF_P(entry)) {
00572               ALLOC_ZVAL(tmp);
00573               *tmp = *entry;
00574               zval_copy_ctor(tmp);
00575               Z_UNSET_ISREF_P(tmp);
00576               Z_SET_REFCOUNT_P(tmp, 0);
00577               entry=tmp;
00578        }
00579        zend_hash_index_update(return_value->value.ht, 1, &entry, sizeof(zval *), NULL);
00580        Z_ADDREF_P(entry);
00581        zend_hash_update(return_value->value.ht, "value", sizeof("value"), &entry, sizeof(zval *), NULL);
00582        Z_ADDREF_P(entry);
00583 
00584        /* add the key elements */
00585        switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 1, NULL)) {
00586               case HASH_KEY_IS_STRING:
00587                      add_get_index_stringl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, 0);
00588                      break;
00589               case HASH_KEY_IS_LONG:
00590                      add_get_index_long(return_value, 0, num_key, (void **) &inserted_pointer);
00591                      break;
00592        }
00593        zend_hash_update(return_value->value.ht, "key", sizeof("key"), inserted_pointer, sizeof(zval *), NULL);
00594        Z_ADDREF_PP(inserted_pointer);
00595        zend_hash_move_forward(target_hash);
00596 }
00597 /* }}} */
00598 
00599 
00600 /* {{{ proto int error_reporting([int new_error_level])
00601    Return the current error_reporting level, and if an argument was passed - change to the new level */
00602 ZEND_FUNCTION(error_reporting)
00603 {
00604        char *err;
00605        int err_len;
00606        int old_error_reporting;
00607 
00608        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &err, &err_len) == FAILURE) {
00609               return;
00610        }
00611 
00612        old_error_reporting = EG(error_reporting);
00613        if(ZEND_NUM_ARGS() != 0) {
00614               zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), err, err_len, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
00615        }
00616 
00617        RETVAL_LONG(old_error_reporting);
00618 }
00619 /* }}} */
00620 
00621 
00622 /* {{{ proto bool define(string constant_name, mixed value, boolean case_insensitive=false)
00623    Define a new constant */
00624 ZEND_FUNCTION(define)
00625 {
00626        char *name;
00627        int name_len;
00628        zval *val;
00629        zval *val_free = NULL;
00630        zend_bool non_cs = 0;
00631        int case_sensitive = CONST_CS;
00632        zend_constant c;
00633 
00634        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &name, &name_len, &val, &non_cs) == FAILURE) {
00635               return;
00636        }
00637 
00638        if(non_cs) {
00639               case_sensitive = 0;
00640        }
00641 
00642        /* class constant, check if there is name and make sure class is valid & exists */
00643        if (zend_memnstr(name, "::", sizeof("::") - 1, name + name_len)) {
00644               zend_error(E_WARNING, "Class constants cannot be defined or redefined");
00645               RETURN_FALSE;
00646        }
00647 
00648 repeat:
00649        switch (Z_TYPE_P(val)) {
00650               case IS_LONG:
00651               case IS_DOUBLE:
00652               case IS_STRING:
00653               case IS_BOOL:
00654               case IS_RESOURCE:
00655               case IS_NULL:
00656                      break;
00657               case IS_OBJECT:
00658                      if (!val_free) {
00659                             if (Z_OBJ_HT_P(val)->get) {
00660                                    val_free = val = Z_OBJ_HT_P(val)->get(val TSRMLS_CC);
00661                                    goto repeat;
00662                             } else if (Z_OBJ_HT_P(val)->cast_object) {
00663                                    ALLOC_INIT_ZVAL(val_free);
00664                                    if (Z_OBJ_HT_P(val)->cast_object(val, val_free, IS_STRING TSRMLS_CC) == SUCCESS) {
00665                                           val = val_free;
00666                                           break;
00667                                    }
00668                             }
00669                      }
00670                      /* no break */
00671               default:
00672                      zend_error(E_WARNING,"Constants may only evaluate to scalar values");
00673                      if (val_free) {
00674                             zval_ptr_dtor(&val_free);
00675                      }
00676                      RETURN_FALSE;
00677        }
00678        
00679        c.value = *val;
00680        zval_copy_ctor(&c.value);
00681        if (val_free) {
00682               zval_ptr_dtor(&val_free);
00683        }
00684        c.flags = case_sensitive; /* non persistent */
00685        c.name = zend_strndup(name, name_len);
00686        c.name_len = name_len+1;
00687        c.module_number = PHP_USER_CONSTANT;
00688        if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
00689               RETURN_TRUE;
00690        } else {
00691               RETURN_FALSE;
00692        }
00693 }
00694 /* }}} */
00695 
00696 
00697 /* {{{ proto bool defined(string constant_name)
00698    Check whether a constant exists */
00699 ZEND_FUNCTION(defined)
00700 {
00701        char *name;
00702        int name_len;
00703        zval c;
00704 
00705        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
00706               return;
00707        }
00708        
00709        if (zend_get_constant_ex(name, name_len, &c, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) {
00710               zval_dtor(&c);
00711               RETURN_TRUE;
00712        } else {
00713               RETURN_FALSE;
00714        }
00715 }
00716 /* }}} */
00717 
00718 
00719 /* {{{ proto string get_class([object object])
00720    Retrieves the class name */
00721 ZEND_FUNCTION(get_class)
00722 {
00723        zval *obj = NULL;
00724        char *name = "";
00725        zend_uint name_len = 0;
00726        int dup;
00727 
00728        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|o!", &obj) == FAILURE) {
00729               RETURN_FALSE;
00730        }
00731 
00732        if (!obj) {
00733               if (EG(scope)) {
00734                      RETURN_STRINGL(EG(scope)->name, EG(scope)->name_length, 1);
00735               } else {
00736                      zend_error(E_WARNING, "get_class() called without object from outside a class");
00737                      RETURN_FALSE;
00738               }
00739        }
00740 
00741        dup = zend_get_object_classname(obj, &name, &name_len TSRMLS_CC);
00742 
00743        RETURN_STRINGL(name, name_len, dup);
00744 }
00745 /* }}} */
00746 
00747 
00748 /* {{{ proto string get_called_class()
00749    Retrieves the "Late Static Binding" class name */
00750 ZEND_FUNCTION(get_called_class)
00751 {
00752        if (zend_parse_parameters_none() == FAILURE) {
00753               return;
00754        }
00755 
00756        if (EG(called_scope)) {
00757               RETURN_STRINGL(EG(called_scope)->name, EG(called_scope)->name_length, 1);
00758        } else if (!EG(scope))  {
00759               zend_error(E_WARNING, "get_called_class() called from outside a class");
00760        }
00761        RETURN_FALSE;
00762 }
00763 /* }}} */
00764 
00765 
00766 /* {{{ proto string get_parent_class([mixed object])
00767    Retrieves the parent class name for object or class or current scope. */
00768 ZEND_FUNCTION(get_parent_class)
00769 {
00770        zval *arg;
00771        zend_class_entry *ce = NULL;
00772        char *name;
00773        zend_uint name_length;
00774        
00775        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) {
00776               return;
00777        }
00778 
00779        if (!ZEND_NUM_ARGS()) {
00780               ce = EG(scope);
00781               if (ce && ce->parent) {
00782                      RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
00783               } else {
00784                      RETURN_FALSE;
00785               }
00786        }
00787 
00788        if (Z_TYPE_P(arg) == IS_OBJECT) {
00789               if (Z_OBJ_HT_P(arg)->get_class_name
00790                      && Z_OBJ_HT_P(arg)->get_class_name(arg, &name, &name_length, 1 TSRMLS_CC) == SUCCESS) {
00791                      RETURN_STRINGL(name, name_length, 0);
00792               } else {
00793                      ce = zend_get_class_entry(arg TSRMLS_CC);
00794               }
00795        } else if (Z_TYPE_P(arg) == IS_STRING) {
00796               zend_class_entry **pce;
00797               
00798               if (zend_lookup_class(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &pce TSRMLS_CC) == SUCCESS) {
00799                      ce = *pce;
00800               }
00801        }
00802 
00803        if (ce && ce->parent) {
00804               RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
00805        } else {
00806               RETURN_FALSE;
00807        }
00808 }
00809 /* }}} */
00810 
00811 
00812 static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
00813 {
00814        zval *obj;
00815        char *class_name;
00816        int class_name_len;
00817        zend_class_entry *instance_ce;
00818        zend_class_entry **ce;
00819        zend_bool allow_string = only_subclass;
00820        zend_bool retval;
00821 
00822        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|b", &obj, &class_name, &class_name_len, &allow_string) == FAILURE) {
00823               return;
00824        }
00825        /*
00826           allow_string - is_a default is no, is_subclass_of is yes. 
00827           if it's allowed, then the autoloader will be called if the class does not exist.
00828           default behaviour is different, as 'is_a' usage is normally to test mixed return values 
00829        */
00830 
00831        if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
00832               zend_class_entry **the_ce;
00833               if (zend_lookup_class(Z_STRVAL_P(obj), Z_STRLEN_P(obj), &the_ce TSRMLS_CC) == FAILURE) {
00834                      RETURN_FALSE;
00835               }
00836               instance_ce = *the_ce;
00837        } else if (Z_TYPE_P(obj) == IS_OBJECT && HAS_CLASS_ENTRY(*obj)) {
00838               instance_ce = Z_OBJCE_P(obj);
00839        } else {
00840               RETURN_FALSE;
00841        }
00842 
00843        if (zend_lookup_class_ex(class_name, class_name_len, 0, &ce TSRMLS_CC) == FAILURE) {
00844               retval = 0;
00845        } else {
00846               if (only_subclass && instance_ce == *ce) {
00847                      retval = 0;
00848               } else {
00849                      retval = instanceof_function(instance_ce, *ce TSRMLS_CC);
00850               }
00851        }
00852 
00853        RETURN_BOOL(retval);
00854 }
00855 
00856 
00857 /* {{{ proto bool is_subclass_of(mixed object_or_string, string class_name [, bool allow_string=true])
00858    Returns true if the object has this class as one of its parents */
00859 ZEND_FUNCTION(is_subclass_of)
00860 {
00861        is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
00862 }
00863 /* }}} */
00864 
00865 
00866 /* {{{ proto bool is_a(mixed object_or_string, string class_name [, bool allow_string=false])
00867    Returns true if the first argument is an object and is this class or has this class as one of its parents, */
00868 ZEND_FUNCTION(is_a)
00869 {
00870        is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
00871 }
00872 /* }}} */
00873 
00874 
00875 /* {{{ add_class_vars */
00876 static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *return_value TSRMLS_DC)
00877 {
00878        if (zend_hash_num_elements(properties) > 0) {
00879               HashPosition pos;
00880               zval **prop;
00881 
00882               zend_hash_internal_pointer_reset_ex(properties, &pos);
00883               while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) {
00884                      char *key, *class_name, *prop_name;
00885                      uint key_len;
00886                      ulong num_index;
00887                      int prop_name_len = 0;                    
00888                      zval *prop_copy;
00889                      zend_property_info *property_info;
00890                      zval zprop_name;
00891 
00892                      zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
00893                      zend_hash_move_forward_ex(properties, &pos);
00894 
00895                      zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
00896                      prop_name_len = strlen(prop_name);
00897 
00898                      ZVAL_STRINGL(&zprop_name, prop_name, prop_name_len, 0);
00899                      property_info = zend_get_property_info(ce, &zprop_name, 1 TSRMLS_CC);
00900 
00901                      if (!property_info || property_info == &EG(std_property_info)) {
00902                             continue;
00903                      }
00904 
00905                      /* copy: enforce read only access */
00906                      ALLOC_ZVAL(prop_copy);
00907                      *prop_copy = **prop;
00908                      zval_copy_ctor(prop_copy);
00909                      INIT_PZVAL(prop_copy);
00910 
00911                      /* this is necessary to make it able to work with default array 
00912                      * properties, returned to user */
00913                      if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
00914                             zval_update_constant(&prop_copy, 0 TSRMLS_CC);
00915                      }
00916 
00917                      add_assoc_zval(return_value, prop_name, prop_copy);
00918               }
00919        }
00920 }
00921 /* }}} */
00922 
00923 
00924 /* {{{ proto array get_class_vars(string class_name)
00925    Returns an array of default properties of the class. */
00926 ZEND_FUNCTION(get_class_vars)
00927 {
00928        char *class_name;
00929        int class_name_len;
00930        zend_class_entry **pce;
00931 
00932        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) {
00933               return;
00934        }
00935 
00936        if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
00937               RETURN_FALSE;
00938        } else {
00939               array_init(return_value);
00940               zend_update_class_constants(*pce TSRMLS_CC);
00941               add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC);
00942               add_class_vars(*pce, CE_STATIC_MEMBERS(*pce), return_value TSRMLS_CC);
00943        }
00944 }
00945 /* }}} */
00946 
00947 
00948 /* {{{ proto array get_object_vars(object obj)
00949    Returns an array of object properties */
00950 ZEND_FUNCTION(get_object_vars)
00951 {
00952        zval *obj;
00953        zval **value;
00954        HashTable *properties;
00955        HashPosition pos;
00956        char *key, *prop_name, *class_name;
00957        uint key_len;
00958        ulong num_index;
00959        zend_object *zobj;
00960 
00961        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
00962               return;
00963        }
00964 
00965        if (Z_OBJ_HT_P(obj)->get_properties == NULL) {
00966               RETURN_FALSE;
00967        }
00968 
00969        properties = Z_OBJ_HT_P(obj)->get_properties(obj TSRMLS_CC);
00970 
00971        if (properties == NULL) {
00972               RETURN_FALSE;
00973        }
00974 
00975        zobj = zend_objects_get_address(obj TSRMLS_CC);
00976 
00977        array_init(return_value);
00978 
00979        zend_hash_internal_pointer_reset_ex(properties, &pos);
00980 
00981        while (zend_hash_get_current_data_ex(properties, (void **) &value, &pos) == SUCCESS) {
00982               if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
00983                      if (zend_check_property_access(zobj, key, key_len-1 TSRMLS_CC) == SUCCESS) {
00984                             zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
00985                             /* Not separating references */
00986                             Z_ADDREF_PP(value);
00987                             add_assoc_zval_ex(return_value, prop_name, strlen(prop_name)+1, *value);
00988                      }
00989               }
00990               zend_hash_move_forward_ex(properties, &pos);
00991        }
00992 }
00993 /* }}} */
00994 
00995 
00996 /* {{{ proto array get_class_methods(mixed class)
00997    Returns an array of method names for class or class instance. */
00998 ZEND_FUNCTION(get_class_methods)
00999 {
01000        zval *klass;
01001        zval *method_name;
01002        zend_class_entry *ce = NULL, **pce;
01003        HashPosition pos;
01004        zend_function *mptr;
01005 
01006        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &klass) == FAILURE) {
01007               return;
01008        }
01009 
01010        if (Z_TYPE_P(klass) == IS_OBJECT) {
01011               /* TBI!! new object handlers */
01012               if (!HAS_CLASS_ENTRY(*klass)) {
01013                      RETURN_FALSE;
01014               }
01015               ce = Z_OBJCE_P(klass);
01016        } else if (Z_TYPE_P(klass) == IS_STRING) {
01017               if (zend_lookup_class(Z_STRVAL_P(klass), Z_STRLEN_P(klass), &pce TSRMLS_CC) == SUCCESS) {
01018                      ce = *pce;
01019               }
01020        }
01021 
01022        if (!ce) {
01023               RETURN_NULL();
01024        }
01025 
01026        array_init(return_value);
01027        zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
01028 
01029        while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
01030               if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) 
01031                || (EG(scope) &&
01032                    (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
01033                      zend_check_protected(mptr->common.scope, EG(scope)))
01034                  || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
01035                      EG(scope) == mptr->common.scope)))) {
01036                      char *key;
01037                      uint key_len;
01038                      ulong num_index;
01039                      uint len = strlen(mptr->common.function_name);
01040 
01041                      /* Do not display old-style inherited constructors */
01042                      if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
01043                          mptr->common.scope == ce ||
01044                          zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING ||
01045                          zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0) {
01046 
01047                             MAKE_STD_ZVAL(method_name);
01048                             ZVAL_STRINGL(method_name, mptr->common.function_name, len, 1);
01049                             zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
01050                      }
01051               }
01052               zend_hash_move_forward_ex(&ce->function_table, &pos);
01053        }
01054 }
01055 /* }}} */
01056 
01057 
01058 /* {{{ proto bool method_exists(object object, string method)
01059    Checks if the class method exists */
01060 ZEND_FUNCTION(method_exists)
01061 {
01062        zval *klass; 
01063        char *method_name;
01064        int method_len;
01065        char *lcname;
01066        zend_class_entry * ce, **pce;
01067 
01068        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &klass, &method_name, &method_len) == FAILURE) {
01069               return;
01070        }
01071        if (Z_TYPE_P(klass) == IS_OBJECT) {
01072               ce = Z_OBJCE_P(klass);
01073        } else if (Z_TYPE_P(klass) == IS_STRING) {
01074               if (zend_lookup_class(Z_STRVAL_P(klass), Z_STRLEN_P(klass), &pce TSRMLS_CC) == FAILURE) {
01075                      RETURN_FALSE;
01076               }
01077               ce = *pce;
01078        } else {
01079               RETURN_FALSE;
01080        }
01081 
01082        lcname = zend_str_tolower_dup(method_name, method_len);
01083        if (zend_hash_exists(&ce->function_table, lcname, method_len+1)) {
01084               efree(lcname);
01085               RETURN_TRUE;
01086        } else {
01087               union _zend_function *func = NULL;
01088 
01089               if (Z_TYPE_P(klass) == IS_OBJECT 
01090               && Z_OBJ_HT_P(klass)->get_method != NULL
01091               && (func = Z_OBJ_HT_P(klass)->get_method(&klass, method_name, method_len TSRMLS_CC)) != NULL
01092               ) {
01093                      if (func->type == ZEND_INTERNAL_FUNCTION 
01094                      && (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0
01095                      ) {
01096                             /* Returns true to the fake Closure's __invoke */
01097                             RETVAL_BOOL((func->common.scope == zend_ce_closure
01098                                    && (method_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
01099                                    && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0) ? 1 : 0);
01100 
01101                             efree(lcname);
01102                             efree(((zend_internal_function*)func)->function_name);
01103                             efree(func);
01104                             return;
01105                      }
01106                      efree(lcname);
01107                      RETURN_TRUE;
01108               }
01109        }
01110        efree(lcname);
01111        RETURN_FALSE;
01112 }
01113 /* }}} */
01114 
01115 /* {{{ proto bool property_exists(mixed object_or_class, string property_name)
01116    Checks if the object or class has a property */
01117 ZEND_FUNCTION(property_exists)
01118 {
01119        zval *object;
01120        char *property;
01121        int property_len;
01122        zend_class_entry *ce, **pce;
01123        zend_property_info *property_info;
01124        zval property_z;
01125        ulong h;
01126 
01127        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &object, &property, &property_len) == FAILURE) {
01128               return;
01129        }
01130 
01131        if (property_len == 0) {
01132               RETURN_FALSE;
01133        }
01134 
01135        if (Z_TYPE_P(object) == IS_STRING) {
01136               if (zend_lookup_class(Z_STRVAL_P(object), Z_STRLEN_P(object), &pce TSRMLS_CC) == FAILURE) {
01137                      RETURN_FALSE;
01138               }
01139               ce = *pce;
01140        } else if (Z_TYPE_P(object) == IS_OBJECT) {
01141               ce = Z_OBJCE_P(object);
01142        } else {
01143               zend_error(E_WARNING, "First parameter must either be an object or the name of an existing class");
01144               RETURN_NULL();
01145        }
01146 
01147        h = zend_get_hash_value(property, property_len+1);
01148        if (zend_hash_quick_find(&ce->properties_info, property, property_len+1, h, (void **) &property_info) == SUCCESS
01149               && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
01150               RETURN_TRUE;
01151        }
01152 
01153        ZVAL_STRINGL(&property_z, property, property_len, 0);
01154 
01155        if (Z_TYPE_P(object) ==  IS_OBJECT &&
01156               Z_OBJ_HANDLER_P(object, has_property) && 
01157               Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2 TSRMLS_CC)) {
01158               RETURN_TRUE;
01159        }
01160        RETURN_FALSE;
01161 }
01162 /* }}} */
01163 
01164 
01165 /* {{{ proto bool class_exists(string classname [, bool autoload])
01166    Checks if the class exists */
01167 ZEND_FUNCTION(class_exists)
01168 {
01169        char *class_name, *lc_name;
01170        zend_class_entry **ce;
01171        int class_name_len;
01172        int found;
01173        zend_bool autoload = 1;
01174        ALLOCA_FLAG(use_heap)
01175 
01176        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &class_name, &class_name_len, &autoload) == FAILURE) {
01177               return;
01178        }
01179 
01180        if (!autoload) {
01181               char *name;
01182               int len;
01183 
01184               lc_name = do_alloca(class_name_len + 1, use_heap);
01185               zend_str_tolower_copy(lc_name, class_name, class_name_len);
01186 
01187               /* Ignore leading "\" */
01188               name = lc_name;
01189               len = class_name_len;
01190               if (lc_name[0] == '\\') {
01191                      name = &lc_name[1];
01192                      len--;
01193               }
01194        
01195               found = zend_hash_find(EG(class_table), name, len+1, (void **) &ce);
01196               free_alloca(lc_name, use_heap);
01197               RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE));
01198        }
01199 
01200        if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
01201               RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) == 0);
01202        } else {
01203               RETURN_FALSE;
01204        }
01205 }
01206 /* }}} */
01207 
01208 /* {{{ proto bool interface_exists(string classname [, bool autoload])
01209    Checks if the class exists */
01210 ZEND_FUNCTION(interface_exists)
01211 {
01212        char *iface_name, *lc_name;
01213        zend_class_entry **ce;
01214        int iface_name_len;
01215        int found;
01216        zend_bool autoload = 1;
01217        ALLOCA_FLAG(use_heap)
01218 
01219        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &iface_name, &iface_name_len, &autoload) == FAILURE) {
01220               return;
01221        }
01222 
01223        if (!autoload) {
01224               char *name;
01225               int len;
01226               
01227               lc_name = do_alloca(iface_name_len + 1, use_heap);
01228               zend_str_tolower_copy(lc_name, iface_name, iface_name_len);
01229        
01230               /* Ignore leading "\" */
01231               name = lc_name;
01232               len = iface_name_len;
01233               if (lc_name[0] == '\\') {
01234                      name = &lc_name[1];
01235                      len--;
01236               }
01237 
01238               found = zend_hash_find(EG(class_table), name, len+1, (void **) &ce);
01239               free_alloca(lc_name, use_heap);
01240               RETURN_BOOL(found == SUCCESS && (*ce)->ce_flags & ZEND_ACC_INTERFACE);
01241        }
01242 
01243        if (zend_lookup_class(iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) {
01244               RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) > 0);
01245        } else {
01246               RETURN_FALSE;
01247        }
01248 }
01249 /* }}} */
01250 
01251 
01252 /* {{{ proto bool function_exists(string function_name) 
01253    Checks if the function exists */
01254 ZEND_FUNCTION(function_exists)
01255 {
01256        char *name;
01257        int name_len;
01258        zend_function *func;
01259        char *lcname;
01260        zend_bool retval;
01261        
01262        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
01263               return;
01264        }
01265 
01266        lcname = zend_str_tolower_dup(name, name_len);
01267        
01268        /* Ignore leading "\" */
01269        name = lcname;
01270        if (lcname[0] == '\\') {
01271               name = &lcname[1];
01272               name_len--;
01273        }
01274 
01275        retval = (zend_hash_find(EG(function_table), name, name_len+1, (void **)&func) == SUCCESS);
01276        
01277        efree(lcname);
01278 
01279        /*
01280         * A bit of a hack, but not a bad one: we see if the handler of the function
01281         * is actually one that displays "function is disabled" message.
01282         */
01283        if (retval && func->type == ZEND_INTERNAL_FUNCTION &&
01284               func->internal_function.handler == zif_display_disabled_function) {
01285               retval = 0;
01286        }
01287 
01288        RETURN_BOOL(retval);
01289 }
01290 /* }}} */
01291 
01292 /* {{{ proto bool class_alias(string user_class_name , string alias_name [, bool autoload])
01293    Creates an alias for user defined class */
01294 ZEND_FUNCTION(class_alias)
01295 {
01296        char *class_name, *lc_name, *alias_name;
01297        zend_class_entry **ce;
01298        int class_name_len, alias_name_len;
01299        int found;
01300        zend_bool autoload = 1;
01301        ALLOCA_FLAG(use_heap)
01302 
01303        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &class_name, &class_name_len, &alias_name, &alias_name_len, &autoload) == FAILURE) {
01304               return;
01305        }
01306 
01307        if (!autoload) {
01308               lc_name = do_alloca(class_name_len + 1, use_heap);
01309               zend_str_tolower_copy(lc_name, class_name, class_name_len);
01310        
01311               found = zend_hash_find(EG(class_table), lc_name, class_name_len+1, (void **) &ce);
01312               free_alloca(lc_name, use_heap);
01313        } else {
01314               found = zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC);
01315        }
01316        if (found == SUCCESS) {
01317               if ((*ce)->type == ZEND_USER_CLASS) { 
01318                      if (zend_register_class_alias_ex(alias_name, alias_name_len, *ce TSRMLS_CC) == SUCCESS) {
01319                             RETURN_TRUE;
01320                      } else {
01321                             zend_error(E_WARNING, "Cannot redeclare class %s", alias_name);
01322                             RETURN_FALSE;
01323                      }
01324               } else {
01325                      zend_error(E_WARNING, "First argument of class_alias() must be a name of user defined class");
01326                      RETURN_FALSE;
01327               }
01328        } else {
01329               zend_error(E_WARNING, "Class '%s' not found", class_name);
01330               RETURN_FALSE;
01331        }
01332 }
01333 /* }}} */
01334 
01335 #if ZEND_DEBUG
01336 /* {{{ proto void leak(int num_bytes=3)
01337    Cause an intentional memory leak, for testing/debugging purposes */
01338 ZEND_FUNCTION(leak)
01339 {
01340        long leakbytes=3;
01341 
01342        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &leakbytes) == FAILURE) {
01343               return;
01344        }
01345 
01346        emalloc(leakbytes);
01347 }
01348 /* }}} */
01349 
01350 
01351 #ifdef ZEND_TEST_EXCEPTIONS
01352 ZEND_FUNCTION(crash)
01353 {
01354        char *nowhere=NULL;
01355 
01356        memcpy(nowhere, "something", sizeof("something"));
01357 }
01358 #endif
01359 
01360 #endif /* ZEND_DEBUG */
01361 
01362 /* {{{ proto array get_included_files(void)
01363    Returns an array with the file names that were include_once()'d */
01364 ZEND_FUNCTION(get_included_files)
01365 {
01366        char *entry;
01367        if (zend_parse_parameters_none() == FAILURE) {
01368               return;
01369        }
01370 
01371        array_init(return_value);
01372        zend_hash_internal_pointer_reset(&EG(included_files));
01373        while (zend_hash_get_current_key(&EG(included_files), &entry, NULL, 1) == HASH_KEY_IS_STRING) {
01374               add_next_index_string(return_value, entry, 0);
01375               zend_hash_move_forward(&EG(included_files));
01376        }
01377 }
01378 /* }}} */
01379 
01380 
01381 /* {{{ proto void trigger_error(string message [, int error_type])
01382    Generates a user-level error/warning/notice message */
01383 ZEND_FUNCTION(trigger_error)
01384 {
01385        long error_type = E_USER_NOTICE;
01386        char *message;
01387        int message_len;
01388 
01389        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &message, &message_len, &error_type) == FAILURE) {
01390               return;
01391        }
01392 
01393        switch (error_type) {
01394               case E_USER_ERROR:
01395               case E_USER_WARNING:
01396               case E_USER_NOTICE:
01397               case E_USER_DEPRECATED:
01398                      break;
01399               default:
01400                      zend_error(E_WARNING, "Invalid error type specified");
01401                      RETURN_FALSE;
01402                      break;
01403        }
01404 
01405        zend_error((int)error_type, "%s", message);
01406        RETURN_TRUE;
01407 }
01408 /* }}} */
01409 
01410 
01411 /* {{{ proto string set_error_handler(string error_handler [, int error_types])
01412    Sets a user-defined error handler function.  Returns the previously defined error handler, or false on error */
01413 ZEND_FUNCTION(set_error_handler)
01414 {
01415        zval *error_handler;
01416        zend_bool had_orig_error_handler=0;
01417        char *error_handler_name = NULL;
01418        long error_type = E_ALL | E_STRICT;
01419 
01420        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &error_handler, &error_type) == FAILURE) {
01421               return;
01422        }
01423 
01424        if (!zend_is_callable(error_handler, 0, &error_handler_name TSRMLS_CC)) {
01425               zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
01426                                get_active_function_name(TSRMLS_C), error_handler_name?error_handler_name:"unknown");
01427               efree(error_handler_name);
01428               return;
01429        }
01430        efree(error_handler_name);
01431 
01432        if (EG(user_error_handler)) {
01433               had_orig_error_handler = 1;
01434               *return_value = *EG(user_error_handler);
01435               zval_copy_ctor(return_value);
01436               INIT_PZVAL(return_value);
01437               zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting), sizeof(EG(user_error_handler_error_reporting)));
01438               zend_ptr_stack_push(&EG(user_error_handlers), EG(user_error_handler));
01439        }
01440        ALLOC_ZVAL(EG(user_error_handler));
01441 
01442        if (!zend_is_true(error_handler)) { /* unset user-defined handler */
01443               FREE_ZVAL(EG(user_error_handler));
01444               EG(user_error_handler) = NULL;
01445               RETURN_TRUE;
01446        }
01447 
01448        EG(user_error_handler_error_reporting) = (int)error_type;
01449        *EG(user_error_handler) = *error_handler;
01450        zval_copy_ctor(EG(user_error_handler));
01451        INIT_PZVAL(EG(user_error_handler));
01452 
01453        if (!had_orig_error_handler) {
01454               RETURN_NULL();
01455        }
01456 }
01457 /* }}} */
01458 
01459 
01460 /* {{{ proto void restore_error_handler(void)
01461    Restores the previously defined error handler function */
01462 ZEND_FUNCTION(restore_error_handler)
01463 {
01464        if (EG(user_error_handler)) {
01465               zval *zeh = EG(user_error_handler);
01466 
01467               EG(user_error_handler) = NULL;
01468               zval_ptr_dtor(&zeh);
01469        }
01470 
01471        if (zend_ptr_stack_num_elements(&EG(user_error_handlers))==0) {
01472               EG(user_error_handler) = NULL;
01473        } else {
01474               EG(user_error_handler_error_reporting) = zend_stack_int_top(&EG(user_error_handlers_error_reporting));
01475               zend_stack_del_top(&EG(user_error_handlers_error_reporting));
01476               EG(user_error_handler) = zend_ptr_stack_pop(&EG(user_error_handlers));
01477        }
01478        RETURN_TRUE;
01479 }
01480 /* }}} */
01481 
01482 
01483 /* {{{ proto string set_exception_handler(callable exception_handler)
01484    Sets a user-defined exception handler function.  Returns the previously defined exception handler, or false on error */
01485 ZEND_FUNCTION(set_exception_handler)
01486 {
01487        zval *exception_handler;
01488        char *exception_handler_name = NULL;
01489        zend_bool had_orig_exception_handler=0;
01490 
01491        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &exception_handler) == FAILURE) {
01492               return;
01493        }
01494 
01495        if (Z_TYPE_P(exception_handler) != IS_NULL) { /* NULL == unset */
01496               if (!zend_is_callable(exception_handler, 0, &exception_handler_name TSRMLS_CC)) {
01497                      zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
01498                                       get_active_function_name(TSRMLS_C), exception_handler_name?exception_handler_name:"unknown");
01499                      efree(exception_handler_name);
01500                      return;
01501               }
01502               efree(exception_handler_name);
01503        }
01504 
01505        if (EG(user_exception_handler)) {
01506               had_orig_exception_handler = 1;
01507               *return_value = *EG(user_exception_handler);
01508               zval_copy_ctor(return_value);
01509               zend_ptr_stack_push(&EG(user_exception_handlers), EG(user_exception_handler));
01510        }
01511        ALLOC_ZVAL(EG(user_exception_handler));
01512 
01513        if (Z_TYPE_P(exception_handler) == IS_NULL) { /* unset user-defined handler */
01514               FREE_ZVAL(EG(user_exception_handler));
01515               EG(user_exception_handler) = NULL;
01516               RETURN_TRUE;
01517        }
01518 
01519        *EG(user_exception_handler) = *exception_handler;
01520        zval_copy_ctor(EG(user_exception_handler));
01521 
01522        if (!had_orig_exception_handler) {
01523               RETURN_NULL();
01524        }
01525 }
01526 /* }}} */
01527 
01528 
01529 /* {{{ proto void restore_exception_handler(void)
01530    Restores the previously defined exception handler function */
01531 ZEND_FUNCTION(restore_exception_handler)
01532 {
01533        if (EG(user_exception_handler)) {
01534               zval_ptr_dtor(&EG(user_exception_handler));
01535        }
01536        if (zend_ptr_stack_num_elements(&EG(user_exception_handlers))==0) {
01537               EG(user_exception_handler) = NULL;
01538        } else {
01539               EG(user_exception_handler) = zend_ptr_stack_pop(&EG(user_exception_handlers));
01540        }
01541        RETURN_TRUE;
01542 }
01543 /* }}} */
01544 
01545 
01546 static int copy_class_or_interface_name(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
01547 {
01548        zval *array = va_arg(args, zval *);
01549        zend_uint mask = va_arg(args, zend_uint);
01550        zend_uint comply = va_arg(args, zend_uint);
01551        zend_uint comply_mask = (comply)? mask:0;
01552        zend_class_entry *ce  = *pce;
01553 
01554        if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
01555               && (comply_mask == (ce->ce_flags & mask))) {
01556               add_next_index_stringl(array, ce->name, ce->name_length, 1);
01557        }
01558        return ZEND_HASH_APPLY_KEEP;
01559 }
01560 
01561 
01562 /* {{{ proto array get_declared_classes()
01563    Returns an array of all declared classes. */
01564 ZEND_FUNCTION(get_declared_classes)
01565 {
01566        zend_uint mask = ZEND_ACC_INTERFACE;
01567        zend_uint comply = 0;
01568 
01569        if (zend_parse_parameters_none() == FAILURE) {
01570               return;
01571        }
01572 
01573        array_init(return_value);
01574        zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) copy_class_or_interface_name, 3, return_value, mask, comply);
01575 }
01576 /* }}} */
01577 
01578 /* {{{ proto array get_declared_interfaces()
01579    Returns an array of all declared interfaces. */
01580 ZEND_FUNCTION(get_declared_interfaces)
01581 {
01582        zend_uint mask = ZEND_ACC_INTERFACE;
01583        zend_uint comply = 1;
01584 
01585        if (zend_parse_parameters_none() == FAILURE) {
01586               return;
01587        }
01588 
01589        array_init(return_value);
01590        zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) copy_class_or_interface_name, 3, return_value, mask, comply);
01591 }
01592 /* }}} */
01593 
01594 
01595 static int copy_function_name(zend_function *func TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
01596 {
01597        zval *internal_ar = va_arg(args, zval *),
01598             *user_ar     = va_arg(args, zval *);
01599 
01600        if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
01601               return 0;
01602        }
01603 
01604        if (func->type == ZEND_INTERNAL_FUNCTION) {
01605               add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
01606        } else if (func->type == ZEND_USER_FUNCTION) {
01607               add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
01608        }
01609 
01610        return 0;
01611 }
01612 
01613 
01614 /* {{{ proto array get_defined_functions(void)
01615    Returns an array of all defined functions */
01616 ZEND_FUNCTION(get_defined_functions)
01617 {
01618        zval *internal;
01619        zval *user;
01620 
01621        if (zend_parse_parameters_none() == FAILURE) {
01622               return;
01623        }
01624 
01625        MAKE_STD_ZVAL(internal);
01626        MAKE_STD_ZVAL(user);
01627 
01628        array_init(internal);
01629        array_init(user);
01630        array_init(return_value);
01631 
01632        zend_hash_apply_with_arguments(EG(function_table) TSRMLS_CC, (apply_func_args_t) copy_function_name, 2, internal, user);
01633 
01634        if (zend_hash_add(Z_ARRVAL_P(return_value), "internal", sizeof("internal"), (void **)&internal, sizeof(zval *), NULL) == FAILURE) {
01635               zval_ptr_dtor(&internal);
01636               zval_ptr_dtor(&user);
01637               zval_dtor(return_value);
01638               zend_error(E_WARNING, "Cannot add internal functions to return value from get_defined_functions()");
01639               RETURN_FALSE;
01640        }
01641 
01642        if (zend_hash_add(Z_ARRVAL_P(return_value), "user", sizeof("user"), (void **)&user, sizeof(zval *), NULL) == FAILURE) {
01643               zval_ptr_dtor(&user);
01644               zval_dtor(return_value);
01645               zend_error(E_WARNING, "Cannot add user functions to return value from get_defined_functions()");
01646               RETURN_FALSE;
01647        }
01648 }
01649 /* }}} */
01650 
01651 
01652 /* {{{ proto array get_defined_vars(void)
01653    Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
01654 ZEND_FUNCTION(get_defined_vars)
01655 {
01656        if (!EG(active_symbol_table)) {
01657               zend_rebuild_symbol_table(TSRMLS_C);
01658        }
01659 
01660        array_init_size(return_value, zend_hash_num_elements(EG(active_symbol_table)));
01661 
01662        zend_hash_copy(Z_ARRVAL_P(return_value), EG(active_symbol_table),
01663                                    (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval *));
01664 }
01665 /* }}} */
01666 
01667 
01668 #define LAMBDA_TEMP_FUNCNAME       "__lambda_func"
01669 /* {{{ proto string create_function(string args, string code)
01670    Creates an anonymous function, and returns its name (funny, eh?) */
01671 ZEND_FUNCTION(create_function)
01672 {
01673        char *eval_code, *function_name, *function_args, *function_code;
01674        int eval_code_length, function_name_length, function_args_len, function_code_len;
01675        int retval;
01676        char *eval_name;
01677 
01678        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &function_args, &function_args_len, &function_code, &function_code_len) == FAILURE) {
01679               return;
01680        }
01681 
01682        eval_code = (char *) emalloc(sizeof("function " LAMBDA_TEMP_FUNCNAME)
01683                      +function_args_len
01684                      +2     /* for the args parentheses */
01685                      +2     /* for the curly braces */
01686                      +function_code_len);
01687 
01688        eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME "(") - 1;
01689        memcpy(eval_code, "function " LAMBDA_TEMP_FUNCNAME "(", eval_code_length);
01690 
01691        memcpy(eval_code + eval_code_length, function_args, function_args_len);
01692        eval_code_length += function_args_len;
01693 
01694        eval_code[eval_code_length++] = ')';
01695        eval_code[eval_code_length++] = '{';
01696 
01697        memcpy(eval_code + eval_code_length, function_code, function_code_len);
01698        eval_code_length += function_code_len;
01699 
01700        eval_code[eval_code_length++] = '}';
01701        eval_code[eval_code_length] = '\0';
01702 
01703        eval_name = zend_make_compiled_string_description("runtime-created function" TSRMLS_CC);
01704        retval = zend_eval_stringl(eval_code, eval_code_length, NULL, eval_name TSRMLS_CC);
01705        efree(eval_code);
01706        efree(eval_name);
01707 
01708        if (retval==SUCCESS) {
01709               zend_function new_function, *func;
01710 
01711               if (zend_hash_find(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME), (void **) &func)==FAILURE) {
01712                      zend_error(E_ERROR, "Unexpected inconsistency in create_function()");
01713                      RETURN_FALSE;
01714               }
01715               new_function = *func;
01716               function_add_ref(&new_function);
01717 
01718               function_name = (char *) emalloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG);
01719               function_name[0] = '\0';
01720 
01721               do {
01722                      function_name_length = 1 + snprintf(function_name + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count));
01723               } while (zend_hash_add(EG(function_table), function_name, function_name_length+1, &new_function, sizeof(zend_function), NULL)==FAILURE);
01724               zend_hash_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME));
01725               RETURN_STRINGL(function_name, function_name_length, 0);
01726        } else {
01727               zend_hash_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME));
01728               RETURN_FALSE;
01729        }
01730 }
01731 /* }}} */
01732 
01733 
01734 #if ZEND_DEBUG
01735 ZEND_FUNCTION(zend_test_func)
01736 {
01737        zval *arg1, *arg2;
01738 
01739        zend_get_parameters(ht, 2, &arg1, &arg2);
01740 }
01741 
01742 
01743 #ifdef ZTS
01744 ZEND_FUNCTION(zend_thread_id)
01745 {
01746        RETURN_LONG((long)tsrm_thread_id());
01747 }
01748 #endif
01749 #endif
01750 
01751 /* {{{ proto string get_resource_type(resource res)
01752    Get the resource type name for a given resource */
01753 ZEND_FUNCTION(get_resource_type)
01754 {
01755        char *resource_type;
01756        zval *z_resource_type;
01757 
01758        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_resource_type) == FAILURE) {
01759               return;
01760        }
01761 
01762        resource_type = zend_rsrc_list_get_rsrc_type(Z_LVAL_P(z_resource_type) TSRMLS_CC);
01763        if (resource_type) {
01764               RETURN_STRING(resource_type, 1);
01765        } else {
01766               RETURN_STRING("Unknown", 1);
01767        }
01768 }
01769 /* }}} */
01770 
01771 
01772 static int add_extension_info(zend_module_entry *module, void *arg TSRMLS_DC)
01773 {
01774        zval *name_array = (zval *)arg;
01775        add_next_index_string(name_array, module->name, 1);
01776        return 0;
01777 }
01778 
01779 static int add_zendext_info(zend_extension *ext, void *arg TSRMLS_DC)
01780 {
01781        zval *name_array = (zval *)arg;
01782        add_next_index_string(name_array, ext->name, 1);
01783        return 0;
01784 }
01785 
01786 static int add_constant_info(zend_constant *constant, void *arg TSRMLS_DC)
01787 {
01788        zval *name_array = (zval *)arg;
01789        zval *const_val;
01790 
01791        MAKE_STD_ZVAL(const_val);
01792        *const_val = constant->value;
01793        zval_copy_ctor(const_val);
01794        INIT_PZVAL(const_val);
01795        add_assoc_zval_ex(name_array, constant->name, constant->name_len, const_val);
01796        return 0;
01797 }
01798 
01799 
01800 /* {{{ proto array get_loaded_extensions([bool zend_extensions]) U
01801    Return an array containing names of loaded extensions */
01802 ZEND_FUNCTION(get_loaded_extensions)
01803 {
01804        zend_bool zendext = 0;
01805 
01806        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &zendext) == FAILURE) {
01807               return;
01808        }
01809 
01810        array_init(return_value);
01811 
01812        if (zendext) {
01813               zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) add_zendext_info, return_value TSRMLS_CC);
01814        } else {
01815               zend_hash_apply_with_argument(&module_registry, (apply_func_arg_t) add_extension_info, return_value TSRMLS_CC);
01816        }
01817 }
01818 /* }}} */
01819 
01820 
01821 /* {{{ proto array get_defined_constants([bool categorize])
01822    Return an array containing the names and values of all defined constants */
01823 ZEND_FUNCTION(get_defined_constants)
01824 {
01825        zend_bool categorize = 0;
01826        
01827        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &categorize) == FAILURE) {
01828               return;
01829        }
01830 
01831        array_init(return_value);
01832 
01833        if (categorize) {
01834               HashPosition pos;
01835               zend_constant *val;
01836               int module_number;
01837               zval **modules;
01838               char **module_names;
01839               zend_module_entry *module;
01840               int i = 1;
01841 
01842               modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval *));
01843               module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
01844 
01845               module_names[0] = "internal";
01846               zend_hash_internal_pointer_reset_ex(&module_registry, &pos);
01847               while (zend_hash_get_current_data_ex(&module_registry, (void *) &module, &pos) != FAILURE) {
01848                      module_names[module->module_number] = (char *)module->name;
01849                      i++;
01850                      zend_hash_move_forward_ex(&module_registry, &pos);
01851               }
01852               module_names[i] = "user";
01853 
01854               zend_hash_internal_pointer_reset_ex(EG(zend_constants), &pos);
01855               while (zend_hash_get_current_data_ex(EG(zend_constants), (void **) &val, &pos) != FAILURE) {
01856                      zval *const_val;
01857 
01858                      if (val->module_number == PHP_USER_CONSTANT) {
01859                             module_number = i;
01860                      } else if (val->module_number > i || val->module_number < 0) {
01861                             /* should not happen */
01862                             goto bad_module_id;
01863                      } else {
01864                             module_number = val->module_number;
01865                      }
01866 
01867                      if (!modules[module_number]) {
01868                             MAKE_STD_ZVAL(modules[module_number]);
01869                             array_init(modules[module_number]);
01870                             add_assoc_zval(return_value, module_names[module_number], modules[module_number]);
01871                      }
01872 
01873                      MAKE_STD_ZVAL(const_val);
01874                      *const_val = val->value;
01875                      zval_copy_ctor(const_val);
01876                      INIT_PZVAL(const_val);
01877 
01878                      add_assoc_zval_ex(modules[module_number], val->name, val->name_len, const_val);
01879 bad_module_id:
01880                      zend_hash_move_forward_ex(EG(zend_constants), &pos);
01881               }
01882               efree(module_names);
01883               efree(modules);
01884        } else {
01885               zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) add_constant_info, return_value TSRMLS_CC);
01886        }
01887 }
01888 /* }}} */
01889 
01890 
01891 static zval *debug_backtrace_get_args(void **curpos TSRMLS_DC)
01892 {
01893        void **p = curpos;
01894        zval *arg_array, **arg;
01895        int arg_count = (int)(zend_uintptr_t) *p;
01896 
01897        MAKE_STD_ZVAL(arg_array);
01898        array_init_size(arg_array, arg_count);
01899        p -= arg_count;
01900 
01901        while (--arg_count >= 0) {
01902               arg = (zval **) p++;
01903               if (*arg) {
01904                      if (Z_TYPE_PP(arg) != IS_OBJECT) {
01905                             SEPARATE_ZVAL_TO_MAKE_IS_REF(arg);
01906                      }
01907                      Z_ADDREF_PP(arg);
01908                      add_next_index_zval(arg_array, *arg);
01909               } else {
01910                      add_next_index_null(arg_array);
01911               }
01912        }
01913 
01914        return arg_array;
01915 }
01916 
01917 void debug_print_backtrace_args(zval *arg_array TSRMLS_DC)
01918 {
01919        zval **tmp;
01920        HashPosition iterator;
01921        int i = 0;
01922 
01923        zend_hash_internal_pointer_reset_ex(arg_array->value.ht, &iterator);
01924        while (zend_hash_get_current_data_ex(arg_array->value.ht, (void **) &tmp, &iterator) == SUCCESS) {
01925               if (i++) {
01926                      ZEND_PUTS(", ");
01927               }
01928               zend_print_flat_zval_r(*tmp TSRMLS_CC);
01929               zend_hash_move_forward_ex(arg_array->value.ht, &iterator);
01930        }
01931 }
01932 
01933 /* {{{ proto void debug_print_backtrace([int options]) */
01934 ZEND_FUNCTION(debug_print_backtrace)
01935 {
01936        zend_execute_data *ptr, *skip;
01937        int lineno;
01938        char *function_name;
01939        char *filename;
01940        char *class_name = NULL;
01941        char *call_type;
01942        char *include_filename = NULL;
01943        zval *arg_array = NULL;
01944        int indent = 0;
01945        long options = 0;
01946 
01947        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &options) == FAILURE) {
01948               return;
01949        }
01950 
01951        ptr = EG(current_execute_data);
01952 
01953        /* skip debug_backtrace() */
01954        ptr = ptr->prev_execute_data;
01955 
01956        while (ptr) {
01957               char *free_class_name = NULL;
01958 
01959               class_name = call_type = NULL;   
01960               arg_array = NULL;
01961 
01962               skip = ptr;
01963               /* skip internal handler */
01964               if (!skip->op_array &&
01965                   skip->prev_execute_data &&
01966                   skip->prev_execute_data->opline &&
01967                   skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
01968                   skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
01969                   skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
01970                      skip = skip->prev_execute_data;
01971               }
01972 
01973               if (skip->op_array) {
01974                      filename = skip->op_array->filename;
01975                      lineno = skip->opline->lineno;
01976               } else {
01977                      filename = NULL;
01978                      lineno = 0;
01979               }
01980 
01981               function_name = ptr->function_state.function->common.function_name;
01982 
01983               if (function_name) {
01984                      if (ptr->object) {
01985                             if (ptr->function_state.function->common.scope) {
01986                                    class_name = ptr->function_state.function->common.scope->name;
01987                             } else {
01988                                    zend_uint class_name_len;
01989                                    int dup;
01990 
01991                                    dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
01992                                    if(!dup) {
01993                                           free_class_name = class_name;
01994                                    }
01995                             }
01996 
01997                             call_type = "->";
01998                      } else if (ptr->function_state.function->common.scope) {
01999                             class_name = ptr->function_state.function->common.scope->name;
02000                             call_type = "::";
02001                      } else {
02002                             class_name = NULL;
02003                             call_type = NULL;
02004                      }
02005                      if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
02006                             if (ptr->function_state.arguments && (options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
02007                                    arg_array = debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC);
02008                             }
02009                      }
02010               } else {
02011                      /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
02012                      zend_bool build_filename_arg = 1;
02013 
02014                      if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
02015                             /* can happen when calling eval from a custom sapi */
02016                             function_name = "unknown";
02017                             build_filename_arg = 0;
02018                      } else
02019                      switch (Z_LVAL(ptr->opline->op2.u.constant)) {
02020                             case ZEND_EVAL:
02021                                    function_name = "eval";
02022                                    build_filename_arg = 0;
02023                                    break;
02024                             case ZEND_INCLUDE:
02025                                    function_name = "include";
02026                                    break;
02027                             case ZEND_REQUIRE:
02028                                    function_name = "require";
02029                                    break;
02030                             case ZEND_INCLUDE_ONCE:
02031                                    function_name = "include_once";
02032                                    break;
02033                             case ZEND_REQUIRE_ONCE:
02034                                    function_name = "require_once";
02035                                    break;
02036                             default:
02037                                    /* this can actually happen if you use debug_backtrace() in your error_handler and 
02038                                     * you're in the top-scope */
02039                                    function_name = "unknown"; 
02040                                    build_filename_arg = 0;
02041                                    break;
02042                      }
02043 
02044                      if (build_filename_arg && include_filename) {
02045                             MAKE_STD_ZVAL(arg_array);
02046                             array_init(arg_array);
02047                             add_next_index_string(arg_array, include_filename, 1);
02048                      }
02049                      call_type = NULL;
02050               }
02051               zend_printf("#%-2d ", indent);
02052               if (class_name) {
02053                      ZEND_PUTS(class_name);
02054                      ZEND_PUTS(call_type);
02055               }
02056               zend_printf("%s(", function_name);
02057               if (arg_array) {
02058                      debug_print_backtrace_args(arg_array TSRMLS_CC);
02059                      zval_ptr_dtor(&arg_array);
02060               }
02061               if (filename) {
02062                      zend_printf(") called at [%s:%d]\n", filename, lineno);
02063               } else {
02064                      zend_execute_data *prev = skip->prev_execute_data;
02065 
02066                      while (prev) {
02067                             if (prev->function_state.function &&
02068                                    prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
02069                                    prev = NULL;
02070                                    break;
02071                             }                               
02072                             if (prev->op_array) {
02073                                    zend_printf(") called at [%s:%d]\n", prev->op_array->filename, prev->opline->lineno);
02074                                    break;
02075                             }
02076                             prev = prev->prev_execute_data;
02077                      }
02078                      if (!prev) {
02079                             ZEND_PUTS(")\n");
02080                      }
02081               }
02082               include_filename = filename;
02083               ptr = skip->prev_execute_data;
02084               ++indent;
02085               if (free_class_name) {
02086                      efree(free_class_name);
02087               }
02088        }
02089 }
02090 
02091 /* }}} */
02092 
02093 ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options TSRMLS_DC)
02094 {
02095        zend_execute_data *ptr, *skip;
02096        int lineno;
02097        char *function_name;
02098        char *filename;
02099        char *class_name;
02100        char *include_filename = NULL;
02101        zval *stack_frame;
02102 
02103        ptr = EG(current_execute_data);
02104 
02105        /* skip "new Exception()" */
02106        if (ptr && (skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) {
02107               ptr = ptr->prev_execute_data;
02108        }
02109 
02110        /* skip debug_backtrace() */
02111        if (skip_last-- && ptr) {
02112               ptr = ptr->prev_execute_data;
02113        }
02114 
02115        array_init(return_value);
02116 
02117        while (ptr) {
02118               MAKE_STD_ZVAL(stack_frame);
02119               array_init(stack_frame);
02120 
02121               skip = ptr;
02122               /* skip internal handler */
02123               if (!skip->op_array &&
02124                   skip->prev_execute_data &&
02125                   skip->prev_execute_data->opline &&
02126                   skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
02127                   skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
02128                   skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
02129                      skip = skip->prev_execute_data;
02130               }
02131 
02132               if (skip->op_array) {
02133                      filename = skip->op_array->filename;
02134                      lineno = skip->opline->lineno;
02135                      add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1);
02136                      add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno);
02137 
02138                      /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
02139                       * and debug_baktrace() might have been called by the error_handler. in this case we don't 
02140                       * want to pop anything of the argument-stack */
02141               } else {
02142                      zend_execute_data *prev = skip->prev_execute_data;
02143 
02144                      while (prev) {
02145                             if (prev->function_state.function &&
02146                                    prev->function_state.function->common.type != ZEND_USER_FUNCTION &&
02147                                    !(prev->function_state.function->common.type == ZEND_INTERNAL_FUNCTION &&
02148                                           (prev->function_state.function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
02149                                    break;
02150                             }                               
02151                             if (prev->op_array) {
02152                                    add_assoc_string_ex(stack_frame, "file", sizeof("file"), prev->op_array->filename, 1);
02153                                    add_assoc_long_ex(stack_frame, "line", sizeof("line"), prev->opline->lineno);
02154                                    break;
02155                             }
02156                             prev = prev->prev_execute_data;
02157                      }
02158                      filename = NULL;
02159               }
02160 
02161               function_name = ptr->function_state.function->common.function_name;
02162 
02163               if (function_name) {
02164                      add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
02165 
02166                      if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) {
02167                             if (ptr->function_state.function->common.scope) {
02168                                    add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
02169                             } else {
02170                                    zend_uint class_name_len;
02171                                    int dup;
02172 
02173                                    dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
02174                                    add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup);
02175                                    
02176                             }
02177                             if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
02178                                    add_assoc_zval_ex(stack_frame, "object", sizeof("object"), ptr->object);
02179                                    Z_ADDREF_P(ptr->object);
02180                             }
02181 
02182                             add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1);
02183                      } else if (ptr->function_state.function->common.scope) {
02184                             add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
02185                             add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1);
02186                      }
02187 
02188                      if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 && 
02189                             ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL)))) {
02190                             if (ptr->function_state.arguments) {
02191                                    add_assoc_zval_ex(stack_frame, "args", sizeof("args"), debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC));
02192                             }
02193                      }
02194               } else {
02195                      /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
02196                      zend_bool build_filename_arg = 1;
02197 
02198                      if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
02199                             /* can happen when calling eval from a custom sapi */
02200                             function_name = "unknown";
02201                             build_filename_arg = 0;
02202                      } else
02203                      switch (ptr->opline->op2.u.constant.value.lval) {
02204                             case ZEND_EVAL:
02205                                    function_name = "eval";
02206                                    build_filename_arg = 0;
02207                                    break;
02208                             case ZEND_INCLUDE:
02209                                    function_name = "include";
02210                                    break;
02211                             case ZEND_REQUIRE:
02212                                    function_name = "require";
02213                                    break;
02214                             case ZEND_INCLUDE_ONCE:
02215                                    function_name = "include_once";
02216                                    break;
02217                             case ZEND_REQUIRE_ONCE:
02218                                    function_name = "require_once";
02219                                    break;
02220                             default:
02221                                    /* this can actually happen if you use debug_backtrace() in your error_handler and 
02222                                     * you're in the top-scope */
02223                                    function_name = "unknown"; 
02224                                    build_filename_arg = 0;
02225                                    break;
02226                      }
02227 
02228                      if (build_filename_arg && include_filename) {
02229                             zval *arg_array;
02230 
02231                             MAKE_STD_ZVAL(arg_array);
02232                             array_init(arg_array);
02233 
02234                             /* include_filename always points to the last filename of the last last called-fuction.
02235                                if we have called include in the frame above - this is the file we have included.
02236                              */
02237 
02238                             add_next_index_string(arg_array, include_filename, 1);
02239                             add_assoc_zval_ex(stack_frame, "args", sizeof("args"), arg_array);
02240                      }
02241 
02242                      add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
02243               }
02244 
02245               add_next_index_zval(return_value, stack_frame);
02246 
02247               include_filename = filename; 
02248 
02249               ptr = skip->prev_execute_data;
02250        }
02251 }
02252 /* }}} */
02253 
02254 
02255 /* {{{ proto array debug_backtrace([int options])
02256    Return backtrace as array */
02257 ZEND_FUNCTION(debug_backtrace)
02258 {
02259        long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
02260        
02261        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &options) == FAILURE) {
02262               return;
02263        }
02264 
02265        zend_fetch_debug_backtrace(return_value, 1, options TSRMLS_CC);
02266 }
02267 /* }}} */
02268 
02269 /* {{{ proto bool extension_loaded(string extension_name)
02270    Returns true if the named extension is loaded */
02271 ZEND_FUNCTION(extension_loaded)
02272 {
02273        char *extension_name;
02274        int extension_name_len;
02275        char *lcname;
02276 
02277        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) {
02278               return;
02279        }
02280 
02281        lcname = zend_str_tolower_dup(extension_name, extension_name_len);
02282        if (zend_hash_exists(&module_registry, lcname, extension_name_len+1)) {
02283               RETVAL_TRUE;
02284        } else {
02285               RETVAL_FALSE;
02286        }
02287        efree(lcname);
02288 }
02289 /* }}} */
02290 
02291 
02292 /* {{{ proto array get_extension_funcs(string extension_name)
02293    Returns an array with the names of functions belonging to the named extension */
02294 ZEND_FUNCTION(get_extension_funcs)
02295 {
02296        char *extension_name;
02297        int extension_name_len;
02298        zend_module_entry *module;
02299        const zend_function_entry *func;
02300 
02301        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) {
02302               return;
02303        }
02304 
02305        if (strncasecmp(extension_name, "zend", sizeof("zend"))) {
02306               char *lcname = zend_str_tolower_dup(extension_name, extension_name_len);
02307               if (zend_hash_find(&module_registry, lcname,
02308                      extension_name_len+1, (void**)&module) == FAILURE) {
02309                      efree(lcname);
02310                      RETURN_FALSE;
02311               }
02312               efree(lcname);
02313 
02314               if (!(func = module->functions)) {
02315                      RETURN_FALSE;
02316               }
02317        } else {
02318               func = builtin_functions;
02319        }
02320 
02321        array_init(return_value);
02322 
02323        while (func->fname) {
02324               add_next_index_string(return_value, func->fname, 1);
02325               func++;
02326        }
02327 }
02328 /* }}} */
02329 
02330 /*
02331  * Local variables:
02332  * tab-width: 4
02333  * c-basic-offset: 4
02334  * indent-tabs-mode: t
02335  * End:
02336  */