1.语法分析

unticked_statement:
|    T_ECHO echo_expr_list ';'
;
echo_expr_list:echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }|    expr                    { zend_do_echo(&$1 TSRMLS_CC); }
;
expr:r_variable                    { $$ = $1; }|    expr_without_variable        { $$ = $1; }
;
r_variable:variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
;
variable:base_variable_with_function_calls
;
base_variable_with_function_calls:base_variable                { $$ = $1; }
;
base_variable:reference_variable { $$ = $1; $$.EA = ZEND_PARSED_VARIABLE; }
;
reference_variable:|    compound_variable            { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
;compound_variable:T_VARIABLE            { $$ = $1; }|    '$' '{' expr '}'    { $$ = $3; }
;|    compound_variable            { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
;
compound_variable:T_VARIABLE            { $$ = $1; }

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_OPLINEzval *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+1, 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, 0);
}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) == 0) { /* optimize away empty strings */if (use_copy) {zval_dtor(expr);}return 0;}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=0;    /* 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 0;}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_WIN32fflush(stderr);
#endifreturn str_len;
}

参考:http://wenku.baidu.com/view/b7d2d4335a8102d276a22fb1.html

转载于:https://www.cnblogs.com/taek/p/4118838.html

php-echo原理相关推荐

  1. php上传头像的代码,php头像上传预览实例代码

    说道上传图片,大家并不陌生,不过,在以后开发的项目中,可能并不会让你使用提交刷新页面式的上传图片,比如上传头像,按照常理,肯定是在相册选择照片之后,确认上传,而肯定不会通过form表单,点击submi ...

  2. 转换汇编到shellcode的过程

    汇编代码如下: section .textglobal _start _start:jmp shell here:xor rax,raxpop rdixor rsi,rsixor rdx,rdxadd ...

  3. 第七天 位置参数 变量运算if case || find locate compress

    export name=VALUE 环境变量赋值,声明 export name=VALUE declare -x name=VALUE 变量引用 ${name} $name 花括号保存了变量完整性 查 ...

  4. Windows下解决依赖动态库问题:bat脚本实现自动复制dll文件

    1. 问题 Windows下,exe文件在设计实现时可能依赖某些动态库(*.dll文件),这些在调试台调试或在本机运行因为指定了包含库文件或者指定了环境变量,使得运行时可以找到并调用这些文件.但是环境 ...

  5. php文件上传实验总结,PHP文件上传一些小收获

    又码了一个周末的代码,这次在做一些关于文件上传的东西.(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来. 开始觉得这玩 ...

  6. Qt 联合Visual Studio编译打包发布

    1.qt 查找项目中使用到的qt动态链接库: 步骤如下 ①打开项目使用的windeployqt工具(qt自带的工具): ②进入到文件夹所在目录:使用 cd 命令 ③使用命令:windeployqt N ...

  7. 声学回声消除(Acoustic Echo Cancellation)原理与实现

    Acoustic Echo Cancellation 回声分类 电路回声 声学回声 AEC的基本原理 回声消除常用方法 自适应滤波器的基本原理 回声消除常用算法 LSM算法 LMS算法实现 NLMS算 ...

  8. shell条件检查原理:command echo ‘success‘ || echo ‘error‘

    ls /xx && echo 'success' || echo 'error' 如果第一个是true,则会检查&&符后面的,因为如果第二个是false会影响整体的值; ...

  9. git原理及常见使用方法

    Git 原理入门-来自阮一峰 Git 是最流行的版本管理工具,也是程序员的必备技能之一. 即使天天使用它,很多人也未必了解它的原理.Git 为什么可以管理版本?git add.git commit这些 ...

  10. php 伪静态 page-18.html,PHP 伪静态实现技术原理讲解

    PHP 伪静态实现技术原理讲解 发布于 2015-01-18 23:52:58 | 129 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext Pre ...

最新文章

  1. 迟语寒:组队学习的那些事
  2. 在linux和windows下自动备份数据库
  3. Cannot load onnxruntime.capi. Error: DLL load failed: 找不到指定的模块
  4. Myeclipse的破解步骤
  5. jdk的安装和环境的配置
  6. 第四代计算机软件系统,第四代计算机是什么计算机
  7. java代码走读,WebRTCDemo.apk代码走读(一):初始化
  8. 文献记录(part92)--Graph regularized low-rank representation for submodule clustering
  9. Linux实训vim编辑器的应用,Linux实训例题(vim编辑器)
  10. SpringBoot-(1)-IDEA创建SpringBoot项目并运行访问接口
  11. 在Vmware下linux与ARM开发板的NFS系统搭建【ZT】
  12. 如何获得onblur中的值_使用带有onBlur的输入字段和来自Reactjs JSX中的状态块输入的值?...
  13. mysql+web日志分析工具_用Python+MySQL实现2017年web日志分析报告
  14. 我们真的搞懂这些排序算法了吗?(一)
  15. Flutter跨组件共享状态的利器Provider原理解析
  16. php增加会员功能_在帝国CMS后台增加手动添加会员功能
  17. CTF__(1)web之Cookie
  18. 【HDU6704】K-th occurrence(后缀数组+二分+st+主席树)
  19. 2112731-95-8,N-(Azido-PEG3)-N-Boc-PEG4-acid与炔丙基、BCN或DBCO试剂进行点击化学反应
  20. 图解java虚拟机_分享java虚拟机原理图解

热门文章

  1. 利用JS提交表单的几种方法和验证
  2. gdb调试之堆栈跟踪
  3. 后台开发经典书籍--大话设计模式
  4. CPU 以字节为单位编址,而 C 语言指针以指向的数据类型长度作自增和自减。
  5. 《深入理解计算机系统》读书笔记八:程序结构和执行
  6. 前端一HTML:三: 浏览器页面的本质-html,html语言规则
  7. MongoDB数据节点基础操作
  8. MySQL数据库从windows迁移到linux
  9. SaaS平台只是传统管理软件的试衣间
  10. 什么叫做类数组对象?