summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeev Suraski <zeev@php.net>1999-07-08 16:55:27 +0000
committerZeev Suraski <zeev@php.net>1999-07-08 16:55:27 +0000
commitd894cf44d8c81e1d6158a78e9d8696fcdc163658 (patch)
tree3d5da3895a82c8ba38d7b5e9e62cae7970a90488
parentff9407b56b42a30070ef19caee0a757b488e622d (diff)
downloadphp-git-d894cf44d8c81e1d6158a78e9d8696fcdc163658.tar.gz
Support definition of classes that are derived from classes that are defined in runtime
-rw-r--r--Zend/zend_compile.c90
-rw-r--r--Zend/zend_compile.h5
2 files changed, 73 insertions, 22 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 566ef0eda6..30b0db63ab 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -846,6 +846,14 @@ void do_return(znode *expr CLS_DC)
}
+static void function_add_ref(zend_function *function)
+{
+ if (function->type == ZEND_USER_FUNCTION) {
+ (*((zend_op_array *) function)->refcount)++;
+ }
+}
+
+
ZEND_API void do_bind_function_or_class(zend_op *opline, HashTable *function_table, HashTable *class_table)
{
switch (opline->extended_value) {
@@ -869,6 +877,38 @@ ZEND_API void do_bind_function_or_class(zend_op *opline, HashTable *function_tab
}
}
break;
+ case ZEND_DECLARE_INHERITED_CLASS: {
+ zend_class_entry *ce, *parent_ce;
+ char *class_name, *parent_name;
+ zend_function tmp_zend_function;
+ zval *tmp;
+
+ zend_hash_index_find(class_table, opline->op1.u.constant.value.lval, (void **) &ce);
+ (*ce->refcount)++;
+
+ /* Restore base class / derived class names */
+ parent_name = opline->op2.u.constant.value.str.val;
+ class_name = strchr(opline->op2.u.constant.value.str.val, ':');
+ if (!class_name) {
+ zend_error(E_COMPILE_ERROR, "Invalid runtime class entry");
+ }
+ *class_name++ = 0;
+
+ /* Obtain parent class */
+ if (zend_hash_find(class_table, parent_name, strlen(parent_name)+1, (void **) &parent_ce)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Class %s: Cannot inherit from undefined class %s", class_name, parent_name);
+ }
+
+ /* Perform inheritence */
+ zend_hash_copy(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function));
+ zend_hash_copy(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *));
+
+ /* Register the derived class */
+ if (zend_hash_add(class_table, class_name, strlen(class_name)+1, ce, sizeof(zend_class_entry), NULL)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ }
+ }
+ break;
}
}
@@ -1161,17 +1201,11 @@ void do_default_before_statement(znode *case_list, znode *default_token CLS_DC)
CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
}
-static void function_add_ref(zend_function *function)
-{
- if (function->type == ZEND_USER_FUNCTION) {
- (*((zend_op_array *) function)->refcount)++;
- }
-}
-
void do_begin_class_declaration(znode *class_name, znode *parent_class_name CLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
+ int runtime_inheritence = 0;
if (CG(active_class_entry)) {
zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
@@ -1196,17 +1230,17 @@ void do_begin_class_declaration(znode *class_name, znode *parent_class_name CLS_
zend_str_tolower(parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len);
- if (zend_hash_find(CG(class_table), parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len+1, (void **) &parent_class)==FAILURE) {
- zend_error(E_COMPILE_ERROR, "Undefined parent class '%s'", parent_class_name->u.constant.value.str.val);
- return;
- }
- /* copy functions */
- zend_hash_copy(&CG(class_entry).function_table, &parent_class->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function));
+ if (zend_hash_find(CG(class_table), parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len+1, (void **) &parent_class)==SUCCESS) {
+ /* copy functions */
+ zend_hash_copy(&CG(class_entry).function_table, &parent_class->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function));
- /* copy default properties */
- zend_hash_copy(&CG(class_entry).default_properties, &parent_class->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *));
+ /* copy default properties */
+ zend_hash_copy(&CG(class_entry).default_properties, &parent_class->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *));
- zval_dtor(&parent_class_name->u.constant);
+ zval_dtor(&parent_class_name->u.constant);
+ } else {
+ runtime_inheritence = 1;
+ }
} else {
CG(class_entry).parent = NULL;
}
@@ -1221,10 +1255,26 @@ void do_begin_class_declaration(znode *class_name, znode *parent_class_name CLS_
opline->op1.u.constant.value.lval = zend_hash_next_free_element(CG(class_table));
opline->op2.op_type = IS_CONST;
opline->op2.u.constant.type = IS_STRING;
- opline->op2.u.constant.value.str.val = estrndup(CG(class_entry).name, CG(class_entry).name_length);
- opline->op2.u.constant.value.str.len = CG(class_entry).name_length;
- opline->extended_value = ZEND_DECLARE_CLASS;
-
+ if (runtime_inheritence) {
+ char *full_class_name;
+
+ opline->op2.u.constant.value.str.len = parent_class_name->u.constant.value.str.len+1+CG(class_entry).name_length;
+ full_class_name = opline->op2.u.constant.value.str.val = (char *) emalloc(opline->op2.u.constant.value.str.len+1);
+
+ memcpy(full_class_name, parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len);
+ full_class_name += parent_class_name->u.constant.value.str.len;
+ full_class_name[0] = ':';
+ full_class_name++;
+ memcpy(full_class_name, CG(class_entry).name, CG(class_entry).name_length);
+ full_class_name += CG(class_entry).name_length;
+ full_class_name[0] = 0;
+ opline->extended_value = ZEND_DECLARE_INHERITED_CLASS;
+ } else {
+ opline->op2.u.constant.value.str.val = estrndup(CG(class_entry).name, CG(class_entry).name_length);
+ opline->op2.u.constant.value.str.len = CG(class_entry).name_length;
+ opline->extended_value = ZEND_DECLARE_CLASS;
+ }
+
zend_hash_next_index_insert(CG(class_table), &CG(class_entry), sizeof(zend_class_entry), (void **) &CG(active_class_entry));
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index adc06080fb..bdbaaafc9a 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -531,8 +531,9 @@ int zendlex(znode *zendlval CLS_DC);
#define ZEND_HANDLE_FP 2
#define ZEND_HANDLE_ISTREAM 3
-#define ZEND_DECLARE_CLASS 1
-#define ZEND_DECLARE_FUNCTION 2
+#define ZEND_DECLARE_CLASS 1
+#define ZEND_DECLARE_FUNCTION 2
+#define ZEND_DECLARE_INHERITED_CLASS 3
#define ZEND_FETCH_STANDARD 0
#define ZEND_FETCH_NO_AI_COUNT 1