File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / zend_closures.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:32:15 2013 UTC (10 years, 11 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29p0, v5_4_20p0, v5_4_20, v5_4_17, HEAD
5.4.17

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | Zend Engine                                                          |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1998-2013 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: Christian Seiler <chris_se@gmx.net>                         |
   16:    |          Dmitry Stogov <dmitry@zend.com>                             |
   17:    |          Marcus Boerger <helly@php.net>                              |
   18:    +----------------------------------------------------------------------+
   19: */
   20: 
   21: /* $Id: zend_closures.c,v 1.1.1.3 2013/07/22 01:32:15 misho Exp $ */
   22: 
   23: #include "zend.h"
   24: #include "zend_API.h"
   25: #include "zend_closures.h"
   26: #include "zend_exceptions.h"
   27: #include "zend_interfaces.h"
   28: #include "zend_objects.h"
   29: #include "zend_objects_API.h"
   30: #include "zend_globals.h"
   31: 
   32: #define ZEND_CLOSURE_PRINT_NAME "Closure object"
   33: 
   34: #define ZEND_CLOSURE_PROPERTY_ERROR() \
   35: 	zend_error(E_RECOVERABLE_ERROR, "Closure object cannot have properties")
   36: 
   37: typedef struct _zend_closure {
   38: 	zend_object    std;
   39: 	zend_function  func;
   40: 	zval          *this_ptr;
   41: 	HashTable     *debug_info;
   42: } zend_closure;
   43: 
   44: /* non-static since it needs to be referenced */
   45: ZEND_API zend_class_entry *zend_ce_closure;
   46: static zend_object_handlers closure_handlers;
   47: 
   48: ZEND_METHOD(Closure, __invoke) /* {{{ */
   49: {
   50: 	zend_function *func = EG(current_execute_data)->function_state.function;
   51: 	zval ***arguments;
   52: 	zval *closure_result_ptr = NULL;
   53: 
   54: 	arguments = emalloc(sizeof(zval**) * ZEND_NUM_ARGS());
   55: 	if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
   56: 		efree(arguments);
   57: 		zend_error(E_RECOVERABLE_ERROR, "Cannot get arguments for calling closure");
   58: 		RETVAL_FALSE;
   59: 	} else if (call_user_function_ex(CG(function_table), NULL, this_ptr, &closure_result_ptr, ZEND_NUM_ARGS(), arguments, 1, NULL TSRMLS_CC) == FAILURE) {
   60: 		RETVAL_FALSE;
   61: 	} else if (closure_result_ptr) {
   62: 		if (Z_ISREF_P(closure_result_ptr) && return_value_ptr) {
   63: 			if (return_value) {
   64: 				zval_ptr_dtor(&return_value);
   65: 			}
   66: 			*return_value_ptr = closure_result_ptr;
   67: 		} else {
   68: 			RETVAL_ZVAL(closure_result_ptr, 1, 1);
   69: 		}
   70: 	}
   71: 	efree(arguments);
   72: 
   73: 	/* destruct the function also, then - we have allocated it in get_method */
   74: 	efree((char*)func->internal_function.function_name);
   75: 	efree(func);
   76: }
   77: /* }}} */
   78: 
   79: /* {{{ proto Closure Closure::bind(Closure $old, object $to [, mixed $scope = "static" ] )
   80:    Create a closure from another one and bind to another object and scope */
   81: ZEND_METHOD(Closure, bind)
   82: {
   83: 	zval *newthis, *zclosure, *scope_arg = NULL;
   84: 	zend_closure *closure;
   85: 	zend_class_entry *ce, **ce_p;
   86: 
   87: 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) {
   88: 		RETURN_NULL();
   89: 	}
   90: 
   91: 	closure = (zend_closure *)zend_object_store_get_object(zclosure TSRMLS_CC);	
   92: 
   93: 	if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) {
   94: 		zend_error(E_WARNING, "Cannot bind an instance to a static closure");
   95: 	}
   96: 
   97: 	if (scope_arg != NULL) { /* scope argument was given */
   98: 		if (IS_ZEND_STD_OBJECT(*scope_arg)) {
   99: 			ce = Z_OBJCE_P(scope_arg);
  100: 		} else if (Z_TYPE_P(scope_arg) == IS_NULL) {
  101: 			ce = NULL;
  102: 		} else {
  103: 			char *class_name;
  104: 			int class_name_len;
  105: 			zval tmp_zval;
  106: 			INIT_ZVAL(tmp_zval);
  107: 
  108: 			if (Z_TYPE_P(scope_arg) == IS_STRING) {
  109: 				class_name = Z_STRVAL_P(scope_arg);
  110: 				class_name_len = Z_STRLEN_P(scope_arg);
  111: 			} else {
  112: 				tmp_zval = *scope_arg;
  113: 				zval_copy_ctor(&tmp_zval);
  114: 				convert_to_string(&tmp_zval);
  115: 				class_name = Z_STRVAL(tmp_zval);
  116: 				class_name_len = Z_STRLEN(tmp_zval);
  117: 			}
  118: 
  119: 			if ((class_name_len == sizeof("static") - 1) &&
  120: 				(memcmp("static", class_name, sizeof("static") - 1) == 0)) {
  121: 				ce = closure->func.common.scope;
  122: 			}
  123: 			else if (zend_lookup_class_ex(class_name, class_name_len, NULL, 1, &ce_p TSRMLS_CC) == FAILURE) {
  124: 				zend_error(E_WARNING, "Class '%s' not found", class_name);
  125: 				zval_dtor(&tmp_zval);
  126: 				RETURN_NULL();
  127: 			} else {
  128: 				ce = *ce_p;
  129: 			}
  130: 			zval_dtor(&tmp_zval);
  131: 		}
  132: 	} else { /* scope argument not given; do not change the scope by default */
  133: 		ce = closure->func.common.scope;
  134: 	}
  135: 
  136: 	zend_create_closure(return_value, &closure->func, ce, newthis TSRMLS_CC);
  137: }
  138: /* }}} */
  139: 
  140: static zend_function *zend_closure_get_constructor(zval *object TSRMLS_DC) /* {{{ */
  141: {
  142: 	zend_error(E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed");
  143: 	return NULL;
  144: }
  145: /* }}} */
  146: 
  147: static int zend_closure_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
  148: {
  149: 	return (Z_OBJ_HANDLE_P(o1) != Z_OBJ_HANDLE_P(o2));
  150: }
  151: /* }}} */
  152: 
  153: ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC) /* {{{ */
  154: {
  155: 	zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);	
  156: 	zend_function *invoke = (zend_function*)emalloc(sizeof(zend_function));
  157: 
  158: 	invoke->common = closure->func.common;
  159: 	invoke->type = ZEND_INTERNAL_FUNCTION;
  160: 	invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & ZEND_ACC_RETURN_REFERENCE);
  161: 	invoke->internal_function.handler = ZEND_MN(Closure___invoke);
  162: 	invoke->internal_function.module = 0;
  163: 	invoke->internal_function.scope = zend_ce_closure;
  164: 	invoke->internal_function.function_name = estrndup(ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1);
  165: 	return invoke;
  166: }
  167: /* }}} */
  168: 
  169: ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC) /* {{{ */
  170: {
  171: 	zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);	
  172: 	return &closure->func;
  173: }
  174: /* }}} */
  175: 
  176: ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC) /* {{{ */
  177: {
  178: 	zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);	
  179: 	return closure->this_ptr;
  180: }
  181: /* }}} */
  182: 
  183: static zend_function *zend_closure_get_method(zval **object_ptr, char *method_name, int method_len, const zend_literal *key TSRMLS_DC) /* {{{ */
  184: {
  185: 	char *lc_name;
  186: 	ALLOCA_FLAG(use_heap)
  187: 
  188: 	lc_name = do_alloca(method_len + 1, use_heap);
  189: 	zend_str_tolower_copy(lc_name, method_name, method_len);
  190: 	if ((method_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) &&
  191: 		memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
  192: 	) {
  193: 		free_alloca(lc_name, use_heap);
  194: 		return zend_get_closure_invoke_method(*object_ptr TSRMLS_CC);
  195: 	}
  196: 	free_alloca(lc_name, use_heap);
  197: 	return std_object_handlers.get_method(object_ptr, method_name, method_len, key TSRMLS_CC);
  198: }
  199: /* }}} */
  200: 
  201: static zval *zend_closure_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
  202: {
  203: 	ZEND_CLOSURE_PROPERTY_ERROR();
  204: 	Z_ADDREF(EG(uninitialized_zval));
  205: 	return &EG(uninitialized_zval);
  206: }
  207: /* }}} */
  208: 
  209: static void zend_closure_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
  210: {
  211: 	ZEND_CLOSURE_PROPERTY_ERROR();
  212: }
  213: /* }}} */
  214: 
  215: static zval **zend_closure_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
  216: {
  217: 	ZEND_CLOSURE_PROPERTY_ERROR();
  218: 	return NULL;
  219: }
  220: /* }}} */
  221: 
  222: static int zend_closure_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */
  223: {
  224: 	if (has_set_exists != 2) {
  225: 		ZEND_CLOSURE_PROPERTY_ERROR();
  226: 	}
  227: 	return 0;
  228: }
  229: /* }}} */
  230: 
  231: static void zend_closure_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
  232: {
  233: 	ZEND_CLOSURE_PROPERTY_ERROR();
  234: }
  235: /* }}} */
  236: 
  237: static void zend_closure_free_storage(void *object TSRMLS_DC) /* {{{ */
  238: {
  239: 	zend_closure *closure = (zend_closure *)object;
  240: 
  241: 	zend_object_std_dtor(&closure->std TSRMLS_CC);
  242: 
  243: 	if (closure->func.type == ZEND_USER_FUNCTION) {
  244: 		zend_execute_data *ex = EG(current_execute_data);
  245: 		while (ex) {
  246: 			if (ex->op_array == &closure->func.op_array) {
  247: 				zend_error(E_ERROR, "Cannot destroy active lambda function");
  248: 			}
  249: 			ex = ex->prev_execute_data;
  250: 		}
  251: 		destroy_op_array(&closure->func.op_array TSRMLS_CC);
  252: 	}
  253: 
  254: 	if (closure->debug_info != NULL) {
  255: 		zend_hash_destroy(closure->debug_info);
  256: 		efree(closure->debug_info);
  257: 	}
  258: 
  259: 	if (closure->this_ptr) {
  260: 		zval_ptr_dtor(&closure->this_ptr);
  261: 	}
  262: 
  263: 	efree(closure);
  264: }
  265: /* }}} */
  266: 
  267: static zend_object_value zend_closure_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
  268: {
  269: 	zend_closure *closure;
  270: 	zend_object_value object;
  271: 
  272: 	closure = emalloc(sizeof(zend_closure));
  273: 	memset(closure, 0, sizeof(zend_closure));
  274: 
  275: 	zend_object_std_init(&closure->std, class_type TSRMLS_CC);
  276: 
  277: 	object.handle = zend_objects_store_put(closure, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_closure_free_storage, NULL TSRMLS_CC);
  278: 	object.handlers = &closure_handlers;
  279: 
  280: 	return object;
  281: }
  282: /* }}} */
  283: 
  284: static zend_object_value zend_closure_clone(zval *zobject TSRMLS_DC) /* {{{ */
  285: {
  286: 	zend_closure *closure = (zend_closure *)zend_object_store_get_object(zobject TSRMLS_CC);
  287: 	zval result;
  288: 
  289: 	zend_create_closure(&result, &closure->func, closure->func.common.scope, closure->this_ptr TSRMLS_CC);
  290: 	return Z_OBJVAL(result);
  291: }
  292: /* }}} */
  293: 
  294: 
  295: int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) /* {{{ */
  296: {
  297: 	zend_closure *closure;
  298: 
  299: 	if (Z_TYPE_P(obj) != IS_OBJECT) {
  300: 		return FAILURE;
  301: 	}
  302: 
  303: 	closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
  304: 	*fptr_ptr = &closure->func;
  305: 
  306: 	if (closure->this_ptr) {
  307: 		if (zobj_ptr) {
  308: 			*zobj_ptr = closure->this_ptr;
  309: 		}
  310: 		*ce_ptr = Z_OBJCE_P(closure->this_ptr);
  311: 	} else {
  312: 		if (zobj_ptr) {
  313: 			*zobj_ptr = NULL;
  314: 		}
  315: 		*ce_ptr = closure->func.common.scope;
  316: 	}
  317: 	return SUCCESS;
  318: }
  319: /* }}} */
  320: 
  321: static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
  322: {
  323: 	zend_closure *closure = (zend_closure *)zend_object_store_get_object(object TSRMLS_CC);
  324: 	zval *val;
  325: 	struct _zend_arg_info *arg_info = closure->func.common.arg_info;
  326: 
  327: 	*is_temp = 0;
  328: 
  329: 	if (closure->debug_info == NULL) {
  330: 		ALLOC_HASHTABLE(closure->debug_info);
  331: 		zend_hash_init(closure->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0);
  332: 	}
  333: 	if (closure->debug_info->nApplyCount == 0) {
  334: 		if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
  335: 			HashTable *static_variables = closure->func.op_array.static_variables;
  336: 			MAKE_STD_ZVAL(val);
  337: 			array_init(val);
  338: 			zend_hash_copy(Z_ARRVAL_P(val), static_variables, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*));
  339: 			zend_hash_update(closure->debug_info, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL);
  340: 		}
  341: 
  342: 		if (closure->this_ptr) {
  343: 			Z_ADDREF_P(closure->this_ptr);
  344: 			zend_symtable_update(closure->debug_info, "this", sizeof("this"), (void *) &closure->this_ptr, sizeof(zval *), NULL);
  345: 		}
  346: 
  347: 		if (arg_info) {
  348: 			zend_uint i, required = closure->func.common.required_num_args;
  349: 
  350: 			MAKE_STD_ZVAL(val);
  351: 			array_init(val);
  352: 
  353: 			for (i = 0; i < closure->func.common.num_args; i++) {
  354: 				char *name, *info;
  355: 				int name_len, info_len;
  356: 				if (arg_info->name) {
  357: 					name_len = zend_spprintf(&name, 0, "%s$%s",
  358: 									arg_info->pass_by_reference ? "&" : "",
  359: 									arg_info->name);
  360: 				} else {
  361: 					name_len = zend_spprintf(&name, 0, "%s$param%d",
  362: 									arg_info->pass_by_reference ? "&" : "",
  363: 									i + 1);
  364: 				}
  365: 				info_len = zend_spprintf(&info, 0, "%s",
  366: 								i >= required ? "<optional>" : "<required>");
  367: 				add_assoc_stringl_ex(val, name, name_len + 1, info, info_len, 0);
  368: 				efree(name);
  369: 				arg_info++;
  370: 			}
  371: 			zend_hash_update(closure->debug_info, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL);
  372: 		}
  373: 	}
  374: 
  375: 	return closure->debug_info;
  376: }
  377: /* }}} */
  378: 
  379: static HashTable *zend_closure_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{ */
  380: {
  381: 	zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);	
  382: 
  383: 	*table = closure->this_ptr ? &closure->this_ptr : NULL;
  384: 	*n = closure->this_ptr ? 1 : 0;
  385: 	return (closure->func.type == ZEND_USER_FUNCTION) ?
  386: 		closure->func.op_array.static_variables : NULL;
  387: }
  388: /* }}} */
  389: 
  390: /* {{{ proto Closure::__construct()
  391:    Private constructor preventing instantiation */
  392: ZEND_METHOD(Closure, __construct)
  393: {
  394: 	zend_error(E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed");
  395: }
  396: /* }}} */
  397: 
  398: ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bindto, 0, 0, 1)
  399: 	ZEND_ARG_INFO(0, newthis)
  400: 	ZEND_ARG_INFO(0, newscope)
  401: ZEND_END_ARG_INFO()
  402: 
  403: ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bind, 0, 0, 2)
  404: 	ZEND_ARG_INFO(0, closure)
  405: 	ZEND_ARG_INFO(0, newthis)
  406: 	ZEND_ARG_INFO(0, newscope)
  407: ZEND_END_ARG_INFO()
  408: 
  409: static const zend_function_entry closure_functions[] = {
  410: 	ZEND_ME(Closure, __construct, NULL, ZEND_ACC_PRIVATE)
  411: 	ZEND_ME(Closure, bind, arginfo_closure_bind, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
  412: 	ZEND_MALIAS(Closure, bindTo, bind, arginfo_closure_bindto, ZEND_ACC_PUBLIC)
  413: 	{NULL, NULL, NULL}
  414: };
  415: 
  416: void zend_register_closure_ce(TSRMLS_D) /* {{{ */
  417: {
  418: 	zend_class_entry ce;
  419: 
  420: 	INIT_CLASS_ENTRY(ce, "Closure", closure_functions);
  421: 	zend_ce_closure = zend_register_internal_class(&ce TSRMLS_CC);
  422: 	zend_ce_closure->ce_flags |= ZEND_ACC_FINAL_CLASS;
  423: 	zend_ce_closure->create_object = zend_closure_new;
  424: 	zend_ce_closure->serialize = zend_class_serialize_deny;
  425: 	zend_ce_closure->unserialize = zend_class_unserialize_deny;
  426: 
  427: 	memcpy(&closure_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
  428: 	closure_handlers.get_constructor = zend_closure_get_constructor;
  429: 	closure_handlers.get_method = zend_closure_get_method;
  430: 	closure_handlers.write_property = zend_closure_write_property;
  431: 	closure_handlers.read_property = zend_closure_read_property;
  432: 	closure_handlers.get_property_ptr_ptr = zend_closure_get_property_ptr_ptr;
  433: 	closure_handlers.has_property = zend_closure_has_property;
  434: 	closure_handlers.unset_property = zend_closure_unset_property;
  435: 	closure_handlers.compare_objects = zend_closure_compare_objects;
  436: 	closure_handlers.clone_obj = zend_closure_clone;
  437: 	closure_handlers.get_debug_info = zend_closure_get_debug_info;
  438: 	closure_handlers.get_closure = zend_closure_get_closure;
  439: 	closure_handlers.get_gc = zend_closure_get_gc;
  440: }
  441: /* }}} */
  442: 
  443: ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_entry *scope, zval *this_ptr TSRMLS_DC) /* {{{ */
  444: {
  445: 	zend_closure *closure;
  446: 
  447: 	object_init_ex(res, zend_ce_closure);
  448: 
  449: 	closure = (zend_closure *)zend_object_store_get_object(res TSRMLS_CC);
  450: 
  451: 	closure->func = *func;
  452: 	closure->func.common.prototype = NULL;
  453: 
  454: 	if ((scope == NULL) && (this_ptr != NULL)) {
  455: 		/* use dummy scope if we're binding an object without specifying a scope */
  456: 		/* maybe it would be better to create one for this purpose */
  457: 		scope = zend_ce_closure;
  458: 	}
  459: 
  460: 	if (closure->func.type == ZEND_USER_FUNCTION) {
  461: 		if (closure->func.op_array.static_variables) {
  462: 			HashTable *static_variables = closure->func.op_array.static_variables;
  463: 
  464: 			ALLOC_HASHTABLE(closure->func.op_array.static_variables);
  465: 			zend_hash_init(closure->func.op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
  466: 			zend_hash_apply_with_arguments(static_variables TSRMLS_CC, (apply_func_args_t)zval_copy_static_var, 1, closure->func.op_array.static_variables);
  467: 		}
  468: 		closure->func.op_array.run_time_cache = NULL;
  469: 		(*closure->func.op_array.refcount)++;
  470: 	} else {
  471: 		/* verify that we aren't binding internal function to a wrong scope */
  472: 		if(func->common.scope != NULL) {
  473: 			if(scope && !instanceof_function(scope, func->common.scope TSRMLS_CC)) {
  474: 				zend_error(E_WARNING, "Cannot bind function %s::%s to scope class %s", func->common.scope->name, func->common.function_name, scope->name);
  475: 				scope = NULL;
  476: 			}
  477: 			if(scope && this_ptr && (func->common.fn_flags & ZEND_ACC_STATIC) == 0 && 
  478: 					!instanceof_function(Z_OBJCE_P(this_ptr), closure->func.common.scope TSRMLS_CC)) {
  479: 				zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", func->common.scope->name, func->common.function_name, Z_OBJCE_P(this_ptr)->name);
  480: 				scope = NULL;
  481: 				this_ptr = NULL;
  482: 			}
  483: 		} else {
  484: 			/* if it's a free function, we won't set scope & this since they're meaningless */
  485: 			this_ptr = NULL;
  486: 			scope = NULL;
  487: 		}
  488: 	}
  489: 
  490: 	/* Invariants:
  491: 	 * If the closure is unscoped, it has no bound object.
  492: 	 * The the closure is scoped, it's either static or it's bound */
  493: 	closure->func.common.scope = scope;
  494: 	if (scope) {
  495: 		closure->func.common.fn_flags |= ZEND_ACC_PUBLIC;
  496: 		if (this_ptr && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0) {
  497: 			closure->this_ptr = this_ptr;
  498: 			Z_ADDREF_P(this_ptr);
  499: 		} else {
  500: 			closure->func.common.fn_flags |= ZEND_ACC_STATIC;
  501: 			closure->this_ptr = NULL;
  502: 		}
  503: 	} else {
  504: 		closure->this_ptr = NULL;
  505: 	}
  506: }
  507: /* }}} */
  508: 
  509: /*
  510:  * Local variables:
  511:  * tab-width: 4
  512:  * c-basic-offset: 4
  513:  * indent-tabs-mode: t
  514:  * End:
  515:  */

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