File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / zend_execute_API.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:47:52 2012 UTC (12 years, 6 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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_execute_API.c,v 1.1 2012/02/21 23:47:52 misho Exp $ */
   21: 
   22: #include <stdio.h>
   23: #include <signal.h>
   24: 
   25: #include "zend.h"
   26: #include "zend_compile.h"
   27: #include "zend_execute.h"
   28: #include "zend_API.h"
   29: #include "zend_ptr_stack.h"
   30: #include "zend_constants.h"
   31: #include "zend_extensions.h"
   32: #include "zend_exceptions.h"
   33: #include "zend_closures.h"
   34: #include "zend_vm.h"
   35: #include "zend_float.h"
   36: #ifdef HAVE_SYS_TIME_H
   37: #include <sys/time.h>
   38: #endif
   39: 
   40: ZEND_API void (*zend_execute)(zend_op_array *op_array TSRMLS_DC);
   41: ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
   42: 
   43: /* true globals */
   44: ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 };
   45: ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
   46: 
   47: #ifdef ZEND_WIN32
   48: #include <process.h>
   49: static WNDCLASS wc;
   50: static HWND timeout_window;
   51: static HANDLE timeout_thread_event;
   52: static HANDLE timeout_thread_handle;
   53: static DWORD timeout_thread_id;
   54: static int timeout_thread_initialized=0;
   55: #endif
   56: 
   57: #if 0&&ZEND_DEBUG
   58: static void (*original_sigsegv_handler)(int);
   59: static void zend_handle_sigsegv(int dummy) /* {{{ */
   60: {
   61: 	fflush(stdout);
   62: 	fflush(stderr);
   63: 	if (original_sigsegv_handler == zend_handle_sigsegv) {
   64: 		signal(SIGSEGV, original_sigsegv_handler);
   65: 	} else {
   66: 		signal(SIGSEGV, SIG_DFL);
   67: 	}
   68: 	{
   69: 		TSRMLS_FETCH();
   70: 
   71: 		fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n",
   72: 				active_opline->opcode,
   73: 				active_opline-EG(active_op_array)->opcodes,
   74: 				get_active_function_name(TSRMLS_C),
   75: 				zend_get_executed_filename(TSRMLS_C),
   76: 				zend_get_executed_lineno(TSRMLS_C));
   77: /* See http://support.microsoft.com/kb/190351 */
   78: #ifdef PHP_WIN32
   79: 		fflush(stderr);
   80: #endif
   81: 	}
   82: 	if (original_sigsegv_handler!=zend_handle_sigsegv) {
   83: 		original_sigsegv_handler(dummy);
   84: 	}
   85: }
   86: /* }}} */
   87: #endif
   88: 
   89: static void zend_extension_activator(zend_extension *extension TSRMLS_DC) /* {{{ */
   90: {
   91: 	if (extension->activate) {
   92: 		extension->activate();
   93: 	}
   94: }
   95: /* }}} */
   96: 
   97: static void zend_extension_deactivator(zend_extension *extension TSRMLS_DC) /* {{{ */
   98: {
   99: 	if (extension->deactivate) {
  100: 		extension->deactivate();
  101: 	}
  102: }
  103: /* }}} */
  104: 
  105: static int clean_non_persistent_function(zend_function *function TSRMLS_DC) /* {{{ */
  106: {
  107: 	return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
  108: }
  109: /* }}} */
  110: 
  111: static int clean_non_persistent_function_full(zend_function *function TSRMLS_DC) /* {{{ */
  112: {
  113: 	return (function->type != ZEND_INTERNAL_FUNCTION);
  114: }
  115: /* }}} */
  116: 
  117: static int clean_non_persistent_class(zend_class_entry **ce TSRMLS_DC) /* {{{ */
  118: {
  119: 	return ((*ce)->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
  120: }
  121: /* }}} */
  122: 
  123: static int clean_non_persistent_class_full(zend_class_entry **ce TSRMLS_DC) /* {{{ */
  124: {
  125: 	return ((*ce)->type != ZEND_INTERNAL_CLASS);
  126: }
  127: /* }}} */
  128: 
  129: void init_executor(TSRMLS_D) /* {{{ */
  130: {
  131: 	zend_init_fpu(TSRMLS_C);
  132: 
  133: 	INIT_ZVAL(EG(uninitialized_zval));
  134: 	/* trick to make uninitialized_zval never be modified, passed by ref, etc. */
  135: 	Z_ADDREF(EG(uninitialized_zval));
  136: 	INIT_ZVAL(EG(error_zval));
  137: 	EG(uninitialized_zval_ptr)=&EG(uninitialized_zval);
  138: 	EG(error_zval_ptr)=&EG(error_zval);
  139: 	zend_ptr_stack_init(&EG(arg_types_stack));
  140: /* destroys stack frame, therefore makes core dumps worthless */
  141: #if 0&&ZEND_DEBUG
  142: 	original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
  143: #endif
  144: 	EG(return_value_ptr_ptr) = NULL;
  145: 
  146: 	EG(symtable_cache_ptr) = EG(symtable_cache) - 1;
  147: 	EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE - 1;
  148: 	EG(no_extensions) = 0;
  149: 
  150: 	EG(function_table) = CG(function_table);
  151: 	EG(class_table) = CG(class_table);
  152: 
  153: 	EG(in_execution) = 0;
  154: 	EG(in_autoload) = NULL;
  155: 	EG(autoload_func) = NULL;
  156: 	EG(error_handling) = EH_NORMAL;
  157: 
  158: 	zend_vm_stack_init(TSRMLS_C);
  159: 	zend_vm_stack_push((void *) NULL TSRMLS_CC);
  160: 
  161: 	zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
  162: 	{
  163: 		zval *globals;
  164: 
  165: 		ALLOC_ZVAL(globals);
  166: 		Z_SET_REFCOUNT_P(globals, 1);
  167: 		Z_SET_ISREF_P(globals);
  168: 		Z_TYPE_P(globals) = IS_ARRAY;
  169: 		Z_ARRVAL_P(globals) = &EG(symbol_table);
  170: 		zend_hash_update(&EG(symbol_table), "GLOBALS", sizeof("GLOBALS"), &globals, sizeof(zval *), NULL);
  171: 	}
  172: 	EG(active_symbol_table) = &EG(symbol_table);
  173: 
  174: 	zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC);
  175: 	EG(opline_ptr) = NULL;
  176: 
  177: 	zend_hash_init(&EG(included_files), 5, NULL, NULL, 0);
  178: 
  179: 	EG(ticks_count) = 0;
  180: 
  181: 	EG(user_error_handler) = NULL;
  182: 
  183: 	EG(current_execute_data) = NULL;
  184: 
  185: 	zend_stack_init(&EG(user_error_handlers_error_reporting));
  186: 	zend_ptr_stack_init(&EG(user_error_handlers));
  187: 	zend_ptr_stack_init(&EG(user_exception_handlers));
  188: 
  189: 	zend_objects_store_init(&EG(objects_store), 1024);
  190: 
  191: 	EG(full_tables_cleanup) = 0;
  192: #ifdef ZEND_WIN32
  193: 	EG(timed_out) = 0;
  194: #endif
  195: 
  196: 	EG(exception) = NULL;
  197: 	EG(prev_exception) = NULL;
  198: 
  199: 	EG(scope) = NULL;
  200: 	EG(called_scope) = NULL;
  201: 
  202: 	EG(This) = NULL;
  203: 
  204: 	EG(active_op_array) = NULL;
  205: 
  206: 	EG(active) = 1;
  207: }
  208: /* }}} */
  209: 
  210: static int zval_call_destructor(zval **zv TSRMLS_DC) /* {{{ */
  211: {
  212: 	if (Z_TYPE_PP(zv) == IS_OBJECT && Z_REFCOUNT_PP(zv) == 1) {
  213: 		return ZEND_HASH_APPLY_REMOVE;
  214: 	} else {
  215: 		return ZEND_HASH_APPLY_KEEP;
  216: 	}
  217: }
  218: /* }}} */
  219: 
  220: void shutdown_destructors(TSRMLS_D) /* {{{ */
  221: {
  222: 	zend_try {
  223: 		int symbols;
  224: 		do {
  225: 			symbols = zend_hash_num_elements(&EG(symbol_table));
  226: 			zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor TSRMLS_CC);
  227: 		} while (symbols != zend_hash_num_elements(&EG(symbol_table)));
  228: 		zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC);
  229: 	} zend_catch {
  230: 		/* if we couldn't destruct cleanly, mark all objects as destructed anyway */
  231: 		zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC);
  232: 	} zend_end_try();
  233: }
  234: /* }}} */
  235: 
  236: void shutdown_executor(TSRMLS_D) /* {{{ */
  237: {
  238: 	zend_try {
  239: 
  240: /* Removed because this can not be safely done, e.g. in this situation:
  241:    Object 1 creates object 2
  242:    Object 3 holds reference to object 2.
  243:    Now when 1 and 2 are destroyed, 3 can still access 2 in its destructor, with
  244:    very problematic results */
  245: /* 		zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); */
  246: 
  247: /* Moved after symbol table cleaners, because  some of the cleaners can call
  248:    destructors, which would use EG(symtable_cache_ptr) and thus leave leaks */
  249: /*		while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
  250: 			zend_hash_destroy(*EG(symtable_cache_ptr));
  251: 			efree(*EG(symtable_cache_ptr));
  252: 			EG(symtable_cache_ptr)--;
  253: 		}
  254: */
  255: 		zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC);
  256: 		zend_hash_graceful_reverse_destroy(&EG(symbol_table));
  257: 	} zend_end_try();
  258: 
  259: 	zend_try {
  260: 		zval *zeh;
  261: 		/* remove error handlers before destroying classes and functions,
  262: 		 * so that if handler used some class, crash would not happen */
  263: 		if (EG(user_error_handler)) {
  264: 			zeh = EG(user_error_handler);
  265: 			EG(user_error_handler) = NULL;
  266: 			zval_dtor(zeh);
  267: 			FREE_ZVAL(zeh);
  268: 		}
  269: 
  270: 		if (EG(user_exception_handler)) {
  271: 			zeh = EG(user_exception_handler);
  272: 			EG(user_exception_handler) = NULL;
  273: 			zval_dtor(zeh);
  274: 			FREE_ZVAL(zeh);
  275: 		}
  276: 
  277: 		zend_stack_destroy(&EG(user_error_handlers_error_reporting));
  278: 		zend_stack_init(&EG(user_error_handlers_error_reporting));
  279: 		zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1);
  280: 		zend_ptr_stack_clean(&EG(user_exception_handlers), ZVAL_DESTRUCTOR, 1);
  281: 	} zend_end_try();
  282: 
  283: 	zend_try {
  284: 		/* Cleanup static data for functions and arrays.
  285: 		 * We need a separate cleanup stage because of the following problem:
  286: 		 * Suppose we destroy class X, which destroys the class's function table,
  287: 		 * and in the function table we have function foo() that has static $bar.
  288: 		 * Now if an object of class X is assigned to $bar, its destructor will be
  289: 		 * called and will fail since X's function table is in mid-destruction.
  290: 		 * So we want first of all to clean up all data and then move to tables destruction.
  291: 		 * Note that only run-time accessed data need to be cleaned up, pre-defined data can
  292: 		 * not contain objects and thus are not probelmatic */
  293: 		if (EG(full_tables_cleanup)) {
  294: 			zend_hash_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
  295: 		} else {
  296: 			zend_hash_reverse_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC);
  297: 		}
  298: 		zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC);
  299: 	} zend_end_try();
  300: 
  301: 	zend_try {
  302: 		zend_vm_stack_destroy(TSRMLS_C);
  303: 
  304: 		zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC);
  305: 
  306: 		/* Destroy all op arrays */
  307: 		if (EG(full_tables_cleanup)) {
  308: 			zend_hash_apply(EG(function_table), (apply_func_t) clean_non_persistent_function_full TSRMLS_CC);
  309: 			zend_hash_apply(EG(class_table), (apply_func_t) clean_non_persistent_class_full TSRMLS_CC);
  310: 		} else {
  311: 			zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function TSRMLS_CC);
  312: 			zend_hash_reverse_apply(EG(class_table), (apply_func_t) clean_non_persistent_class TSRMLS_CC);
  313: 		}
  314: 
  315: 		while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
  316: 			zend_hash_destroy(*EG(symtable_cache_ptr));
  317: 			FREE_HASHTABLE(*EG(symtable_cache_ptr));
  318: 			EG(symtable_cache_ptr)--;
  319: 		}
  320: 	} zend_end_try();
  321: 
  322: 	zend_try {
  323: 		clean_non_persistent_constants(TSRMLS_C);
  324: 	} zend_end_try();
  325: 
  326: 	zend_try {
  327: #if 0&&ZEND_DEBUG
  328: 	signal(SIGSEGV, original_sigsegv_handler);
  329: #endif
  330: 
  331: 		zend_hash_destroy(&EG(included_files));
  332: 
  333: 		zend_ptr_stack_destroy(&EG(arg_types_stack));
  334: 		zend_stack_destroy(&EG(user_error_handlers_error_reporting));
  335: 		zend_ptr_stack_destroy(&EG(user_error_handlers));
  336: 		zend_ptr_stack_destroy(&EG(user_exception_handlers));
  337: 		zend_objects_store_destroy(&EG(objects_store));
  338: 		if (EG(in_autoload)) {
  339: 			zend_hash_destroy(EG(in_autoload));
  340: 			FREE_HASHTABLE(EG(in_autoload));
  341: 		}
  342: 	} zend_end_try();
  343: 
  344: 	zend_shutdown_fpu(TSRMLS_C);
  345: 
  346: 	EG(active) = 0;
  347: }
  348: /* }}} */
  349: 
  350: /* return class name and "::" or "". */
  351: ZEND_API char *get_active_class_name(char **space TSRMLS_DC) /* {{{ */
  352: {
  353: 	if (!zend_is_executing(TSRMLS_C)) {
  354: 		if (space) {
  355: 			*space = "";
  356: 		}
  357: 		return "";
  358: 	}
  359: 	switch (EG(current_execute_data)->function_state.function->type) {
  360: 		case ZEND_USER_FUNCTION:
  361: 		case ZEND_INTERNAL_FUNCTION:
  362: 		{
  363: 			zend_class_entry *ce = EG(current_execute_data)->function_state.function->common.scope;
  364: 
  365: 			if (space) {
  366: 				*space = ce ? "::" : "";
  367: 			}
  368: 			return ce ? ce->name : "";
  369: 		}
  370: 		default:
  371: 			if (space) {
  372: 				*space = "";
  373: 			}
  374: 			return "";
  375: 	}
  376: }
  377: /* }}} */
  378: 
  379: ZEND_API char *get_active_function_name(TSRMLS_D) /* {{{ */
  380: {
  381: 	if (!zend_is_executing(TSRMLS_C)) {
  382: 		return NULL;
  383: 	}
  384: 	switch (EG(current_execute_data)->function_state.function->type) {
  385: 		case ZEND_USER_FUNCTION: {
  386: 				char *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
  387: 
  388: 				if (function_name) {
  389: 					return function_name;
  390: 				} else {
  391: 					return "main";
  392: 				}
  393: 			}
  394: 			break;
  395: 		case ZEND_INTERNAL_FUNCTION:
  396: 			return ((zend_internal_function *) EG(current_execute_data)->function_state.function)->function_name;
  397: 			break;
  398: 		default:
  399: 			return NULL;
  400: 	}
  401: }
  402: /* }}} */
  403: 
  404: ZEND_API char *zend_get_executed_filename(TSRMLS_D) /* {{{ */
  405: {
  406: 	if (EG(active_op_array)) {
  407: 		return EG(active_op_array)->filename;
  408: 	} else {
  409: 		return "[no active file]";
  410: 	}
  411: }
  412: /* }}} */
  413: 
  414: ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */
  415: {
  416: 	if(EG(exception) && EG(opline_ptr) && active_opline->opcode == ZEND_HANDLE_EXCEPTION && 
  417: 		active_opline->lineno == 0 && EG(opline_before_exception)) {
  418: 		return EG(opline_before_exception)->lineno;
  419: 	}
  420: 	if (EG(opline_ptr)) {
  421: 		return active_opline->lineno;
  422: 	} else {
  423: 		return 0;
  424: 	}
  425: }
  426: /* }}} */
  427: 
  428: ZEND_API zend_bool zend_is_executing(TSRMLS_D) /* {{{ */
  429: {
  430: 	return EG(in_execution);
  431: }
  432: /* }}} */
  433: 
  434: ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
  435: {
  436: 	zval *zv = *zval_ptr;
  437: 
  438: #if DEBUG_ZEND>=2
  439: 	printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1);
  440: #endif
  441: 	Z_DELREF_P(zv);
  442: 	if (Z_REFCOUNT_P(zv) == 0) {
  443: 		TSRMLS_FETCH();
  444: 
  445: 		if (zv != &EG(uninitialized_zval)) {
  446: 			GC_REMOVE_ZVAL_FROM_BUFFER(zv);
  447: 			zval_dtor(zv);
  448: 			efree_rel(zv);
  449: 		}
  450: 	} else {
  451: 		TSRMLS_FETCH();
  452: 
  453: 		if (Z_REFCOUNT_P(zv) == 1) {
  454: 			Z_UNSET_ISREF_P(zv);
  455: 		}
  456: 
  457: 		GC_ZVAL_CHECK_POSSIBLE_ROOT(zv);
  458: 	}
  459: }
  460: /* }}} */
  461: 
  462: ZEND_API void _zval_internal_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
  463: {
  464: #if DEBUG_ZEND>=2
  465: 	printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1);
  466: #endif
  467: 	Z_DELREF_PP(zval_ptr);
  468: 	if (Z_REFCOUNT_PP(zval_ptr) == 0) {
  469: 		zval_internal_dtor(*zval_ptr);
  470: 		free(*zval_ptr);
  471: 	} else if (Z_REFCOUNT_PP(zval_ptr) == 1) {
  472: 		Z_UNSET_ISREF_PP(zval_ptr);
  473: 	}
  474: }
  475: /* }}} */
  476: 
  477: ZEND_API int zend_is_true(zval *op) /* {{{ */
  478: {
  479: 	return i_zend_is_true(op);
  480: }
  481: /* }}} */
  482: 
  483: #include "../TSRM/tsrm_strtok_r.h"
  484: 
  485: #define IS_VISITED_CONSTANT			IS_CONSTANT_INDEX
  486: #define IS_CONSTANT_VISITED(p)		(Z_TYPE_P(p) & IS_VISITED_CONSTANT)
  487: #define Z_REAL_TYPE_P(p)			(Z_TYPE_P(p) & ~IS_VISITED_CONSTANT)
  488: #define MARK_CONSTANT_VISITED(p)	Z_TYPE_P(p) |= IS_VISITED_CONSTANT
  489: 
  490: static void zval_deep_copy(zval **p)
  491: {
  492: 	zval *value;
  493: 
  494: 	ALLOC_ZVAL(value);
  495: 	*value = **p;
  496: 	Z_TYPE_P(value) &= ~IS_CONSTANT_INDEX;
  497: 	zval_copy_ctor(value);
  498: 	Z_TYPE_P(value) = Z_TYPE_PP(p);
  499: 	INIT_PZVAL(value);
  500: 	*p = value;
  501: }
  502: 
  503: ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC) /* {{{ */
  504: {
  505: 	zval *p = *pp;
  506: 	zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg;
  507: 	zval const_value;
  508: 	char *colon;
  509: 
  510: 	if (IS_CONSTANT_VISITED(p)) {
  511: 		zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
  512: 	} else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
  513: 		int refcount;
  514: 		zend_uchar is_ref;
  515: 
  516: 		SEPARATE_ZVAL_IF_NOT_REF(pp);
  517: 		p = *pp;
  518: 
  519: 		MARK_CONSTANT_VISITED(p);
  520: 
  521: 		refcount = Z_REFCOUNT_P(p);
  522: 		is_ref = Z_ISREF_P(p);
  523: 
  524: 		if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
  525: 			char *actual = Z_STRVAL_P(p);
  526: 
  527: 			if ((colon = zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
  528: 				zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
  529: 				Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
  530: 				if (inline_change) {
  531: 					colon = estrndup(colon, Z_STRLEN_P(p));
  532: 					efree(Z_STRVAL_P(p));
  533: 					Z_STRVAL_P(p) = colon;
  534: 				} else {
  535: 					Z_STRVAL_P(p) = colon + 1;
  536: 				}
  537: 			} else {
  538: 				char *save = actual, *slash;
  539: 				int actual_len = Z_STRLEN_P(p);
  540: 				if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
  541: 					actual = slash + 1;
  542: 					actual_len -= (actual - Z_STRVAL_P(p));
  543: 					if (inline_change) {
  544: 						actual = estrndup(actual, actual_len);
  545: 						Z_STRVAL_P(p) = actual;
  546: 						Z_STRLEN_P(p) = actual_len;
  547: 					}
  548: 				}
  549: 				if (actual[0] == '\\') {
  550: 					if (inline_change) {
  551: 						memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
  552: 						--Z_STRLEN_P(p);
  553: 					} else {
  554: 						++actual;
  555: 					}
  556: 					--actual_len;
  557: 				}
  558: 				if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
  559: 					int fix_save = 0;
  560: 					if (save[0] == '\\') {
  561: 						save++;
  562: 						fix_save = 1;
  563: 					}
  564: 					zend_error(E_ERROR, "Undefined constant '%s'", save);
  565: 					if (fix_save) {
  566: 						save--;
  567: 					}
  568: 					if (inline_change) {
  569: 						efree(save);
  570: 					}
  571: 					save = NULL;
  572: 				}
  573: 				if (inline_change && save && save != actual) {
  574: 					efree(save);
  575: 				}
  576: 				zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",  actual,  actual);
  577: 				p->type = IS_STRING;
  578: 				if (!inline_change) {
  579: 					Z_STRVAL_P(p) = actual;
  580: 					Z_STRLEN_P(p) = actual_len;
  581: 					zval_copy_ctor(p);
  582: 				}
  583: 			}
  584: 		} else {
  585: 			if (inline_change) {
  586: 				STR_FREE(Z_STRVAL_P(p));
  587: 			}
  588: 			*p = const_value;
  589: 		}
  590: 
  591: 		Z_SET_REFCOUNT_P(p, refcount);
  592: 		Z_SET_ISREF_TO_P(p, is_ref);
  593: 	} else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
  594: 		zval **element, *new_val;
  595: 		char *str_index;
  596: 		uint str_index_len;
  597: 		ulong num_index;
  598: 		int ret;
  599: 
  600: 		SEPARATE_ZVAL_IF_NOT_REF(pp);
  601: 		p = *pp;
  602: 		Z_TYPE_P(p) = IS_ARRAY;
  603: 
  604: 		if (!inline_change) {
  605: 			zval *tmp;
  606: 			HashTable *tmp_ht = NULL;
  607: 
  608: 			ALLOC_HASHTABLE(tmp_ht);
  609: 			zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
  610: 			zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
  611: 			Z_ARRVAL_P(p) = tmp_ht;
  612: 		} 
  613: 
  614: 		/* First go over the array and see if there are any constant indices */
  615: 		zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
  616: 		while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
  617: 			if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
  618: 				zend_hash_move_forward(Z_ARRVAL_P(p));
  619: 				continue;
  620: 			}
  621: 			Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
  622: 			if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
  623: 				zend_hash_move_forward(Z_ARRVAL_P(p));
  624: 				continue;
  625: 			}
  626: 			if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
  627: 				char *actual, *save = str_index;
  628: 				if ((colon = zend_memrchr(str_index, ':', str_index_len - 3))) {
  629: 					zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
  630: 					str_index_len -= ((colon - str_index) + 1);
  631: 					str_index = colon;
  632: 				} else {
  633: 					if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
  634: 						if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
  635: 							actual++;
  636: 							str_index_len -= (actual - str_index);
  637: 							str_index = actual;
  638: 						}
  639: 					}
  640: 					if (str_index[0] == '\\') {
  641: 						++str_index;
  642: 						--str_index_len;
  643: 					}
  644: 					if (save[0] == '\\') {
  645: 						++save;
  646: 					}
  647: 					if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
  648: 						zend_error(E_ERROR, "Undefined constant '%s'", save);
  649: 					}
  650: 					zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",	str_index, str_index);
  651: 				}
  652: 				ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
  653: 			}
  654: 
  655: 			if (Z_REFCOUNT_PP(element) > 1) {
  656: 				ALLOC_ZVAL(new_val);
  657: 				*new_val = **element;
  658: 				zval_copy_ctor(new_val);
  659: 				Z_SET_REFCOUNT_P(new_val, 1);
  660: 				Z_UNSET_ISREF_P(new_val);
  661: 
  662: 				/* preserve this bit for inheritance */
  663: 				Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
  664: 				zval_ptr_dtor(element);
  665: 				*element = new_val;
  666: 			}
  667: 
  668: 			switch (Z_TYPE(const_value)) {
  669: 				case IS_STRING:
  670: 					ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
  671: 					break;
  672: 				case IS_BOOL:
  673: 				case IS_LONG:
  674: 					ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
  675: 					break;
  676: 				case IS_DOUBLE:
  677: 					ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
  678: 					break;
  679: 				case IS_NULL:
  680: 					ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
  681: 					break;
  682: 				default:
  683: 					ret = SUCCESS;
  684: 					break;
  685: 			}
  686: 			if (ret == SUCCESS) {
  687: 				zend_hash_move_forward(Z_ARRVAL_P(p));
  688: 			}
  689: 			zval_dtor(&const_value);
  690: 		}
  691: 		zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC);
  692: 		zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
  693: 	}
  694: 	return 0;
  695: }
  696: /* }}} */
  697: 
  698: ZEND_API int zval_update_constant_inline_change(zval **pp, void *scope TSRMLS_DC) /* {{{ */
  699: {
  700: 	return zval_update_constant_ex(pp, (void*)1, scope TSRMLS_CC);
  701: }
  702: /* }}} */
  703: 
  704: ZEND_API int zval_update_constant_no_inline_change(zval **pp, void *scope TSRMLS_DC) /* {{{ */
  705: {
  706: 	return zval_update_constant_ex(pp, (void*)0, scope TSRMLS_CC);
  707: }
  708: /* }}} */
  709: 
  710: ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) /* {{{ */
  711: {
  712: 	return zval_update_constant_ex(pp, arg, NULL TSRMLS_CC);
  713: }
  714: /* }}} */
  715: 
  716: int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC) /* {{{ */
  717: {
  718: 	zval ***params_array;
  719: 	zend_uint i;
  720: 	int ex_retval;
  721: 	zval *local_retval_ptr = NULL;
  722: 
  723: 	if (param_count) {
  724: 		params_array = (zval ***) emalloc(sizeof(zval **)*param_count);
  725: 		for (i=0; i<param_count; i++) {
  726: 			params_array[i] = &params[i];
  727: 		}
  728: 	} else {
  729: 		params_array = NULL;
  730: 	}
  731: 	ex_retval = call_user_function_ex(function_table, object_pp, function_name, &local_retval_ptr, param_count, params_array, 1, NULL TSRMLS_CC);
  732: 	if (local_retval_ptr) {
  733: 		COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr);
  734: 	} else {
  735: 		INIT_ZVAL(*retval_ptr);
  736: 	}
  737: 	if (params_array) {
  738: 		efree(params_array);
  739: 	}
  740: 	return ex_retval;
  741: }
  742: /* }}} */
  743: 
  744: int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC) /* {{{ */
  745: {
  746: 	zend_fcall_info fci;
  747: 
  748: 	fci.size = sizeof(fci);
  749: 	fci.function_table = function_table;
  750: 	fci.object_ptr = object_pp ? *object_pp : NULL;
  751: 	fci.function_name = function_name;
  752: 	fci.retval_ptr_ptr = retval_ptr_ptr;
  753: 	fci.param_count = param_count;
  754: 	fci.params = params;
  755: 	fci.no_separation = (zend_bool) no_separation;
  756: 	fci.symbol_table = symbol_table;
  757: 
  758: 	return zend_call_function(&fci, NULL TSRMLS_CC);
  759: }
  760: /* }}} */
  761: 
  762: int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) /* {{{ */
  763: {
  764: 	zend_uint i;
  765: 	zval **original_return_value;
  766: 	HashTable *calling_symbol_table;
  767: 	zend_op_array *original_op_array;
  768: 	zend_op **original_opline_ptr;
  769: 	zend_class_entry *current_scope;
  770: 	zend_class_entry *current_called_scope;
  771: 	zend_class_entry *calling_scope = NULL;
  772: 	zend_class_entry *called_scope = NULL;
  773: 	zval *current_this;
  774: 	zend_execute_data execute_data;
  775: 
  776: 	*fci->retval_ptr_ptr = NULL;
  777: 
  778: 	if (!EG(active)) {
  779: 		return FAILURE; /* executor is already inactive */
  780: 	}
  781: 
  782: 	if (EG(exception)) {
  783: 		return FAILURE; /* we would result in an instable executor otherwise */
  784: 	}
  785: 
  786: 	switch (fci->size) {
  787: 		case sizeof(zend_fcall_info):
  788: 			break; /* nothing to do currently */
  789: 		default:
  790: 			zend_error(E_ERROR, "Corrupted fcall_info provided to zend_call_function()");
  791: 			break;
  792: 	}
  793: 
  794: 	/* Initialize execute_data */
  795: 	if (EG(current_execute_data)) {
  796: 		execute_data = *EG(current_execute_data);
  797: 		EX(op_array) = NULL;
  798: 		EX(opline) = NULL;
  799: 		EX(object) = NULL;
  800: 	} else {
  801: 		/* This only happens when we're called outside any execute()'s
  802: 		 * It shouldn't be strictly necessary to NULL execute_data out,
  803: 		 * but it may make bugs easier to spot
  804: 		 */
  805: 		memset(&execute_data, 0, sizeof(zend_execute_data));
  806: 	}
  807: 
  808: 	if (!fci_cache || !fci_cache->initialized) {
  809: 		zend_fcall_info_cache fci_cache_local;
  810: 		char *callable_name;
  811: 		char *error = NULL;
  812: 
  813: 		if (!fci_cache) {
  814: 			fci_cache = &fci_cache_local;
  815: 		}
  816: 
  817: 		if (!zend_is_callable_ex(fci->function_name, fci->object_ptr, IS_CALLABLE_CHECK_SILENT, &callable_name, NULL, fci_cache, &error TSRMLS_CC)) {
  818: 			if (error) {
  819: 				zend_error(E_WARNING, "Invalid callback %s, %s", callable_name, error);
  820: 				efree(error);
  821: 			}
  822: 			if (callable_name) {
  823: 				efree(callable_name);
  824: 			}
  825: 			return FAILURE;
  826: 		} else if (error) {
  827: 			/* Capitalize the first latter of the error message */
  828: 			if (error[0] >= 'a' && error[0] <= 'z') {
  829: 				error[0] += ('A' - 'a');
  830: 			}
  831: 			zend_error(E_STRICT, "%s", error);
  832: 			efree(error);
  833: 		}
  834: 		efree(callable_name);
  835: 	}
  836: 
  837: 	EX(function_state).function = fci_cache->function_handler;
  838: 	calling_scope = fci_cache->calling_scope;
  839: 	called_scope = fci_cache->called_scope;
  840: 	fci->object_ptr = fci_cache->object_ptr;
  841: 	EX(object) = fci->object_ptr;
  842: 	if (fci->object_ptr && Z_TYPE_P(fci->object_ptr) == IS_OBJECT &&
  843: 	    (!EG(objects_store).object_buckets || !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(fci->object_ptr)].valid)) {
  844: 		return FAILURE;
  845: 	}
  846: 
  847: 	if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
  848: 		if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
  849: 			zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
  850: 		}
  851: 		if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
  852:  			zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
  853: 				EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "",
  854: 				EX(function_state).function->common.scope ? "::" : "",
  855: 				EX(function_state).function->common.function_name);
  856: 		}
  857: 	}
  858: 
  859: 	ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1);
  860: 
  861: 	for (i=0; i<fci->param_count; i++) {
  862: 		zval *param;
  863: 
  864: 		if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION 
  865: 			&& (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 
  866: 			&& !ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)
  867: 			&& PZVAL_IS_REF(*fci->params[i])) {
  868: 			ALLOC_ZVAL(param);
  869: 			*param = **(fci->params[i]);
  870: 			INIT_PZVAL(param);
  871: 			zval_copy_ctor(param);
  872: 		} else if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)
  873: 			&& !PZVAL_IS_REF(*fci->params[i])) {
  874: 
  875: 			if (Z_REFCOUNT_PP(fci->params[i]) > 1) {
  876: 				zval *new_zval;
  877: 
  878: 				if (fci->no_separation &&
  879: 				    !ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
  880: 					if(i) {
  881: 						/* hack to clean up the stack */
  882: 						zend_vm_stack_push_nocheck((void *) (zend_uintptr_t)i TSRMLS_CC);
  883: 						zend_vm_stack_clear_multiple(TSRMLS_C);
  884: 					}
  885: 
  886: 					zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
  887: 						i+1,
  888: 						EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "",
  889: 						EX(function_state).function->common.scope ? "::" : "",
  890: 						EX(function_state).function->common.function_name);
  891: 					return FAILURE;
  892: 				}
  893: 
  894: 				ALLOC_ZVAL(new_zval);
  895: 				*new_zval = **fci->params[i];
  896: 				zval_copy_ctor(new_zval);
  897: 				Z_SET_REFCOUNT_P(new_zval, 1);
  898: 				Z_DELREF_PP(fci->params[i]);
  899: 				*fci->params[i] = new_zval;
  900: 			}
  901: 			Z_ADDREF_PP(fci->params[i]);
  902: 			Z_SET_ISREF_PP(fci->params[i]);
  903: 			param = *fci->params[i];
  904: 		} else if (*fci->params[i] != &EG(uninitialized_zval)) {
  905: 			Z_ADDREF_PP(fci->params[i]);
  906: 			param = *fci->params[i];
  907: 		} else {
  908: 			ALLOC_ZVAL(param);
  909: 			*param = **(fci->params[i]);
  910: 			INIT_PZVAL(param);
  911: 		}
  912: 		zend_vm_stack_push_nocheck(param TSRMLS_CC);
  913: 	}
  914: 
  915: 	EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
  916: 	zend_vm_stack_push_nocheck((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC);
  917: 
  918: 	current_scope = EG(scope);
  919: 	EG(scope) = calling_scope;
  920: 
  921: 	current_this = EG(This);
  922: 
  923: 	current_called_scope = EG(called_scope);
  924: 	if (called_scope) {
  925: 		EG(called_scope) = called_scope;
  926: 	} else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) {
  927: 		EG(called_scope) = NULL;
  928: 	}
  929: 
  930: 	if (fci->object_ptr) {
  931: 		if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
  932: 			EG(This) = NULL;
  933: 		} else {
  934: 			EG(This) = fci->object_ptr;
  935: 
  936: 			if (!PZVAL_IS_REF(EG(This))) {
  937: 				Z_ADDREF_P(EG(This)); /* For $this pointer */
  938: 			} else {
  939: 				zval *this_ptr;
  940: 
  941: 				ALLOC_ZVAL(this_ptr);
  942: 				*this_ptr = *EG(This);
  943: 				INIT_PZVAL(this_ptr);
  944: 				zval_copy_ctor(this_ptr);
  945: 				EG(This) = this_ptr;
  946: 			}
  947: 		}
  948: 	} else {
  949: 		EG(This) = NULL;
  950: 	}
  951: 
  952: 	EX(prev_execute_data) = EG(current_execute_data);
  953: 	EG(current_execute_data) = &execute_data;
  954: 
  955: 	if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
  956: 		calling_symbol_table = EG(active_symbol_table);
  957: 		EG(scope) = EX(function_state).function->common.scope;
  958: 		if (fci->symbol_table) {
  959: 			EG(active_symbol_table) = fci->symbol_table;
  960: 		} else {
  961: 			EG(active_symbol_table) = NULL;
  962: 		}
  963: 
  964: 		original_return_value = EG(return_value_ptr_ptr);
  965: 		original_op_array = EG(active_op_array);
  966: 		EG(return_value_ptr_ptr) = fci->retval_ptr_ptr;
  967: 		EG(active_op_array) = (zend_op_array *) EX(function_state).function;
  968: 		original_opline_ptr = EG(opline_ptr);
  969: 		zend_execute(EG(active_op_array) TSRMLS_CC);
  970: 		if (!fci->symbol_table && EG(active_symbol_table)) {
  971: 			if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
  972: 				zend_hash_destroy(EG(active_symbol_table));
  973: 				FREE_HASHTABLE(EG(active_symbol_table));
  974: 			} else {
  975: 				/* clean before putting into the cache, since clean
  976: 				   could call dtors, which could use cached hash */
  977: 				zend_hash_clean(EG(active_symbol_table));
  978: 				*(++EG(symtable_cache_ptr)) = EG(active_symbol_table);
  979: 			}
  980: 		}
  981: 		EG(active_symbol_table) = calling_symbol_table;
  982: 		EG(active_op_array) = original_op_array;
  983: 		EG(return_value_ptr_ptr)=original_return_value;
  984: 		EG(opline_ptr) = original_opline_ptr;
  985: 	} else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
  986: 		int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
  987: 		ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
  988: 		if (EX(function_state).function->common.scope) {
  989: 			EG(scope) = EX(function_state).function->common.scope;
  990: 		}
  991: 		((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
  992: 		/*  We shouldn't fix bad extensions here,
  993: 			because it can break proper ones (Bug #34045)
  994: 		if (!EX(function_state).function->common.return_reference)
  995: 		{
  996: 			INIT_PZVAL(*fci->retval_ptr_ptr);
  997: 		}*/
  998: 		if (EG(exception) && fci->retval_ptr_ptr) {
  999: 			zval_ptr_dtor(fci->retval_ptr_ptr);
 1000: 			*fci->retval_ptr_ptr = NULL;
 1001: 		}
 1002: 
 1003: 		if (call_via_handler) {
 1004: 			/* We must re-initialize function again */
 1005: 			fci_cache->initialized = 0;
 1006: 		}
 1007: 	} else { /* ZEND_OVERLOADED_FUNCTION */
 1008: 		ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
 1009: 
 1010: 		/* Not sure what should be done here if it's a static method */
 1011: 		if (fci->object_ptr) {
 1012: 			Z_OBJ_HT_P(fci->object_ptr)->call_method(EX(function_state).function->common.function_name, fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
 1013: 		} else {
 1014: 			zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
 1015: 		}
 1016: 
 1017: 		if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
 1018: 			efree(EX(function_state).function->common.function_name);
 1019: 		}
 1020: 		efree(EX(function_state).function);
 1021: 
 1022: 		if (EG(exception) && fci->retval_ptr_ptr) {
 1023: 			zval_ptr_dtor(fci->retval_ptr_ptr);
 1024: 			*fci->retval_ptr_ptr = NULL;
 1025: 		}
 1026: 	}
 1027: 	zend_vm_stack_clear_multiple(TSRMLS_C);
 1028: 
 1029: 	if (EG(This)) {
 1030: 		zval_ptr_dtor(&EG(This));
 1031: 	}
 1032: 	EG(called_scope) = current_called_scope;
 1033: 	EG(scope) = current_scope;
 1034: 	EG(This) = current_this;
 1035: 	EG(current_execute_data) = EX(prev_execute_data);
 1036: 
 1037: 	if (EG(exception)) {
 1038: 		zend_throw_exception_internal(NULL TSRMLS_CC);
 1039: 	}
 1040: 	return SUCCESS;
 1041: }
 1042: /* }}} */
 1043: 
 1044: ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
 1045: {
 1046: 	zval **args[1];
 1047: 	zval autoload_function;
 1048: 	zval *class_name_ptr;
 1049: 	zval *retval_ptr = NULL;
 1050: 	int retval, lc_length;
 1051: 	char *lc_name;
 1052: 	char *lc_free;
 1053: 	zend_fcall_info fcall_info;
 1054: 	zend_fcall_info_cache fcall_cache;
 1055: 	char dummy = 1;
 1056: 	ulong hash;
 1057: 	ALLOCA_FLAG(use_heap)
 1058: 
 1059: 	if (name == NULL || !name_length) {
 1060: 		return FAILURE;
 1061: 	}
 1062: 
 1063: 	lc_free = lc_name = do_alloca(name_length + 1, use_heap);
 1064: 	zend_str_tolower_copy(lc_name, name, name_length);
 1065: 	lc_length = name_length + 1;
 1066: 
 1067: 	if (lc_name[0] == '\\') {
 1068: 		lc_name += 1;
 1069: 		lc_length -= 1;
 1070: 	}
 1071: 
 1072: 	hash = zend_inline_hash_func(lc_name, lc_length);
 1073: 
 1074: 	if (zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce) == SUCCESS) {
 1075: 		free_alloca(lc_free, use_heap);
 1076: 		return SUCCESS;
 1077: 	}
 1078: 
 1079: 	/* The compiler is not-reentrant. Make sure we __autoload() only during run-time
 1080: 	 * (doesn't impact fuctionality of __autoload()
 1081: 	*/
 1082: 	if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
 1083: 		free_alloca(lc_free, use_heap);
 1084: 		return FAILURE;
 1085: 	}
 1086: 
 1087: 	if (EG(in_autoload) == NULL) {
 1088: 		ALLOC_HASHTABLE(EG(in_autoload));
 1089: 		zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0);
 1090: 	}
 1091: 
 1092: 	if (zend_hash_quick_add(EG(in_autoload), lc_name, lc_length, hash, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
 1093: 		free_alloca(lc_free, use_heap);
 1094: 		return FAILURE;
 1095: 	}
 1096: 
 1097: 	ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1, 0);
 1098: 
 1099: 	ALLOC_ZVAL(class_name_ptr);
 1100: 	INIT_PZVAL(class_name_ptr);
 1101: 	if (name[0] == '\\') {
 1102: 		ZVAL_STRINGL(class_name_ptr, name+1, name_length-1, 1);
 1103: 	} else {
 1104: 		ZVAL_STRINGL(class_name_ptr, name, name_length, 1);
 1105: 	}
 1106: 
 1107: 	args[0] = &class_name_ptr;
 1108: 
 1109: 	fcall_info.size = sizeof(fcall_info);
 1110: 	fcall_info.function_table = EG(function_table);
 1111: 	fcall_info.function_name = &autoload_function;
 1112: 	fcall_info.symbol_table = NULL;
 1113: 	fcall_info.retval_ptr_ptr = &retval_ptr;
 1114: 	fcall_info.param_count = 1;
 1115: 	fcall_info.params = args;
 1116: 	fcall_info.object_ptr = NULL;
 1117: 	fcall_info.no_separation = 1;
 1118: 
 1119: 	fcall_cache.initialized = EG(autoload_func) ? 1 : 0;
 1120: 	fcall_cache.function_handler = EG(autoload_func);
 1121: 	fcall_cache.calling_scope = NULL;
 1122: 	fcall_cache.called_scope = NULL;
 1123: 	fcall_cache.object_ptr = NULL;
 1124: 
 1125: 	zend_exception_save(TSRMLS_C);
 1126: 	retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
 1127: 	zend_exception_restore(TSRMLS_C);
 1128: 
 1129: 	EG(autoload_func) = fcall_cache.function_handler;
 1130: 
 1131: 	zval_ptr_dtor(&class_name_ptr);
 1132: 
 1133: 	zend_hash_quick_del(EG(in_autoload), lc_name, lc_length, hash);
 1134: 
 1135: 	if (retval_ptr) {
 1136: 		zval_ptr_dtor(&retval_ptr);
 1137: 	}
 1138: 
 1139: 	if (retval == FAILURE) {
 1140: 		free_alloca(lc_free, use_heap);
 1141: 		return FAILURE;
 1142: 	}
 1143: 
 1144: 	retval = zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce);
 1145: 	free_alloca(lc_free, use_heap);
 1146: 	return retval;
 1147: }
 1148: /* }}} */
 1149: 
 1150: ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
 1151: {
 1152: 	return zend_lookup_class_ex(name, name_length, 1, ce TSRMLS_CC);
 1153: }
 1154: /* }}} */
 1155: 
 1156: ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */
 1157: {
 1158: 	zval pv;
 1159: 	zend_op_array *new_op_array;
 1160: 	zend_op_array *original_active_op_array = EG(active_op_array);
 1161: 	zend_uint original_compiler_options;
 1162: 	int retval;
 1163: 
 1164: 	if (retval_ptr) {
 1165: 		Z_STRLEN(pv) = str_len + sizeof("return ;") - 1;
 1166: 		Z_STRVAL(pv) = emalloc(Z_STRLEN(pv) + 1);
 1167: 		memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1);
 1168: 		memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, str, str_len);
 1169: 		Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';';
 1170: 		Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0';
 1171: 	} else {
 1172: 		Z_STRLEN(pv) = str_len;
 1173: 		Z_STRVAL(pv) = str;
 1174: 	}
 1175: 	Z_TYPE(pv) = IS_STRING;
 1176: 
 1177: 	/*printf("Evaluating '%s'\n", pv.value.str.val);*/
 1178: 
 1179: 	original_compiler_options = CG(compiler_options);
 1180: 	CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
 1181: 	new_op_array = zend_compile_string(&pv, string_name TSRMLS_CC);
 1182: 	CG(compiler_options) = original_compiler_options;
 1183: 
 1184: 	if (new_op_array) {
 1185: 		zval *local_retval_ptr=NULL;
 1186: 		zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
 1187: 		zend_op **original_opline_ptr = EG(opline_ptr);
 1188: 		int orig_interactive = CG(interactive);
 1189: 
 1190: 		EG(return_value_ptr_ptr) = &local_retval_ptr;
 1191: 		EG(active_op_array) = new_op_array;
 1192: 		EG(no_extensions)=1;
 1193: 		if (!EG(active_symbol_table)) {
 1194: 			zend_rebuild_symbol_table(TSRMLS_C);
 1195: 		}
 1196: 		CG(interactive) = 0;
 1197: 
 1198: 		zend_execute(new_op_array TSRMLS_CC);
 1199: 
 1200: 		CG(interactive) = orig_interactive;
 1201: 		if (local_retval_ptr) {
 1202: 			if (retval_ptr) {
 1203: 				COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr);
 1204: 			} else {
 1205: 				zval_ptr_dtor(&local_retval_ptr);
 1206: 			}
 1207: 		} else {
 1208: 			if (retval_ptr) {
 1209: 				INIT_ZVAL(*retval_ptr);
 1210: 			}
 1211: 		}
 1212: 
 1213: 		EG(no_extensions)=0;
 1214: 		EG(opline_ptr) = original_opline_ptr;
 1215: 		EG(active_op_array) = original_active_op_array;
 1216: 		destroy_op_array(new_op_array TSRMLS_CC);
 1217: 		efree(new_op_array);
 1218: 		EG(return_value_ptr_ptr) = original_return_value_ptr_ptr;
 1219: 		retval = SUCCESS;
 1220: 	} else {
 1221: 		retval = FAILURE;
 1222: 	}
 1223: 	if (retval_ptr) {
 1224: 		zval_dtor(&pv);
 1225: 	}
 1226: 	return retval;
 1227: }
 1228: /* }}} */
 1229: 
 1230: ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */
 1231: {
 1232: 	return zend_eval_stringl(str, strlen(str), retval_ptr, string_name TSRMLS_CC);
 1233: }
 1234: /* }}} */
 1235: 
 1236: ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */
 1237: {
 1238: 	int result;
 1239: 
 1240: 	result = zend_eval_stringl(str, str_len, retval_ptr, string_name TSRMLS_CC);
 1241: 	if (handle_exceptions && EG(exception)) {
 1242: 		zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
 1243: 		result = FAILURE;
 1244: 	}
 1245: 	return result;
 1246: }
 1247: /* }}} */
 1248: 
 1249: ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */
 1250: {
 1251: 	return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions TSRMLS_CC);
 1252: }
 1253: /* }}} */
 1254: 
 1255: void execute_new_code(TSRMLS_D) /* {{{ */
 1256: {
 1257: 	zend_op *opline, *end;
 1258: 	zend_op *ret_opline;
 1259: 	int orig_interactive;
 1260: 
 1261: 	if (!(CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE)
 1262: 		|| CG(active_op_array)->backpatch_count>0
 1263: 		|| CG(active_op_array)->function_name
 1264: 		|| CG(active_op_array)->type!=ZEND_USER_FUNCTION) {
 1265: 		return;
 1266: 	}
 1267: 
 1268: 	ret_opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 1269: 	ret_opline->opcode = ZEND_RETURN;
 1270: 	ret_opline->op1.op_type = IS_CONST;
 1271: 	INIT_ZVAL(ret_opline->op1.u.constant);
 1272: 	SET_UNUSED(ret_opline->op2);
 1273: 
 1274: 	if (!CG(active_op_array)->start_op) {
 1275: 		CG(active_op_array)->start_op = CG(active_op_array)->opcodes;
 1276: 	}
 1277: 
 1278: 	opline=CG(active_op_array)->start_op;
 1279: 	end=CG(active_op_array)->opcodes+CG(active_op_array)->last;
 1280: 
 1281: 	while (opline<end) {
 1282: 		if (opline->op1.op_type == IS_CONST) {
 1283: 			Z_SET_ISREF(opline->op1.u.constant);
 1284: 			Z_SET_REFCOUNT(opline->op1.u.constant, 2); /* Make sure is_ref won't be reset */
 1285: 		}
 1286: 		if (opline->op2.op_type == IS_CONST) {
 1287: 			Z_SET_ISREF(opline->op2.u.constant);
 1288: 			Z_SET_REFCOUNT(opline->op2.u.constant, 2);
 1289: 		}
 1290: 		switch (opline->opcode) {
 1291: 			case ZEND_GOTO:
 1292: 				if (Z_TYPE(opline->op2.u.constant) != IS_LONG) {
 1293: 					zend_resolve_goto_label(CG(active_op_array), opline, 1 TSRMLS_CC);
 1294: 				}
 1295: 				/* break omitted intentionally */
 1296: 			case ZEND_JMP:
 1297: 				opline->op1.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.u.opline_num];
 1298: 				break;
 1299: 			case ZEND_JMPZ:
 1300: 			case ZEND_JMPNZ:
 1301: 			case ZEND_JMPZ_EX:
 1302: 			case ZEND_JMPNZ_EX:
 1303: 			case ZEND_JMP_SET:
 1304: 				opline->op2.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.u.opline_num];
 1305: 				break;
 1306: 		}
 1307: 		ZEND_VM_SET_OPCODE_HANDLER(opline);
 1308: 		opline++;
 1309: 	}
 1310: 	
 1311: 	zend_release_labels(TSRMLS_C);
 1312: 	
 1313: 	EG(return_value_ptr_ptr) = NULL;
 1314: 	EG(active_op_array) = CG(active_op_array);
 1315: 	orig_interactive = CG(interactive);
 1316: 	CG(interactive) = 0;
 1317: 	zend_execute(CG(active_op_array) TSRMLS_CC);
 1318: 	CG(interactive) = orig_interactive;
 1319: 
 1320: 	if (EG(exception)) {
 1321: 		zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
 1322: 	}
 1323: 
 1324: 	CG(active_op_array)->last -= 1;	/* get rid of that ZEND_RETURN */
 1325: 	CG(active_op_array)->start_op = CG(active_op_array)->opcodes+CG(active_op_array)->last;
 1326: }
 1327: /* }}} */
 1328: 
 1329: ZEND_API void zend_timeout(int dummy) /* {{{ */
 1330: {
 1331: 	TSRMLS_FETCH();
 1332: 
 1333: 	if (zend_on_timeout) {
 1334: 		zend_on_timeout(EG(timeout_seconds) TSRMLS_CC);
 1335: 	}
 1336: 
 1337: 	zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
 1338: }
 1339: /* }}} */
 1340: 
 1341: #ifdef ZEND_WIN32
 1342: static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /* {{{ */
 1343: {
 1344: 	switch (message) {
 1345: 		case WM_DESTROY:
 1346: 			PostQuitMessage(0);
 1347: 			break;
 1348: 		case WM_REGISTER_ZEND_TIMEOUT:
 1349: 			/* wParam is the thread id pointer, lParam is the timeout amount in seconds */
 1350: 			if (lParam == 0) {
 1351: 				KillTimer(timeout_window, wParam);
 1352: 			} else {
 1353: #ifdef ZTS
 1354: 				void ***tsrm_ls;
 1355: #endif
 1356: 				SetTimer(timeout_window, wParam, lParam*1000, NULL);
 1357: #ifdef ZTS
 1358: 				tsrm_ls = ts_resource_ex(0, &wParam);
 1359: 				if (!tsrm_ls) {
 1360: 					/* shouldn't normally happen */
 1361: 					break;
 1362: 				}
 1363: #endif
 1364: 				EG(timed_out) = 0;
 1365: 			}
 1366: 			break;
 1367: 		case WM_UNREGISTER_ZEND_TIMEOUT:
 1368: 			/* wParam is the thread id pointer */
 1369: 			KillTimer(timeout_window, wParam);
 1370: 			break;
 1371: 		case WM_TIMER: {
 1372: #ifdef ZTS
 1373: 				void ***tsrm_ls;
 1374: 
 1375: 				tsrm_ls = ts_resource_ex(0, &wParam);
 1376: 				if (!tsrm_ls) {
 1377: 					/* Thread died before receiving its timeout? */
 1378: 					break;
 1379: 				}
 1380: #endif
 1381: 				KillTimer(timeout_window, wParam);
 1382: 				EG(timed_out) = 1;
 1383: 			}
 1384: 			break;
 1385: 		default:
 1386: 			return DefWindowProc(hWnd, message, wParam, lParam);
 1387: 	}
 1388: 	return 0;
 1389: }
 1390: /* }}} */
 1391: 
 1392: static unsigned __stdcall timeout_thread_proc(void *pArgs) /* {{{ */
 1393: {
 1394: 	MSG message;
 1395: 
 1396: 	wc.style=0;
 1397: 	wc.lpfnWndProc = zend_timeout_WndProc;
 1398: 	wc.cbClsExtra=0;
 1399: 	wc.cbWndExtra=0;
 1400: 	wc.hInstance=NULL;
 1401: 	wc.hIcon=NULL;
 1402: 	wc.hCursor=NULL;
 1403: 	wc.hbrBackground=(HBRUSH)(COLOR_BACKGROUND + 5);
 1404: 	wc.lpszMenuName=NULL;
 1405: 	wc.lpszClassName = "Zend Timeout Window";
 1406: 	if (!RegisterClass(&wc)) {
 1407: 		return -1;
 1408: 	}
 1409: 	timeout_window = CreateWindow(wc.lpszClassName, wc.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
 1410: 	SetEvent(timeout_thread_event);
 1411: 	while (GetMessage(&message, NULL, 0, 0)) {
 1412: 		SendMessage(timeout_window, message.message, message.wParam, message.lParam);
 1413: 		if (message.message == WM_QUIT) {
 1414: 			break;
 1415: 		}
 1416: 	}
 1417: 	DestroyWindow(timeout_window);
 1418: 	UnregisterClass(wc.lpszClassName, NULL);
 1419: 	SetEvent(timeout_thread_handle);
 1420: 	return 0;
 1421: }
 1422: /* }}} */
 1423: 
 1424: void zend_init_timeout_thread(void) /* {{{ */
 1425: {
 1426: 	timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL);
 1427: 	timeout_thread_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
 1428: 	_beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id);
 1429: 	WaitForSingleObject(timeout_thread_event, INFINITE);
 1430: }
 1431: /* }}} */
 1432: 
 1433: void zend_shutdown_timeout_thread(void) /* {{{ */
 1434: {
 1435: 	if (!timeout_thread_initialized) {
 1436: 		return;
 1437: 	}
 1438: 	PostThreadMessage(timeout_thread_id, WM_QUIT, 0, 0);
 1439: 
 1440: 	/* Wait for thread termination */
 1441: 	WaitForSingleObject(timeout_thread_handle, 5000);
 1442: 	CloseHandle(timeout_thread_handle);
 1443: 	timeout_thread_initialized = 0;
 1444: }
 1445: /* }}} */
 1446: 
 1447: #endif
 1448: 
 1449: /* This one doesn't exists on QNX */
 1450: #ifndef SIGPROF
 1451: #define SIGPROF 27
 1452: #endif
 1453: 
 1454: void zend_set_timeout(long seconds, int reset_signals) /* {{{ */
 1455: {
 1456: 	TSRMLS_FETCH();
 1457: 
 1458: 	EG(timeout_seconds) = seconds;
 1459: 
 1460: #ifdef ZEND_WIN32
 1461: 	if(!seconds) {
 1462: 		return;
 1463: 	}
 1464: 	if (timeout_thread_initialized == 0 && InterlockedIncrement(&timeout_thread_initialized) == 1) {
 1465: 		/* We start up this process-wide thread here and not in zend_startup(), because if Zend
 1466: 		 * is initialized inside a DllMain(), you're not supposed to start threads from it.
 1467: 		 */
 1468: 		zend_init_timeout_thread();
 1469: 	}
 1470: 	PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds);
 1471: #else
 1472: #	ifdef HAVE_SETITIMER
 1473: 	{
 1474: 		struct itimerval t_r;		/* timeout requested */
 1475: 		sigset_t sigset;
 1476: 
 1477: 		if(seconds) {
 1478: 			t_r.it_value.tv_sec = seconds;
 1479: 			t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
 1480: 
 1481: #	ifdef __CYGWIN__
 1482: 			setitimer(ITIMER_REAL, &t_r, NULL);
 1483: 		}
 1484: 		if(reset_signals) {
 1485: 			signal(SIGALRM, zend_timeout);
 1486: 			sigemptyset(&sigset);
 1487: 			sigaddset(&sigset, SIGALRM);
 1488: 		}
 1489: #	else
 1490: 			setitimer(ITIMER_PROF, &t_r, NULL);
 1491: 		}
 1492: 		if(reset_signals) {
 1493: 			signal(SIGPROF, zend_timeout);
 1494: 			sigemptyset(&sigset);
 1495: 			sigaddset(&sigset, SIGPROF);
 1496: 		}
 1497: #	endif
 1498: 		if(reset_signals) {
 1499: 			sigprocmask(SIG_UNBLOCK, &sigset, NULL);
 1500: 		}
 1501: 	}
 1502: #	endif
 1503: #endif
 1504: }
 1505: /* }}} */
 1506: 
 1507: void zend_unset_timeout(TSRMLS_D) /* {{{ */
 1508: {
 1509: #ifdef ZEND_WIN32
 1510: 	if(timeout_thread_initialized) {
 1511: 		PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0);
 1512: 	}
 1513: #else
 1514: #	ifdef HAVE_SETITIMER
 1515: 	if (EG(timeout_seconds)) {
 1516: 		struct itimerval no_timeout;
 1517: 
 1518: 		no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0;
 1519: 
 1520: #ifdef __CYGWIN__
 1521: 		setitimer(ITIMER_REAL, &no_timeout, NULL);
 1522: #else
 1523: 		setitimer(ITIMER_PROF, &no_timeout, NULL);
 1524: #endif
 1525: 	}
 1526: #	endif
 1527: #endif
 1528: }
 1529: /* }}} */
 1530: 
 1531: zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC) /* {{{ */
 1532: {
 1533: 	zend_class_entry **pce;
 1534: 	int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
 1535: 	int silent       = (fetch_type & ZEND_FETCH_CLASS_SILENT) != 0;
 1536: 
 1537: 	fetch_type &= ZEND_FETCH_CLASS_MASK;
 1538: 
 1539: check_fetch_type:
 1540: 	switch (fetch_type) {
 1541: 		case ZEND_FETCH_CLASS_SELF:
 1542: 			if (!EG(scope)) {
 1543: 				zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
 1544: 			}
 1545: 			return EG(scope);
 1546: 		case ZEND_FETCH_CLASS_PARENT:
 1547: 			if (!EG(scope)) {
 1548: 				zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
 1549: 			}
 1550: 			if (!EG(scope)->parent) {
 1551: 				zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
 1552: 			}
 1553: 			return EG(scope)->parent;
 1554: 		case ZEND_FETCH_CLASS_STATIC:
 1555: 			if (!EG(called_scope)) {
 1556: 				zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
 1557: 			}
 1558: 			return EG(called_scope);
 1559: 		case ZEND_FETCH_CLASS_AUTO: {
 1560: 				fetch_type = zend_get_class_fetch_type(class_name, class_name_len);
 1561: 				if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {
 1562: 					goto check_fetch_type;
 1563: 				}
 1564: 			}
 1565: 			break;
 1566: 	}
 1567: 
 1568: 	if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC) == FAILURE) {
 1569: 		if (use_autoload) {
 1570: 			if (!silent && !EG(exception)) {
 1571: 				if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
 1572: 					zend_error(E_ERROR, "Interface '%s' not found", class_name);
 1573: 				} else {
 1574: 					zend_error(E_ERROR, "Class '%s' not found", class_name);
 1575: 				}	
 1576: 			}
 1577: 		}
 1578: 		return NULL;
 1579: 	}
 1580: 	return *pce;
 1581: }
 1582: /* }}} */
 1583: 
 1584: #define MAX_ABSTRACT_INFO_CNT 3
 1585: #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
 1586: #define DISPLAY_ABSTRACT_FN(idx) \
 1587: 	ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
 1588: 	ai.afn[idx] ? "::" : "", \
 1589: 	ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \
 1590: 	ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
 1591: 
 1592: typedef struct _zend_abstract_info {
 1593: 	zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1];
 1594: 	int cnt;
 1595: 	int ctor;
 1596: } zend_abstract_info;
 1597: 
 1598: static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) /* {{{ */
 1599: {
 1600: 	if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
 1601: 		if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
 1602: 			ai->afn[ai->cnt] = fn;
 1603: 		}
 1604: 		if (fn->common.fn_flags & ZEND_ACC_CTOR) {
 1605: 			if (!ai->ctor) {
 1606: 				ai->cnt++;
 1607: 				ai->ctor = 1;
 1608: 			} else {
 1609: 				ai->afn[ai->cnt] = NULL;
 1610: 			}
 1611: 		} else {
 1612: 			ai->cnt++;
 1613: 		}
 1614: 	}
 1615: 	return 0;
 1616: }
 1617: /* }}} */
 1618: 
 1619: void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */
 1620: {
 1621: 	zend_abstract_info ai;
 1622: 
 1623: 	if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
 1624: 		memset(&ai, 0, sizeof(ai));
 1625: 
 1626: 		zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC);
 1627: 
 1628: 		if (ai.cnt) {
 1629: 			zend_error(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
 1630: 				ce->name, ai.cnt,
 1631: 				ai.cnt > 1 ? "s" : "",
 1632: 				DISPLAY_ABSTRACT_FN(0),
 1633: 				DISPLAY_ABSTRACT_FN(1),
 1634: 				DISPLAY_ABSTRACT_FN(2)
 1635: 				);
 1636: 		}
 1637: 	}
 1638: }
 1639: /* }}} */
 1640: 
 1641: ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) /* {{{ */
 1642: {
 1643: 	zend_execute_data *ex;
 1644: 	int i;
 1645: 
 1646: 	for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
 1647: 		if (ex->op_array && ex->symbol_table == symbol_table) {
 1648: 			for (i = 0; i < ex->op_array->last_var; i++) {
 1649: 				ex->CVs[i] = NULL;
 1650: 			}
 1651: 		}
 1652: 	}
 1653: }
 1654: /* }}} */
 1655: 
 1656: ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC) /* {{{ */
 1657: {
 1658: 	zend_execute_data *ex;
 1659: 	ulong hash_value = zend_inline_hash_func(name, name_len + 1);
 1660: 
 1661: 	if (zend_hash_quick_exists(&EG(symbol_table), name, name_len + 1, hash_value)) {
 1662: 		for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
 1663: 			if (ex->op_array && ex->symbol_table == &EG(symbol_table)) {
 1664: 				int i;
 1665: 				for (i = 0; i < ex->op_array->last_var; i++) {
 1666: 					if (ex->op_array->vars[i].hash_value == hash_value &&
 1667: 						ex->op_array->vars[i].name_len == name_len &&
 1668: 						!memcmp(ex->op_array->vars[i].name, name, name_len)
 1669: 					) {
 1670: 						ex->CVs[i] = NULL;
 1671: 						break;
 1672: 					}
 1673: 				}
 1674: 			}
 1675: 		}
 1676: 		return zend_hash_quick_del(&EG(symbol_table), name, name_len + 1, hash_value);
 1677: 	}
 1678: 	return FAILURE;
 1679: }
 1680: /* }}} */
 1681: 
 1682: ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
 1683: {
 1684: 	zend_uint i;
 1685: 	zend_execute_data *ex;
 1686: 
 1687: 	if (!EG(active_symbol_table)) {
 1688: 		
 1689: 		/* Search for last called user function */
 1690: 		ex = EG(current_execute_data);
 1691: 		while (ex && !ex->op_array) {
 1692: 			ex = ex->prev_execute_data;
 1693: 		}
 1694: 		if (ex && ex->symbol_table) {
 1695: 			EG(active_symbol_table) = ex->symbol_table;
 1696: 			return;
 1697: 		}
 1698: 
 1699: 		if (ex && ex->op_array) {
 1700: 			if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
 1701: 				/*printf("Cache hit!  Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
 1702: 				EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
 1703: 			} else {
 1704: 				ALLOC_HASHTABLE(EG(active_symbol_table));
 1705: 				zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
 1706: 				/*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
 1707: 			}
 1708: 			ex->symbol_table = EG(active_symbol_table);
 1709: 
 1710: 			if (ex->op_array->this_var != -1 &&
 1711: 			    !ex->CVs[ex->op_array->this_var] &&
 1712: 			    EG(This)) {
 1713: 				ex->CVs[ex->op_array->this_var] = (zval**)ex->CVs + ex->op_array->last_var + ex->op_array->this_var;
 1714: 				*ex->CVs[ex->op_array->this_var] = EG(This);
 1715:  			}
 1716: 			for (i = 0; i < ex->op_array->last_var; i++) {
 1717: 				if (ex->CVs[i]) {
 1718: 					zend_hash_quick_update(EG(active_symbol_table),
 1719: 						ex->op_array->vars[i].name,
 1720: 						ex->op_array->vars[i].name_len + 1,
 1721: 						ex->op_array->vars[i].hash_value,
 1722: 						(void**)ex->CVs[i],
 1723: 						sizeof(zval*),
 1724: 						(void**)&ex->CVs[i]);
 1725: 				}
 1726: 			}
 1727: 		}
 1728: 	}
 1729: }
 1730: /* }}} */
 1731: 
 1732: /*
 1733:  * Local variables:
 1734:  * tab-width: 4
 1735:  * c-basic-offset: 4
 1736:  * indent-tabs-mode: t
 1737:  * End:
 1738:  */

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