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. vue学习:解决Apycharm的 * is only available in ES6(use 'esversion: 6') 问题

    使用pycharm打开main.js,代码前出现黄点,js报错了 把鼠标移至import的波浪线上,出现提示:W119 - ‘import’  is only available in ES6(use ...

  2. 使用UltraEdit 替换解决---文字中含有逗号的文件,如何把逗号自动转换成为:回车换行呢?

    实际工作中有时经常遇到一个问题: 一行文字中含有逗号,如何把逗号自动转换成为:回车换行呢? 普遍存在的问题,用Ultredit中^r^n(回车换行)也可以完成.提供大家参考. 王乐,李宏宇,张志鹏,刘 ...

  3. jump 转换进制+dp

    from Contest1024 - 省选模拟题14 题目大意 MMM站在x=0的地方,她想跳到x=t的地方.MMM每次跳跃可以选择跳到x - k或者x + k的地方,其中k={base^n | ba ...

  4. Windows server 2008 R2 + IIS7.5,ASP网站设置

    Windows server 2008 R2 + IIS7.5,ASP网站设置 1. 让IIS7支持ASP Win2008 IIS7 默认不安装ASP,如果需要ASP 的支持,需要将这个角色服务选上. ...

  5. luogu 1327 数列排序 & 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 J题 循环节

    luogu 1327 数列排序 题意 给定一个数列\(\{an\}\),这个数列满足\(ai≠aj(i≠j)\),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换? ...

  6. WebRTC VoiceEngine综合应用示例(一)——基本结构分析(转)

    把自己这两天学习VoiceEngine的成果分享出来,供大家参考,有什么问题也欢迎大家指出,一起学习一起进步. 本文将对VoiceEngine的基本结构做一个分析,分析的方法是自底向上的:看一个音频编 ...

  7. Linux 虚拟地址与物理地址的映射关系分析【转】

    转自:http://blog.csdn.net/ordeder/article/details/41630945 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...

  8. Perl语言入门--4--列表

    1.列表也是数组的形式:(1,'a',2,3,4) 元素可以是任意类型,变量,表达式 2.空列表:() 单元素列表:(2)  .与值2不同 qw(1 $a str)   #qw是用空格作为分隔符,元素 ...

  9. Linux 之 Samba服务器

    Samba服务器 参考教程:[千峰教育] 一:Samba简介: 360百科: Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成. SMB(Server M ...

  10. HDU 1969 Pie【二分】

    [分析] “虽然不是求什么最大的最小值(或者反过来)什么的……但还是可以用二分的,因为之前就做过一道小数型二分题(下面等会讲) 考虑二分面积,下界L=0,上界R=∑ni=1nπ∗ri2.对于一个中值x ...