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 > ) {
/* ignore ZEND_EXT_STMT and ZEND_TICKS */
int num = CG(active_op_array)->last;
while (num > &&
(CG(active_op_array)->opcodes[num-].opcode == ZEND_EXT_STMT ||
CG(active_op_array)->opcodes[num-].opcode == ZEND_TICKS)) {
--num;
}
if (num > ) {
zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
}
} CG(in_namespace) = ;
if (with_bracket) {
CG(has_bracketed_namespaces) = ;
} 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")-) &&
!memcmp(lcname, "self", sizeof("self")-)) ||
((Z_STRLEN(name->u.constant) == sizeof("parent")-) &&
!memcmp(lcname, "parent", sizeof("parent")-))) {
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) = ;
}
}

解析

该函数是在语法解析的时候,编译器扫描到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

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

php源码zend_do_begin_namespace函数详解的更多相关文章

  1. React源码 commit阶段详解

    转: React源码 commit阶段详解 点击进入React源码调试仓库. 当render阶段完成后,意味着在内存中构建的workInProgress树所有更新工作已经完成,这包括树中fiber节点 ...

  2. Android源码下载方法详解

    转自:http://www.cnblogs.com/anakin/archive/2011/12/20/2295276.html Android源码下载方法详解 相信很多下载过内核的人都对这个很熟悉 ...

  3. 【Java】HashMap源码分析——常用方法详解

    上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ...

  4. 【转】ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解

    原文地址:http://blog.csdn.net/a396901990/article/details/36475213 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量—— ...

  5. Spring Boot源码中模块详解

    Spring Boot源码中模块详解 一.源码 spring boot2.1版本源码地址:https://github.com/spring-projects/spring-boot/tree/2.1 ...

  6. ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解

    简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3. ...

  7. 【转】ANDROID自定义视图——onLayout源码 流程 思路详解

    转载(http://blog.csdn.net/a396901990) 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量——onMeasure():决定View的大小 2.布局 ...

  8. vue新手入门之使用vue框架搭建用户登录注册案例,手动搭建webpack+Vue项目(附源码,图文详解,亲测有效)

    前言 本篇随笔主要写了手动搭建一个webpack+Vue项目,掌握相关loader的安装与使用,包括css-loader.style-loader.vue-loader.url-loader.sass ...

  9. Android源码目录结构详解(转载)

    转自:http://blog.csdn.net/xiangjai/article/details/9012387 在学习Android的过程中,学习写应用还好,一开始不用管太多代码,直接调用函数就可以 ...

随机推荐

  1. 刷题总结——二逼平衡树(bzoj3224线段树套splay)

    题目: Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在 ...

  2. C# IEnumerable to List 的转换

    一.使用Linq using System.Linq; Example: IEnumerable<, ); List<int> asList = enumerable.ToList( ...

  3. tyvj 2002 扑克牌

    期望DP 本题递推比较麻烦,可以记忆化搜索 注意搜索的边界条件 以及每一次转移 #include <iostream> #include <cstdio> #include & ...

  4. 【BZOJ4472】salesman(树形DP)

    题意: 给定一颗有点权的树,每个树上的节点最多能走到lim[u]次,求一条路径,使路径上的点权和最大,每个节点上的点权如果走了多次只能算一次.还要求方案是否唯一. 思路:每个点只能取lim[u]-1个 ...

  5. 05深入理解C指针之---指针声明和解引

    该系列文章源于<深入理解C指针>的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教. 一.指针声明: 1.声明普通变量:“数据类型 + 空格 +  变量名 + :”实现普通 ...

  6. 44深入理解C指针之---指针安全

    一.指针安全:指针的声明和初始化问题 1.指针不恰当的声明: 1).声明的意思和真是的意图不一致,可以通过格式搞定: 2).使用宏定义时,展开的含义有变,通过格式搞定: 3).使用类型定义,使用更加方 ...

  7. Charger Battery Warning Message 的 改善

    今天與人聊到有關 charger battery safety 的 warning message, 認為說 warning message 真的有起到 保護 user 的作用? 譬如: batter ...

  8. 禁用VMware的vmem文件

    新建一个虚拟机,VMWare会默认为其创建一个虚拟内存文件*.VMEM, 这个文件会影响系统的磁盘性能,所以最好关闭它. 该当是找到*.vmx文件,在文件最后加入一行 mainMem.useNamed ...

  9. Python初见

    参考资料:http://wenku.baidu.com/link?url=_akpT-G5Tvf7ECyszSipOAhHXzjlpYu-RWPcRTYp_tecPOollPGUxXG4MH69MLN ...

  10. Wannafly挑战赛2 C.Butterfly(线段树优化枚举)

    题目链接  C.Butterfly 令$fd[i][j]$为以$s[i][j]$为起点开始往下走最大连续的‘X’个数 令$fl[i][j]$为以$s[i][j]$为起点开始往左下走最大连续的‘X’个数 ...