php-echo原理
1.语法分析
unticked_statement:
| T_ECHO echo_expr_list ';'
;
echo_expr_list:
echo_expr_list ',' expr { zend_do_echo(&$ TSRMLS_CC); }
| expr { zend_do_echo(&$ TSRMLS_CC); }
;
expr:
r_variable { $$ = $; }
| expr_without_variable { $$ = $; }
;
r_variable:
variable { zend_do_end_variable_parse(&$, BP_VAR_R, TSRMLS_CC); $$ = $; }
;
variable:
base_variable_with_function_calls
;
base_variable_with_function_calls:
base_variable { $$ = $; }
;
base_variable:
reference_variable { $$ = $; $$.EA = ZEND_PARSED_VARIABLE; }
;
reference_variable:
| compound_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$, TSRMLS_CC); }
; compound_variable:
T_VARIABLE { $$ = $; }
| '$' '{' expr '}' { $$ = $; }
;
| compound_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$, TSRMLS_CC); }
;
compound_variable:
T_VARIABLE { $$ = $; }
2.编译生成opcode
void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ECHO;
SET_NODE(opline->op1, arg);
SET_UNUSED(opline->op2);
}
3.执行已经生成的opcode
static int ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE zval *z; SAVE_OPLINE();
z = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); //这个z已经是值了 if (IS_CV == IS_TMP_VAR && Z_TYPE_P(z) == IS_OBJECT) {
INIT_PZVAL(z);
}
zend_print_variable(z); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(zval ***CVs, zend_uint var TSRMLS_DC)
{
zval ***ptr = &CV(var); //EG(active_op_array).vars[key]该结果是个zend_compile_variable ,其中key为znod_op的变量var,是个数字,可理解为第几个变量,最终在EG(active_sysbole_table)中取出数据,放到EX(CVs)[key]中 if (UNEXPECTED(*ptr == NULL)) {
return *_get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC);
}
return **ptr;
} static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_R(zval ***ptr, zend_uint var TSRMLS_DC)
{
zend_compiled_variable *cv = &CV_DEF_OF(var); if (!EG(active_symbol_table) ||
zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+, cv->hash_value, (void **)ptr)==FAILURE) {
zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
return &EG(uninitialized_zval_ptr);
}
return *ptr;
}
ZEND_API int zend_print_variable(zval *var)
{
return zend_print_zval(var, );
} ZEND_API int zend_print_zval(zval *expr, int indent) /* {{{ */
{
return zend_print_zval_ex(zend_write, expr, indent);
} ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent) /* {{{ */
{
zval expr_copy;
int use_copy; zend_make_printable_zval(expr, &expr_copy, &use_copy);
if (use_copy) {
expr = &expr_copy;
}
if (Z_STRLEN_P(expr) == ) { /* optimize away empty strings */
if (use_copy) {
zval_dtor(expr);
}
return ;
}
write_func(Z_STRVAL_P(expr), Z_STRLEN_P(expr));
if (use_copy) {
zval_dtor(expr);
}
return Z_STRLEN_P(expr);
} int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
{
zend_utility_functions zuf;
zend_utility_values zuv;
int retval = SUCCESS, module_number=; /* for REGISTER_INI_ENTRIES() */
。。。。。。。。。。。。。。 sapi_module = *sf; php_output_startup(); zuf.error_function = php_error_cb;
zuf.printf_function = php_printf;
zuf.write_function = php_output_wrapper;
zuf.fopen_function = php_fopen_wrapper_for_zend;
zuf.message_handler = php_message_handler_for_zend;
zuf.block_interruptions = sapi_module.block_interruptions;
zuf.unblock_interruptions = sapi_module.unblock_interruptions;
zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
zuf.ticks_function = php_run_ticks;
zuf.on_timeout = php_on_timeout;
zuf.stream_open_function = php_stream_open_for_zend;
zuf.vspprintf_function = vspprintf;
zuf.getenv_function = sapi_getenv;
zuf.resolve_path_function = php_resolve_path_for_zend;
zend_startup(&zuf, NULL TSRMLS_CC);
static int php_output_wrapper(const char *str, uint str_length)
{
TSRMLS_FETCH();
return php_output_write(str, str_length TSRMLS_CC);
}
PHPAPI int php_output_write(const char *str, size_t len TSRMLS_DC)
{
if (OG(flags) & PHP_OUTPUT_DISABLED) {
return ;
}
if (OG(flags) & PHP_OUTPUT_ACTIVATED) {
php_output_op(PHP_OUTPUT_HANDLER_WRITE, str, len TSRMLS_CC);
return (int) len;
}
return php_output_direct(str, len);
}
static int (*php_output_direct)(const char *str, size_t str_len) = php_output_stderr; static int php_output_stderr(const char *str, size_t str_len)
{
fwrite(str, 1, str_len, stderr); //可知道echo 是用fwrite输出的
/* See http://support.microsoft.com/kb/190351 */
#ifdef PHP_WIN32
fflush(stderr);
#endif
return str_len;
}
参考:http://wenku.baidu.com/view/b7d2d4335a8102d276a22fb1.html
php-echo原理的更多相关文章
- 用 程序 解决 windows防火墙 的 弹窗 问题
今天用户反馈了一个问题,运行程序弹了个框 这个只有程序第一次运行会出来,之后就不会了. 当然改个程序名字,又会弹出来. 强烈怀疑是写到了注册表,果然被我找到了. “HKEY_LOCAL_MACHINE ...
- 让bat文件自动以管理员身份运行
· 让bat文件自动以管理员身份运行 如何让bat文件自动以管理员身份运行,将这段写在bat文件的前头即可 : %1 mshta vbscript:CreateObject("Shell.A ...
- TOP100summit 2017:亚马逊Echo音箱能够语音识人,华人工程师揭秘设计原理
本文编辑:Cynthia 2017年,人工智能的消费产品落地聚焦在了智能音箱上,谷歌.亚马逊纷纷推出智能音箱产品,国内的阿里巴巴推出天猫精灵,小米推出小米AI音箱.智能音箱通过语音可以发出指令,未 ...
- 使用echo $? 查看命令成功执行的原理
转载于:http://blog.csdn.net/cmzsteven/article/details/49049387 在进行源代码编译,或者执行命令无法确认所执行的命令是否成功执行的情况下,我们都会 ...
- 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现
本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...
- 【夯实Nginx基础】Nginx工作原理和优化、漏洞
本文地址 原文地址 本文提纲: 1. Nginx的模块与工作原理 2. Nginx的进程模型 3 . NginxFastCGI运行原理 3.1 什么是 FastCGI ...
- JSONP的诞生、原理及应用实例
问题: 页面中有一个按钮,点击之后会更新网页中的一个盒子的内容. Ajax可以很容易的满足这种无须刷新整个页面就可以实现数据变换的需求. 但是,Ajax有一个缺点,就是他不允许跨域请求资源. 如果我的 ...
- When I see you again(加密原理介绍,代码实现DES、AES、RSA、Base64、MD5)
关于网络安全的数据加密部分,本来打算总结一篇博客搞定,没想到东西太多,这已是第三篇了,而且这篇写了多次,熬了多次夜,真是again and again.起个名字:数据加密三部曲,前两部链接如下: 整体 ...
- 12月13日上午Smarty模版原理
模板主要是用来让前端和后端分离的,前台页面只是一个前台页面,后台页面用php代码写逻辑,写完逻辑拿到前台显示. 一.写法 一般需要以下:写3个页面: 1.显示页面aa.html <!DOCTYP ...
- PHP框架模板原理
PHP框架现在是一种很流行的东西了,很多朋友开发应用与网站都会选择一个PHP框架或模板了,下面我们来看看PHP框架是如何实现的吧. 本文主要来聊聊框架理论,但不针对任何一款框架,不过任何 ...
随机推荐
- 2018.07.20 bzoj3211: 花神游历各国(线段树)
传送门 维护区间开方,区间求和.这个是线段树常规操作. 显然一个数被开方若干次之后要么是1,要么是0,所以用线段树维护区间最大和区间和,如果区间最大不超过1就剪枝剪掉,不然就继续递归直到叶节点时停下进 ...
- Django入门指南-第7章:模板引擎设置(完结)
http://127.0.0.1:8000/ <!--templates/home.html--> <!DOCTYPE html> <html> <head& ...
- JPA数据懒加载LAZY和实时加载EAGER(转)
原文:https://www.cnblogs.com/MrSi/p/8081811.html 懒加载LAZY和实时加载EAGER的概念,在各种开发语言中都有广泛应用.其目的是实现关联数据的选择性加载, ...
- Linux 修改 IP地址 和 网关
修改IP地址和网关是很常见的操作,在做相关实验的时候,如果没有设置好,会带来很多不必要的麻烦.. 1. 修改IP地址vi /etc/sysconfig/network-scripts/ifcfg-et ...
- AE IRasterCursor 获取栅格图层像素值
在编写使用栅格图层的代码时,常常要获取栅格图层的像素值(PixelValue).如果想获取某一点的像素值,可以使用IRaster2中的getPixelValue方法.但如果想要获得的是图层中的某一块甚 ...
- DEVEXPRESS 破解方法
Devexpress 是.net的一个非常好用的插件.能够轻松的帮你实现一个非常炫的UI,无论是C#的Winform还是ASP.NET的网站. 鄙人这两天在用DEVEXPRESS的过程中发现在网上并未 ...
- wordpaster更新说明
官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/wordpaster/index.aspx 在线演示:FCKEditor2x示例 ...
- 浅谈webuploader上传文件
官网:http://c7.gg/fw4sn 案例: 文件上传进度 // 文件上传过程中创建进度条实时显示. uploader.on( 'uploadProgress', function( file, ...
- 一种基于Redis的10行代码实现IP频率控制方法
优点:可支持海量访问的频率控制,只需要增加Redis机器,单个Redis节点(只占用一个cpu core)即可支持10万/s以上的处理. 基于IP频率限制是种常见需求,基于Redis可以十分简单实现对 ...
- systemtap安装
一.systemtap介绍 SystemTap是一个强大的调试工具,是监控和跟踪运行中的Linux 内核的操作的动态方法,确切的说应该是一门调试语言,因为它有自己的语法,也有解析.编译.运行等过程(准 ...