From 9d7122fb53fd7f043f2cde7eeb4f9aa0e2115adf Mon Sep 17 00:00:00 2001 From: Zeev Suraski Date: Sun, 3 Aug 2003 08:21:08 +0000 Subject: [PATCH] Generalize fetch_class --- Zend/zend_compile.c | 39 +++++++++++++------ Zend/zend_compile.h | 2 + Zend/zend_execute.c | 86 +++++++++++------------------------------ Zend/zend_execute.h | 1 + Zend/zend_execute_API.c | 37 ++++++++++++++++++ 5 files changed, 89 insertions(+), 76 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 605e4e491d..a4e212a973 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1185,19 +1185,20 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) opline->extended_value = ZEND_FETCH_CLASS_GLOBAL; CG(catch_begin) = fetch_class_op_number; if (class_name->op_type == IS_CONST) { + int fetch_type; + zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); - if ((class_name->u.constant.value.str.len == (sizeof("self") - 1)) && - !memcmp(class_name->u.constant.value.str.val, "self", sizeof("self"))) { - SET_UNUSED(opline->op2); - opline->extended_value = ZEND_FETCH_CLASS_SELF; - zval_dtor(&class_name->u.constant); - } else if ((class_name->u.constant.value.str.len == (sizeof("parent") - 1)) && - !memcmp(class_name->u.constant.value.str.val, "parent", sizeof("parent"))) { - SET_UNUSED(opline->op2); - opline->extended_value = ZEND_FETCH_CLASS_PARENT; - zval_dtor(&class_name->u.constant); - } else { - opline->op2 = *class_name; + fetch_type = zend_get_class_fetch_type(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + case ZEND_FETCH_CLASS_PARENT: + SET_UNUSED(opline->op2); + opline->extended_value = fetch_type; + zval_dtor(&class_name->u.constant); + break; + default: + opline->op2 = *class_name; + break; } } else { opline->op2 = *class_name; @@ -3414,6 +3415,20 @@ void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers ce->interfaces = NULL; } + +int zend_get_class_fetch_type(char *class_name, uint class_name_len) +{ + if ((class_name_len == sizeof("self")-1) && + !memcmp(class_name, "self", sizeof("self"))) { + return ZEND_FETCH_CLASS_SELF; + } else if ((class_name_len == sizeof("parent")-1) && + !memcmp(class_name, "parent", sizeof("parent"))) { + return ZEND_FETCH_CLASS_PARENT; + } else { + return ZEND_FETCH_CLASS_DEFAULT; + } +} + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index d28fa53e40..59e05ea273 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -465,6 +465,7 @@ zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array); ZEND_API zend_bool zend_is_compiling(TSRMLS_D); ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC); void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC); +int zend_get_class_fetch_type(char *class_name, uint class_name_len); typedef zend_bool (*zend_auto_global_callback)(char *name, uint name_len TSRMLS_DC); typedef struct _zend_auto_global { @@ -680,6 +681,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_CLASS_PARENT 2 #define ZEND_FETCH_CLASS_MAIN 3 #define ZEND_FETCH_CLASS_GLOBAL 4 +#define ZEND_FETCH_CLASS_AUTO 5 /* variable parsing type (compile-time) */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 1c0866d8a1..64325d2394 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2202,81 +2202,39 @@ int zend_add_var_handler(ZEND_OPCODE_HANDLER_ARGS) NEXT_OPCODE(); } + int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS) { - zend_class_entry **pce; - zend_class_entry *ce = NULL; - zend_bool is_const; char *class_name_strval; - zend_uint class_name_strlen; - zend_bool free_class_name = 0; - zval *class_name; + zval *class_name; + if (EX(opline)->op2.op_type == IS_UNUSED) { - if (EX(opline)->extended_value == ZEND_FETCH_CLASS_SELF) { - if (!EG(scope)) { - zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); - } - EX_T(EX(opline)->result.u.var).EA.class_entry = EG(scope); - NEXT_OPCODE(); - } else if (EX(opline)->extended_value == ZEND_FETCH_CLASS_PARENT) { - if (!EG(scope)) { - zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); - } - if (!EG(scope)->parent) { - zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); - } - EX_T(EX(opline)->result.u.var).EA.class_entry = EG(scope)->parent; - NEXT_OPCODE(); - } + EX_T(EX(opline)->result.u.var).EA.class_entry = zend_fetch_class(NULL, 0, EX(opline)->extended_value TSRMLS_CC); + NEXT_OPCODE(); } - is_const = (EX(opline)->op2.op_type == IS_CONST); + class_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - if (is_const) { - class_name_strval = EX(opline)->op2.u.constant.value.str.val; - class_name_strlen = EX(opline)->op2.u.constant.value.str.len; - } else { - class_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - - switch (class_name->type) { - case IS_OBJECT: - ce = Z_OBJCE_P(class_name); - break; - case IS_STRING: - convert_to_string_ex(&class_name); + switch (class_name->type) { + case IS_OBJECT: + EX_T(EX(opline)->result.u.var).EA.class_entry = Z_OBJCE_P(class_name); + break; + case IS_STRING: + if (EX(opline)->op2.op_type != IS_CONST) { class_name_strval = zend_str_tolower_dup(class_name->value.str.val, class_name->value.str.len); - class_name_strlen = class_name->value.str.len; - free_class_name = 1; - break; - default: - zend_error(E_ERROR, "Class name must be a valid object or a string"); - break; - } - } - - if (!ce) { - int retval; - - if (EX(opline)->op1.op_type == IS_UNUSED) { - retval = zend_lookup_class(class_name_strval, class_name_strlen, &pce TSRMLS_CC); - } - if (retval==SUCCESS) { - ce = *pce; - } + EX_T(EX(opline)->result.u.var).EA.class_entry = zend_fetch_class(class_name_strval, Z_STRLEN_P(class_name), ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); + efree(class_name_strval); + } else { + EX_T(EX(opline)->result.u.var).EA.class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); + } + break; + default: + zend_error(E_ERROR, "Class name must be a valid object or a string"); + break; } - if (!ce) { - zend_error(E_ERROR, "Class '%s' not found", class_name_strval); - } else { - EX_T(EX(opline)->result.u.var).EA.class_entry = ce; - } - if (!is_const) { - if (free_class_name) { - efree(class_name_strval); - } - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); NEXT_OPCODE(); } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 01075f3ffc..39b2ee6e87 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -147,6 +147,7 @@ ZEND_API zend_bool zend_is_executing(TSRMLS_D); ZEND_API void zend_set_timeout(long seconds); ZEND_API void zend_unset_timeout(TSRMLS_D); ZEND_API void zend_timeout(int dummy); +ZEND_API zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC); #ifdef ZEND_WIN32 void zend_init_timeout_thread(); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 78c35d56f4..d57ac934db 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1049,6 +1049,43 @@ void zend_unset_timeout(TSRMLS_D) #endif } + +zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC) +{ + zend_class_entry **pce; + zend_class_entry *ce = NULL; + zend_bool free_class_name = 0; + +check_fetch_type: + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + if (!EG(scope)) { + zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); + } + return EG(scope); + case ZEND_FETCH_CLASS_PARENT: + if (!EG(scope)) { + zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); + } + if (!EG(scope)->parent) { + zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); + } + return EG(scope)->parent; + case ZEND_FETCH_CLASS_AUTO: { + fetch_type = zend_get_class_fetch_type(class_name, class_name_len); + if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) { + goto check_fetch_type; + } + } + break; + } + + if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) { + zend_error(E_ERROR, "Class '%s' not found", class_name); + } + return *pce; +} + /* * Local variables: * tab-width: 4 -- 2.40.0