]> granicus.if.org Git - php/commitdiff
Multi-purpose patch:
authorAndrei Zmievski <andrei@php.net>
Mon, 31 Mar 2003 20:42:01 +0000 (20:42 +0000)
committerAndrei Zmievski <andrei@php.net>
Mon, 31 Mar 2003 20:42:01 +0000 (20:42 +0000)
 - The fields of zend_namespace were not completely initialized which
   led to a variety of problems.
 - The occurrence of class/interface/namespace definition is now
   captured.
 - Functions/classes/interfaces/namespaces can be preceded by doc
   comments which are stored for use by extensions.

Zend/zend.h
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_globals.h
Zend/zend_language_parser.y
Zend/zend_language_scanner.l
Zend/zend_opcode.c

index 3cf15371f0ced455bff619e4b1c92493e3c76592..a2212446ff47455cfbf8a483d707ecdf5dc132bb 100644 (file)
@@ -335,6 +335,12 @@ struct _zend_class_entry {
        zend_class_entry **interfaces;
        zend_uint num_interfaces;
 
+       char *filename;
+       zend_uint line_start;
+       zend_uint line_end;
+       char *doc_comment;
+       zend_uint doc_comment_len;
+
        /* old handlers */
 #if 0
        void (*handle_function_call)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
index 8de33ae5a0b75033a37c5c6fc2c28ba47cafa543..38f0ead9bfcd256c2d8283be2d491472894fde1c 100644 (file)
@@ -977,7 +977,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
        op_array.ns = CG(active_namespace);
        op_array.prototype = NULL;
 
-       op_array.line_start = CG(zend_lineno);
+       op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
 
        if (is_method) {
                char *short_class_name = CG(active_class_entry)->name;
@@ -1071,12 +1071,16 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
 }
 
 
-void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
+void zend_do_end_function_declaration(znode *function_token, znode *doc_comment TSRMLS_DC)
 {
        zend_do_extended_info(TSRMLS_C);
        zend_do_return(NULL, 0 TSRMLS_CC);
        pass_two(CG(active_op_array) TSRMLS_CC);
-       CG(active_op_array)->line_end = CG(zend_lineno);
+       CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
+       if (doc_comment && doc_comment->op_type != IS_UNUSED) {
+               CG(active_op_array)->doc_comment = doc_comment->u.constant.value.str.val;
+               CG(active_op_array)->doc_comment_len = doc_comment->u.constant.value.str.len;
+       }
        CG(active_op_array) = function_token->u.op_array;
 
        /* Pop the switch and foreach seperators */
@@ -2202,6 +2206,8 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
        new_class_entry->num_interfaces = 0;
 
        zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
+       new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C);
+       new_class_entry->line_start = zend_get_compiled_lineno(TSRMLS_C);
        new_class_entry->ce_flags |= class_token->u.constant.value.lval;
 
        if (parent_class_name->op_type != IS_UNUSED) {
@@ -2245,10 +2251,17 @@ static void do_verify_abstract_class(TSRMLS_D)
 }
 
 
-void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRMLS_DC)
+void zend_do_end_class_declaration(znode *class_token, znode *parent_token, znode *doc_comment TSRMLS_DC)
 {
        do_inherit_parent_constructor(CG(active_class_entry));
 
+       CG(active_class_entry)->line_end = zend_get_compiled_lineno(TSRMLS_C);
+
+       if (doc_comment && doc_comment->op_type != IS_UNUSED) {
+               CG(active_class_entry)->doc_comment = doc_comment->u.constant.value.str.val;
+               CG(active_class_entry)->doc_comment_len = doc_comment->u.constant.value.str.len;
+       }
+
        if (CG(active_class_entry)->num_interfaces > 0) {
                CG(active_class_entry)->interfaces = (zend_class_entry **) emalloc(sizeof(zend_class_entry *)*CG(active_class_entry)->num_interfaces);
        }
@@ -3279,7 +3292,6 @@ int zendlex(znode *zendlval TSRMLS_DC)
        retval = lex_scan(&zendlval->u.constant TSRMLS_CC);
        switch (retval) {
                case T_COMMENT:
-               case T_DOC_COMMENT:
                case T_OPEN_TAG:
                case T_WHITESPACE:
                        retval = zendlex(zendlval TSRMLS_CC);
@@ -3318,12 +3330,30 @@ void zend_destroy_property_info(zend_property_info *property_info)
 
 void zend_init_namespace(zend_namespace *ns TSRMLS_DC)
 {
+       ns->refcount = 1;
+       ns->constants_updated = 0;
+       ns->ce_flags = 0;
+
+       ns->filename = NULL;
+       ns->doc_comment = NULL;
+       ns->doc_comment_len = 0;
+
        zend_hash_init(&ns->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
        zend_hash_init(&ns->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
        zend_hash_init(&ns->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
        ALLOC_HASHTABLE(ns->static_members);
        zend_hash_init(ns->static_members, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+       ns->parent = NULL;
+       ns->ns = NULL;
        ns->constructor = NULL;
+       ns->destructor = NULL;
+       ns->clone = NULL;
+       ns->__get = NULL;
+       ns->__set = NULL;
+       ns->__call = NULL;
+       ns->create_object = NULL;
+
        ns->type = ZEND_NAMESPACE;
 }
 
@@ -3346,6 +3376,7 @@ void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC)
                ns->name_length = ns_name->u.constant.value.str.len;
                zend_hash_add(&CG(global_namespace).class_table, ns->name, ns->name_length+1, (void **)&ns, sizeof(zend_namespace *), NULL);
                zend_init_namespace(ns TSRMLS_CC);
+               ns->line_start = zend_get_compiled_lineno(TSRMLS_C);
        }
 
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
@@ -3367,11 +3398,34 @@ void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC)
        CG(function_table) = &ns->function_table;
 }
 
-void zend_do_end_namespace(znode *ns_token TSRMLS_DC)
+void zend_do_end_namespace(znode *ns_token, znode *doc_comment TSRMLS_DC)
 {
        zend_namespace *ns = ns_token->u.previously_active_namespace;
        zend_op *opline;
 
+       /*
+        * If the filename field has not been initialized yet, it means that we are
+        * on the first definition of namespace and should capture the definition
+        * information.
+        */
+       if (CG(active_namespace)->filename == NULL) {
+               CG(active_namespace)->filename = zend_get_compiled_filename(TSRMLS_C);
+               CG(active_namespace)->line_end = zend_get_compiled_lineno(TSRMLS_C);
+       }
+
+       if (doc_comment && doc_comment->op_type != IS_UNUSED) {
+               /*
+                * Do not overwrite previously declared doc comment in case the namespace is
+                * split over several parts.
+                */
+               if (CG(active_namespace)->doc_comment == NULL) {
+                       CG(active_namespace)->doc_comment = doc_comment->u.constant.value.str.val;
+                       CG(active_namespace)->doc_comment_len = doc_comment->u.constant.value.str.len;
+               } else {
+                       zval_dtor(&doc_comment->u.constant);
+               }
+       }
+
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
        opline->opcode = ZEND_START_NAMESPACE;
@@ -3436,6 +3490,9 @@ void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers
        ce->constants_updated = 0;
        ce->ce_flags = 0;
 
+       ce->doc_comment = NULL;
+       ce->doc_comment_len = 0;
+
        zend_hash_init_ex(&ce->default_properties, 0, NULL, ZVAL_PTR_DTOR, persistent_hashes, 0);
        zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) zend_destroy_property_info, persistent_hashes, 0);
 
index c522fc01b1d99a0dab83d72f2e4ee7ec8566da90..f2b7b8b27ae750e4b66d0f317c944592a4d346aa 100644 (file)
@@ -148,8 +148,10 @@ struct _zend_op_array {
        zend_bool uses_this;
 
        char *filename;
-       int  line_start;
-       int  line_end;
+       zend_uint line_start;
+       zend_uint line_end;
+       char *doc_comment;
+       zend_uint doc_comment_len;
 
        void *reserved[ZEND_MAX_RESERVED_RESOURCES];
 };
@@ -318,7 +320,7 @@ void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 
 int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier);
 void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC);
-void zend_do_end_function_declaration(znode *function_token TSRMLS_DC);
+void zend_do_end_function_declaration(znode *function_token, znode *doc_comment TSRMLS_DC);
 void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, zend_uchar pass_type TSRMLS_DC);
 int zend_do_begin_function_call(znode *function_name TSRMLS_DC);
 void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
@@ -360,7 +362,7 @@ void zend_do_case_after_statement(znode *result, znode *case_token TSRMLS_DC);
 void zend_do_default_before_statement(znode *case_list, znode *default_token TSRMLS_DC);
 
 void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name TSRMLS_DC);
-void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRMLS_DC);
+void zend_do_end_class_declaration(znode *class_token, znode *parent_token, znode *doc_comment TSRMLS_DC);
 void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC);
 void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC);
 
@@ -449,7 +451,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce);
 void zend_class_add_ref(zend_class_entry **ce);
 
 void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC);
-void zend_do_end_namespace(znode *ns_token TSRMLS_DC);
+void zend_do_end_namespace(znode *ns_token, znode *doc_comment TSRMLS_DC);
 void zend_init_namespace(zend_namespace *ns TSRMLS_DC);
 void zend_do_declare_namespace_var(znode *name, znode *value TSRMLS_DC);
 void zend_do_declare_namespace_constant(znode *name, znode *value TSRMLS_DC);
index 3ac7e6aafffdf7a69f1367ffa6b8ac0104cd1c91..ac335fc47326f87b742fd23c67e224fc58a6e4e3 100644 (file)
@@ -85,8 +85,6 @@ struct _zend_compiler_globals {
        int comment_start_line;
        char *heredoc;
        int heredoc_len;
-       char *doc_comment;
-       int doc_comment_len;
 
        zend_op_array *active_op_array;
 
index b95d3a8c84989498f346b95498fa6b9e1df34a4a..35689198b6eebcd3b4770c5bda19d81f6566113b 100644 (file)
@@ -179,6 +179,7 @@ inner_statement:
 
 statement:
                unticked_statement { zend_do_ticks(TSRMLS_C); }
+    |   doc_comment { zend_do_free(&$1 TSRMLS_CC); } unticked_statement { zend_do_ticks(TSRMLS_C); }
 ;
 
 unticked_statement:
@@ -284,17 +285,27 @@ is_reference:
 
 
 unticked_function_declaration_statement:
-               T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 0, $3.op_type, NULL TSRMLS_CC); }
-                       '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
+               optional_doc_comment T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 0, $4.op_type, NULL TSRMLS_CC); }
+                       '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2, &$1 TSRMLS_CC); }
 ;
 
 unticked_class_declaration_statement:
-               class_entry_type T_STRING extends_from
-                       { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } 
+               optional_doc_comment class_entry_type T_STRING extends_from
+                       { zend_do_begin_class_declaration(&$2, &$3, &$4 TSRMLS_CC); } 
                        implements_list
                        '{'
                                class_statement_list
-                       '}' { zend_do_end_class_declaration(&$1, &$2 TSRMLS_CC); }
+                       '}' { zend_do_end_class_declaration(&$2, &$4, &$1 TSRMLS_CC); }
+;
+
+optional_doc_comment:
+       /* empty */             { $$.op_type = IS_UNUSED; }
+       |       doc_comment             { $$ = $1; }
+;
+
+
+doc_comment:
+               T_DOC_COMMENT { $$ = $1; }
 ;
 
 
@@ -305,7 +316,7 @@ class_entry_type:
 ;
 
 namespace_declaration_statement:
-               T_NAMESPACE namespace_name '{' { zend_do_begin_namespace(&$1, &$2 TSRMLS_CC); } namespace_statement_list '}' { zend_do_end_namespace(&$1 TSRMLS_CC); }
+               optional_doc_comment T_NAMESPACE namespace_name '{' { zend_do_begin_namespace(&$2, &$3 TSRMLS_CC); } namespace_statement_list '}' { zend_do_end_namespace(&$2, &$1 TSRMLS_CC); }
 ;
 
 namespace_statement_list:
@@ -503,7 +514,9 @@ class_statement:
                variable_modifiers { CG(access_type) = $1.u.constant.value.lval; } class_variable_declaration ';'
        |       class_constant_declaration ';'
        |       method_modifiers T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, &$1 TSRMLS_CC); } '(' 
-                       parameter_list ')' method_body { zend_do_abstract_method(&$5, &$1, &$10 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
+                       parameter_list ')' method_body { zend_do_abstract_method(&$5, &$1, &$10 TSRMLS_CC); zend_do_end_function_declaration(&$2, NULL TSRMLS_CC); }
+       |       doc_comment method_modifiers T_FUNCTION { $3.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$3, &$6, 1, $5.op_type, &$2 TSRMLS_CC); } '(' 
+                       parameter_list ')' method_body { zend_do_abstract_method(&$6, &$2, &$11 TSRMLS_CC); zend_do_end_function_declaration(&$3, &$1 TSRMLS_CC); }
 ;
 
 
index 16fd9efa6cb31f946ab1e7b3c42d48b8b275ddfc..800261580fa54d1f0b05109ac6710a10ed227071 100644 (file)
@@ -124,8 +124,6 @@ void startup_scanner(TSRMLS_D)
 {
        CG(heredoc) = NULL;
        CG(heredoc_len)=0;
-       CG(doc_comment) = NULL;
-       CG(doc_comment_len) = 0;
        SCNG(yy_start_stack_ptr) = 0;
        SCNG(yy_start_stack_depth) = 0;
 }
@@ -137,10 +135,6 @@ void shutdown_scanner(TSRMLS_D)
                efree(CG(heredoc));
                CG(heredoc_len)=0;
        }
-       if (CG(doc_comment)) {
-               efree(CG(doc_comment));
-               CG(doc_comment_len) = 0;
-       }
 }
 END_EXTERN_C()
 
@@ -1176,7 +1170,7 @@ NAMESPACE_NAME ({LABEL}":")+{LABEL}
        }
 }
 
-<ST_IN_SCRIPTING>"/** "{NEWLINE} {
+<ST_IN_SCRIPTING>"/**"{NEWLINE} {
        CG(comment_start_line) = CG(zend_lineno);
        BEGIN(ST_DOC_COMMENT);
        yymore();
@@ -1194,11 +1188,9 @@ NAMESPACE_NAME ({LABEL}":")+{LABEL}
 }
 
 <ST_DOC_COMMENT>"*/" {
-       if (CG(doc_comment)) {
-               efree(CG(doc_comment));
-       }
-       CG(doc_comment) = estrndup(yytext, yyleng);
-       CG(doc_comment_len) = yyleng;
+       zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
+       zendlval->value.str.len = yyleng;
+       zendlval->type = IS_STRING;
        HANDLE_NEWLINES(yytext, yyleng);
        BEGIN(ST_IN_SCRIPTING);
        return T_DOC_COMMENT;
index 11e6c9c4b43c6ea8fbfe1ac8af9be0b2d42a80fd..31ddb4557ef6beb61acbfa7af638f6a8d398e980 100644 (file)
@@ -74,6 +74,8 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
 
        op_array->function_name = NULL;
        op_array->filename = zend_get_compiled_filename(TSRMLS_C);
+    op_array->doc_comment = NULL;
+    op_array->doc_comment_len = 0;
 
        op_array->arg_types = NULL;
 
@@ -157,6 +159,9 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                        if (ce->num_interfaces > 0) {
                                efree(ce->interfaces);
                        }
+                       if (ce->doc_comment) {
+                               efree(ce->doc_comment);
+                       }
                        efree(ce);
                        break;
                case ZEND_INTERNAL_CLASS:
@@ -184,6 +189,9 @@ ZEND_API void destroy_zend_namespace(zend_namespace **pns)
        zend_hash_destroy(&ns->constants_table);
        zend_hash_destroy(ns->static_members);
        FREE_HASHTABLE(ns->static_members);
+       if (ns->doc_comment) {
+               efree(ns->doc_comment);
+       }
        efree(ns->name);
        efree(ns);
 }
@@ -229,6 +237,9 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
        if (op_array->function_name) {
                efree(op_array->function_name);
        }
+    if (op_array->doc_comment) {
+        efree(op_array->doc_comment);
+    }
        if (op_array->arg_types) {
                efree(op_array->arg_types);
        }