File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / zend_builtin_functions.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:35 2012 UTC (12 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, HEAD
php 5.4.3+patches

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | Zend Engine                                                          |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
    6:    +----------------------------------------------------------------------+
    7:    | This source file is subject to version 2.00 of the Zend license,     |
    8:    | that is bundled with this package in the file LICENSE, and is        |
    9:    | available through the world-wide-web at the following url:           |
   10:    | http://www.zend.com/license/2_00.txt.                                |
   11:    | If you did not receive a copy of the Zend license and are unable to  |
   12:    | obtain it through the world-wide-web, please send a note to          |
   13:    | license@zend.com so we can mail you a copy immediately.              |
   14:    +----------------------------------------------------------------------+
   15:    | Authors: Andi Gutmans <andi@zend.com>                                |
   16:    |          Zeev Suraski <zeev@zend.com>                                |
   17:    +----------------------------------------------------------------------+
   18: */
   19: 
   20: /* $Id: zend_builtin_functions.c,v 1.1.1.2 2012/05/29 12:34:35 misho Exp $ */
   21: 
   22: #include "zend.h"
   23: #include "zend_API.h"
   24: #include "zend_builtin_functions.h"
   25: #include "zend_constants.h"
   26: #include "zend_ini.h"
   27: #include "zend_exceptions.h"
   28: #include "zend_extensions.h"
   29: #include "zend_closures.h"
   30: 
   31: #undef ZEND_TEST_EXCEPTIONS
   32: 
   33: static ZEND_FUNCTION(zend_version);
   34: static ZEND_FUNCTION(func_num_args);
   35: static ZEND_FUNCTION(func_get_arg);
   36: static ZEND_FUNCTION(func_get_args);
   37: static ZEND_FUNCTION(strlen);
   38: static ZEND_FUNCTION(strcmp);
   39: static ZEND_FUNCTION(strncmp);
   40: static ZEND_FUNCTION(strcasecmp);
   41: static ZEND_FUNCTION(strncasecmp);
   42: static ZEND_FUNCTION(each);
   43: static ZEND_FUNCTION(error_reporting);
   44: static ZEND_FUNCTION(define);
   45: static ZEND_FUNCTION(defined);
   46: static ZEND_FUNCTION(get_class);
   47: static ZEND_FUNCTION(get_called_class);
   48: static ZEND_FUNCTION(get_parent_class);
   49: static ZEND_FUNCTION(method_exists);
   50: static ZEND_FUNCTION(property_exists);
   51: static ZEND_FUNCTION(class_exists);
   52: static ZEND_FUNCTION(interface_exists);
   53: static ZEND_FUNCTION(trait_exists);
   54: static ZEND_FUNCTION(function_exists);
   55: static ZEND_FUNCTION(class_alias);
   56: #if ZEND_DEBUG
   57: static ZEND_FUNCTION(leak);
   58: static ZEND_FUNCTION(leak_variable);
   59: #ifdef ZEND_TEST_EXCEPTIONS
   60: static ZEND_FUNCTION(crash);
   61: #endif
   62: #endif
   63: static ZEND_FUNCTION(get_included_files);
   64: static ZEND_FUNCTION(is_subclass_of);
   65: static ZEND_FUNCTION(is_a);
   66: static ZEND_FUNCTION(get_class_vars);
   67: static ZEND_FUNCTION(get_object_vars);
   68: static ZEND_FUNCTION(get_class_methods);
   69: static ZEND_FUNCTION(trigger_error);
   70: static ZEND_FUNCTION(set_error_handler);
   71: static ZEND_FUNCTION(restore_error_handler);
   72: static ZEND_FUNCTION(set_exception_handler);
   73: static ZEND_FUNCTION(restore_exception_handler);
   74: static ZEND_FUNCTION(get_declared_classes);
   75: static ZEND_FUNCTION(get_declared_traits);
   76: static ZEND_FUNCTION(get_declared_interfaces);
   77: static ZEND_FUNCTION(get_defined_functions);
   78: static ZEND_FUNCTION(get_defined_vars);
   79: static ZEND_FUNCTION(create_function);
   80: static ZEND_FUNCTION(get_resource_type);
   81: static ZEND_FUNCTION(get_loaded_extensions);
   82: static ZEND_FUNCTION(extension_loaded);
   83: static ZEND_FUNCTION(get_extension_funcs);
   84: static ZEND_FUNCTION(get_defined_constants);
   85: static ZEND_FUNCTION(debug_backtrace);
   86: static ZEND_FUNCTION(debug_print_backtrace);
   87: #if ZEND_DEBUG
   88: static ZEND_FUNCTION(zend_test_func);
   89: #ifdef ZTS
   90: static ZEND_FUNCTION(zend_thread_id);
   91: #endif
   92: #endif
   93: static ZEND_FUNCTION(gc_collect_cycles);
   94: static ZEND_FUNCTION(gc_enabled);
   95: static ZEND_FUNCTION(gc_enable);
   96: static ZEND_FUNCTION(gc_disable);
   97: 
   98: /* {{{ arginfo */
   99: ZEND_BEGIN_ARG_INFO(arginfo_zend__void, 0)
  100: ZEND_END_ARG_INFO()
  101: 
  102: ZEND_BEGIN_ARG_INFO_EX(arginfo_func_get_arg, 0, 0, 1)
  103: 	ZEND_ARG_INFO(0, arg_num)
  104: ZEND_END_ARG_INFO()
  105: 
  106: ZEND_BEGIN_ARG_INFO_EX(arginfo_strlen, 0, 0, 1)
  107: 	ZEND_ARG_INFO(0, str)
  108: ZEND_END_ARG_INFO()
  109: 
  110: ZEND_BEGIN_ARG_INFO_EX(arginfo_strcmp, 0, 0, 2)
  111: 	ZEND_ARG_INFO(0, str1)
  112: 	ZEND_ARG_INFO(0, str2)
  113: ZEND_END_ARG_INFO()
  114: 
  115: ZEND_BEGIN_ARG_INFO_EX(arginfo_strncmp, 0, 0, 3)
  116: 	ZEND_ARG_INFO(0, str1)
  117: 	ZEND_ARG_INFO(0, str2)
  118: 	ZEND_ARG_INFO(0, len)
  119: ZEND_END_ARG_INFO()
  120: 
  121: ZEND_BEGIN_ARG_INFO_EX(arginfo_each, 0, 0, 1)
  122: 	ZEND_ARG_INFO(1, arr)
  123: ZEND_END_ARG_INFO()
  124: 
  125: ZEND_BEGIN_ARG_INFO_EX(arginfo_error_reporting, 0, 0, 0)
  126: 	ZEND_ARG_INFO(0, new_error_level)
  127: ZEND_END_ARG_INFO()
  128: 
  129: ZEND_BEGIN_ARG_INFO_EX(arginfo_define, 0, 0, 3)
  130: 	ZEND_ARG_INFO(0, constant_name)
  131: 	ZEND_ARG_INFO(0, value)
  132: 	ZEND_ARG_INFO(0, case_insensitive)
  133: ZEND_END_ARG_INFO()
  134: 
  135: ZEND_BEGIN_ARG_INFO_EX(arginfo_defined, 0, 0, 1)
  136: 	ZEND_ARG_INFO(0, constant_name)
  137: ZEND_END_ARG_INFO()
  138: 
  139: ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class, 0, 0, 0)
  140: 	ZEND_ARG_INFO(0, object)
  141: ZEND_END_ARG_INFO()
  142: 
  143: ZEND_BEGIN_ARG_INFO_EX(arginfo_is_subclass_of, 0, 0, 2)
  144: 	ZEND_ARG_INFO(0, object)
  145: 	ZEND_ARG_INFO(0, class_name)
  146: 	ZEND_ARG_INFO(0, allow_string)
  147: ZEND_END_ARG_INFO()
  148: 
  149: ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_vars, 0, 0, 1)
  150: 	ZEND_ARG_INFO(0, class_name)
  151: ZEND_END_ARG_INFO()
  152: 
  153: ZEND_BEGIN_ARG_INFO_EX(arginfo_get_object_vars, 0, 0, 1)
  154: 	ZEND_ARG_INFO(0, obj)
  155: ZEND_END_ARG_INFO()
  156: 
  157: ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_methods, 0, 0, 1)
  158: 	ZEND_ARG_INFO(0, class)
  159: ZEND_END_ARG_INFO()
  160: 
  161: ZEND_BEGIN_ARG_INFO_EX(arginfo_method_exists, 0, 0, 2)
  162: 	ZEND_ARG_INFO(0, object)
  163: 	ZEND_ARG_INFO(0, method)
  164: ZEND_END_ARG_INFO()
  165: 
  166: ZEND_BEGIN_ARG_INFO_EX(arginfo_property_exists, 0, 0, 2)
  167: 	ZEND_ARG_INFO(0, object_or_class)
  168: 	ZEND_ARG_INFO(0, property_name)
  169: ZEND_END_ARG_INFO()
  170: 
  171: ZEND_BEGIN_ARG_INFO_EX(arginfo_class_exists, 0, 0, 1)
  172: 	ZEND_ARG_INFO(0, classname)
  173: 	ZEND_ARG_INFO(0, autoload)
  174: ZEND_END_ARG_INFO()
  175: 
  176: ZEND_BEGIN_ARG_INFO_EX(arginfo_trait_exists, 0, 0, 1)
  177: 	ZEND_ARG_INFO(0, traitname)
  178: 	ZEND_ARG_INFO(0, autoload)
  179: ZEND_END_ARG_INFO()
  180: 
  181: ZEND_BEGIN_ARG_INFO_EX(arginfo_function_exists, 0, 0, 1)
  182: 	ZEND_ARG_INFO(0, function_name)
  183: ZEND_END_ARG_INFO()
  184: 
  185: ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2)
  186: 	ZEND_ARG_INFO(0, user_class_name)
  187: 	ZEND_ARG_INFO(0, alias_name)
  188: 	ZEND_ARG_INFO(0, autoload)
  189: ZEND_END_ARG_INFO()
  190: 
  191: #if ZEND_DEBUG
  192: ZEND_BEGIN_ARG_INFO_EX(arginfo_leak_variable, 0, 0, 1)
  193: 	ZEND_ARG_INFO(0, variable)
  194: 	ZEND_ARG_INFO(0, leak_data)
  195: ZEND_END_ARG_INFO()
  196: #endif
  197: 
  198: ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1)
  199: 	ZEND_ARG_INFO(0, message)
  200: 	ZEND_ARG_INFO(0, error_type)
  201: ZEND_END_ARG_INFO()
  202: 
  203: ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1)
  204: 	ZEND_ARG_INFO(0, error_handler)
  205: 	ZEND_ARG_INFO(0, error_types)
  206: ZEND_END_ARG_INFO()
  207: 
  208: ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1)
  209: 	ZEND_ARG_INFO(0, exception_handler)
  210: ZEND_END_ARG_INFO()
  211: 
  212: ZEND_BEGIN_ARG_INFO_EX(arginfo_create_function, 0, 0, 2)
  213: 	ZEND_ARG_INFO(0, args)
  214: 	ZEND_ARG_INFO(0, code)
  215: ZEND_END_ARG_INFO()
  216: 
  217: ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1)
  218: 	ZEND_ARG_INFO(0, res)
  219: ZEND_END_ARG_INFO()
  220: 
  221: ZEND_BEGIN_ARG_INFO_EX(arginfo_get_loaded_extensions, 0, 0, 0)
  222: 	ZEND_ARG_INFO(0, zend_extensions)
  223: ZEND_END_ARG_INFO()
  224: 
  225: ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0)
  226: 	ZEND_ARG_INFO(0, categorize)
  227: ZEND_END_ARG_INFO()
  228: 
  229: ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0)
  230: 	ZEND_ARG_INFO(0, options)
  231: 	ZEND_ARG_INFO(0, limit)
  232: ZEND_END_ARG_INFO()
  233: 
  234: ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_print_backtrace, 0, 0, 0)
  235: 	ZEND_ARG_INFO(0, options)
  236: ZEND_END_ARG_INFO()
  237: 
  238: ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1)
  239: 	ZEND_ARG_INFO(0, extension_name)
  240: ZEND_END_ARG_INFO()
  241: /* }}} */
  242: 
  243: static const zend_function_entry builtin_functions[] = { /* {{{ */
  244: 	ZEND_FE(zend_version,		arginfo_zend__void)
  245: 	ZEND_FE(func_num_args,		arginfo_zend__void)
  246: 	ZEND_FE(func_get_arg,		arginfo_func_get_arg)
  247: 	ZEND_FE(func_get_args,		arginfo_zend__void)
  248: 	ZEND_FE(strlen,				arginfo_strlen)
  249: 	ZEND_FE(strcmp,				arginfo_strcmp)
  250: 	ZEND_FE(strncmp,			arginfo_strncmp)
  251: 	ZEND_FE(strcasecmp,			arginfo_strcmp)
  252: 	ZEND_FE(strncasecmp,		arginfo_strncmp)
  253: 	ZEND_FE(each,				arginfo_each)
  254: 	ZEND_FE(error_reporting,	arginfo_error_reporting)
  255: 	ZEND_FE(define,				arginfo_define)
  256: 	ZEND_FE(defined,			arginfo_defined)
  257: 	ZEND_FE(get_class,			arginfo_get_class)
  258: 	ZEND_FE(get_called_class,	arginfo_zend__void)
  259: 	ZEND_FE(get_parent_class,	arginfo_get_class)
  260: 	ZEND_FE(method_exists,		arginfo_method_exists)
  261: 	ZEND_FE(property_exists,	arginfo_property_exists)
  262: 	ZEND_FE(class_exists,		arginfo_class_exists)
  263: 	ZEND_FE(interface_exists,	arginfo_class_exists)
  264: 	ZEND_FE(trait_exists,		arginfo_trait_exists)
  265: 	ZEND_FE(function_exists,	arginfo_function_exists)
  266: 	ZEND_FE(class_alias,		arginfo_class_alias)
  267: #if ZEND_DEBUG
  268: 	ZEND_FE(leak,				NULL)
  269: 	ZEND_FE(leak_variable,		arginfo_leak_variable)
  270: #ifdef ZEND_TEST_EXCEPTIONS
  271: 	ZEND_FE(crash,				NULL)
  272: #endif
  273: #endif
  274: 	ZEND_FE(get_included_files,	arginfo_zend__void)
  275: 	ZEND_FALIAS(get_required_files,	get_included_files,		arginfo_zend__void)
  276: 	ZEND_FE(is_subclass_of,		arginfo_is_subclass_of)
  277: 	ZEND_FE(is_a,				arginfo_is_subclass_of)
  278: 	ZEND_FE(get_class_vars,		arginfo_get_class_vars)
  279: 	ZEND_FE(get_object_vars,	arginfo_get_object_vars)
  280: 	ZEND_FE(get_class_methods,	arginfo_get_class_methods)
  281: 	ZEND_FE(trigger_error,		arginfo_trigger_error)
  282: 	ZEND_FALIAS(user_error,		trigger_error,		arginfo_trigger_error)
  283: 	ZEND_FE(set_error_handler,			arginfo_set_error_handler)
  284: 	ZEND_FE(restore_error_handler,		arginfo_zend__void)
  285: 	ZEND_FE(set_exception_handler,		arginfo_set_exception_handler)
  286: 	ZEND_FE(restore_exception_handler,	arginfo_zend__void)
  287: 	ZEND_FE(get_declared_classes, 		arginfo_zend__void)
  288: 	ZEND_FE(get_declared_traits, 		arginfo_zend__void)
  289: 	ZEND_FE(get_declared_interfaces, 	arginfo_zend__void)
  290: 	ZEND_FE(get_defined_functions, 		arginfo_zend__void)
  291: 	ZEND_FE(get_defined_vars,			arginfo_zend__void)
  292: 	ZEND_FE(create_function,			arginfo_create_function)
  293: 	ZEND_FE(get_resource_type,			arginfo_get_resource_type)
  294: 	ZEND_FE(get_loaded_extensions,		arginfo_get_loaded_extensions)
  295: 	ZEND_FE(extension_loaded,			arginfo_extension_loaded)
  296: 	ZEND_FE(get_extension_funcs,		arginfo_extension_loaded)
  297: 	ZEND_FE(get_defined_constants,		arginfo_get_defined_constants)
  298: 	ZEND_FE(debug_backtrace, 			arginfo_debug_backtrace)
  299: 	ZEND_FE(debug_print_backtrace, 		arginfo_debug_print_backtrace)
  300: #if ZEND_DEBUG
  301: 	ZEND_FE(zend_test_func,		NULL)
  302: #ifdef ZTS
  303: 	ZEND_FE(zend_thread_id,		NULL)
  304: #endif
  305: #endif
  306: 	ZEND_FE(gc_collect_cycles, 	arginfo_zend__void)
  307: 	ZEND_FE(gc_enabled, 		arginfo_zend__void)
  308: 	ZEND_FE(gc_enable, 			arginfo_zend__void)
  309: 	ZEND_FE(gc_disable, 		arginfo_zend__void)
  310: 	ZEND_FE_END
  311: };
  312: /* }}} */
  313: 
  314: ZEND_MINIT_FUNCTION(core) { /* {{{ */
  315: 	zend_class_entry class_entry;
  316: 
  317: 	INIT_CLASS_ENTRY(class_entry, "stdClass", NULL);
  318: 	zend_standard_class_def = zend_register_internal_class(&class_entry TSRMLS_CC);
  319: 
  320: 	zend_register_default_classes(TSRMLS_C);
  321: 
  322: 	return SUCCESS;
  323: }
  324: /* }}} */
  325: 
  326: zend_module_entry zend_builtin_module = { /* {{{ */
  327:     STANDARD_MODULE_HEADER,
  328: 	"Core",
  329: 	builtin_functions,
  330: 	ZEND_MINIT(core),
  331: 	NULL,
  332: 	NULL,
  333: 	NULL,
  334: 	NULL,
  335: 	ZEND_VERSION,
  336: 	STANDARD_MODULE_PROPERTIES
  337: };
  338: /* }}} */
  339: 
  340: int zend_startup_builtin_functions(TSRMLS_D) /* {{{ */
  341: {
  342: 	zend_builtin_module.module_number = 0;
  343: 	zend_builtin_module.type = MODULE_PERSISTENT;
  344: 	return (EG(current_module) = zend_register_module_ex(&zend_builtin_module TSRMLS_CC)) == NULL ? FAILURE : SUCCESS;
  345: }
  346: /* }}} */
  347: 
  348: /* {{{ proto string zend_version(void)
  349:    Get the version of the Zend Engine */
  350: ZEND_FUNCTION(zend_version)
  351: {
  352: 	RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1, 1);
  353: }
  354: /* }}} */
  355: 
  356: /* {{{ proto int gc_collect_cycles(void)
  357:    Forces collection of any existing garbage cycles.
  358:    Returns number of freed zvals */
  359: ZEND_FUNCTION(gc_collect_cycles)
  360: {
  361: 	RETURN_LONG(gc_collect_cycles(TSRMLS_C));
  362: }
  363: /* }}} */
  364: 
  365: /* {{{ proto void gc_enabled(void)
  366:    Returns status of the circular reference collector */
  367: ZEND_FUNCTION(gc_enabled)
  368: {
  369: 	RETURN_BOOL(GC_G(gc_enabled));
  370: }
  371: /* }}} */
  372: 
  373: /* {{{ proto void gc_enable(void)
  374:    Activates the circular reference collector */
  375: ZEND_FUNCTION(gc_enable)
  376: {
  377: 	zend_alter_ini_entry("zend.enable_gc", sizeof("zend.enable_gc"), "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
  378: }
  379: /* }}} */
  380: 
  381: /* {{{ proto void gc_disable(void)
  382:    Deactivates the circular reference collector */
  383: ZEND_FUNCTION(gc_disable)
  384: {
  385: 	zend_alter_ini_entry("zend.enable_gc", sizeof("zend.enable_gc"), "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
  386: }
  387: /* }}} */
  388: 
  389: /* {{{ proto int func_num_args(void)
  390:    Get the number of arguments that were passed to the function */
  391: ZEND_FUNCTION(func_num_args)
  392: {
  393: 	zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
  394: 
  395: 	if (ex && ex->function_state.arguments) {
  396: 		RETURN_LONG((long)(zend_uintptr_t)*(ex->function_state.arguments));
  397: 	} else {
  398: 		zend_error(E_WARNING, "func_num_args():  Called from the global scope - no function context");
  399: 		RETURN_LONG(-1);
  400: 	}
  401: }
  402: /* }}} */
  403: 
  404: 
  405: /* {{{ proto mixed func_get_arg(int arg_num)
  406:    Get the $arg_num'th argument that was passed to the function */
  407: ZEND_FUNCTION(func_get_arg)
  408: {
  409: 	void **p;
  410: 	int arg_count;
  411: 	zval *arg;
  412: 	long requested_offset;
  413: 	zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
  414: 
  415: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &requested_offset) == FAILURE) {
  416: 		return;
  417: 	}
  418: 
  419: 	if (requested_offset < 0) {
  420: 		zend_error(E_WARNING, "func_get_arg():  The argument number should be >= 0");
  421: 		RETURN_FALSE;
  422: 	}
  423: 
  424: 	if (!ex || !ex->function_state.arguments) {
  425: 		zend_error(E_WARNING, "func_get_arg():  Called from the global scope - no function context");
  426: 		RETURN_FALSE;
  427: 	}
  428: 
  429: 	p = ex->function_state.arguments;
  430: 	arg_count = (int)(zend_uintptr_t) *p;		/* this is the amount of arguments passed to func_get_arg(); */
  431: 
  432: 	if (requested_offset >= arg_count) {
  433: 		zend_error(E_WARNING, "func_get_arg():  Argument %ld not passed to function", requested_offset);
  434: 		RETURN_FALSE;
  435: 	}
  436: 
  437: 	arg = *(p-(arg_count-requested_offset));
  438: 	*return_value = *arg;
  439: 	zval_copy_ctor(return_value);
  440: 	INIT_PZVAL(return_value);
  441: }
  442: /* }}} */
  443: 
  444: 
  445: /* {{{ proto array func_get_args()
  446:    Get an array of the arguments that were passed to the function */
  447: ZEND_FUNCTION(func_get_args)
  448: {
  449: 	void **p;
  450: 	int arg_count;
  451: 	int i;
  452: 	zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
  453: 
  454: 	if (!ex || !ex->function_state.arguments) {
  455: 		zend_error(E_WARNING, "func_get_args():  Called from the global scope - no function context");
  456: 		RETURN_FALSE;
  457: 	}
  458: 
  459: 	p = ex->function_state.arguments;
  460: 	arg_count = (int)(zend_uintptr_t) *p;		/* this is the amount of arguments passed to func_get_args(); */
  461: 
  462: 	array_init_size(return_value, arg_count);
  463: 	for (i=0; i<arg_count; i++) {
  464: 		zval *element;
  465: 
  466: 		ALLOC_ZVAL(element);
  467: 		*element = **((zval **) (p-(arg_count-i)));
  468: 		zval_copy_ctor(element);
  469: 		INIT_PZVAL(element);
  470: 		zend_hash_next_index_insert(return_value->value.ht, &element, sizeof(zval *), NULL);
  471: 	}
  472: }
  473: /* }}} */
  474: 
  475: 
  476: /* {{{ proto int strlen(string str)
  477:    Get string length */
  478: ZEND_FUNCTION(strlen)
  479: {
  480: 	char *s1;
  481: 	int s1_len;
  482: 
  483: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &s1, &s1_len) == FAILURE) {
  484: 		return;
  485: 	}
  486: 
  487: 	RETVAL_LONG(s1_len);
  488: }
  489: /* }}} */
  490: 
  491: 
  492: /* {{{ proto int strcmp(string str1, string str2)
  493:    Binary safe string comparison */
  494: ZEND_FUNCTION(strcmp)
  495: {
  496: 	char *s1, *s2;
  497: 	int s1_len, s2_len;
  498: 	
  499: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &s1_len, &s2, &s2_len) == FAILURE) {
  500: 		return;
  501: 	}
  502: 
  503: 	RETURN_LONG(zend_binary_strcmp(s1, s1_len, s2, s2_len));
  504: }
  505: /* }}} */
  506: 
  507: 
  508: /* {{{ proto int strncmp(string str1, string str2, int len)
  509:    Binary safe string comparison */
  510: ZEND_FUNCTION(strncmp)
  511: {
  512: 	char *s1, *s2;
  513: 	int s1_len, s2_len;
  514: 	long len;
  515: 
  516: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &s1, &s1_len, &s2, &s2_len, &len) == FAILURE) {
  517: 		return;
  518: 	}
  519: 
  520: 	if (len < 0) {
  521: 		zend_error(E_WARNING, "Length must be greater than or equal to 0");
  522: 		RETURN_FALSE;
  523: 	}
  524: 
  525: 	RETURN_LONG(zend_binary_strncmp(s1, s1_len, s2, s2_len, len));
  526: }
  527: /* }}} */
  528: 
  529: 
  530: /* {{{ proto int strcasecmp(string str1, string str2)
  531:    Binary safe case-insensitive string comparison */
  532: ZEND_FUNCTION(strcasecmp)
  533: {
  534: 	char *s1, *s2;
  535: 	int s1_len, s2_len;
  536: 	
  537: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &s1_len, &s2, &s2_len) == FAILURE) {
  538: 		return;
  539: 	}
  540: 
  541: 	RETURN_LONG(zend_binary_strcasecmp(s1, s1_len, s2, s2_len));
  542: }
  543: /* }}} */
  544: 
  545: 
  546: /* {{{ proto int strncasecmp(string str1, string str2, int len)
  547:    Binary safe string comparison */
  548: ZEND_FUNCTION(strncasecmp)
  549: {
  550: 	char *s1, *s2;
  551: 	int s1_len, s2_len;
  552: 	long len;
  553: 
  554: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &s1, &s1_len, &s2, &s2_len, &len) == FAILURE) {
  555: 		return;
  556: 	}
  557: 
  558: 	if (len < 0) {
  559: 		zend_error(E_WARNING, "Length must be greater than or equal to 0");
  560: 		RETURN_FALSE;
  561: 	}
  562: 
  563: 	RETURN_LONG(zend_binary_strncasecmp(s1, s1_len, s2, s2_len, len));
  564: }
  565: /* }}} */
  566: 
  567: 
  568: /* {{{ proto array each(array arr)
  569:    Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element */
  570: ZEND_FUNCTION(each)
  571: {
  572: 	zval *array, *entry, **entry_ptr, *tmp;
  573: 	char *string_key;
  574: 	uint string_key_len;
  575: 	ulong num_key;
  576: 	zval **inserted_pointer;
  577: 	HashTable *target_hash;
  578: 
  579: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &array) == FAILURE) {
  580: 		return;
  581: 	}
  582: 
  583: 	target_hash = HASH_OF(array);
  584: 	if (!target_hash) {
  585: 		zend_error(E_WARNING,"Variable passed to each() is not an array or object");
  586: 		return;
  587: 	}
  588: 	if (zend_hash_get_current_data(target_hash, (void **) &entry_ptr)==FAILURE) {
  589: 		RETURN_FALSE;
  590: 	}
  591: 	array_init(return_value);
  592: 	entry = *entry_ptr;
  593: 
  594: 	/* add value elements */
  595: 	if (Z_ISREF_P(entry)) {
  596: 		ALLOC_ZVAL(tmp);
  597: 		*tmp = *entry;
  598: 		zval_copy_ctor(tmp);
  599: 		Z_UNSET_ISREF_P(tmp);
  600: 		Z_SET_REFCOUNT_P(tmp, 0);
  601: 		entry=tmp;
  602: 	}
  603: 	zend_hash_index_update(return_value->value.ht, 1, &entry, sizeof(zval *), NULL);
  604: 	Z_ADDREF_P(entry);
  605: 	zend_hash_update(return_value->value.ht, "value", sizeof("value"), &entry, sizeof(zval *), NULL);
  606: 	Z_ADDREF_P(entry);
  607: 
  608: 	/* add the key elements */
  609: 	switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 1, NULL)) {
  610: 		case HASH_KEY_IS_STRING:
  611: 			add_get_index_stringl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, 0);
  612: 			break;
  613: 		case HASH_KEY_IS_LONG:
  614: 			add_get_index_long(return_value, 0, num_key, (void **) &inserted_pointer);
  615: 			break;
  616: 	}
  617: 	zend_hash_update(return_value->value.ht, "key", sizeof("key"), inserted_pointer, sizeof(zval *), NULL);
  618: 	Z_ADDREF_PP(inserted_pointer);
  619: 	zend_hash_move_forward(target_hash);
  620: }
  621: /* }}} */
  622: 
  623: 
  624: /* {{{ proto int error_reporting([int new_error_level])
  625:    Return the current error_reporting level, and if an argument was passed - change to the new level */
  626: ZEND_FUNCTION(error_reporting)
  627: {
  628: 	char *err;
  629: 	int err_len;
  630: 	int old_error_reporting;
  631: 
  632: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &err, &err_len) == FAILURE) {
  633: 		return;
  634: 	}
  635: 
  636: 	old_error_reporting = EG(error_reporting);
  637: 	if(ZEND_NUM_ARGS() != 0) {
  638: 		zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), err, err_len, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
  639: 	}
  640: 
  641: 	RETVAL_LONG(old_error_reporting);
  642: }
  643: /* }}} */
  644: 
  645: 
  646: /* {{{ proto bool define(string constant_name, mixed value, boolean case_insensitive=false)
  647:    Define a new constant */
  648: ZEND_FUNCTION(define)
  649: {
  650: 	char *name;
  651: 	int name_len;
  652: 	zval *val;
  653: 	zval *val_free = NULL;
  654: 	zend_bool non_cs = 0;
  655: 	int case_sensitive = CONST_CS;
  656: 	zend_constant c;
  657: 
  658: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &name, &name_len, &val, &non_cs) == FAILURE) {
  659: 		return;
  660: 	}
  661: 
  662: 	if(non_cs) {
  663: 		case_sensitive = 0;
  664: 	}
  665: 
  666: 	/* class constant, check if there is name and make sure class is valid & exists */
  667: 	if (zend_memnstr(name, "::", sizeof("::") - 1, name + name_len)) {
  668: 		zend_error(E_WARNING, "Class constants cannot be defined or redefined");
  669: 		RETURN_FALSE;
  670: 	}
  671: 
  672: repeat:
  673: 	switch (Z_TYPE_P(val)) {
  674: 		case IS_LONG:
  675: 		case IS_DOUBLE:
  676: 		case IS_STRING:
  677: 		case IS_BOOL:
  678: 		case IS_RESOURCE:
  679: 		case IS_NULL:
  680: 			break;
  681: 		case IS_OBJECT:
  682: 			if (!val_free) {
  683: 				if (Z_OBJ_HT_P(val)->get) {
  684: 					val_free = val = Z_OBJ_HT_P(val)->get(val TSRMLS_CC);
  685: 					goto repeat;
  686: 				} else if (Z_OBJ_HT_P(val)->cast_object) {
  687: 					ALLOC_INIT_ZVAL(val_free);
  688: 					if (Z_OBJ_HT_P(val)->cast_object(val, val_free, IS_STRING TSRMLS_CC) == SUCCESS) {
  689: 						val = val_free;
  690: 						break;
  691: 					}
  692: 				}
  693: 			}
  694: 			/* no break */
  695: 		default:
  696: 			zend_error(E_WARNING,"Constants may only evaluate to scalar values");
  697: 			if (val_free) {
  698: 				zval_ptr_dtor(&val_free);
  699: 			}
  700: 			RETURN_FALSE;
  701: 	}
  702: 	
  703: 	c.value = *val;
  704: 	zval_copy_ctor(&c.value);
  705: 	if (val_free) {
  706: 		zval_ptr_dtor(&val_free);
  707: 	}
  708: 	c.flags = case_sensitive; /* non persistent */
  709: 	c.name = IS_INTERNED(name) ? name : zend_strndup(name, name_len);
  710: 	if(c.name == NULL) {
  711: 		RETURN_FALSE;
  712: 	}
  713: 	c.name_len = name_len+1;
  714: 	c.module_number = PHP_USER_CONSTANT;
  715: 	if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
  716: 		RETURN_TRUE;
  717: 	} else {
  718: 		RETURN_FALSE;
  719: 	}
  720: }
  721: /* }}} */
  722: 
  723: 
  724: /* {{{ proto bool defined(string constant_name)
  725:    Check whether a constant exists */
  726: ZEND_FUNCTION(defined)
  727: {
  728: 	char *name;
  729: 	int name_len;
  730: 	zval c;
  731: 
  732: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
  733: 		return;
  734: 	}
  735: 	
  736: 	if (zend_get_constant_ex(name, name_len, &c, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) {
  737: 		zval_dtor(&c);
  738: 		RETURN_TRUE;
  739: 	} else {
  740: 		RETURN_FALSE;
  741: 	}
  742: }
  743: /* }}} */
  744: 
  745: 
  746: /* {{{ proto string get_class([object object])
  747:    Retrieves the class name */
  748: ZEND_FUNCTION(get_class)
  749: {
  750: 	zval *obj = NULL;
  751: 	const char *name = "";
  752: 	zend_uint name_len = 0;
  753: 	int dup;
  754: 
  755: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|o!", &obj) == FAILURE) {
  756: 		RETURN_FALSE;
  757: 	}
  758: 
  759: 	if (!obj) {
  760: 		if (EG(scope)) {
  761: 			RETURN_STRINGL(EG(scope)->name, EG(scope)->name_length, 1);
  762: 		} else {
  763: 			zend_error(E_WARNING, "get_class() called without object from outside a class");
  764: 			RETURN_FALSE;
  765: 		}
  766: 	}
  767: 
  768: 	dup = zend_get_object_classname(obj, &name, &name_len TSRMLS_CC);
  769: 
  770: 	RETURN_STRINGL(name, name_len, dup);
  771: }
  772: /* }}} */
  773: 
  774: 
  775: /* {{{ proto string get_called_class()
  776:    Retrieves the "Late Static Binding" class name */
  777: ZEND_FUNCTION(get_called_class)
  778: {
  779: 	if (zend_parse_parameters_none() == FAILURE) {
  780: 		return;
  781: 	}
  782: 
  783: 	if (EG(called_scope)) {
  784: 		RETURN_STRINGL(EG(called_scope)->name, EG(called_scope)->name_length, 1);
  785: 	} else if (!EG(scope))  {
  786: 		zend_error(E_WARNING, "get_called_class() called from outside a class");
  787: 	}
  788: 	RETURN_FALSE;
  789: }
  790: /* }}} */
  791: 
  792: 
  793: /* {{{ proto string get_parent_class([mixed object])
  794:    Retrieves the parent class name for object or class or current scope. */
  795: ZEND_FUNCTION(get_parent_class)
  796: {
  797: 	zval *arg;
  798: 	zend_class_entry *ce = NULL;
  799: 	const char *name;
  800: 	zend_uint name_length;
  801: 	
  802: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) {
  803: 		return;
  804: 	}
  805: 
  806: 	if (!ZEND_NUM_ARGS()) {
  807: 		ce = EG(scope);
  808: 		if (ce && ce->parent) {
  809: 			RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
  810: 		} else {
  811: 			RETURN_FALSE;
  812: 		}
  813: 	}
  814: 
  815: 	if (Z_TYPE_P(arg) == IS_OBJECT) {
  816: 		if (Z_OBJ_HT_P(arg)->get_class_name
  817: 			&& Z_OBJ_HT_P(arg)->get_class_name(arg, &name, &name_length, 1 TSRMLS_CC) == SUCCESS) {
  818: 			RETURN_STRINGL(name, name_length, 0);
  819: 		} else {
  820: 			ce = zend_get_class_entry(arg TSRMLS_CC);
  821: 		}
  822: 	} else if (Z_TYPE_P(arg) == IS_STRING) {
  823: 		zend_class_entry **pce;
  824: 		
  825: 		if (zend_lookup_class(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &pce TSRMLS_CC) == SUCCESS) {
  826: 			ce = *pce;
  827: 		}
  828: 	}
  829: 
  830: 	if (ce && ce->parent) {
  831: 		RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
  832: 	} else {
  833: 		RETURN_FALSE;
  834: 	}
  835: }
  836: /* }}} */
  837: 
  838: 
  839: static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
  840: {
  841: 	zval *obj;
  842: 	char *class_name;
  843: 	int class_name_len;
  844: 	zend_class_entry *instance_ce;
  845: 	zend_class_entry **ce;
  846: 	zend_bool allow_string = only_subclass;
  847: 	zend_bool retval;
  848: 
  849: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|b", &obj, &class_name, &class_name_len, &allow_string) == FAILURE) {
  850: 		return;
  851: 	}
  852: 	/*
  853: 	 * allow_string - is_a default is no, is_subclass_of is yes. 
  854: 	 *   if it's allowed, then the autoloader will be called if the class does not exist.
  855: 	 *   default behaviour is different, as 'is_a' used to be used to test mixed return values
  856: 	 *   and there is no easy way to deprecate this.
  857: 	 */
  858: 
  859: 	if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
  860: 		zend_class_entry **the_ce;
  861: 		if (zend_lookup_class(Z_STRVAL_P(obj), Z_STRLEN_P(obj), &the_ce TSRMLS_CC) == FAILURE) {
  862: 			RETURN_FALSE;
  863: 		}
  864: 		instance_ce = *the_ce;
  865: 	} else if (Z_TYPE_P(obj) == IS_OBJECT && HAS_CLASS_ENTRY(*obj)) {
  866: 		instance_ce = Z_OBJCE_P(obj);
  867: 	} else {
  868: 		RETURN_FALSE;
  869: 	}
  870: 
  871: 	if (zend_lookup_class_ex(class_name, class_name_len, NULL, 0, &ce TSRMLS_CC) == FAILURE) {
  872: 		retval = 0;
  873: 	} else {
  874: 		if (only_subclass && instance_ce == *ce) {
  875: 			retval = 0;
  876:  		} else {
  877: 			retval = instanceof_function(instance_ce, *ce TSRMLS_CC);
  878: 		}
  879: 	}
  880: 
  881: 	RETURN_BOOL(retval);
  882: }
  883: 
  884: 
  885: /* {{{ proto bool is_subclass_of(mixed object_or_string, string class_name [, bool allow_string=true])
  886:    Returns true if the object has this class as one of its parents */
  887: ZEND_FUNCTION(is_subclass_of)
  888: {
  889: 	is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  890: }
  891: /* }}} */
  892: 
  893: 
  894: /* {{{ proto bool is_a(mixed object_or_string, string class_name [, bool allow_string=false])
  895:    Returns true if the first argument is an object and is this class or has this class as one of its parents, */
  896: ZEND_FUNCTION(is_a)
  897: {
  898: 	is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  899: }
  900: /* }}} */
  901: 
  902: 
  903: /* {{{ add_class_vars */
  904: static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC)
  905: {
  906: 	HashPosition pos;
  907: 	zend_property_info *prop_info;
  908: 	zval *prop, *prop_copy;
  909: 	char *key;
  910: 	uint key_len;
  911: 	ulong num_index;
  912: 
  913: 	zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
  914: 	while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) {
  915: 		zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos);
  916: 		zend_hash_move_forward_ex(&ce->properties_info, &pos);
  917: 		if (((prop_info->flags & ZEND_ACC_SHADOW) &&
  918: 		     prop_info->ce != EG(scope)) ||
  919: 		    ((prop_info->flags & ZEND_ACC_PROTECTED) &&
  920: 		     !zend_check_protected(prop_info->ce, EG(scope))) ||
  921: 		    ((prop_info->flags & ZEND_ACC_PRIVATE) &&
  922: 		      ce != EG(scope) &&
  923: 			  prop_info->ce != EG(scope))) {
  924: 			continue;
  925: 		}
  926: 		prop = NULL;
  927: 		if (prop_info->offset >= 0) {
  928: 			if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
  929: 				prop = ce->default_static_members_table[prop_info->offset];
  930: 			} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
  931: 				prop = ce->default_properties_table[prop_info->offset];
  932:  			}
  933: 		}
  934: 		if (!prop) {
  935: 			continue;
  936: 		}
  937: 
  938: 		/* copy: enforce read only access */
  939: 		ALLOC_ZVAL(prop_copy);
  940: 		*prop_copy = *prop;
  941: 		zval_copy_ctor(prop_copy);
  942: 		INIT_PZVAL(prop_copy);
  943: 
  944: 		/* this is necessary to make it able to work with default array
  945: 		 * properties, returned to user */
  946: 		if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
  947: 			zval_update_constant(&prop_copy, 0 TSRMLS_CC);
  948: 		}
  949: 
  950: 		add_assoc_zval(return_value, key, prop_copy);
  951: 	}
  952: }
  953: /* }}} */
  954: 
  955: 
  956: /* {{{ proto array get_class_vars(string class_name)
  957:    Returns an array of default properties of the class. */
  958: ZEND_FUNCTION(get_class_vars)
  959: {
  960: 	char *class_name;
  961: 	int class_name_len;
  962: 	zend_class_entry **pce;
  963: 
  964: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) {
  965: 		return;
  966: 	}
  967: 
  968: 	if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
  969: 		RETURN_FALSE;
  970: 	} else {
  971: 		array_init(return_value);
  972: 		zend_update_class_constants(*pce TSRMLS_CC);
  973: 		add_class_vars(*pce, 0, return_value TSRMLS_CC);
  974: 		add_class_vars(*pce, 1, return_value TSRMLS_CC);
  975: 	}
  976: }
  977: /* }}} */
  978: 
  979: 
  980: /* {{{ proto array get_object_vars(object obj)
  981:    Returns an array of object properties */
  982: ZEND_FUNCTION(get_object_vars)
  983: {
  984: 	zval *obj;
  985: 	zval **value;
  986: 	HashTable *properties;
  987: 	HashPosition pos;
  988: 	char *key;
  989: 	const char *prop_name, *class_name;
  990: 	uint key_len;
  991: 	ulong num_index;
  992: 	zend_object *zobj;
  993: 
  994: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
  995: 		return;
  996: 	}
  997: 
  998: 	if (Z_OBJ_HT_P(obj)->get_properties == NULL) {
  999: 		RETURN_FALSE;
 1000: 	}
 1001: 
 1002: 	properties = Z_OBJ_HT_P(obj)->get_properties(obj TSRMLS_CC);
 1003: 
 1004: 	if (properties == NULL) {
 1005: 		RETURN_FALSE;
 1006: 	}
 1007: 
 1008: 	zobj = zend_objects_get_address(obj TSRMLS_CC);
 1009: 
 1010: 	array_init(return_value);
 1011: 
 1012: 	zend_hash_internal_pointer_reset_ex(properties, &pos);
 1013: 
 1014: 	while (zend_hash_get_current_data_ex(properties, (void **) &value, &pos) == SUCCESS) {
 1015: 		if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
 1016: 			if (zend_check_property_access(zobj, key, key_len-1 TSRMLS_CC) == SUCCESS) {
 1017: 				zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
 1018: 				/* Not separating references */
 1019: 				Z_ADDREF_PP(value);
 1020: 				add_assoc_zval_ex(return_value, prop_name, strlen(prop_name)+1, *value);
 1021: 			}
 1022: 		}
 1023: 		zend_hash_move_forward_ex(properties, &pos);
 1024: 	}
 1025: }
 1026: /* }}} */
 1027: 
 1028: 
 1029: /* {{{ proto array get_class_methods(mixed class)
 1030:    Returns an array of method names for class or class instance. */
 1031: ZEND_FUNCTION(get_class_methods)
 1032: {
 1033: 	zval *klass;
 1034: 	zval *method_name;
 1035: 	zend_class_entry *ce = NULL, **pce;
 1036: 	HashPosition pos;
 1037: 	zend_function *mptr;
 1038: 
 1039: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &klass) == FAILURE) {
 1040: 		return;
 1041: 	}
 1042: 
 1043: 	if (Z_TYPE_P(klass) == IS_OBJECT) {
 1044: 		/* TBI!! new object handlers */
 1045: 		if (!HAS_CLASS_ENTRY(*klass)) {
 1046: 			RETURN_FALSE;
 1047: 		}
 1048: 		ce = Z_OBJCE_P(klass);
 1049: 	} else if (Z_TYPE_P(klass) == IS_STRING) {
 1050: 		if (zend_lookup_class(Z_STRVAL_P(klass), Z_STRLEN_P(klass), &pce TSRMLS_CC) == SUCCESS) {
 1051: 			ce = *pce;
 1052: 		}
 1053: 	}
 1054: 
 1055: 	if (!ce) {
 1056: 		RETURN_NULL();
 1057: 	}
 1058: 
 1059: 	array_init(return_value);
 1060: 	zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
 1061: 
 1062: 	while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
 1063: 		if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) 
 1064: 		 || (EG(scope) &&
 1065: 		     (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
 1066: 		       zend_check_protected(mptr->common.scope, EG(scope)))
 1067: 		   || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
 1068: 		       EG(scope) == mptr->common.scope)))) {
 1069: 			char *key;
 1070: 			uint key_len;
 1071: 			ulong num_index;
 1072: 			uint len = strlen(mptr->common.function_name);
 1073: 
 1074: 			/* Do not display old-style inherited constructors */
 1075: 			if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
 1076: 			    mptr->common.scope == ce ||
 1077: 			    zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING ||
 1078: 			    zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0) {
 1079: 
 1080: 				MAKE_STD_ZVAL(method_name);
 1081: 				ZVAL_STRINGL(method_name, mptr->common.function_name, len, 1);
 1082: 				zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
 1083: 			}
 1084: 		}
 1085: 		zend_hash_move_forward_ex(&ce->function_table, &pos);
 1086: 	}
 1087: }
 1088: /* }}} */
 1089: 
 1090: 
 1091: /* {{{ proto bool method_exists(object object, string method)
 1092:    Checks if the class method exists */
 1093: ZEND_FUNCTION(method_exists)
 1094: {
 1095: 	zval *klass; 
 1096: 	char *method_name;
 1097: 	int method_len;
 1098: 	char *lcname;
 1099: 	zend_class_entry * ce, **pce;
 1100: 
 1101: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &klass, &method_name, &method_len) == FAILURE) {
 1102: 		return;
 1103: 	}
 1104: 	if (Z_TYPE_P(klass) == IS_OBJECT) {
 1105: 		ce = Z_OBJCE_P(klass);
 1106: 	} else if (Z_TYPE_P(klass) == IS_STRING) {
 1107: 		if (zend_lookup_class(Z_STRVAL_P(klass), Z_STRLEN_P(klass), &pce TSRMLS_CC) == FAILURE) {
 1108: 			RETURN_FALSE;
 1109: 		}
 1110: 		ce = *pce;
 1111: 	} else {
 1112: 		RETURN_FALSE;
 1113: 	}
 1114: 
 1115: 	lcname = zend_str_tolower_dup(method_name, method_len);
 1116: 	if (zend_hash_exists(&ce->function_table, lcname, method_len+1)) {
 1117: 		efree(lcname);
 1118: 		RETURN_TRUE;
 1119: 	} else {
 1120: 		union _zend_function *func = NULL;
 1121: 
 1122: 		if (Z_TYPE_P(klass) == IS_OBJECT 
 1123: 		&& Z_OBJ_HT_P(klass)->get_method != NULL
 1124: 		&& (func = Z_OBJ_HT_P(klass)->get_method(&klass, method_name, method_len, NULL TSRMLS_CC)) != NULL
 1125: 		) {
 1126: 			if (func->type == ZEND_INTERNAL_FUNCTION 
 1127: 			&& (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0
 1128: 			) {
 1129: 				/* Returns true to the fake Closure's __invoke */
 1130: 				RETVAL_BOOL((func->common.scope == zend_ce_closure
 1131: 					&& (method_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
 1132: 					&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0) ? 1 : 0);
 1133: 					
 1134: 				efree(lcname);
 1135: 				efree((char*)((zend_internal_function*)func)->function_name);
 1136: 				efree(func);
 1137: 				return;
 1138: 			}
 1139: 			efree(lcname);
 1140: 			RETURN_TRUE;
 1141: 		}
 1142: 	}
 1143: 	efree(lcname);
 1144: 	RETURN_FALSE;
 1145: }
 1146: /* }}} */
 1147: 
 1148: /* {{{ proto bool property_exists(mixed object_or_class, string property_name)
 1149:    Checks if the object or class has a property */
 1150: ZEND_FUNCTION(property_exists)
 1151: {
 1152: 	zval *object;
 1153: 	char *property;
 1154: 	int property_len;
 1155: 	zend_class_entry *ce, **pce;
 1156: 	zend_property_info *property_info;
 1157: 	zval property_z;
 1158: 	ulong h;
 1159: 
 1160: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &object, &property, &property_len) == FAILURE) {
 1161: 		return;
 1162: 	}
 1163: 
 1164: 	if (property_len == 0) {
 1165: 		RETURN_FALSE;
 1166: 	}
 1167: 
 1168: 	if (Z_TYPE_P(object) == IS_STRING) {
 1169: 		if (zend_lookup_class(Z_STRVAL_P(object), Z_STRLEN_P(object), &pce TSRMLS_CC) == FAILURE) {
 1170: 			RETURN_FALSE;
 1171: 		}
 1172: 		ce = *pce;
 1173: 	} else if (Z_TYPE_P(object) == IS_OBJECT) {
 1174: 		ce = Z_OBJCE_P(object);
 1175: 	} else {
 1176: 		zend_error(E_WARNING, "First parameter must either be an object or the name of an existing class");
 1177: 		RETURN_NULL();
 1178: 	}
 1179: 
 1180: 	h = zend_get_hash_value(property, property_len+1);
 1181: 	if (zend_hash_quick_find(&ce->properties_info, property, property_len+1, h, (void **) &property_info) == SUCCESS
 1182: 		&& (property_info->flags & ZEND_ACC_SHADOW) == 0) {
 1183: 		RETURN_TRUE;
 1184: 	}
 1185: 
 1186: 	ZVAL_STRINGL(&property_z, property, property_len, 0);
 1187: 
 1188: 	if (Z_TYPE_P(object) ==  IS_OBJECT &&
 1189: 		Z_OBJ_HANDLER_P(object, has_property) && 
 1190: 		Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, 0 TSRMLS_CC)) {
 1191: 		RETURN_TRUE;
 1192: 	}
 1193: 	RETURN_FALSE;
 1194: }
 1195: /* }}} */
 1196: 
 1197: 
 1198: /* {{{ proto bool class_exists(string classname [, bool autoload])
 1199:    Checks if the class exists */
 1200: ZEND_FUNCTION(class_exists)
 1201: {
 1202: 	char *class_name, *lc_name;
 1203: 	zend_class_entry **ce;
 1204: 	int class_name_len;
 1205: 	int found;
 1206: 	zend_bool autoload = 1;
 1207: 	ALLOCA_FLAG(use_heap)
 1208: 
 1209: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &class_name, &class_name_len, &autoload) == FAILURE) {
 1210: 		return;
 1211: 	}
 1212: 
 1213: 	if (!autoload) {
 1214: 		char *name;
 1215: 		int len;
 1216: 
 1217: 		lc_name = do_alloca(class_name_len + 1, use_heap);
 1218: 		zend_str_tolower_copy(lc_name, class_name, class_name_len);
 1219: 
 1220: 		/* Ignore leading "\" */
 1221: 		name = lc_name;
 1222: 		len = class_name_len;
 1223: 		if (lc_name[0] == '\\') {
 1224: 			name = &lc_name[1];
 1225: 			len--;
 1226: 		}
 1227: 	
 1228: 		found = zend_hash_find(EG(class_table), name, len+1, (void **) &ce);
 1229: 		free_alloca(lc_name, use_heap);
 1230: 		RETURN_BOOL(found == SUCCESS && !(((*ce)->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
 1231: 	}
 1232: 
 1233:  	if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
 1234:  		RETURN_BOOL(((*ce)->ce_flags & (ZEND_ACC_INTERFACE | (ZEND_ACC_TRAIT - ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) == 0);
 1235: 	} else {
 1236: 		RETURN_FALSE;
 1237: 	}
 1238: }
 1239: /* }}} */
 1240: 
 1241: /* {{{ proto bool interface_exists(string classname [, bool autoload])
 1242:    Checks if the class exists */
 1243: ZEND_FUNCTION(interface_exists)
 1244: {
 1245: 	char *iface_name, *lc_name;
 1246: 	zend_class_entry **ce;
 1247: 	int iface_name_len;
 1248: 	int found;
 1249: 	zend_bool autoload = 1;
 1250: 	ALLOCA_FLAG(use_heap)
 1251: 
 1252: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &iface_name, &iface_name_len, &autoload) == FAILURE) {
 1253: 		return;
 1254: 	}
 1255: 
 1256: 	if (!autoload) {
 1257: 		char *name;
 1258: 		int len;
 1259: 		
 1260: 		lc_name = do_alloca(iface_name_len + 1, use_heap);
 1261: 		zend_str_tolower_copy(lc_name, iface_name, iface_name_len);
 1262: 	
 1263: 		/* Ignore leading "\" */
 1264: 		name = lc_name;
 1265: 		len = iface_name_len;
 1266: 		if (lc_name[0] == '\\') {
 1267: 			name = &lc_name[1];
 1268: 			len--;
 1269: 		}
 1270: 
 1271: 		found = zend_hash_find(EG(class_table), name, len+1, (void **) &ce);
 1272: 		free_alloca(lc_name, use_heap);
 1273: 		RETURN_BOOL(found == SUCCESS && (*ce)->ce_flags & ZEND_ACC_INTERFACE);
 1274: 	}
 1275: 
 1276:  	if (zend_lookup_class(iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) {
 1277:  		RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) > 0);
 1278: 	} else {
 1279: 		RETURN_FALSE;
 1280: 	}
 1281: }
 1282: /* }}} */
 1283: 
 1284: /* {{{ proto bool trait_exists(string traitname [, bool autoload])
 1285:  Checks if the trait exists */
 1286: ZEND_FUNCTION(trait_exists)
 1287: {
 1288: 	char *trait_name, *lc_name;
 1289: 	zend_class_entry **ce;
 1290: 	int trait_name_len;
 1291: 	int found;
 1292: 	zend_bool autoload = 1;
 1293: 	ALLOCA_FLAG(use_heap)
 1294:   
 1295: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &trait_name, &trait_name_len, &autoload) == FAILURE) {
 1296: 		return;
 1297: 	}
 1298:   
 1299: 	if (!autoload) {
 1300: 		char *name;
 1301: 		int len;
 1302: 		
 1303: 		lc_name = do_alloca(trait_name_len + 1, use_heap);
 1304: 		zend_str_tolower_copy(lc_name, trait_name, trait_name_len);
 1305:     
 1306: 		/* Ignore leading "\" */
 1307: 		name = lc_name;
 1308: 		len = trait_name_len;
 1309: 		if (lc_name[0] == '\\') {
 1310: 			name = &lc_name[1];
 1311: 			len--;
 1312: 		}
 1313:     
 1314: 		found = zend_hash_find(EG(class_table), name, len+1, (void **) &ce);
 1315: 		free_alloca(lc_name, use_heap);
 1316: 		RETURN_BOOL(found == SUCCESS && (((*ce)->ce_flags & ZEND_ACC_TRAIT) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
 1317: 	}
 1318:   
 1319:  	if (zend_lookup_class(trait_name, trait_name_len, &ce TSRMLS_CC) == SUCCESS) {
 1320:  		RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_TRAIT) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
 1321: 	} else {
 1322: 		RETURN_FALSE;
 1323: 	}
 1324: }
 1325: /* }}} */
 1326: 
 1327: 
 1328: /* {{{ proto bool function_exists(string function_name) 
 1329:    Checks if the function exists */
 1330: ZEND_FUNCTION(function_exists)
 1331: {
 1332: 	char *name;
 1333: 	int name_len;
 1334: 	zend_function *func;
 1335: 	char *lcname;
 1336: 	zend_bool retval;
 1337: 	
 1338: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
 1339: 		return;
 1340: 	}
 1341: 
 1342: 	lcname = zend_str_tolower_dup(name, name_len);
 1343: 	
 1344: 	/* Ignore leading "\" */
 1345: 	name = lcname;
 1346: 	if (lcname[0] == '\\') {
 1347: 		name = &lcname[1];
 1348: 		name_len--;
 1349: 	}
 1350: 
 1351: 	retval = (zend_hash_find(EG(function_table), name, name_len+1, (void **)&func) == SUCCESS);
 1352: 	
 1353: 	efree(lcname);
 1354: 
 1355: 	/*
 1356: 	 * A bit of a hack, but not a bad one: we see if the handler of the function
 1357: 	 * is actually one that displays "function is disabled" message.
 1358: 	 */
 1359: 	if (retval && func->type == ZEND_INTERNAL_FUNCTION &&
 1360: 		func->internal_function.handler == zif_display_disabled_function) {
 1361: 		retval = 0;
 1362: 	}
 1363: 
 1364: 	RETURN_BOOL(retval);
 1365: }
 1366: /* }}} */
 1367: 
 1368: /* {{{ proto bool class_alias(string user_class_name , string alias_name [, bool autoload])
 1369:    Creates an alias for user defined class */
 1370: ZEND_FUNCTION(class_alias)
 1371: {
 1372: 	char *class_name, *lc_name, *alias_name;
 1373: 	zend_class_entry **ce;
 1374: 	int class_name_len, alias_name_len;
 1375: 	int found;
 1376: 	zend_bool autoload = 1;
 1377: 	ALLOCA_FLAG(use_heap)
 1378: 
 1379: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &class_name, &class_name_len, &alias_name, &alias_name_len, &autoload) == FAILURE) {
 1380: 		return;
 1381: 	}
 1382: 
 1383: 	if (!autoload) {
 1384: 		lc_name = do_alloca(class_name_len + 1, use_heap);
 1385: 		zend_str_tolower_copy(lc_name, class_name, class_name_len);
 1386: 	
 1387: 		found = zend_hash_find(EG(class_table), lc_name, class_name_len+1, (void **) &ce);
 1388: 		free_alloca(lc_name, use_heap);
 1389: 	} else {
 1390: 		found = zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC);
 1391: 	}
 1392: 	if (found == SUCCESS) {
 1393: 		if ((*ce)->type == ZEND_USER_CLASS) { 
 1394: 			if (zend_register_class_alias_ex(alias_name, alias_name_len, *ce TSRMLS_CC) == SUCCESS) {
 1395: 				RETURN_TRUE;
 1396: 			} else {
 1397: 				zend_error(E_WARNING, "Cannot redeclare class %s", alias_name);
 1398: 				RETURN_FALSE;
 1399: 			}
 1400: 		} else {
 1401: 			zend_error(E_WARNING, "First argument of class_alias() must be a name of user defined class");
 1402: 			RETURN_FALSE;
 1403: 		}
 1404: 	} else {
 1405: 		zend_error(E_WARNING, "Class '%s' not found", class_name);
 1406: 		RETURN_FALSE;
 1407: 	}
 1408: }
 1409: /* }}} */
 1410: 
 1411: #if ZEND_DEBUG
 1412: /* {{{ proto void leak(int num_bytes=3)
 1413:    Cause an intentional memory leak, for testing/debugging purposes */
 1414: ZEND_FUNCTION(leak)
 1415: {
 1416: 	long leakbytes=3;
 1417: 
 1418: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &leakbytes) == FAILURE) {
 1419: 		return;
 1420: 	}
 1421: 
 1422: 	emalloc(leakbytes);
 1423: }
 1424: /* }}} */
 1425: 
 1426: /* {{{ proto leak_variable(mixed variable [, bool leak_data]) */
 1427: ZEND_FUNCTION(leak_variable)
 1428: {
 1429: 	zval *zv;
 1430: 	zend_bool leak_data = 0;
 1431: 
 1432: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &zv, &leak_data) == FAILURE) {
 1433: 		return;
 1434: 	}
 1435: 
 1436: 	if (!leak_data) {
 1437: 		zval_add_ref(&zv);
 1438: 	} else if (Z_TYPE_P(zv) == IS_RESOURCE) {
 1439: 		zend_list_addref(Z_RESVAL_P(zv));
 1440: 	} else if (Z_TYPE_P(zv) == IS_OBJECT) {
 1441: 		Z_OBJ_HANDLER_P(zv, add_ref)(zv TSRMLS_CC);
 1442: 	} else {
 1443: 		zend_error(E_WARNING, "Leaking non-zval data is only applicable to resources and objects");
 1444: 	}
 1445: }
 1446: /* }}} */
 1447: 
 1448: 
 1449: #ifdef ZEND_TEST_EXCEPTIONS
 1450: ZEND_FUNCTION(crash)
 1451: {
 1452: 	char *nowhere=NULL;
 1453: 
 1454: 	memcpy(nowhere, "something", sizeof("something"));
 1455: }
 1456: #endif
 1457: 
 1458: #endif /* ZEND_DEBUG */
 1459: 
 1460: /* {{{ proto array get_included_files(void)
 1461:    Returns an array with the file names that were include_once()'d */
 1462: ZEND_FUNCTION(get_included_files)
 1463: {
 1464: 	char *entry;
 1465: 
 1466: 	if (zend_parse_parameters_none() == FAILURE) {
 1467: 		return;
 1468: 	}
 1469: 
 1470: 	array_init(return_value);
 1471: 	zend_hash_internal_pointer_reset(&EG(included_files));
 1472: 	while (zend_hash_get_current_key(&EG(included_files), &entry, NULL, 1) == HASH_KEY_IS_STRING) {
 1473: 		add_next_index_string(return_value, entry, 0);
 1474: 		zend_hash_move_forward(&EG(included_files));
 1475: 	}
 1476: }
 1477: /* }}} */
 1478: 
 1479: 
 1480: /* {{{ proto void trigger_error(string message [, int error_type])
 1481:    Generates a user-level error/warning/notice message */
 1482: ZEND_FUNCTION(trigger_error)
 1483: {
 1484: 	long error_type = E_USER_NOTICE;
 1485: 	char *message;
 1486: 	int message_len;
 1487: 
 1488: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &message, &message_len, &error_type) == FAILURE) {
 1489: 		return;
 1490: 	}
 1491: 
 1492: 	switch (error_type) {
 1493: 		case E_USER_ERROR:
 1494: 		case E_USER_WARNING:
 1495: 		case E_USER_NOTICE:
 1496: 		case E_USER_DEPRECATED:
 1497: 			break;
 1498: 		default:
 1499: 			zend_error(E_WARNING, "Invalid error type specified");
 1500: 			RETURN_FALSE;
 1501: 			break;
 1502: 	}
 1503: 
 1504: 	zend_error((int)error_type, "%s", message);
 1505: 	RETURN_TRUE;
 1506: }
 1507: /* }}} */
 1508: 
 1509: 
 1510: /* {{{ proto string set_error_handler(string error_handler [, int error_types])
 1511:    Sets a user-defined error handler function.  Returns the previously defined error handler, or false on error */
 1512: ZEND_FUNCTION(set_error_handler)
 1513: {
 1514: 	zval *error_handler;
 1515: 	zend_bool had_orig_error_handler=0;
 1516: 	char *error_handler_name = NULL;
 1517: 	long error_type = E_ALL;
 1518: 
 1519: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &error_handler, &error_type) == FAILURE) {
 1520: 		return;
 1521: 	}
 1522: 
 1523: 	if (!zend_is_callable(error_handler, 0, &error_handler_name TSRMLS_CC)) {
 1524: 		zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
 1525: 				   get_active_function_name(TSRMLS_C), error_handler_name?error_handler_name:"unknown");
 1526: 		efree(error_handler_name);
 1527: 		return;
 1528: 	}
 1529: 	efree(error_handler_name);
 1530: 
 1531: 	if (EG(user_error_handler)) {
 1532: 		had_orig_error_handler = 1;
 1533: 		*return_value = *EG(user_error_handler);
 1534: 		zval_copy_ctor(return_value);
 1535: 		INIT_PZVAL(return_value);
 1536: 		zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting), sizeof(EG(user_error_handler_error_reporting)));
 1537: 		zend_ptr_stack_push(&EG(user_error_handlers), EG(user_error_handler));
 1538: 	}
 1539: 	ALLOC_ZVAL(EG(user_error_handler));
 1540: 
 1541: 	if (!zend_is_true(error_handler)) { /* unset user-defined handler */
 1542: 		FREE_ZVAL(EG(user_error_handler));
 1543: 		EG(user_error_handler) = NULL;
 1544: 		RETURN_TRUE;
 1545: 	}
 1546: 
 1547: 	EG(user_error_handler_error_reporting) = (int)error_type;
 1548: 	*EG(user_error_handler) = *error_handler;
 1549: 	zval_copy_ctor(EG(user_error_handler));
 1550: 	INIT_PZVAL(EG(user_error_handler));
 1551: 
 1552: 	if (!had_orig_error_handler) {
 1553: 		RETURN_NULL();
 1554: 	}
 1555: }
 1556: /* }}} */
 1557: 
 1558: 
 1559: /* {{{ proto void restore_error_handler(void)
 1560:    Restores the previously defined error handler function */
 1561: ZEND_FUNCTION(restore_error_handler)
 1562: {
 1563: 	if (EG(user_error_handler)) {
 1564: 		zval *zeh = EG(user_error_handler);
 1565: 
 1566: 		EG(user_error_handler) = NULL;
 1567: 		zval_ptr_dtor(&zeh);
 1568: 	}
 1569: 
 1570: 	if (zend_ptr_stack_num_elements(&EG(user_error_handlers))==0) {
 1571: 		EG(user_error_handler) = NULL;
 1572: 	} else {
 1573: 		EG(user_error_handler_error_reporting) = zend_stack_int_top(&EG(user_error_handlers_error_reporting));
 1574: 		zend_stack_del_top(&EG(user_error_handlers_error_reporting));
 1575: 		EG(user_error_handler) = zend_ptr_stack_pop(&EG(user_error_handlers));
 1576: 	}
 1577: 	RETURN_TRUE;
 1578: }
 1579: /* }}} */
 1580: 
 1581: 
 1582: /* {{{ proto string set_exception_handler(callable exception_handler)
 1583:    Sets a user-defined exception handler function.  Returns the previously defined exception handler, or false on error */
 1584: ZEND_FUNCTION(set_exception_handler)
 1585: {
 1586: 	zval *exception_handler;
 1587: 	char *exception_handler_name = NULL;
 1588: 	zend_bool had_orig_exception_handler=0;
 1589: 
 1590: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &exception_handler) == FAILURE) {
 1591: 		return;
 1592: 	}
 1593: 
 1594: 	if (Z_TYPE_P(exception_handler) != IS_NULL) { /* NULL == unset */
 1595: 		if (!zend_is_callable(exception_handler, 0, &exception_handler_name TSRMLS_CC)) {
 1596: 			zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
 1597: 					   get_active_function_name(TSRMLS_C), exception_handler_name?exception_handler_name:"unknown");
 1598: 			efree(exception_handler_name);
 1599: 			return;
 1600: 		}
 1601: 		efree(exception_handler_name);
 1602: 	}
 1603: 
 1604: 	if (EG(user_exception_handler)) {
 1605: 		had_orig_exception_handler = 1;
 1606: 		*return_value = *EG(user_exception_handler);
 1607: 		zval_copy_ctor(return_value);
 1608: 		zend_ptr_stack_push(&EG(user_exception_handlers), EG(user_exception_handler));
 1609: 	}
 1610: 	ALLOC_ZVAL(EG(user_exception_handler));
 1611: 
 1612: 	if (Z_TYPE_P(exception_handler) == IS_NULL) { /* unset user-defined handler */
 1613: 		FREE_ZVAL(EG(user_exception_handler));
 1614: 		EG(user_exception_handler) = NULL;
 1615: 		RETURN_TRUE;
 1616: 	}
 1617: 
 1618: 	MAKE_COPY_ZVAL(&exception_handler, EG(user_exception_handler))
 1619: 
 1620: 	if (!had_orig_exception_handler) {
 1621: 		RETURN_NULL();
 1622: 	}
 1623: }
 1624: /* }}} */
 1625: 
 1626: 
 1627: /* {{{ proto void restore_exception_handler(void)
 1628:    Restores the previously defined exception handler function */
 1629: ZEND_FUNCTION(restore_exception_handler)
 1630: {
 1631: 	if (EG(user_exception_handler)) {
 1632: 		zval_ptr_dtor(&EG(user_exception_handler));
 1633: 	}
 1634: 	if (zend_ptr_stack_num_elements(&EG(user_exception_handlers))==0) {
 1635: 		EG(user_exception_handler) = NULL;
 1636: 	} else {
 1637: 		EG(user_exception_handler) = zend_ptr_stack_pop(&EG(user_exception_handlers));
 1638: 	}
 1639: 	RETURN_TRUE;
 1640: }
 1641: /* }}} */
 1642: 
 1643: 
 1644: static int copy_class_or_interface_name(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
 1645: {
 1646: 	zval *array = va_arg(args, zval *);
 1647: 	zend_uint mask = va_arg(args, zend_uint);
 1648: 	zend_uint comply = va_arg(args, zend_uint);
 1649: 	zend_uint comply_mask = (comply)? mask:0;
 1650: 	zend_class_entry *ce  = *pce;
 1651: 
 1652: 	if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
 1653: 		&& (comply_mask == (ce->ce_flags & mask))) {
 1654: 		add_next_index_stringl(array, ce->name, ce->name_length, 1);
 1655: 	}
 1656: 	return ZEND_HASH_APPLY_KEEP;
 1657: }
 1658: 
 1659: /* {{{ proto array get_declared_traits()
 1660:    Returns an array of all declared traits. */
 1661: ZEND_FUNCTION(get_declared_traits)
 1662: {
 1663: 	zend_uint mask = ZEND_ACC_TRAIT;
 1664: 	zend_uint comply = 1;
 1665: 
 1666: 	if (zend_parse_parameters_none() == FAILURE) {
 1667: 		return;
 1668: 	}
 1669: 
 1670: 	array_init(return_value);
 1671: 	zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) copy_class_or_interface_name, 3, return_value, mask, comply);
 1672: }
 1673: /* }}} */
 1674: 
 1675: 
 1676: /* {{{ proto array get_declared_classes()
 1677:    Returns an array of all declared classes. */
 1678: ZEND_FUNCTION(get_declared_classes)
 1679: {
 1680: 	zend_uint mask = ZEND_ACC_INTERFACE | (ZEND_ACC_TRAIT & ~ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
 1681: 	zend_uint comply = 0;
 1682: 
 1683: 	if (zend_parse_parameters_none() == FAILURE) {
 1684: 		return;
 1685: 	}
 1686: 
 1687: 	array_init(return_value);
 1688: 	zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) copy_class_or_interface_name, 3, return_value, mask, comply);
 1689: }
 1690: /* }}} */
 1691: 
 1692: /* {{{ proto array get_declared_interfaces()
 1693:    Returns an array of all declared interfaces. */
 1694: ZEND_FUNCTION(get_declared_interfaces)
 1695: {
 1696: 	zend_uint mask = ZEND_ACC_INTERFACE;
 1697: 	zend_uint comply = 1;
 1698: 
 1699: 	if (zend_parse_parameters_none() == FAILURE) {
 1700: 		return;
 1701: 	}
 1702: 
 1703: 	array_init(return_value);
 1704: 	zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) copy_class_or_interface_name, 3, return_value, mask, comply);
 1705: }
 1706: /* }}} */
 1707: 
 1708: 
 1709: static int copy_function_name(zend_function *func TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
 1710: {
 1711: 	zval *internal_ar = va_arg(args, zval *),
 1712: 	     *user_ar     = va_arg(args, zval *);
 1713: 
 1714: 	if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
 1715: 		return 0;
 1716: 	}
 1717: 
 1718: 	if (func->type == ZEND_INTERNAL_FUNCTION) {
 1719: 		add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
 1720: 	} else if (func->type == ZEND_USER_FUNCTION) {
 1721: 		add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
 1722: 	}
 1723: 
 1724: 	return 0;
 1725: }
 1726: 
 1727: 
 1728: /* {{{ proto array get_defined_functions(void)
 1729:    Returns an array of all defined functions */
 1730: ZEND_FUNCTION(get_defined_functions)
 1731: {
 1732: 	zval *internal;
 1733: 	zval *user;
 1734: 
 1735: 	if (zend_parse_parameters_none() == FAILURE) {
 1736: 		return;
 1737: 	}
 1738: 
 1739: 	MAKE_STD_ZVAL(internal);
 1740: 	MAKE_STD_ZVAL(user);
 1741: 
 1742: 	array_init(internal);
 1743: 	array_init(user);
 1744: 	array_init(return_value);
 1745: 
 1746: 	zend_hash_apply_with_arguments(EG(function_table) TSRMLS_CC, (apply_func_args_t) copy_function_name, 2, internal, user);
 1747: 
 1748: 	if (zend_hash_add(Z_ARRVAL_P(return_value), "internal", sizeof("internal"), (void **)&internal, sizeof(zval *), NULL) == FAILURE) {
 1749: 		zval_ptr_dtor(&internal);
 1750: 		zval_ptr_dtor(&user);
 1751: 		zval_dtor(return_value);
 1752: 		zend_error(E_WARNING, "Cannot add internal functions to return value from get_defined_functions()");
 1753: 		RETURN_FALSE;
 1754: 	}
 1755: 
 1756: 	if (zend_hash_add(Z_ARRVAL_P(return_value), "user", sizeof("user"), (void **)&user, sizeof(zval *), NULL) == FAILURE) {
 1757: 		zval_ptr_dtor(&user);
 1758: 		zval_dtor(return_value);
 1759: 		zend_error(E_WARNING, "Cannot add user functions to return value from get_defined_functions()");
 1760: 		RETURN_FALSE;
 1761: 	}
 1762: }
 1763: /* }}} */
 1764: 
 1765: 
 1766: /* {{{ proto array get_defined_vars(void)
 1767:    Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
 1768: ZEND_FUNCTION(get_defined_vars)
 1769: {
 1770: 	if (!EG(active_symbol_table)) {
 1771: 		zend_rebuild_symbol_table(TSRMLS_C);
 1772: 	}
 1773: 
 1774: 	array_init_size(return_value, zend_hash_num_elements(EG(active_symbol_table)));
 1775: 
 1776: 	zend_hash_copy(Z_ARRVAL_P(return_value), EG(active_symbol_table),
 1777: 					(copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval *));
 1778: }
 1779: /* }}} */
 1780: 
 1781: 
 1782: #define LAMBDA_TEMP_FUNCNAME	"__lambda_func"
 1783: /* {{{ proto string create_function(string args, string code)
 1784:    Creates an anonymous function, and returns its name (funny, eh?) */
 1785: ZEND_FUNCTION(create_function)
 1786: {
 1787: 	char *eval_code, *function_name, *function_args, *function_code;
 1788: 	int eval_code_length, function_name_length, function_args_len, function_code_len;
 1789: 	int retval;
 1790: 	char *eval_name;
 1791: 
 1792: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &function_args, &function_args_len, &function_code, &function_code_len) == FAILURE) {
 1793: 		return;
 1794: 	}
 1795: 
 1796: 	eval_code = (char *) emalloc(sizeof("function " LAMBDA_TEMP_FUNCNAME)
 1797: 			+function_args_len
 1798: 			+2	/* for the args parentheses */
 1799: 			+2	/* for the curly braces */
 1800: 			+function_code_len);
 1801: 
 1802: 	eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME "(") - 1;
 1803: 	memcpy(eval_code, "function " LAMBDA_TEMP_FUNCNAME "(", eval_code_length);
 1804: 
 1805: 	memcpy(eval_code + eval_code_length, function_args, function_args_len);
 1806: 	eval_code_length += function_args_len;
 1807: 
 1808: 	eval_code[eval_code_length++] = ')';
 1809: 	eval_code[eval_code_length++] = '{';
 1810: 
 1811: 	memcpy(eval_code + eval_code_length, function_code, function_code_len);
 1812: 	eval_code_length += function_code_len;
 1813: 
 1814: 	eval_code[eval_code_length++] = '}';
 1815: 	eval_code[eval_code_length] = '\0';
 1816: 
 1817: 	eval_name = zend_make_compiled_string_description("runtime-created function" TSRMLS_CC);
 1818: 	retval = zend_eval_stringl(eval_code, eval_code_length, NULL, eval_name TSRMLS_CC);
 1819: 	efree(eval_code);
 1820: 	efree(eval_name);
 1821: 
 1822: 	if (retval==SUCCESS) {
 1823: 		zend_function new_function, *func;
 1824: 
 1825: 		if (zend_hash_find(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME), (void **) &func)==FAILURE) {
 1826: 			zend_error(E_ERROR, "Unexpected inconsistency in create_function()");
 1827: 			RETURN_FALSE;
 1828: 		}
 1829: 		new_function = *func;
 1830: 		function_add_ref(&new_function);
 1831: 
 1832: 		function_name = (char *) emalloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG);
 1833: 		function_name[0] = '\0';
 1834: 
 1835: 		do {
 1836: 			function_name_length = 1 + snprintf(function_name + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count));
 1837: 		} while (zend_hash_add(EG(function_table), function_name, function_name_length+1, &new_function, sizeof(zend_function), NULL)==FAILURE);
 1838: 		zend_hash_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME));
 1839: 		RETURN_STRINGL(function_name, function_name_length, 0);
 1840: 	} else {
 1841: 		zend_hash_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME));
 1842: 		RETURN_FALSE;
 1843: 	}
 1844: }
 1845: /* }}} */
 1846: 
 1847: 
 1848: #if ZEND_DEBUG
 1849: ZEND_FUNCTION(zend_test_func)
 1850: {
 1851: 	zval *arg1, *arg2;
 1852: 
 1853: 	zend_get_parameters(ht, 2, &arg1, &arg2);
 1854: }
 1855: 
 1856: 
 1857: #ifdef ZTS
 1858: ZEND_FUNCTION(zend_thread_id)
 1859: {
 1860: 	RETURN_LONG((long)tsrm_thread_id());
 1861: }
 1862: #endif
 1863: #endif
 1864: 
 1865: /* {{{ proto string get_resource_type(resource res)
 1866:    Get the resource type name for a given resource */
 1867: ZEND_FUNCTION(get_resource_type)
 1868: {
 1869: 	const char *resource_type;
 1870: 	zval *z_resource_type;
 1871: 
 1872: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_resource_type) == FAILURE) {
 1873: 		return;
 1874: 	}
 1875: 
 1876: 	resource_type = zend_rsrc_list_get_rsrc_type(Z_LVAL_P(z_resource_type) TSRMLS_CC);
 1877: 	if (resource_type) {
 1878: 		RETURN_STRING(resource_type, 1);
 1879: 	} else {
 1880: 		RETURN_STRING("Unknown", 1);
 1881: 	}
 1882: }
 1883: /* }}} */
 1884: 
 1885: 
 1886: static int add_extension_info(zend_module_entry *module, void *arg TSRMLS_DC)
 1887: {
 1888: 	zval *name_array = (zval *)arg;
 1889: 	add_next_index_string(name_array, module->name, 1);
 1890: 	return 0;
 1891: }
 1892: 
 1893: static int add_zendext_info(zend_extension *ext, void *arg TSRMLS_DC)
 1894: {
 1895: 	zval *name_array = (zval *)arg;
 1896: 	add_next_index_string(name_array, ext->name, 1);
 1897: 	return 0;
 1898: }
 1899: 
 1900: static int add_constant_info(zend_constant *constant, void *arg TSRMLS_DC)
 1901: {
 1902: 	zval *name_array = (zval *)arg;
 1903: 	zval *const_val;
 1904: 
 1905: 	MAKE_STD_ZVAL(const_val);
 1906: 	*const_val = constant->value;
 1907: 	zval_copy_ctor(const_val);
 1908: 	INIT_PZVAL(const_val);
 1909: 	add_assoc_zval_ex(name_array, constant->name, constant->name_len, const_val);
 1910: 	return 0;
 1911: }
 1912: 
 1913: 
 1914: /* {{{ proto array get_loaded_extensions([bool zend_extensions]) U
 1915:    Return an array containing names of loaded extensions */
 1916: ZEND_FUNCTION(get_loaded_extensions)
 1917: {
 1918: 	zend_bool zendext = 0;
 1919: 
 1920: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &zendext) == FAILURE) {
 1921: 		return;
 1922: 	}
 1923: 
 1924: 	array_init(return_value);
 1925: 
 1926: 	if (zendext) {
 1927: 		zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) add_zendext_info, return_value TSRMLS_CC);
 1928: 	} else {
 1929: 		zend_hash_apply_with_argument(&module_registry, (apply_func_arg_t) add_extension_info, return_value TSRMLS_CC);
 1930: 	}
 1931: }
 1932: /* }}} */
 1933: 
 1934: 
 1935: /* {{{ proto array get_defined_constants([bool categorize])
 1936:    Return an array containing the names and values of all defined constants */
 1937: ZEND_FUNCTION(get_defined_constants)
 1938: {
 1939: 	zend_bool categorize = 0;
 1940: 	
 1941: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &categorize) == FAILURE) {
 1942: 		return;
 1943: 	}
 1944: 
 1945: 	array_init(return_value);
 1946: 
 1947: 	if (categorize) {
 1948: 		HashPosition pos;
 1949: 		zend_constant *val;
 1950: 		int module_number;
 1951: 		zval **modules;
 1952: 		char **module_names;
 1953: 		zend_module_entry *module;
 1954: 		int i = 1;
 1955: 
 1956: 		modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval *));
 1957: 		module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
 1958: 
 1959: 		module_names[0] = "internal";
 1960: 		zend_hash_internal_pointer_reset_ex(&module_registry, &pos);
 1961: 		while (zend_hash_get_current_data_ex(&module_registry, (void *) &module, &pos) != FAILURE) {
 1962: 			module_names[module->module_number] = (char *)module->name;
 1963: 			i++;
 1964: 			zend_hash_move_forward_ex(&module_registry, &pos);
 1965: 		}
 1966: 		module_names[i] = "user";
 1967: 
 1968: 		zend_hash_internal_pointer_reset_ex(EG(zend_constants), &pos);
 1969: 		while (zend_hash_get_current_data_ex(EG(zend_constants), (void **) &val, &pos) != FAILURE) {
 1970: 			zval *const_val;
 1971: 
 1972: 			if (val->module_number == PHP_USER_CONSTANT) {
 1973: 				module_number = i;
 1974: 			} else if (val->module_number > i || val->module_number < 0) {
 1975: 				/* should not happen */
 1976: 				goto bad_module_id;
 1977: 			} else {
 1978: 				module_number = val->module_number;
 1979: 			}
 1980: 
 1981: 			if (!modules[module_number]) {
 1982: 				MAKE_STD_ZVAL(modules[module_number]);
 1983: 				array_init(modules[module_number]);
 1984: 				add_assoc_zval(return_value, module_names[module_number], modules[module_number]);
 1985: 			}
 1986: 
 1987: 			MAKE_STD_ZVAL(const_val);
 1988: 			*const_val = val->value;
 1989: 			zval_copy_ctor(const_val);
 1990: 			INIT_PZVAL(const_val);
 1991: 
 1992: 			add_assoc_zval_ex(modules[module_number], val->name, val->name_len, const_val);
 1993: bad_module_id:
 1994: 			zend_hash_move_forward_ex(EG(zend_constants), &pos);
 1995: 		}
 1996: 		efree(module_names);
 1997: 		efree(modules);
 1998: 	} else {
 1999: 		zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) add_constant_info, return_value TSRMLS_CC);
 2000: 	}
 2001: }
 2002: /* }}} */
 2003: 
 2004: 
 2005: static zval *debug_backtrace_get_args(void **curpos TSRMLS_DC)
 2006: {
 2007: 	void **p = curpos;
 2008: 	zval *arg_array, **arg;
 2009: 	int arg_count = (int)(zend_uintptr_t) *p;
 2010: 
 2011: 	MAKE_STD_ZVAL(arg_array);
 2012: 	array_init_size(arg_array, arg_count);
 2013: 	p -= arg_count;
 2014: 
 2015: 	while (--arg_count >= 0) {
 2016: 		arg = (zval **) p++;
 2017: 		if (*arg) {
 2018: 			if (Z_TYPE_PP(arg) != IS_OBJECT) {
 2019: 				SEPARATE_ZVAL_TO_MAKE_IS_REF(arg);
 2020: 			}
 2021: 			Z_ADDREF_PP(arg);
 2022: 			add_next_index_zval(arg_array, *arg);
 2023: 		} else {
 2024: 			add_next_index_null(arg_array);
 2025: 		}
 2026: 	}
 2027: 
 2028: 	return arg_array;
 2029: }
 2030: 
 2031: void debug_print_backtrace_args(zval *arg_array TSRMLS_DC)
 2032: {
 2033: 	zval **tmp;
 2034: 	HashPosition iterator;
 2035: 	int i = 0;
 2036: 
 2037: 	zend_hash_internal_pointer_reset_ex(arg_array->value.ht, &iterator);
 2038: 	while (zend_hash_get_current_data_ex(arg_array->value.ht, (void **) &tmp, &iterator) == SUCCESS) {
 2039: 		if (i++) {
 2040: 			ZEND_PUTS(", ");
 2041: 		}
 2042: 		zend_print_flat_zval_r(*tmp TSRMLS_CC);
 2043: 		zend_hash_move_forward_ex(arg_array->value.ht, &iterator);
 2044: 	}
 2045: }
 2046: 
 2047: /* {{{ proto void debug_print_backtrace([int options[, int limit]]) */
 2048: ZEND_FUNCTION(debug_print_backtrace)
 2049: {
 2050: 	zend_execute_data *ptr, *skip;
 2051: 	int lineno, frameno = 0;
 2052: 	const char *function_name;
 2053: 	const char *filename;
 2054: 	const char *class_name = NULL;
 2055: 	char *call_type;
 2056: 	const char *include_filename = NULL;
 2057: 	zval *arg_array = NULL;
 2058: 	int indent = 0;
 2059: 	long options = 0;
 2060: 	long limit = 0;
 2061: 
 2062: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &options, &limit) == FAILURE) {
 2063: 		return;
 2064: 	}
 2065: 
 2066: 	ptr = EG(current_execute_data);
 2067: 
 2068: 	/* skip debug_backtrace() */
 2069: 	ptr = ptr->prev_execute_data;
 2070: 
 2071: 	while (ptr && (limit == 0 || frameno < limit)) {
 2072: 		const char *free_class_name = NULL;
 2073: 
 2074: 		frameno++;
 2075: 		class_name = call_type = NULL;   
 2076: 		arg_array = NULL;
 2077: 
 2078: 		skip = ptr;
 2079: 		/* skip internal handler */
 2080: 		if (!skip->op_array &&
 2081: 		    skip->prev_execute_data &&
 2082: 		    skip->prev_execute_data->opline &&
 2083: 		    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
 2084: 		    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
 2085: 		    skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
 2086: 			skip = skip->prev_execute_data;
 2087: 		}
 2088: 
 2089: 		if (skip->op_array) {
 2090: 			filename = skip->op_array->filename;
 2091: 			lineno = skip->opline->lineno;
 2092: 		} else {
 2093: 			filename = NULL;
 2094: 			lineno = 0;
 2095: 		}
 2096: 
 2097: 		function_name = ptr->function_state.function->common.function_name;
 2098: 
 2099: 		if (function_name) {
 2100: 			if (ptr->object) {
 2101: 				if (ptr->function_state.function->common.scope) {
 2102: 					class_name = ptr->function_state.function->common.scope->name;
 2103: 				} else {
 2104: 					zend_uint class_name_len;
 2105: 					int dup;
 2106: 
 2107: 					dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
 2108: 					if(!dup) {
 2109: 						free_class_name = class_name;
 2110: 					}
 2111: 				}
 2112: 
 2113: 				call_type = "->";
 2114: 			} else if (ptr->function_state.function->common.scope) {
 2115: 				class_name = ptr->function_state.function->common.scope->name;
 2116: 				call_type = "::";
 2117: 			} else {
 2118: 				class_name = NULL;
 2119: 				call_type = NULL;
 2120: 			}
 2121: 			if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
 2122: 				if (ptr->function_state.arguments && (options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
 2123: 					arg_array = debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC);
 2124: 				}
 2125: 			}
 2126: 		} else {
 2127: 			/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
 2128: 			zend_bool build_filename_arg = 1;
 2129: 
 2130: 			if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
 2131: 				/* can happen when calling eval from a custom sapi */
 2132: 				function_name = "unknown";
 2133: 				build_filename_arg = 0;
 2134: 			} else
 2135: 			switch (ptr->opline->extended_value) {
 2136: 				case ZEND_EVAL:
 2137: 					function_name = "eval";
 2138: 					build_filename_arg = 0;
 2139: 					break;
 2140: 				case ZEND_INCLUDE:
 2141: 					function_name = "include";
 2142: 					break;
 2143: 				case ZEND_REQUIRE:
 2144: 					function_name = "require";
 2145: 					break;
 2146: 				case ZEND_INCLUDE_ONCE:
 2147: 					function_name = "include_once";
 2148: 					break;
 2149: 				case ZEND_REQUIRE_ONCE:
 2150: 					function_name = "require_once";
 2151: 					break;
 2152: 				default:
 2153: 					/* this can actually happen if you use debug_backtrace() in your error_handler and 
 2154: 					 * you're in the top-scope */
 2155: 					function_name = "unknown"; 
 2156: 					build_filename_arg = 0;
 2157: 					break;
 2158: 			}
 2159: 
 2160: 			if (build_filename_arg && include_filename) {
 2161: 				MAKE_STD_ZVAL(arg_array);
 2162: 				array_init(arg_array);
 2163: 				add_next_index_string(arg_array, (char*)include_filename, 1);
 2164: 			}
 2165: 			call_type = NULL;
 2166: 		}
 2167: 		zend_printf("#%-2d ", indent);
 2168: 		if (class_name) {
 2169: 			ZEND_PUTS(class_name);
 2170: 			ZEND_PUTS(call_type);
 2171: 		}
 2172: 		zend_printf("%s(", function_name);
 2173: 		if (arg_array) {
 2174: 			debug_print_backtrace_args(arg_array TSRMLS_CC);
 2175: 			zval_ptr_dtor(&arg_array);
 2176: 		}
 2177: 		if (filename) {
 2178: 			zend_printf(") called at [%s:%d]\n", filename, lineno);
 2179: 		} else {
 2180: 			zend_execute_data *prev = skip->prev_execute_data;
 2181: 
 2182: 			while (prev) {
 2183: 				if (prev->function_state.function &&
 2184: 					prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
 2185: 					prev = NULL;
 2186: 					break;
 2187: 				}				    
 2188: 				if (prev->op_array) {
 2189: 					zend_printf(") called at [%s:%d]\n", prev->op_array->filename, prev->opline->lineno);
 2190: 					break;
 2191: 				}
 2192: 				prev = prev->prev_execute_data;
 2193: 			}
 2194: 			if (!prev) {
 2195: 				ZEND_PUTS(")\n");
 2196: 			}
 2197: 		}
 2198: 		include_filename = filename;
 2199: 		ptr = skip->prev_execute_data;
 2200: 		++indent;
 2201: 		if (free_class_name) {
 2202: 			efree((char*)free_class_name);
 2203: 		}
 2204: 	}
 2205: }
 2206: 
 2207: /* }}} */
 2208: 
 2209: ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit TSRMLS_DC)
 2210: {
 2211: 	zend_execute_data *ptr, *skip;
 2212: 	int lineno, frameno = 0;
 2213: 	const char *function_name;
 2214: 	const char *filename;
 2215: 	const char *class_name;
 2216: 	const char *include_filename = NULL;
 2217: 	zval *stack_frame;
 2218: 
 2219: 	ptr = EG(current_execute_data);
 2220: 
 2221: 	/* skip "new Exception()" */
 2222: 	if (ptr && (skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) {
 2223: 		ptr = ptr->prev_execute_data;
 2224: 	}
 2225: 
 2226: 	/* skip debug_backtrace() */
 2227: 	if (skip_last-- && ptr) {
 2228: 		ptr = ptr->prev_execute_data;
 2229: 	}
 2230: 
 2231: 	array_init(return_value);
 2232: 
 2233: 	while (ptr && (limit == 0 || frameno < limit)) {
 2234: 		frameno++;
 2235: 		MAKE_STD_ZVAL(stack_frame);
 2236: 		array_init(stack_frame);
 2237: 
 2238: 		skip = ptr;
 2239: 		/* skip internal handler */
 2240: 		if (!skip->op_array &&
 2241: 		    skip->prev_execute_data &&
 2242: 		    skip->prev_execute_data->opline &&
 2243: 		    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
 2244: 		    skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
 2245: 		    skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
 2246: 			skip = skip->prev_execute_data;
 2247: 		}
 2248: 
 2249: 		if (skip->op_array) {
 2250: 			filename = skip->op_array->filename;
 2251: 			lineno = skip->opline->lineno;
 2252: 			add_assoc_string_ex(stack_frame, "file", sizeof("file"), (char*)filename, 1);
 2253: 			add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno);
 2254: 
 2255: 			/* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
 2256: 			 * and debug_baktrace() might have been called by the error_handler. in this case we don't 
 2257: 			 * want to pop anything of the argument-stack */
 2258: 		} else {
 2259: 			zend_execute_data *prev = skip->prev_execute_data;
 2260: 
 2261: 			while (prev) {
 2262: 				if (prev->function_state.function &&
 2263: 					prev->function_state.function->common.type != ZEND_USER_FUNCTION &&
 2264: 					!(prev->function_state.function->common.type == ZEND_INTERNAL_FUNCTION &&
 2265: 						(prev->function_state.function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
 2266: 					break;
 2267: 				}				    
 2268: 				if (prev->op_array) {
 2269: 					add_assoc_string_ex(stack_frame, "file", sizeof("file"), (char*)prev->op_array->filename, 1);
 2270: 					add_assoc_long_ex(stack_frame, "line", sizeof("line"), prev->opline->lineno);
 2271: 					break;
 2272: 				}
 2273: 				prev = prev->prev_execute_data;
 2274: 			}
 2275: 			filename = NULL;
 2276: 		}
 2277: 
 2278: 		function_name = ptr->function_state.function->common.function_name;
 2279: 
 2280: 		if (function_name) {
 2281: 			add_assoc_string_ex(stack_frame, "function", sizeof("function"), (char*)function_name, 1);
 2282: 
 2283: 			if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) {
 2284: 				if (ptr->function_state.function->common.scope) {
 2285: 					add_assoc_string_ex(stack_frame, "class", sizeof("class"), (char*)ptr->function_state.function->common.scope->name, 1);
 2286: 				} else {
 2287: 					zend_uint class_name_len;
 2288: 					int dup;
 2289: 
 2290: 					dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
 2291: 					add_assoc_string_ex(stack_frame, "class", sizeof("class"), (char*)class_name, dup);
 2292: 					
 2293: 				}
 2294: 				if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
 2295: 					add_assoc_zval_ex(stack_frame, "object", sizeof("object"), ptr->object);
 2296: 					Z_ADDREF_P(ptr->object);
 2297: 				}
 2298: 
 2299: 				add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1);
 2300: 			} else if (ptr->function_state.function->common.scope) {
 2301: 				add_assoc_string_ex(stack_frame, "class", sizeof("class"), (char*)ptr->function_state.function->common.scope->name, 1);
 2302: 				add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1);
 2303: 			}
 2304: 
 2305: 			if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 && 
 2306: 				((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL)))) {
 2307: 				if (ptr->function_state.arguments) {
 2308: 					add_assoc_zval_ex(stack_frame, "args", sizeof("args"), debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC));
 2309: 				}
 2310: 			}
 2311: 		} else {
 2312: 			/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
 2313: 			zend_bool build_filename_arg = 1;
 2314: 
 2315: 			if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
 2316: 				/* can happen when calling eval from a custom sapi */
 2317: 				function_name = "unknown";
 2318: 				build_filename_arg = 0;
 2319: 			} else
 2320: 			switch (ptr->opline->extended_value) {
 2321: 				case ZEND_EVAL:
 2322: 					function_name = "eval";
 2323: 					build_filename_arg = 0;
 2324: 					break;
 2325: 				case ZEND_INCLUDE:
 2326: 					function_name = "include";
 2327: 					break;
 2328: 				case ZEND_REQUIRE:
 2329: 					function_name = "require";
 2330: 					break;
 2331: 				case ZEND_INCLUDE_ONCE:
 2332: 					function_name = "include_once";
 2333: 					break;
 2334: 				case ZEND_REQUIRE_ONCE:
 2335: 					function_name = "require_once";
 2336: 					break;
 2337: 				default:
 2338: 					/* this can actually happen if you use debug_backtrace() in your error_handler and 
 2339: 					 * you're in the top-scope */
 2340: 					function_name = "unknown"; 
 2341: 					build_filename_arg = 0;
 2342: 					break;
 2343: 			}
 2344: 
 2345: 			if (build_filename_arg && include_filename) {
 2346: 				zval *arg_array;
 2347: 
 2348: 				MAKE_STD_ZVAL(arg_array);
 2349: 				array_init(arg_array);
 2350: 
 2351: 				/* include_filename always points to the last filename of the last last called-fuction.
 2352: 				   if we have called include in the frame above - this is the file we have included.
 2353: 				 */
 2354: 
 2355: 				add_next_index_string(arg_array, (char*)include_filename, 1);
 2356: 				add_assoc_zval_ex(stack_frame, "args", sizeof("args"), arg_array);
 2357: 			}
 2358: 
 2359: 			add_assoc_string_ex(stack_frame, "function", sizeof("function"), (char*)function_name, 1);
 2360: 		}
 2361: 
 2362: 		add_next_index_zval(return_value, stack_frame);
 2363: 
 2364: 		include_filename = filename; 
 2365: 
 2366: 		ptr = skip->prev_execute_data;
 2367: 	}
 2368: }
 2369: /* }}} */
 2370: 
 2371: 
 2372: /* {{{ proto array debug_backtrace([int options[, int limit]])
 2373:    Return backtrace as array */
 2374: ZEND_FUNCTION(debug_backtrace)
 2375: {
 2376: 	long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
 2377: 	long limit = 0;
 2378: 	
 2379: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &options, &limit) == FAILURE) {
 2380: 		return;
 2381: 	}
 2382: 
 2383: 	zend_fetch_debug_backtrace(return_value, 1, options, limit TSRMLS_CC);
 2384: }
 2385: /* }}} */
 2386: 
 2387: /* {{{ proto bool extension_loaded(string extension_name)
 2388:    Returns true if the named extension is loaded */
 2389: ZEND_FUNCTION(extension_loaded)
 2390: {
 2391: 	char *extension_name;
 2392: 	int extension_name_len;
 2393: 	char *lcname;
 2394: 
 2395: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) {
 2396: 		return;
 2397: 	}
 2398: 
 2399: 	lcname = zend_str_tolower_dup(extension_name, extension_name_len);
 2400: 	if (zend_hash_exists(&module_registry, lcname, extension_name_len+1)) {
 2401: 		RETVAL_TRUE;
 2402: 	} else {
 2403: 		RETVAL_FALSE;
 2404: 	}
 2405: 	efree(lcname);
 2406: }
 2407: /* }}} */
 2408: 
 2409: 
 2410: /* {{{ proto array get_extension_funcs(string extension_name)
 2411:    Returns an array with the names of functions belonging to the named extension */
 2412: ZEND_FUNCTION(get_extension_funcs)
 2413: {
 2414: 	char *extension_name;
 2415: 	int extension_name_len;
 2416: 	zend_module_entry *module;
 2417: 	const zend_function_entry *func;
 2418: 
 2419: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) {
 2420: 		return;
 2421: 	}
 2422: 
 2423: 	if (strncasecmp(extension_name, "zend", sizeof("zend"))) {
 2424: 		char *lcname = zend_str_tolower_dup(extension_name, extension_name_len);
 2425: 		if (zend_hash_find(&module_registry, lcname,
 2426: 			extension_name_len+1, (void**)&module) == FAILURE) {
 2427: 			efree(lcname);
 2428: 			RETURN_FALSE;
 2429: 		}
 2430: 		efree(lcname);
 2431: 
 2432: 		if (!(func = module->functions)) {
 2433: 			RETURN_FALSE;
 2434: 		}
 2435: 	} else {
 2436: 		func = builtin_functions;
 2437: 	}
 2438: 
 2439: 	array_init(return_value);
 2440: 
 2441: 	while (func->fname) {
 2442: 		add_next_index_string(return_value, func->fname, 1);
 2443: 		func++;
 2444: 	}
 2445: }
 2446: /* }}} */
 2447: 
 2448: /*
 2449:  * Local variables:
 2450:  * tab-width: 4
 2451:  * c-basic-offset: 4
 2452:  * indent-tabs-mode: t
 2453:  * End:
 2454:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>