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;
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
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 {
#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) */
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();
}
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();
#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