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的过程中,学习写应用还好,一开始不用管太多代码,直接调用函数就可以 ...
随机推荐
- [USACO Section 4.4]追查坏牛奶Pollutant Control (最小割)
题目链接 Solution 一眼看过去就是最小割,但是要求割边最少的最小的割. 所以要用骚操作... 建边的时候每条边权 \(w = w * (E+1) + 1;\) 那么这样建图跑出来的 \(max ...
- [NOIP2017] 时间复杂度 (模拟,栈)
题目链接 Solution 用栈进行模拟. 记录一个 \(map\) 来看循环变量有没有用过. 对于每一次入栈都加信息. 出栈直接将 \(top\) 减一下. 反正一堆乱七八糟的东西瞎搞... 注意条 ...
- 【基础操作】2-sat
$2-sat$ 是一个很不怎么考的内容($NOI2017$ 除外) 例题
- 答题小程序开发之socket编程 微信小程序答题 直播答题开发 直播弹幕使用web socket编程
最近有一个项目很火,那就是直播答题的,接到公司的这个任务,开发直播答题的聊天室功能.在线的人相互聊天.之前做过类似的,当时都是使用的ajax轮询的,这种非常的耗费服务器.所以这次就开始使用socket ...
- python 粘包问题及解决方法
一粘包 TCP协议是面向对象的,面向流的,提高可靠性服务.使用了优化算法,Nagle算法.将多次间隔较少且数据量小的数据,合并成一个大的数据块,然后进行封包.这样接收端就很难分辨出来.TCP协议数据是 ...
- 【CF1028B】Unnatural Conditions(构造)
题意:给定n与m,要求构造两个长度不超过2230的数字x,y使得x,y各自的数位和>=n,x+y的数位和<=n 思路: #include<cstdio> #include< ...
- IOS-<input>表单元素只能读,设置readonly时光标仍然可见的解决办
在HTML中,如果把一个<input>的readonly属性设置为"readonly",表示这个表单元素不能编辑. 但是,鼠标点击之后,这个表单元素还是有光标存在的. ...
- JS快速上手-基础Javascript
1.1背景 1.1.1 ECMAScript与javascript ECMAScript是javascript的官方命名.因为java已经是一个商标.如今,一些早前收到过授权的公司,如Moailla, ...
- 用线段树写Dijkstar
如题 noip前就想用线段树优化Dijkstar 写那啥,感觉挺好玩的 写了个线段树优化的Dijkstar #include<cstdio> #include<cstring> ...
- 电影TS/TC/SCR/R5/BD/HD/HC版本意思收集(转)
一.版本说明: 1.CAM(枪版) CAM通常是用数码摄像机从电影院盗录.有时会使用小三角架,但大多数时候不可能使用,所以摄像机会抖动.因此我们看到画面通常偏暗人物常常会失真,下方的 字幕时常会出现倾 ...