cvs: ZendEngine2 / zend_compile.c zend_compile.h zend_execute.c zend_execute.h zend_execute_API.c zend_language_parser.y
| From: | Zeev Suraski | Date: | Wed, 04 Feb 2004 16:30:17 +0000 |
| Subject: | cvs: ZendEngine2 / zend_compile.c zend_compile.h zend_execute.c zend_execute.h zend_execute_API.c zend_language_parser.y | ||
| Groups: | php.zend-engine.cvs | ||
| Request: | Send a blank email to php-zend-engine-cvs+get-2320@lists.php.net to get a copy of this message | ||
zeev Wed Feb 4 11:30:17 2004 EDT
Modified files:
/ZendEngine2 zend_compile.c zend_compile.h zend_execute.c
zend_execute.h zend_execute_API.c
zend_language_parser.y
Log:
Reinstate early-binding for classes.
Note that this is available for downwards compatibility only - and it doesn't
work if you use new features (namely, interfaces). Generally, people should
declare their classes before using them, but we just didn't want hell to break
loose (c)
http://cvs.php.net/diff.php/ZendEngine2/zend_compile.c?r1=1.532&r2=1.533&ty=u Index: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.532 ZendEngine2/zend_compile.c:1.533 --- ZendEngine2/zend_compile.c:1.532 Wed Feb 4 09:25:25 2004 +++ ZendEngine2/zend_compile.c Wed Feb 4 11:30:14 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.c,v 1.532 2004/02/04 14:25:25 zeev Exp $ */ +/* $Id: zend_compile.c,v 1.533 2004/02/04 16:30:14 zeev Exp $ */ #include "zend_language_parser.h" #include "zend.h" @@ -1980,7 +1980,7 @@ } -ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time) +ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time) { zend_function *function; @@ -2012,7 +2012,7 @@ } -ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *function_table, HashTable *class_table TSRMLS_DC) +ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) { zend_class_entry *ce, **pce; @@ -2025,14 +2025,23 @@ ce->refcount++; if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) { ce->refcount--; - zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + if (!compile_time) { + /* If we're in compile time, in practice, it's quite possible + * that we'll never reach this class declaration at runtime, + * so we shut up about it. This allows the if (!defined('FOO')) { return; } + * approach to work. + */ + zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + } return NULL; } else { + zend_verify_abstract_class(ce TSRMLS_CC); return ce; } } -ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *function_table, HashTable *class_table, zend_class_entry *parent_ce TSRMLS_DC) + +ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC) { zend_class_entry *ce, **pce; int found_ce; @@ -2040,7 +2049,14 @@ found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce); if (found_ce == FAILURE) { - zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + if (!compile_time) { + /* If we're in compile time, in practice, it's quite possible + * that we'll never reach this class declaration at runtime, + * so we shut up about it. This allows the if (!defined('FOO')) { return; } + * approach to work. + */ + zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + } return NULL; } else { ce = *pce; @@ -2068,16 +2084,56 @@ void zend_do_early_binding(TSRMLS_D) { zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; + HashTable *table; while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) { opline--; } - if (do_bind_function(opline, CG(function_table), CG(class_table), 1) == FAILURE) { - return; + switch (opline->opcode) { + case ZEND_DECLARE_FUNCTION: + if (do_bind_function(opline, CG(function_table), 1) == FAILURE) { + return; + } + table = CG(function_table); + break; + case ZEND_VERIFY_ABSTRACT_CLASS: { + zend_op *verify_abstract_class_op = opline; + + opline--; + if (opline->opcode == ZEND_DECLARE_CLASS) { + if (do_bind_class(opline, CG(class_table), 1 TSRMLS_CC) == NULL) { + return; + } + } else if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS) { + zval *parent_name = &(opline-1)->op2.u.constant; + zend_class_entry **pce; + + if (zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) { + return; + } + if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) { + return; + } + } else { + /* We currently don't early-bind classes that implement interfaces */ + return; + } + table = CG(class_table); + /* clear the verify_abstract_class op */ + init_op(verify_abstract_class_op TSRMLS_CC); + SET_UNUSED(verify_abstract_class_op->op1); + SET_UNUSED(verify_abstract_class_op->op2); + verify_abstract_class_op->opcode = ZEND_NOP; + } + + break; + default: + zend_error(E_COMPILE_ERROR, "Invalid binding type"); + return; } - zend_hash_del(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len); + zend_hash_del(table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len); zval_dtor(&opline->op1.u.constant); zval_dtor(&opline->op2.u.constant); opline->opcode = ZEND_NOP; http://cvs.php.net/diff.php/ZendEngine2/zend_compile.h?r1=1.273&r2=1.274&ty=u Index: ZendEngine2/zend_compile.h diff -u ZendEngine2/zend_compile.h:1.273 ZendEngine2/zend_compile.h:1.274 --- ZendEngine2/zend_compile.h:1.273 Tue Feb 3 07:17:09 2004 +++ ZendEngine2/zend_compile.h Wed Feb 4 11:30:14 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.h,v 1.273 2004/02/03 12:17:09 zeev Exp $ */ +/* $Id: zend_compile.h,v 1.274 2004/02/04 16:30:14 zeev Exp $ */ #ifndef ZEND_COMPILE_H #define ZEND_COMPILE_H @@ -367,9 +367,9 @@ void zend_do_end_catch(znode *try_token TSRMLS_DC); void zend_do_throw(znode *expr TSRMLS_DC); -ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time); -ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *function_table, HashTable *class_table TSRMLS_DC); -ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *function_table, HashTable *class_table, zend_class_entry *parent_ce TSRMLS_DC); +ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time); +ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC); +ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC); ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC); ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC); void zend_do_implements_interface(znode *interface_znode TSRMLS_DC); http://cvs.php.net/diff.php/ZendEngine2/zend_execute.c?r1=1.597&r2=1.598&ty=u Index: ZendEngine2/zend_execute.c diff -u ZendEngine2/zend_execute.c:1.597 ZendEngine2/zend_execute.c:1.598 --- ZendEngine2/zend_execute.c:1.597 Wed Feb 4 06:47:54 2004 +++ ZendEngine2/zend_execute.c Wed Feb 4 11:30:15 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute.c,v 1.597 2004/02/04 11:47:54 zeev Exp $ */ +/* $Id: zend_execute.c,v 1.598 2004/02/04 16:30:15 zeev Exp $ */ #define ZEND_INTENSIVE_DEBUGGING 0 @@ -4006,21 +4006,21 @@ int zend_declare_class_handler(ZEND_OPCODE_HANDLER_ARGS) { - EX_T(opline->result.u.var).class_entry = do_bind_class(opline, EG(function_table), EG(class_table) TSRMLS_CC); + EX_T(opline->result.u.var).class_entry = do_bind_class(opline, EG(class_table), 0 TSRMLS_CC); NEXT_OPCODE(); } int zend_declare_inherited_class_handler(ZEND_OPCODE_HANDLER_ARGS) { - EX_T(opline->result.u.var).class_entry = do_bind_inherited_class(opline, EG(function_table), EG(class_table), EX_T(opline->extended_value).class_entry TSRMLS_CC); + EX_T(opline->result.u.var).class_entry = do_bind_inherited_class(opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC); NEXT_OPCODE(); } int zend_declare_function_handler(ZEND_OPCODE_HANDLER_ARGS) { - do_bind_function(opline, EG(function_table), EG(class_table), 0); + do_bind_function(opline, EG(function_table), 0); NEXT_OPCODE(); } @@ -4107,52 +4107,9 @@ } -#define MAX_ABSTRACT_INFO_CNT 3 -#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" - -#define DISPLAY_ABSTRACT_FN(idx) \ - ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ - ai.afn[idx] ? "::" : "", \ - ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \ - ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt >= MAX_ABSTRACT_INFO_CNT ? ", ..." : "") - - -typedef struct _zend_abstract_info { - zend_function *afn[MAX_ABSTRACT_INFO_CNT+1]; - int cnt; -} zend_abstract_info; - - -int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) -{ - if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { - if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { - ai->afn[ai->cnt] = fn; - } - ai->cnt++; - } - return 0; -} - - int zend_verify_abstract_class_handler(ZEND_OPCODE_HANDLER_ARGS) { - zend_class_entry *ce = EX_T(opline->op1.u.var).class_entry; - zend_abstract_info ai; - - if ((ce->ce_flags & ZEND_ACC_ABSTRACT) && !(ce->ce_flags & ZEND_ACC_ABSTRACT_CLASS)) { - memset(&ai, 0, sizeof(ai)); - - zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); - - zend_error(E_ERROR, "Class %s contains %d abstract methods and must therefore be declared abstract (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", - ce->name, ai.cnt, - DISPLAY_ABSTRACT_FN(0), - DISPLAY_ABSTRACT_FN(1), - DISPLAY_ABSTRACT_FN(2) - ); - } - + zend_verify_abstract_class(EX_T(opline->op1.u.var).class_entry TSRMLS_CC); NEXT_OPCODE(); } http://cvs.php.net/diff.php/ZendEngine2/zend_execute.h?r1=1.64&r2=1.65&ty=u Index: ZendEngine2/zend_execute.h diff -u ZendEngine2/zend_execute.h:1.64 ZendEngine2/zend_execute.h:1.65 --- ZendEngine2/zend_execute.h:1.64 Tue Feb 3 07:17:09 2004 +++ ZendEngine2/zend_execute.h Wed Feb 4 11:30:15 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute.h,v 1.64 2004/02/03 12:17:09 zeev Exp $ */ +/* $Id: zend_execute.h,v 1.65 2004/02/04 16:30:15 zeev Exp $ */ #ifndef ZEND_EXECUTE_H #define ZEND_EXECUTE_H @@ -145,7 +145,7 @@ ZEND_API zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC); void zend_throw_exception_internal(zval *exception TSRMLS_DC); ZEND_API void zend_clear_exception(TSRMLS_D); - +void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC); #ifdef ZEND_WIN32 void zend_init_timeout_thread(); @@ -161,8 +161,6 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, zval **value_ptr_ptr, temp_variable *Ts TSRMLS_DC); -#define IS_STRING_OFFSET 2 - /* The following tries to resolve the classname of a zval of type object. * Since it is slow it should be only used in error messages. */ http://cvs.php.net/diff.php/ZendEngine2/zend_execute_API.c?r1=1.259&r2=1.260&ty=u Index: ZendEngine2/zend_execute_API.c diff -u ZendEngine2/zend_execute_API.c:1.259 ZendEngine2/zend_execute_API.c:1.260 --- ZendEngine2/zend_execute_API.c:1.259 Wed Feb 4 04:56:20 2004 +++ ZendEngine2/zend_execute_API.c Wed Feb 4 11:30:15 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute_API.c,v 1.259 2004/02/04 09:56:20 zeev Exp $ */ +/* $Id: zend_execute_API.c,v 1.260 2004/02/04 16:30:15 zeev Exp $ */ #include <stdio.h> #include <signal.h> @@ -1225,6 +1225,51 @@ } +#define MAX_ABSTRACT_INFO_CNT 3 +#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" +#define DISPLAY_ABSTRACT_FN(idx) \ + ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ + ai.afn[idx] ? "::" : "", \ + ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \ + ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt >= MAX_ABSTRACT_INFO_CNT ? ", ..." : "") + +typedef struct _zend_abstract_info { + zend_function *afn[MAX_ABSTRACT_INFO_CNT+1]; + int cnt; +} zend_abstract_info; + + +static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) +{ + if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { + ai->afn[ai->cnt] = fn; + } + ai->cnt++; + } + return 0; +} + + +void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) +{ + zend_abstract_info ai; + + if ((ce->ce_flags & ZEND_ACC_ABSTRACT) && !(ce->ce_flags & ZEND_ACC_ABSTRACT_CLASS)) { + memset(&ai, 0, sizeof(ai)); + + zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); + + zend_error(E_ERROR, "Class %s contains %d abstract methods and must therefore be declared abstract (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", + ce->name, ai.cnt, + DISPLAY_ABSTRACT_FN(0), + DISPLAY_ABSTRACT_FN(1), + DISPLAY_ABSTRACT_FN(2) + ); + } +} + + /* * Local variables: * tab-width: 4 http://cvs.php.net/diff.php/ZendEngine2/zend_language_parser.y?r1=1.136&r2=1.137&ty=u Index: ZendEngine2/zend_language_parser.y diff -u ZendEngine2/zend_language_parser.y:1.136 ZendEngine2/zend_language_parser.y:1.137 --- ZendEngine2/zend_language_parser.y:1.136 Tue Feb 3 07:17:09 2004 +++ ZendEngine2/zend_language_parser.y Wed Feb 4 11:30:15 2004 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_language_parser.y,v 1.136 2004/02/03 12:17:09 zeev Exp $ */ +/* $Id: zend_language_parser.y,v 1.137 2004/02/04 16:30:15 zeev Exp $ */ /* * LALR shift/reduce conflicts and how they are resolved: @@ -156,7 +156,7 @@ top_statement: statement | function_declaration_statement { zend_do_early_binding(TSRMLS_C); } - | class_declaration_statement + | class_declaration_statement { zend_do_early_binding(TSRMLS_C); } ;
http://cvs.php.net/diff.php/ZendEngine2/zend_compile.c?r1=1.532&r2=1.533&ty=u Index: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.532 ZendEngine2/zend_compile.c:1.533 --- ZendEngine2/zend_compile.c:1.532 Wed Feb 4 09:25:25 2004 +++ ZendEngine2/zend_compile.c Wed Feb 4 11:30:14 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.c,v 1.532 2004/02/04 14:25:25 zeev Exp $ */ +/* $Id: zend_compile.c,v 1.533 2004/02/04 16:30:14 zeev Exp $ */ #include "zend_language_parser.h" #include "zend.h" @@ -1980,7 +1980,7 @@ } -ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time) +ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time) { zend_function *function; @@ -2012,7 +2012,7 @@ } -ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *function_table, HashTable *class_table TSRMLS_DC) +ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) { zend_class_entry *ce, **pce; @@ -2025,14 +2025,23 @@ ce->refcount++; if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) { ce->refcount--; - zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + if (!compile_time) { + /* If we're in compile time, in practice, it's quite possible + * that we'll never reach this class declaration at runtime, + * so we shut up about it. This allows the if (!defined('FOO')) { return; } + * approach to work. + */ + zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + } return NULL; } else { + zend_verify_abstract_class(ce TSRMLS_CC); return ce; } } -ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *function_table, HashTable *class_table, zend_class_entry *parent_ce TSRMLS_DC) + +ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC) { zend_class_entry *ce, **pce; int found_ce; @@ -2040,7 +2049,14 @@ found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce); if (found_ce == FAILURE) { - zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + if (!compile_time) { + /* If we're in compile time, in practice, it's quite possible + * that we'll never reach this class declaration at runtime, + * so we shut up about it. This allows the if (!defined('FOO')) { return; } + * approach to work. + */ + zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + } return NULL; } else { ce = *pce; @@ -2068,16 +2084,56 @@ void zend_do_early_binding(TSRMLS_D) { zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; + HashTable *table; while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) { opline--; } - if (do_bind_function(opline, CG(function_table), CG(class_table), 1) == FAILURE) { - return; + switch (opline->opcode) { + case ZEND_DECLARE_FUNCTION: + if (do_bind_function(opline, CG(function_table), 1) == FAILURE) { + return; + } + table = CG(function_table); + break; + case ZEND_VERIFY_ABSTRACT_CLASS: { + zend_op *verify_abstract_class_op = opline; + + opline--; + if (opline->opcode == ZEND_DECLARE_CLASS) { + if (do_bind_class(opline, CG(class_table), 1 TSRMLS_CC) == NULL) { + return; + } + } else if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS) { + zval *parent_name = &(opline-1)->op2.u.constant; + zend_class_entry **pce; + + if (zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) { + return; + } + if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) { + return; + } + } else { + /* We currently don't early-bind classes that implement interfaces */ + return; + } + table = CG(class_table); + /* clear the verify_abstract_class op */ + init_op(verify_abstract_class_op TSRMLS_CC); + SET_UNUSED(verify_abstract_class_op->op1); + SET_UNUSED(verify_abstract_class_op->op2); + verify_abstract_class_op->opcode = ZEND_NOP; + } + + break; + default: + zend_error(E_COMPILE_ERROR, "Invalid binding type"); + return; } - zend_hash_del(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len); + zend_hash_del(table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len); zval_dtor(&opline->op1.u.constant); zval_dtor(&opline->op2.u.constant); opline->opcode = ZEND_NOP; http://cvs.php.net/diff.php/ZendEngine2/zend_compile.h?r1=1.273&r2=1.274&ty=u Index: ZendEngine2/zend_compile.h diff -u ZendEngine2/zend_compile.h:1.273 ZendEngine2/zend_compile.h:1.274 --- ZendEngine2/zend_compile.h:1.273 Tue Feb 3 07:17:09 2004 +++ ZendEngine2/zend_compile.h Wed Feb 4 11:30:14 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.h,v 1.273 2004/02/03 12:17:09 zeev Exp $ */ +/* $Id: zend_compile.h,v 1.274 2004/02/04 16:30:14 zeev Exp $ */ #ifndef ZEND_COMPILE_H #define ZEND_COMPILE_H @@ -367,9 +367,9 @@ void zend_do_end_catch(znode *try_token TSRMLS_DC); void zend_do_throw(znode *expr TSRMLS_DC); -ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time); -ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *function_table, HashTable *class_table TSRMLS_DC); -ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *function_table, HashTable *class_table, zend_class_entry *parent_ce TSRMLS_DC); +ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time); +ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC); +ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC); ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC); ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC); void zend_do_implements_interface(znode *interface_znode TSRMLS_DC); http://cvs.php.net/diff.php/ZendEngine2/zend_execute.c?r1=1.597&r2=1.598&ty=u Index: ZendEngine2/zend_execute.c diff -u ZendEngine2/zend_execute.c:1.597 ZendEngine2/zend_execute.c:1.598 --- ZendEngine2/zend_execute.c:1.597 Wed Feb 4 06:47:54 2004 +++ ZendEngine2/zend_execute.c Wed Feb 4 11:30:15 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute.c,v 1.597 2004/02/04 11:47:54 zeev Exp $ */ +/* $Id: zend_execute.c,v 1.598 2004/02/04 16:30:15 zeev Exp $ */ #define ZEND_INTENSIVE_DEBUGGING 0 @@ -4006,21 +4006,21 @@ int zend_declare_class_handler(ZEND_OPCODE_HANDLER_ARGS) { - EX_T(opline->result.u.var).class_entry = do_bind_class(opline, EG(function_table), EG(class_table) TSRMLS_CC); + EX_T(opline->result.u.var).class_entry = do_bind_class(opline, EG(class_table), 0 TSRMLS_CC); NEXT_OPCODE(); } int zend_declare_inherited_class_handler(ZEND_OPCODE_HANDLER_ARGS) { - EX_T(opline->result.u.var).class_entry = do_bind_inherited_class(opline, EG(function_table), EG(class_table), EX_T(opline->extended_value).class_entry TSRMLS_CC); + EX_T(opline->result.u.var).class_entry = do_bind_inherited_class(opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC); NEXT_OPCODE(); } int zend_declare_function_handler(ZEND_OPCODE_HANDLER_ARGS) { - do_bind_function(opline, EG(function_table), EG(class_table), 0); + do_bind_function(opline, EG(function_table), 0); NEXT_OPCODE(); } @@ -4107,52 +4107,9 @@ } -#define MAX_ABSTRACT_INFO_CNT 3 -#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" - -#define DISPLAY_ABSTRACT_FN(idx) \ - ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ - ai.afn[idx] ? "::" : "", \ - ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \ - ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt >= MAX_ABSTRACT_INFO_CNT ? ", ..." : "") - - -typedef struct _zend_abstract_info { - zend_function *afn[MAX_ABSTRACT_INFO_CNT+1]; - int cnt; -} zend_abstract_info; - - -int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) -{ - if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { - if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { - ai->afn[ai->cnt] = fn; - } - ai->cnt++; - } - return 0; -} - - int zend_verify_abstract_class_handler(ZEND_OPCODE_HANDLER_ARGS) { - zend_class_entry *ce = EX_T(opline->op1.u.var).class_entry; - zend_abstract_info ai; - - if ((ce->ce_flags & ZEND_ACC_ABSTRACT) && !(ce->ce_flags & ZEND_ACC_ABSTRACT_CLASS)) { - memset(&ai, 0, sizeof(ai)); - - zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); - - zend_error(E_ERROR, "Class %s contains %d abstract methods and must therefore be declared abstract (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", - ce->name, ai.cnt, - DISPLAY_ABSTRACT_FN(0), - DISPLAY_ABSTRACT_FN(1), - DISPLAY_ABSTRACT_FN(2) - ); - } - + zend_verify_abstract_class(EX_T(opline->op1.u.var).class_entry TSRMLS_CC); NEXT_OPCODE(); } http://cvs.php.net/diff.php/ZendEngine2/zend_execute.h?r1=1.64&r2=1.65&ty=u Index: ZendEngine2/zend_execute.h diff -u ZendEngine2/zend_execute.h:1.64 ZendEngine2/zend_execute.h:1.65 --- ZendEngine2/zend_execute.h:1.64 Tue Feb 3 07:17:09 2004 +++ ZendEngine2/zend_execute.h Wed Feb 4 11:30:15 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute.h,v 1.64 2004/02/03 12:17:09 zeev Exp $ */ +/* $Id: zend_execute.h,v 1.65 2004/02/04 16:30:15 zeev Exp $ */ #ifndef ZEND_EXECUTE_H #define ZEND_EXECUTE_H @@ -145,7 +145,7 @@ ZEND_API zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC); void zend_throw_exception_internal(zval *exception TSRMLS_DC); ZEND_API void zend_clear_exception(TSRMLS_D); - +void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC); #ifdef ZEND_WIN32 void zend_init_timeout_thread(); @@ -161,8 +161,6 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, zval **value_ptr_ptr, temp_variable *Ts TSRMLS_DC); -#define IS_STRING_OFFSET 2 - /* The following tries to resolve the classname of a zval of type object. * Since it is slow it should be only used in error messages. */ http://cvs.php.net/diff.php/ZendEngine2/zend_execute_API.c?r1=1.259&r2=1.260&ty=u Index: ZendEngine2/zend_execute_API.c diff -u ZendEngine2/zend_execute_API.c:1.259 ZendEngine2/zend_execute_API.c:1.260 --- ZendEngine2/zend_execute_API.c:1.259 Wed Feb 4 04:56:20 2004 +++ ZendEngine2/zend_execute_API.c Wed Feb 4 11:30:15 2004 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute_API.c,v 1.259 2004/02/04 09:56:20 zeev Exp $ */ +/* $Id: zend_execute_API.c,v 1.260 2004/02/04 16:30:15 zeev Exp $ */ #include <stdio.h> #include <signal.h> @@ -1225,6 +1225,51 @@ } +#define MAX_ABSTRACT_INFO_CNT 3 +#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" +#define DISPLAY_ABSTRACT_FN(idx) \ + ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ + ai.afn[idx] ? "::" : "", \ + ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \ + ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt >= MAX_ABSTRACT_INFO_CNT ? ", ..." : "") + +typedef struct _zend_abstract_info { + zend_function *afn[MAX_ABSTRACT_INFO_CNT+1]; + int cnt; +} zend_abstract_info; + + +static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) +{ + if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { + ai->afn[ai->cnt] = fn; + } + ai->cnt++; + } + return 0; +} + + +void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) +{ + zend_abstract_info ai; + + if ((ce->ce_flags & ZEND_ACC_ABSTRACT) && !(ce->ce_flags & ZEND_ACC_ABSTRACT_CLASS)) { + memset(&ai, 0, sizeof(ai)); + + zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); + + zend_error(E_ERROR, "Class %s contains %d abstract methods and must therefore be declared abstract (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", + ce->name, ai.cnt, + DISPLAY_ABSTRACT_FN(0), + DISPLAY_ABSTRACT_FN(1), + DISPLAY_ABSTRACT_FN(2) + ); + } +} + + /* * Local variables: * tab-width: 4 http://cvs.php.net/diff.php/ZendEngine2/zend_language_parser.y?r1=1.136&r2=1.137&ty=u Index: ZendEngine2/zend_language_parser.y diff -u ZendEngine2/zend_language_parser.y:1.136 ZendEngine2/zend_language_parser.y:1.137 --- ZendEngine2/zend_language_parser.y:1.136 Tue Feb 3 07:17:09 2004 +++ ZendEngine2/zend_language_parser.y Wed Feb 4 11:30:15 2004 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_language_parser.y,v 1.136 2004/02/03 12:17:09 zeev Exp $ */ +/* $Id: zend_language_parser.y,v 1.137 2004/02/04 16:30:15 zeev Exp $ */ /* * LALR shift/reduce conflicts and how they are resolved: @@ -156,7 +156,7 @@ top_statement: statement | function_declaration_statement { zend_do_early_binding(TSRMLS_C); } - | class_declaration_statement + | class_declaration_statement { zend_do_early_binding(TSRMLS_C); } ;