zoukankan      html  css  js  c++  java
  • php源码zend_do_begin_namespace函数详解

    version:5.6.21

    file:Zend/zend_compile.c

    line:7055-7152

    void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC) /* {{{ */
    {
        char *lcname;
    
        /* handle mixed syntax declaration or nested namespaces */
        if (!CG(has_bracketed_namespaces)) {
            if (CG(current_namespace)) {
                /* previous namespace declarations were unbracketed */
                if (with_bracket) {
                    zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
                }
            }
        } else {
            /* previous namespace declarations were bracketed */
            if (!with_bracket) {
                zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
            } else if (CG(current_namespace) || CG(in_namespace)) {
                zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
            }
        }
    
        if (((!with_bracket && !CG(current_namespace)) || (with_bracket && !CG(has_bracketed_namespaces))) && CG(active_op_array)->last > 0) {
            /* ignore ZEND_EXT_STMT and ZEND_TICKS */
            int num = CG(active_op_array)->last;
            while (num > 0 &&
                   (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
                    CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
                --num;
            }
            if (num > 0) {
                zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
            }
        }
    
        CG(in_namespace) = 1;
        if (with_bracket) {
            CG(has_bracketed_namespaces) = 1;
        }
    
        if (name) {
            lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
            if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
                  !memcmp(lcname, "self", sizeof("self")-1)) ||
                ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
                  !memcmp(lcname, "parent", sizeof("parent")-1))) {
                zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
            }
            efree(lcname);
    
            if (CG(current_namespace)) {
                zval_dtor(CG(current_namespace));
            } else {
                ALLOC_ZVAL(CG(current_namespace));
            }
            *CG(current_namespace) = name->u.constant;
        } else {
            if (CG(current_namespace)) {
                zval_dtor(CG(current_namespace));
                FREE_ZVAL(CG(current_namespace));
                CG(current_namespace) = NULL;
            }
        }
    
        if (CG(current_import)) {
            zend_hash_destroy(CG(current_import));
            efree(CG(current_import));
            CG(current_import) = NULL;
        }
    
        if (CG(current_import_function)) {
            zend_hash_destroy(CG(current_import_function));
            efree(CG(current_import_function));
            CG(current_import_function) = NULL;
        }
    
        if (CG(current_import_const)) {
            zend_hash_destroy(CG(current_import_const));
            efree(CG(current_import_const));
            CG(current_import_const) = NULL;
        }
    
        if (CG(doc_comment)) {
            efree(CG(doc_comment));
            CG(doc_comment) = NULL;
            CG(doc_comment_len) = 0;
        }
    }

    解析

    该函数是在语法解析的时候,编译器扫描到namespace xxx;namespace xxx{};namespace {};三种形式的时候调用

    zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC)的参数name为znode结构的命名空间名称,with_bracket表示是否为括号型的命名空间(1表示带括号)

    函数刚开始会判断代码中是否同时用了不带括号和带括号的形式,如果是这样的话,会抛出一个编译类型错误:Cannot mix bracketed namespace declarations with unbracketed namespace declaration

    例如

    <?php
    namespace a;
    
    echo "I belong to namespace a";
    
    namespace b {
        echo "I'm from namespace b";
    }

    或者命名空间被嵌套使用的话,会抛出一个编译类型错误:Namespace declarations cannot be nested

    例如

    <?php
    namespace b {
        namespace a{
            echo "I belong to namespace a";
        }
    }

    且命名空间不能为self和parent的任何大小写形式,否则会抛出一个编译类型错误:Cannot use xxx as namespace name

    例如

    <?php
    namespace sElf;
    
    echo "I belong to namespace sElf";

    命名空间的错误检查完了以后,就是下面的工作了

    如果命名空间是有名称值的,将会把名称存入*CG(current_namespace)中

    CG(current_namespace)等价于compile_globals.current_namespace

    其他细节不做讲解,请读者自行查看

  • 相关阅读:
    简单的MsChart使用与遇到的麻烦
    SQLServer中case when 与列拼接
    关于集成单点登录问题
    IIS部署网站后,只有本服务器才能登录
    获取本周的周一日期与本周的周日日期
    34个漂亮的应用程序后台管理系统界面(系列二)
    2011年最佳免费 PSD 用户界面素材揭晓
    编程你使用快捷键了吗?
    汉字转全拼音函数优化方案(SQLServer),值得你看看
    WinForm企业应用框架设计【四】动态创建业务窗体
  • 原文地址:https://www.cnblogs.com/xiaozong/p/6298127.html
Copyright © 2011-2022 走看看