]> granicus.if.org Git - php/commitdiff
- Initial support for class constants. There are still a few semantic
authorAndi Gutmans <andi@php.net>
Fri, 30 Nov 2001 16:29:47 +0000 (16:29 +0000)
committerAndi Gutmans <andi@php.net>
Fri, 30 Nov 2001 16:29:47 +0000 (16:29 +0000)
- issues which need to be looked into but basically it seems to work.
- Example:
<?php
class foo
{
const hey = "hello";
}

print foo::hey;
?>

Zend/zend.c
Zend/zend.h
Zend/zend_API.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_language_parser.y
Zend/zend_opcode.c

index 6ca79e954c77d0e38385098acaf9231dbe9fc693..67b269c7cc1b3b05c51052c83dd782a582435efa 100644 (file)
@@ -252,6 +252,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.static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+       zend_hash_init_ex(&zend_standard_class_def.constants, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
        zend_hash_init_ex(&zend_standard_class_def.class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
        zend_hash_init_ex(&zend_standard_class_def.function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0);
        zend_standard_class_def.constructor = NULL;
index 924f5410911627baa293bad43284dce1bb2763a0..d835014ab997b1312a9136dac0b46eed6b0d0979 100644 (file)
@@ -285,6 +285,7 @@ struct _zend_class_entry {
        HashTable default_properties;
        HashTable class_table;
        HashTable static_members;
+       HashTable constants;
        zend_function_entry *builtin_functions;
 
        union _zend_function *constructor;
index 670e2e3c1ff185d4f09c88e3e1c349719688af18..e013d16a57866cca003a6fd1ac5272cffdaec593 100644 (file)
@@ -1217,6 +1217,7 @@ ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_
        class_entry->constants_updated = 0;
        zend_hash_init(&class_entry->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
        zend_hash_init(&class_entry->static_members, 0, NULL, ZVAL_PTR_DTOR, 1);
+       zend_hash_init(&class_entry->constants, 0, NULL, ZVAL_PTR_DTOR, 1);
        zend_hash_init(&class_entry->function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1);
        zend_hash_init(&class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 1);
 
index c1596ac3efe8782fdac2cc747be61c03a2ccee2a..5c6b4a9144a8daf761d7567f1bd18e95f45e5cb7 100644 (file)
@@ -937,6 +937,25 @@ void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_
        *result = opline->result;
 }
 
+
+void do_fetch_class_name(znode *result, znode *class_name_entry, znode *class_name TSRMLS_DC)
+{
+       zend_uint length;
+
+       if (!result) {
+               result = class_name_entry;
+       } else {
+               *result = *class_name_entry;
+       }
+
+       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);
+       memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len+1], class_name->u.constant.value.str.val, class_name->u.constant.value.str.len+1);
+       STR_FREE(class_name->u.constant.value.str.val);
+       result->u.constant.value.str.len = length;
+}
+
 void zend_do_begin_class_member_function_call(znode *class_name, znode *function_name TSRMLS_DC)
 {
        unsigned char *ptr = NULL;
@@ -1265,6 +1284,7 @@ void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
        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, &parent_ce->constants, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
        zend_hash_merge(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function), 0);
        ce->parent = parent_ce;
        if (!ce->handle_property_get)
@@ -1372,6 +1392,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->static_members);
+                                       zend_hash_destroy(&ce->constants);
                                        return FAILURE;
                                }
                                return SUCCESS;
@@ -1704,6 +1725,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.static_members, 10, NULL, ZVAL_PTR_DTOR, 0);
+       zend_hash_init(&new_class_entry.constants, 10, NULL, ZVAL_PTR_DTOR, 0);
 
        new_class_entry.constructor = NULL;
 
@@ -1731,6 +1753,9 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
                        /* copy static members */
                        zend_hash_copy(&new_class_entry.static_members, &parent_class->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
 
+                       /* copy constants */
+                       zend_hash_copy(&new_class_entry.constants, &parent_class->constants, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+
                        new_class_entry.constructor = parent_class->constructor;
 
                        /* copy overloaded handlers */
@@ -1808,10 +1833,16 @@ void zend_do_declare_property(znode *var_name, znode *value, int declaration_typ
                ALLOC_ZVAL(property);
 
                *property = value->u.constant;
-               if (declaration_type == 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);
-               } else {
-                       zend_hash_update(&CG(active_class_entry)->static_members, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
+               switch (declaration_type) {
+                       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;
+                       case T_STATIC:
+                               zend_hash_update(&CG(active_class_entry)->static_members, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
+                               break;
+                       case T_CONST:
+                               zend_hash_update(&CG(active_class_entry)->constants, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
+                               break;
                }
        }
        FREE_PNODE(var_name);
@@ -1892,22 +1923,32 @@ void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_lis
 }
 
 
-void zend_do_fetch_constant(znode *result, znode *constant_name, int mode TSRMLS_DC)
+void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC)
 {
        switch (mode) {
                case ZEND_CT:
-                       *result = *constant_name;
+                       if (constant_container) {
+                               do_fetch_class_name(NULL, constant_container, constant_name TSRMLS_CC);
+                               *result = *constant_container;
+                       } else {
+                               *result = *constant_name;
+                       }
                        result->u.constant.type = IS_CONSTANT;
                        break;
-               case ZEND_RT: {
+               case ZEND_RT:
+                       {
                                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        
                                opline->opcode = ZEND_FETCH_CONSTANT;
                                opline->result.op_type = IS_TMP_VAR;
                                opline->result.u.var = get_temporary_variable(CG(active_op_array));
-                               opline->op1 = *constant_name;
+                               if (constant_container) {
+                                       opline->op1 = *constant_container;
+                               } else {
+                                       SET_UNUSED(opline->op1);
+                               }
+                               opline->op2 = *constant_name;
                                *result = opline->result;
-                               SET_UNUSED(opline->op2);
                        }
                        break;
        }
index 27266f4b7edde9fbeb0e350c161e07d30010cd3e..0c9b439dbac7028eb8dcf219d46296112a64cee0 100644 (file)
@@ -273,6 +273,7 @@ int zend_do_begin_function_call(znode *function_name TSRMLS_DC);
 void zend_do_begin_method_call(znode *object, znode *function_name TSRMLS_DC);
 void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC);
 void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_DC);
+void do_fetch_class_name(znode *result, znode *class_entry, znode *class_name TSRMLS_DC);
 void zend_do_begin_class_member_function_call(znode *class_name, znode *function_name TSRMLS_DC);
 void zend_do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC);
 void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
@@ -316,7 +317,7 @@ void zend_do_pop_object(znode *object TSRMLS_DC);
 void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC);
 void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC);
 
-void zend_do_fetch_constant(znode *result, znode *constant_name, int mode TSRMLS_DC);
+void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC);
 
 void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC);
 
index 77f39bd0aa91342cf291838ef28ae5e26248b3fd..cb6b569fce9032193a1b7a1bc4016d62e5e49fac 100644 (file)
@@ -2043,12 +2043,25 @@ send_by_ref:
                                }
                                NEXT_OPCODE();
                        case ZEND_FETCH_CONSTANT:
-                               if (!zend_get_constant(EX(opline)->op1.u.constant.value.str.val, EX(opline)->op1.u.constant.value.str.len, &EX(Ts)[EX(opline)->result.u.var].tmp_var TSRMLS_CC)) {
-                                       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
-                                                               EX(opline)->op1.u.constant.value.str.val,
-                                                               EX(opline)->op1.u.constant.value.str.val);
-                                       EX(Ts)[EX(opline)->result.u.var].tmp_var = EX(opline)->op1.u.constant;
-                                       zval_copy_ctor(&EX(Ts)[EX(opline)->result.u.var].tmp_var);
+                               if (EX(opline)->op1.op_type == IS_UNUSED) {
+                                       if (!zend_get_constant(EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len, &EX(Ts)[EX(opline)->result.u.var].tmp_var TSRMLS_CC)) {
+                                               zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+                                                                       EX(opline)->op2.u.constant.value.str.val,
+                                                                       EX(opline)->op2.u.constant.value.str.val);
+                                               EX(Ts)[EX(opline)->result.u.var].tmp_var = EX(opline)->op2.u.constant;
+                                               zval_copy_ctor(&EX(Ts)[EX(opline)->result.u.var].tmp_var);
+                                       }
+                               } else {
+                                       zend_class_entry *ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry;
+                                       zval **value;
+
+                                       if (zend_hash_find(&ce->constants, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
+                                               zval_update_constant(value, (void *) 1 TSRMLS_CC);
+                                               EX(Ts)[EX(opline)->result.u.var].tmp_var = **value;
+                                               zval_copy_ctor(&EX(Ts)[EX(opline)->result.u.var].tmp_var);
+                                       } else {
+                                               zend_error(E_ERROR, "Undefined constant. Improve this error message");
+                                       }
                                }
                                NEXT_OPCODE();
                        case ZEND_INIT_ARRAY:
index 5cff595e15aeb899cc76bf57fbd0def28f248018..a6790aa35718dbc0b64cb1d0c4ce8208832d3703 100644 (file)
@@ -289,6 +289,7 @@ ZEND_API int zend_is_true(zval *op)
        return i_zend_is_true(op);
 }
 
+#include "../TSRM/tsrm_strtok_r.h"
 
 ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
 {
@@ -304,19 +305,52 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
 
                refcount = p->refcount;
 
-               if (!zend_get_constant(p->value.str.val, p->value.str.len, &const_value TSRMLS_CC)) {
-                       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
-                                               p->value.str.val,
-                                               p->value.str.val);
-                       p->type = IS_STRING;
-                       if (!inline_change) {
-                               zval_copy_ctor(p);
+               if (strchr(p->value.str.val, ':')) {
+                       char *cur, *temp;
+                       char *last;
+                       zend_class_entry *ce;
+                       zval **value;
+
+                       last = tsrm_strtok_r(p->value.str.val, ":", &temp);
+
+                       if (zend_hash_find(EG(class_table), last, strlen(last)+1, &ce) == FAILURE) {
+                               zend_error(E_ERROR, "Invalid class! Improve this error message");
                        }
-               } else {
+
+                       for(;;) {
+                               cur = tsrm_strtok_r(NULL, ":", &temp);
+                               if (!cur) {
+                                       break;
+                               }
+                               if (zend_hash_find(EG(class_table), last, strlen(last)+1, &ce) == FAILURE) {
+                                       zend_error(E_ERROR, "Invalid class! Improve this error message");
+                               }
+                               last = cur;
+                       }
+                       if (zend_hash_find(&ce->constants, last, strlen(last)+1, (void **) &value) == FAILURE) {
+                               zend_error(E_ERROR, "Invalid class! Improve this error message");
+                       }
+                       const_value = **value;
+                       zval_copy_ctor(&const_value);
                        if (inline_change) {
                                STR_FREE(p->value.str.val);
                        }
                        *p = const_value;
+               } else {
+                       if (!zend_get_constant(p->value.str.val, p->value.str.len, &const_value TSRMLS_CC)) {
+                               zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+                                                       p->value.str.val,
+                                                       p->value.str.val);
+                               p->type = IS_STRING;
+                               if (!inline_change) {
+                                       zval_copy_ctor(p);
+                               }
+                       } else {
+                               if (inline_change) {
+                                       STR_FREE(p->value.str.val);
+                               }
+                               *p = const_value;
+                       }
                }
                INIT_PZVAL(p);
                p->refcount = refcount;
index 31e2b997f6aa75d97bd4c6254419ef9832bdcf25..6740f44111f1df7efde1b212b5da6d33384c947b 100644 (file)
@@ -387,6 +387,7 @@ class_statement_list:
 
 class_statement:
                class_variable_decleration ';'
+       |       class_constant_decleration ';'
        |       T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 1, $3.op_type TSRMLS_CC); } '(' 
                        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, 1, $3.op_type TSRMLS_CC); }
@@ -411,6 +412,11 @@ class_decleration_type:
        |       T_STATIC        { $$.op_type = T_STATIC; }
 ;
 
+class_constant_decleration:
+       |       T_CONST ',' T_STRING '=' static_scalar  { zend_do_declare_property(&$3, &$5, T_CONST TSRMLS_CC); }
+       |       T_CONST T_STRING '=' static_scalar      { zend_do_declare_property(&$2, &$4, T_CONST TSRMLS_CC); }
+;
+
 echo_expr_list:        
        |       echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }
        |       expr                                    { zend_do_echo(&$1 TSRMLS_CC); }
@@ -515,6 +521,11 @@ parse_class_entry:
        |       T_STRING T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
 ;
 
+parse_class_name_entry:
+               parse_class_name_entry T_STRING T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class_name(&$$, &$1, &$2 TSRMLS_CC); }
+       |       T_STRING T_PAAMAYIM_NEKUDOTAYIM { $$ = $1; }
+;
+
 new_class_entry:
                parse_class_entry static_or_variable_string { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); }
        |       static_or_variable_string { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
@@ -550,17 +561,18 @@ common_scalar:
 
 static_scalar: /* compile-time evaluated scalars */
                common_scalar           { $$ = $1; }
-       |       T_STRING                { zend_do_fetch_constant(&$$, &$1, ZEND_CT TSRMLS_CC); }
+       |       T_STRING                { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT TSRMLS_CC); }
        |       '+' static_scalar       { $$ = $1; }
        |       '-' static_scalar       { zval minus_one;  minus_one.type = IS_LONG; minus_one.value.lval = -1;  mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC);  $$ = $2; }
        |       T_ARRAY '(' static_array_pair_list ')' { $$ = $3; $$.u.constant.type = IS_CONSTANT_ARRAY; }
+       |       parse_class_name_entry T_STRING { zend_do_fetch_constant(&$$, &$1, &$2, ZEND_CT TSRMLS_CC); }
 ;
 
 
 scalar:
-               T_STRING                                { zend_do_fetch_constant(&$$, &$1, ZEND_RT TSRMLS_CC); }
+               T_STRING                                { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT TSRMLS_CC); }
        |       T_STRING_VARNAME                { $$ = $1; }
-       |       parse_class_entry T_STRING
+       |       parse_class_entry T_STRING { zend_do_fetch_constant(&$$, &$1, &$2, ZEND_RT TSRMLS_CC); }
        |       common_scalar                   { $$ = $1; }
        |       '"' encaps_list '"'     { $$ = $2; }
        |       '\'' encaps_list '\''   { $$ = $2; }
index 6d16b719b38e2d5ce8bd650b687de57eaafce43f..9d9b924632def73cf0a534ef3b6c38dd7063c987 100644 (file)
@@ -118,6 +118,7 @@ ZEND_API void destroy_zend_class(zend_class_entry *ce)
                        zend_hash_destroy(&ce->function_table);
                        zend_hash_destroy(&ce->default_properties);
                        zend_hash_destroy(&ce->static_members);
+                       zend_hash_destroy(&ce->constants);
                        zend_hash_destroy(&ce->class_table);
                        break;
                case ZEND_INTERNAL_CLASS:
@@ -126,6 +127,7 @@ ZEND_API void destroy_zend_class(zend_class_entry *ce)
                        zend_hash_destroy(&ce->function_table);
                        zend_hash_destroy(&ce->default_properties);
                        zend_hash_destroy(&ce->static_members);
+                       zend_hash_destroy(&ce->constants);
                        zend_hash_destroy(&ce->class_table);
                        break;
        }