]> granicus.if.org Git - php/commitdiff
Generalize fetch_class
authorZeev Suraski <zeev@php.net>
Sun, 3 Aug 2003 08:21:08 +0000 (08:21 +0000)
committerZeev Suraski <zeev@php.net>
Sun, 3 Aug 2003 08:21:08 +0000 (08:21 +0000)
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_execute_API.c

index 605e4e491dc7039fd5bafbea71e1af36914e9df1..a4e212a973fe9b0e59937d62be798d6088f677c7 100644 (file)
@@ -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
index d28fa53e405ff0b5a98c5bafefa760b69867d10d..59e05ea27376e807b79db56b1384660d3d997a09 100644 (file)
@@ -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) */
index 1c0866d8a1c4459a9a5bac6f30857c570ed71fdf..64325d23943977492386a80345bec40931beef74 100644 (file)
@@ -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();
 }
 
index 01075f3ffc36043c4457655d11f26b59c5e81ce9..39b2ee6e873ac520d09f9b490440d09631e82f93 100644 (file)
@@ -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();
index 78c35d56f40bcca14a29ee9405bd3c8bfc7fb421..d57ac934dbc6f05508afcdeb16ba614e50051445 100644 (file)
@@ -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