]> granicus.if.org Git - php/commitdiff
- Commit patch to support protected member variables (by Timm Friebe w/
authorAndi Gutmans <andi@php.net>
Mon, 15 Jul 2002 18:09:56 +0000 (18:09 +0000)
committerAndi Gutmans <andi@php.net>
Mon, 15 Jul 2002 18:09:56 +0000 (18:09 +0000)
- some fixes by me).
- You can't access protected variables from outside the object. If you want
- to see a protected member from your ancestors you need to declare the
- member as protected in the class you want to use it in. You can't
- redeclare a protected variable as private nor the other way around.

Zend/ZEND_CHANGES
Zend/zend.c
Zend/zend.h
Zend/zend_API.c
Zend/zend_compile.c
Zend/zend_language_parser.y
Zend/zend_language_scanner.l
Zend/zend_opcode.c

index 1e96a5a021d6810155bb2cb0bd65b926e6e2dd51..8b7f465964f4f458c978e853687f601cb495f1a7 100644 (file)
@@ -19,39 +19,58 @@ Changes in the Zend Engine 2.0
       the box or after a very small amount of modifications would be
       high.
 
-    * Private Members.
+    * Private and Protected Members.
 
-      The Zend Engine 2.0 introduces private member variables. Note
-      that for performance reasons no error message is emitted in
-      case of an illegal access to a private member variable.
+      The Zend Engine 2.0 introduces private and protected member variables. 
+      Note that for performance reasons no error message is emitted in
+      case of an illegal access to a private or protectecd member variable.
 
       Example:
 
         <?php
         class MyClass {
             private $Hello = "Hello, World!\n";
+            protected $Bar = "Hello, Foo!\n";
+            protected $Foo = "Hello, Bar!\n";
 
             function printHello() {
-                print $this->Hello;
+                print "MyClass::printHello() ".$this->Hello;
+                print "MyClass::printHello() ".$this->Bar;
+                print "MyClass::printHello() ".$this->Foo;
             }
         }
 
         class MyClass2 extends MyClass {
+            protected $Foo;
+            
             function printHello() {
                 MyClass::printHello(); /* Should print */
-                print $this->Hello;    /* Shouldn't print out anything */
+                print "MyClass2::printHello() ".$this->Hello;    /* Shouldn't print out anything */
+                print "MyClass2::printHello() ".$this->Bar;      /* Shouldn't print (not declared)*/
+                print "MyClass2::printHello() ".$this->Foo;      /* Should print */
             }
         }
 
         $obj = new MyClass();
         print $obj->Hello;  /* Shouldn't print out anything */
+        print $obj->Bar;    /* Shouldn't print out anything */
+        print $obj->Foo;    /* Shouldn't print out anything */
         $obj->printHello(); /* Should print */
 
         $obj = new MyClass2();
         print $obj->Hello;  /* Shouldn't print out anything */
+        print $obj->Bar;    /* Shouldn't print out anything */
+        print $obj->Foo;    /* Shouldn't print out anything */
         $obj->printHello();
         ?>
-
+        
+      Protected member variables can be accessed in classes extending the class
+      they are declared in, whereas private member variables can only be accessed
+      by the class they belong to.
+      
+      Note: Protected member variables have to be declared in every class they 
+      are used!
+        
     * Object Cloning.
 
       The Zend Engine 1.0 offered no way a user could decide what copy
index fdc7019025cb7c616debcc4a7765fdf282710624..a3d8d070695e1bc9b247fe6395f734e43c2b6a82 100644 (file)
@@ -254,6 +254,7 @@ static void register_standard_class(void)
        zend_standard_class_def->parent = NULL;
        zend_hash_init_ex(&zend_standard_class_def->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
        zend_hash_init_ex(&zend_standard_class_def->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+       zend_hash_init_ex(&zend_standard_class_def->protected_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
        zend_standard_class_def->static_members = (HashTable *) malloc(sizeof(HashTable));
        zend_hash_init_ex(zend_standard_class_def->static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
        zend_hash_init_ex(&zend_standard_class_def->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
index ab526c90437caf8245b9b05f958e06bbe957f73b..d0c2667b6dba0bb0c066f0113a17263c64e7f332 100644 (file)
@@ -291,6 +291,7 @@ struct _zend_class_entry {
        HashTable function_table;
        HashTable default_properties;
        HashTable private_properties; /* This is only needed at compile-time */
+       HashTable protected_properties; /* This is only needed at compile-time */
        HashTable class_table;
        HashTable *static_members;
        HashTable constants_table;
index cfd9159ac384af0cd020058811cb9e2594299a00..f1acf85024a481523d6ebd20f51bdc09ff2abc42 100644 (file)
@@ -1237,6 +1237,7 @@ ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_c
        class_entry->constants_updated = 0;
        zend_hash_init(&class_entry->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
        zend_hash_init(&class_entry->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
+       zend_hash_init(&class_entry->protected_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
        class_entry->static_members = (HashTable *) malloc(sizeof(HashTable));
        zend_hash_init(class_entry->static_members, 0, NULL, ZVAL_PTR_DTOR, 1);
        zend_hash_init(&class_entry->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1);
index a927731a175e0a10cacac974132400a9b2fd0a39..dd35df6bb0ab6ec86e13e602ca13c776a9bb716b 100644 (file)
@@ -34,7 +34,6 @@ ZEND_API zend_compiler_globals compiler_globals;
 ZEND_API zend_executor_globals executor_globals;
 #endif
 
-
 static void build_runtime_defined_function_key(zval *result, zval *name, zend_op *opline TSRMLS_DC)
 {
        char lineno_buf[32];
@@ -1151,6 +1150,7 @@ void do_fetch_class_name(znode *result, znode *class_name_entry, znode *class_na
        if (!case_sensitive) {
                zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
        }
+
        length = 1 + result->u.constant.value.str.len + class_name->u.constant.value.str.len;
        result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
        memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], ":", sizeof(":")-1);
@@ -1499,6 +1499,7 @@ void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
 
        /* Perform inheritance */
        zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
+
        /* STATIC_MEMBERS_FIXME */
        zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
        zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
@@ -1531,6 +1532,7 @@ static void create_class(HashTable *class_table, char *name, int name_length, ze
        zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
        zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
        zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
+       zend_hash_init(&new_class_entry->protected_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
        ALLOC_HASHTABLE(new_class_entry->static_members);
        zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0);
        zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
@@ -1651,7 +1653,6 @@ ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_tabl
                                char *class_name, *parent_name;
                                int found_ce;
 
-                               
                                found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce);
 
                                /* Restore base class / derived class names */
@@ -1693,6 +1694,7 @@ ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_tabl
                                        zend_hash_destroy(&ce->function_table);
                                        zend_hash_destroy(&ce->default_properties);
                                        zend_hash_destroy(&ce->private_properties);
+                                       zend_hash_destroy(&ce->protected_properties);
                                        zend_hash_destroy(ce->static_members);
                                        zend_hash_destroy(&ce->constants_table);
                                        return FAILURE;
@@ -2029,6 +2031,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
        zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
        zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
        zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
+       zend_hash_init(&new_class_entry->protected_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
        ALLOC_HASHTABLE(new_class_entry->static_members);
        zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0);
        zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
@@ -2139,19 +2142,19 @@ void zend_do_end_class_declaration(znode *class_token TSRMLS_DC)
        }
 }
 
-void mangle_private_property_name(char **dest, int *dest_length, char *src1, int src1_length, char *src2, int src2_length)
+void mangle_property_name(char **dest, int *dest_length, char *src1, int src1_length, char *src2, int src2_length)
 {
-       char *priv_name;
-       int priv_name_length;
-
-       priv_name_length = 1 + src1_length + 1 + src2_length;
-       priv_name = emalloc(priv_name_length+1);
-       priv_name[0] = '\0';
-       memcpy(priv_name + 1, src1, src1_length+1);
-       memcpy(priv_name + 1 + src1_length + 1, src2, src2_length+1);
+       char *prop_name;
+       int prop_name_length;
+        
+       prop_name_length = 1 + src1_length + 1 + src2_length;
+       prop_name = emalloc(prop_name_length+1);
+       prop_name[0] = '\0';
+       memcpy(prop_name + 1, src1, src1_length+1);
+       memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1);
 
-       *dest = priv_name;
-       *dest_length = priv_name_length;
+       *dest = prop_name;
+       *dest_length = prop_name_length;
 }
 
 void zend_do_declare_property(znode *var_name, znode *value, int declaration_type TSRMLS_DC)
@@ -2172,15 +2175,43 @@ void zend_do_declare_property(znode *var_name, znode *value, int declaration_typ
                        {
                                char *priv_name;
                                int priv_name_length;
-
-                               mangle_private_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len);
+                                
+                               mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len);
                                zend_hash_update(&CG(active_class_entry)->default_properties, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
                                efree(priv_name);
 
                                property->refcount++;
+                                
                                zend_hash_update(&CG(active_class_entry)->private_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
                                break;
                        }
+               case T_PROTECTED:
+                       {
+                               char *prot_name;
+                               int prot_name_length;
+                               zval **found = NULL;
+                                
+                               if (CG(active_class_entry)->parent) {
+                                       zend_hash_find(&CG(active_class_entry)->parent->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &found);
+                               }
+
+                               mangle_property_name(&prot_name, &prot_name_length, "*", 1, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len);
+                               /* If we don't have a value and it exists in our parent then use the parent's value */
+                               if (!value && found) {
+                                       (*found)->refcount++;
+                                       zend_hash_update(&CG(active_class_entry)->default_properties, prot_name, prot_name_length+1, found, sizeof(zval *), NULL);
+                                       (*found)->refcount++;
+                                       zend_hash_update(&CG(active_class_entry)->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, found, sizeof(zval *), NULL);
+                                       zval_ptr_dtor(&property);
+                               } else {
+                                       zend_hash_update(&CG(active_class_entry)->default_properties, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
+                                       property->refcount++;
+                                       zend_hash_update(&CG(active_class_entry)->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
+
+                               }
+                               efree(prot_name);
+                               break;
+                       }
                case T_VAR:
                        zend_hash_update(&CG(active_class_entry)->default_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
                        break;
@@ -2194,20 +2225,20 @@ void zend_do_declare_property(znode *var_name, znode *value, int declaration_typ
        FREE_PNODE(var_name);
 }
 
-
 void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC)
 {
        zend_op opline;
        zend_llist *fetch_list_ptr;
-       
+        
        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
-
+        
        if (fetch_list_ptr->count == 1) {
                zend_llist_element *le;
                zend_op *opline_ptr;
 
                le = fetch_list_ptr->head;
                opline_ptr = (zend_op *) le->data;
+                
                if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) &&
                (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) &&
                !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) {
@@ -2215,17 +2246,26 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
                        opline_ptr->op1 = *property;
                        SET_UNUSED(opline_ptr->op2);
                        opline_ptr->op2.u.EA.type = ZEND_FETCH_FROM_THIS;
-
-                       if (CG(active_class_entry)) {
-                               if ((opline_ptr->op1.op_type == IS_CONST) && zend_hash_exists(&CG(active_class_entry)->private_properties, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len+1)) {
+                        
+                       if (CG(active_class_entry) && (opline_ptr->op1.op_type == IS_CONST)) {
+                               if (zend_hash_exists(&CG(active_class_entry)->private_properties, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len+1)) {
                                        char *priv_name;
                                        int priv_name_length;
-
-                                       mangle_private_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len);
+                                        
+                                       mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len);
 
                                        STR_FREE(opline_ptr->op1.u.constant.value.str.val);
                                        opline_ptr->op1.u.constant.value.str.val = priv_name;
                                        opline_ptr->op1.u.constant.value.str.len = priv_name_length;
+                               } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len+1)) {
+                                       char *prot_name;
+                                       int prot_name_length;
+                                        
+                                       mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len);
+
+                                       STR_FREE(opline_ptr->op1.u.constant.value.str.val);
+                                       opline_ptr->op1.u.constant.value.str.val = prot_name;
+                                       opline_ptr->op1.u.constant.value.str.len = prot_name_length;
                                }
                        }
                        *result = opline_ptr->result;
@@ -2239,7 +2279,7 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
        opline.result.u.EA.type = 0;
        opline.result.u.var = get_temporary_variable(CG(active_op_array));
        opline.op1 = *object;
-       opline. op2 = *property;
+       opline.op2 = *property;
        *result = opline.result;
 
        zend_llist_add_element(fetch_list_ptr, &opline);
index 5d89928981cc0f129ba240fea3967ef7b306bf39..08b420f1b62ddb0311dd0a467a3d7f903613f980 100644 (file)
 %token T_GLOBAL
 %token T_STATIC
 %token T_PRIVATE
+%token T_PROTECTED
 %token T_VAR
 %token T_UNSET
 %token T_ISSET
@@ -451,6 +452,7 @@ class_declaration_type:
                T_VAR           { $$.op_type = T_VAR; }
        |       T_STATIC        { $$.op_type = T_STATIC; }
        |       T_PRIVATE       { $$.op_type = T_PRIVATE; }
+       |       T_PROTECTED     { $$.op_type = T_PROTECTED; }
 ;
 
 class_constant_declaration:
index 90449598620ffddf07fc7bde5b06513bbbe98f73..fd597a713baedac50e06908ca75c69e781affa79 100644 (file)
@@ -709,6 +709,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
        return T_PRIVATE;
 }
 
+<ST_IN_SCRIPTING>"protected" {
+       return T_PROTECTED;
+}
+
 <ST_IN_SCRIPTING>"unset" {
        return T_UNSET;
 }
index 62d80e29ef1ac9bcb12e3cfca5129d46ccbb2e0f..94e587c8c2c567280ef6c8ec87b1e41cbeabfcb8 100644 (file)
@@ -119,6 +119,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                case ZEND_USER_CLASS:
                        zend_hash_destroy(&ce->default_properties);
                        zend_hash_destroy(&ce->private_properties);
+                       zend_hash_destroy(&ce->protected_properties);
                        zend_hash_destroy(ce->static_members);
                        efree(ce->name);
                        zend_hash_destroy(&ce->function_table);
@@ -130,6 +131,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                case ZEND_INTERNAL_CLASS:
                        zend_hash_destroy(&ce->default_properties);
                        zend_hash_destroy(&ce->private_properties);
+                       zend_hash_destroy(&ce->protected_properties);
                        zend_hash_destroy(ce->static_members);
                        free(ce->name);
                        zend_hash_destroy(&ce->function_table);