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的过程中,学习写应用还好,一开始不用管太多代码,直接调用函数就可以 ...
随机推荐
- 表单编码 appliation/x-www-form-urlencoded 与 multipart/form-data 的区别
当表单使用POST方法时,表单数据提交到服务器端之前有两种编码类型可供选择.默认编码类型为 application/x-www-form-urlencoded,此时所有非字母数字类型的字符都需要转换为 ...
- bzoj 1857 三分套三分
题目大意 在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段.两条传送带分别为线段AB和线段CD.lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R.现在lxh ...
- foj 2144 三位几何+区间覆盖
题目大意:一个人站在三维坐标系下的原点处用炮打蚊子,给出n个蚊子的起始坐标跟单位时间匀速移动的方向向量,距离他R以内的蚊子都可以打到,不过他也需要休息,没蚊子的时候也可以休息下.求他要起来多少次打蚊子 ...
- foj Problem 2283 Tic-Tac-Toe
Prob ...
- POJ 2893 M × N Puzzle
逆序对 n 数码问题的扩展 对于一个n * m 的问题来说,结论和 列数 m 奇偶有关 对于 m 是奇数来说 , 两个局面互相可达,当且仅当这两个局面按顺序写成一个数列,这个数列的逆序对数的奇偶性相同 ...
- 百万级日活 App 的屏幕录制功能是如何实现的
Android 从 4.0 开始就提供了手机录屏方法,但是需要 root 权限,比较麻烦不容易实现.但是从 5.0 开始,系统提供给了 App 录制屏幕的一系列方法,不需要 root 权限,只需要用户 ...
- w3school JavaScript 简介
JavaScript 简介 转自: http://www.w3school.com.cn/js/js_intro.asp JavaScript 是脚本语言 JavaScript 是一种轻量级的编程语言 ...
- 本地安装Sass,Compass
使用本地的gem文件来安装Sass和Compass. 1.安装Ruby http://rubyinstaller.org/downloads/ 下载之后双击安装即可,在安装过程中可以选择“Add Ru ...
- 微信小程序之微信支付C#后台(统一下单)
一.微信小程序支付 1.微信小程序端请求支付接口 商户在小程序中先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易后调起支付.具体可以查看接口示例. 接口传入参数示例: <xm ...
- Swoole RPC 的实现
目录 概述 实现效果 代码 小结 概述 这是关于 Swoole 学习的第七篇文章:Swoole RPC 的实现. 第六篇:Swoole 整合成一个小框架 第五篇:Swoole 多协议 多端口 的应用 ...