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

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