cvs: ZendEngine2 / ZEND_CHANGES zend.c zend.h zend_API.c zend_compile.c zend_language_parser.y zend_language_scanner.l zend_opcode.c
| From: | Andi Gutmans | Date: | Mon, 15 Jul 2002 18:09:56 +0000 |
| Subject: | cvs: ZendEngine2 / ZEND_CHANGES zend.c zend.h zend_API.c zend_compile.c zend_language_parser.y zend_language_scanner.l zend_opcode.c | ||
| Groups: | php.zend-engine.cvs | ||
| Request: | Send a blank email to php-zend-engine-cvs+get-258@lists.php.net to get a copy of this message | ||
andi Mon Jul 15 14:09:56 2002 EDT
Modified files:
/ZendEngine2 ZEND_CHANGES zend.c zend.h zend_API.c zend_compile.c
zend_language_parser.y zend_language_scanner.l
zend_opcode.c
Log:
- Commit patch to support protected member variables (by Timm Friebe w/
- 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.
Index: ZendEngine2/ZEND_CHANGES diff -u ZendEngine2/ZEND_CHANGES:1.30 ZendEngine2/ZEND_CHANGES:1.31 --- ZendEngine2/ZEND_CHANGES:1.30 Sun Jul 14 15:23:17 2002 +++ ZendEngine2/ZEND_CHANGES Mon Jul 15 14:09:56 2002 @@ -19,39 +19,58 @@ 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: ZendEngine2/zend.c diff -u ZendEngine2/zend.c:1.167 ZendEngine2/zend.c:1.168 --- ZendEngine2/zend.c:1.167 Tue Jun 18 13:36:33 2002 +++ ZendEngine2/zend.c Mon Jul 15 14:09:56 2002 @@ -254,6 +254,7 @@ 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: ZendEngine2/zend.h diff -u ZendEngine2/zend.h:1.175 ZendEngine2/zend.h:1.176 --- ZendEngine2/zend.h:1.175 Sat Jun 29 15:37:10 2002 +++ ZendEngine2/zend.h Mon Jul 15 14:09:56 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend.h,v 1.175 2002/06/29 19:37:10 andi Exp $ */ +/* $Id: zend.h,v 1.176 2002/07/15 18:09:56 andi Exp $ */ #ifndef ZEND_H #define ZEND_H @@ -291,6 +291,7 @@ 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: ZendEngine2/zend_API.c diff -u ZendEngine2/zend_API.c:1.129 ZendEngine2/zend_API.c:1.130 --- ZendEngine2/zend_API.c:1.129 Wed Jun 26 10:24:23 2002 +++ ZendEngine2/zend_API.c Mon Jul 15 14:09:56 2002 @@ -1237,6 +1237,7 @@ 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: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.292 ZendEngine2/zend_compile.c:1.293 --- ZendEngine2/zend_compile.c:1.292 Sun Jul 14 15:23:18 2002 +++ ZendEngine2/zend_compile.c Mon Jul 15 14:09:56 2002 @@ -34,7 +34,6 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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_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 @@ 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 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 @@ { 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 @@ 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 @@ 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 @@ 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: ZendEngine2/zend_language_parser.y diff -u ZendEngine2/zend_language_parser.y:1.62 ZendEngine2/zend_language_parser.y:1.63 --- ZendEngine2/zend_language_parser.y:1.62 Sun Jul 14 15:23:18 2002 +++ ZendEngine2/zend_language_parser.y Mon Jul 15 14:09:56 2002 @@ -112,6 +112,7 @@ %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 @@ 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: ZendEngine2/zend_language_scanner.l diff -u ZendEngine2/zend_language_scanner.l:1.52 ZendEngine2/zend_language_scanner.l:1.53 --- ZendEngine2/zend_language_scanner.l:1.52 Sun Jul 14 15:23:18 2002 +++ ZendEngine2/zend_language_scanner.l Mon Jul 15 14:09:56 2002 @@ -709,6 +709,10 @@ return T_PRIVATE; } +<ST_IN_SCRIPTING>"protected" { + return T_PROTECTED; +} + <ST_IN_SCRIPTING>"unset" { return T_UNSET; } Index: ZendEngine2/zend_opcode.c diff -u ZendEngine2/zend_opcode.c:1.71 ZendEngine2/zend_opcode.c:1.72 --- ZendEngine2/zend_opcode.c:1.71 Tue Apr 23 14:06:54 2002 +++ ZendEngine2/zend_opcode.c Mon Jul 15 14:09:56 2002 @@ -119,6 +119,7 @@ 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 @@ 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);
Index: ZendEngine2/ZEND_CHANGES diff -u ZendEngine2/ZEND_CHANGES:1.30 ZendEngine2/ZEND_CHANGES:1.31 --- ZendEngine2/ZEND_CHANGES:1.30 Sun Jul 14 15:23:17 2002 +++ ZendEngine2/ZEND_CHANGES Mon Jul 15 14:09:56 2002 @@ -19,39 +19,58 @@ 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: ZendEngine2/zend.c diff -u ZendEngine2/zend.c:1.167 ZendEngine2/zend.c:1.168 --- ZendEngine2/zend.c:1.167 Tue Jun 18 13:36:33 2002 +++ ZendEngine2/zend.c Mon Jul 15 14:09:56 2002 @@ -254,6 +254,7 @@ 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: ZendEngine2/zend.h diff -u ZendEngine2/zend.h:1.175 ZendEngine2/zend.h:1.176 --- ZendEngine2/zend.h:1.175 Sat Jun 29 15:37:10 2002 +++ ZendEngine2/zend.h Mon Jul 15 14:09:56 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend.h,v 1.175 2002/06/29 19:37:10 andi Exp $ */ +/* $Id: zend.h,v 1.176 2002/07/15 18:09:56 andi Exp $ */ #ifndef ZEND_H #define ZEND_H @@ -291,6 +291,7 @@ 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: ZendEngine2/zend_API.c diff -u ZendEngine2/zend_API.c:1.129 ZendEngine2/zend_API.c:1.130 --- ZendEngine2/zend_API.c:1.129 Wed Jun 26 10:24:23 2002 +++ ZendEngine2/zend_API.c Mon Jul 15 14:09:56 2002 @@ -1237,6 +1237,7 @@ 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: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.292 ZendEngine2/zend_compile.c:1.293 --- ZendEngine2/zend_compile.c:1.292 Sun Jul 14 15:23:18 2002 +++ ZendEngine2/zend_compile.c Mon Jul 15 14:09:56 2002 @@ -34,7 +34,6 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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_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 @@ 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 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 @@ { 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 @@ 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 @@ 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 @@ 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: ZendEngine2/zend_language_parser.y diff -u ZendEngine2/zend_language_parser.y:1.62 ZendEngine2/zend_language_parser.y:1.63 --- ZendEngine2/zend_language_parser.y:1.62 Sun Jul 14 15:23:18 2002 +++ ZendEngine2/zend_language_parser.y Mon Jul 15 14:09:56 2002 @@ -112,6 +112,7 @@ %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 @@ 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: ZendEngine2/zend_language_scanner.l diff -u ZendEngine2/zend_language_scanner.l:1.52 ZendEngine2/zend_language_scanner.l:1.53 --- ZendEngine2/zend_language_scanner.l:1.52 Sun Jul 14 15:23:18 2002 +++ ZendEngine2/zend_language_scanner.l Mon Jul 15 14:09:56 2002 @@ -709,6 +709,10 @@ return T_PRIVATE; } +<ST_IN_SCRIPTING>"protected" { + return T_PROTECTED; +} + <ST_IN_SCRIPTING>"unset" { return T_UNSET; } Index: ZendEngine2/zend_opcode.c diff -u ZendEngine2/zend_opcode.c:1.71 ZendEngine2/zend_opcode.c:1.72 --- ZendEngine2/zend_opcode.c:1.71 Tue Apr 23 14:06:54 2002 +++ ZendEngine2/zend_opcode.c Mon Jul 15 14:09:56 2002 @@ -119,6 +119,7 @@ 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 @@ 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);