]> granicus.if.org Git - php/commitdiff
- Add initial capability of defining nested classes as class foo::bar
authorAndi Gutmans <andi@php.net>
Sat, 22 Dec 2001 15:31:44 +0000 (15:31 +0000)
committerAndi Gutmans <andi@php.net>
Sat, 22 Dec 2001 15:31:44 +0000 (15:31 +0000)
Zend/zend_compile.c
Zend/zend_execute_API.c
Zend/zend_language_parser.y

index b74946b96f00e816d2061796c1220282e64d6f5b..81c4e25fd3d97c7ec003b9242afbdf142cc567cf 100644 (file)
@@ -1321,6 +1321,75 @@ void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
        do_inherit_parent_constructor(ce);
 }
 
+static void create_class(HashTable *class_table, char *name, int name_length, zend_class_entry **ce)
+{
+       zend_class_entry new_class_entry;
+
+       new_class_entry.type = ZEND_USER_CLASS;
+       new_class_entry.name = estrndup(name, name_length);
+       new_class_entry.name_length = name_length;
+       new_class_entry.refcount = (int *) emalloc(sizeof(int));
+       *new_class_entry.refcount = 1;
+       new_class_entry.constants_updated = 0;
+
+       zend_str_tolower(new_class_entry.name, new_class_entry.name_length);
+
+       zend_hash_init(&new_class_entry.function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
+       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);
+       new_class_entry.static_members = (HashTable *) emalloc(sizeof(HashTable));
+       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);
+
+       new_class_entry.constructor = NULL;
+
+       new_class_entry.handle_function_call = NULL;
+       new_class_entry.handle_property_set = NULL;
+       new_class_entry.handle_property_get = NULL;
+
+       new_class_entry.parent = NULL;
+
+       if (zend_hash_update(class_table, name, name_length+1, &new_class_entry, sizeof(zend_class_entry), ce) == FAILURE) {
+               zend_error(E_ERROR, "Can't create class. Fatal error, please report!");
+       }
+}
+
+
+#include "../TSRM/tsrm_strtok_r.h"
+
+static int create_nested_class(HashTable *class_table, char *path, zend_class_entry *new_ce)
+{
+       char *cur, *temp;
+       char *last;
+       zend_class_entry *ce;
+
+
+       cur = tsrm_strtok_r(path, ":", &temp);
+
+       if (zend_hash_find(class_table, cur, strlen(cur)+1, &ce) == FAILURE) {
+               create_class(class_table, cur, strlen(cur), &ce);
+       }
+
+       last = tsrm_strtok_r(NULL, ":", &temp);
+
+       for(;;) {
+               cur = tsrm_strtok_r(NULL, ":", &temp);
+               if (!cur) {
+                       break;
+               }
+               if (zend_hash_find(&ce->class_table, last, strlen(last)+1, &ce) == FAILURE) {
+                       create_class(&ce->class_table, last, strlen(last), &ce);
+               }
+               last = cur;
+       }
+       (*new_ce->refcount)++;
+       if (zend_hash_add(&ce->class_table, last, strlen(last)+1, new_ce, sizeof(zend_class_entry), NULL) == FAILURE) {
+               (*new_ce->refcount)--;
+               zend_error(E_ERROR, "Cannot redeclare class %s", last);
+               return FAILURE;
+       }
+       return SUCCESS;
+}
 
 ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time)
 {
@@ -1358,6 +1427,9 @@ ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_tabl
                                        zend_error(E_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
                                        return FAILURE;
                                }
+                               if (strchr(opline->op2.u.constant.value.str.val, ':')) {
+                                       return create_nested_class(class_table, opline->op2.u.constant.value.str.val, ce);
+                               }
                                (*ce->refcount)++;
                                if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, ce, sizeof(zend_class_entry), NULL)==FAILURE) {
                                        (*ce->refcount)--;
@@ -1433,6 +1505,9 @@ void zend_do_early_binding(TSRMLS_D)
        zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
        HashTable *table;
 
+       if (strchr(opline->op2.u.constant.value.str.val, ':')) {
+               return;
+       }
        if (do_bind_function_or_class(opline, CG(function_table), CG(class_table), 1)==FAILURE) {
                return;
        }
index 7141391975dc9bd810a14e5db8d2b515ca4240be..e9719e028799d9a08c75e7e6eb81163ffd4450c9 100644 (file)
@@ -321,13 +321,15 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
                        if (zend_hash_find(EG(class_table), last, strlen(last)+1, &ce) == FAILURE) {
                                zend_error(E_ERROR, "Invalid class! Improve this error message");
                        }
+                       
+                       last = tsrm_strtok_r(NULL, ":", &temp);
 
                        for(;;) {
                                cur = tsrm_strtok_r(NULL, ":", &temp);
                                if (!cur) {
                                        break;
                                }
-                               if (zend_hash_find(EG(class_table), last, strlen(last)+1, &ce) == FAILURE) {
+                               if (zend_hash_find(&ce->class_table, last, strlen(last)+1, &ce) == FAILURE) {
                                        zend_error(E_ERROR, "Invalid class! Improve this error message");
                                }
                                last = cur;
index 1fd53883b6d64b82351e9f4f9aa02e5e292be216..d013fe294e443e78cffd2d6e5a8b68e2b3e8dcb4 100644 (file)
@@ -238,10 +238,14 @@ unticked_declaration_statement:
                        '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
        |       T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING  { zend_do_begin_function_declaration(&$1, &$4, 0, $3.op_type TSRMLS_CC); }
                        parameter_list '(' inner_statement_list ')' ';' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
-       |       T_CLASS T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
+       |       T_CLASS decleration_class_name { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
        |       T_CLASS T_STRING T_EXTENDS T_STRING { zend_do_begin_class_declaration(&$1, &$2, &$4 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
 ;
 
+decleration_class_name:
+       |       parse_class_name_entry T_STRING { do_fetch_class_name(&$$, &$1, &$2 TSRMLS_CC); }
+       |       T_STRING { $$ = $1; }
+;
 
 foreach_optional_arg:
                /* empty */                             { $$.op_type = IS_UNUSED; }