文件 php-5.6.26/Zend/zend_language_scanner.c
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) { zend_lex_state original_lex_state; zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); zend_op_array *original_active_op_array = CG(active_op_array); // 保存 op_code 现场(保存现场) zend_op_array *retval=NULL; int compiler_result; zend_bool compilation_successful=0; znode retval_znode; zend_bool original_in_compilation = CG(in_compilation); retval_znode.op_type = IS_CONST; INIT_PZVAL(&retval_znode.u.constant); ZVAL_LONG(&retval_znode.u.constant, 1); zend_save_lexical_state(&original_lex_state TSRMLS_CC); // 保存词法分析器的状态(保存现场) retval = op_array; /* success oriented */ if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) { // 打开文件、设置扫描器的指针 if (type==ZEND_REQUIRE) { zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); zend_bailout(); // !!! require、require_once 会抛出异常 ----------------- } else { zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC); // 没有抛出异常 ----------------- } compilation_successful=0; } else { // 扫描后、初始化 op_array init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); // 1、初始化一些数据、申请空间 2、迭代调用所有zend扩展的op_array_ctor函数 CG(in_compilation) = 1; // 是否处于汇编状态 CG(active_op_array) = op_array; // 操作码数组 zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context))); // 把当前上下文入栈 zend_init_compiler_context(TSRMLS_C); // 初始化编译器上下文 compiler_result = zendparse(TSRMLS_C); // 开始解析 zend_do_return(&retval_znode, 0 TSRMLS_CC); // 返回 CG(in_compilation) = original_in_compilation; // 还原现场 if (compiler_result != 0) { /* parser error */ zend_bailout(); } compilation_successful=1; // 汇编成功 } if (retval) { CG(active_op_array) = original_active_op_array; // 还原原来 op_code 现场(还原现场) if (compilation_successful) { // 汇编成功 pass_two(op_array TSRMLS_CC); // 注入“opcode处理器” zend_release_labels(0 TSRMLS_CC); } else { efree(op_array); retval = NULL; } } zend_restore_lexical_state(&original_lex_state TSRMLS_CC); // 还原原来词法解析器的状态(还原现场) return retval; }