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 > ) {
/* 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函数详解的更多相关文章
- React源码 commit阶段详解
转: React源码 commit阶段详解 点击进入React源码调试仓库. 当render阶段完成后,意味着在内存中构建的workInProgress树所有更新工作已经完成,这包括树中fiber节点 ...
- Android源码下载方法详解
转自:http://www.cnblogs.com/anakin/archive/2011/12/20/2295276.html Android源码下载方法详解 相信很多下载过内核的人都对这个很熟悉 ...
- 【Java】HashMap源码分析——常用方法详解
上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ...
- 【转】ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解
原文地址:http://blog.csdn.net/a396901990/article/details/36475213 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量—— ...
- Spring Boot源码中模块详解
Spring Boot源码中模块详解 一.源码 spring boot2.1版本源码地址:https://github.com/spring-projects/spring-boot/tree/2.1 ...
- ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解
简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3. ...
- 【转】ANDROID自定义视图——onLayout源码 流程 思路详解
转载(http://blog.csdn.net/a396901990) 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量——onMeasure():决定View的大小 2.布局 ...
- vue新手入门之使用vue框架搭建用户登录注册案例,手动搭建webpack+Vue项目(附源码,图文详解,亲测有效)
前言 本篇随笔主要写了手动搭建一个webpack+Vue项目,掌握相关loader的安装与使用,包括css-loader.style-loader.vue-loader.url-loader.sass ...
- Android源码目录结构详解(转载)
转自:http://blog.csdn.net/xiangjai/article/details/9012387 在学习Android的过程中,学习写应用还好,一开始不用管太多代码,直接调用函数就可以 ...
随机推荐
- android 脱壳 之 dvmDexFileOpenPartial断点脱壳原理分析
android 脱壳 之 dvmDexFileOpenPartial断点脱壳原理分析 导语: 笔者主要研究方向是网络通信协议的加密解密, 对应用程序加固脱壳技术很少研究, 脱壳壳经历更是经历少之甚少. ...
- c#.NET的事件与委托例子
原文发布时间为:2008-07-25 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...
- 学习javascript设计模式之发布-订阅(观察者)模式
1.发布-订阅模式又叫观察者模式,它定义对象之间一种一对多的依赖关系. 2.如何实现发布-订阅模式 2-1.首先指定好发布者 2-2.给发布者添加一个缓冲列表,用户存放回调函数以便通知订阅者 2-3. ...
- vue.js源码学习分享(四)
/** * Generate a static keys string from compiler modules.//从编译器生成一个静态键字符串模块. */ function genStaticK ...
- unix网络编程第一章demo
之前一直以为time_wait状态就是主动关闭的那一方产生.然后这个端口一直不可以用.实际我发现服务端监听一个端口.客户端发来连接后.传输数据后.服务端关闭客户端套接字后.用netstat -nat ...
- 【面试】最容易被问到的N种排序算法!
面试官:小明,是吧?你都知道哪些排序算法,哪几种是稳定排序? 小明:这个我有总结! 关于排序稳定性的定义 通俗地讲就是能保证排序前两个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同. ...
- CUDA 实现JPEG图像解码为RGB数据
了解JPEG数据格式的人应该easy想到.其对图像以8*8像素块大小进行切割压缩的方法非常好用并行处理的思想来实现.而其实英伟达的CUDA自v5.5開始也提供了JPEG编解码的演示样例.该演示样例存储 ...
- selector在手机上或浏览器显示各种姿势(虚拟下拉菜单)
测试机型:小米.华为.苹果 测试浏览器:Chrome.Safari.Firefox 最后的结果就是你搞你的,我搞我的! 我认为这样漂亮,你认为那样漂亮(我认为你们都统一!) 因为项目时间紧,所以直接用 ...
- hdu5373
题先附上:水题,可是思路不正确,特easy超时(TLE) The shortest problem Time Limit: 3000/1500 MS (Java/Others) Memory L ...
- Hadoop 源码阅读技巧
http://www.cnblogs.com/xuxm2007/category/388607.html 个人谈谈阅读hadoop源代码的经验.首先,不得不说,hadoop发展到现在这个阶段, ...