From: Andi Gutmans Date: Sat, 22 Dec 2001 15:31:44 +0000 (+0000) Subject: - Add initial capability of defining nested classes as class foo::bar X-Git-Tag: PRE_ISSET_PATCH~446 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9e7c0d67d002f5be0328d9de575dc0d6e2a1dd78;p=php - Add initial capability of defining nested classes as class foo::bar --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index b74946b96f..81c4e25fd3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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; } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 7141391975..e9719e0287 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 1fd53883b6..d013fe294e 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -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; }