zoukankan      html  css  js  c++  java
  • php-echo原理

    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_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+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_WIN32
        fflush(stderr);
    #endif
        return str_len;
    }

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

     

     

  • 相关阅读:
    【01】国内外git托管平台(总结by魔芋)
    【01】git下载和安装的完整过程
    分享一些正确的放松方式
    【03】图解原型和原型链by魔芋
    求一个正整数的阶乘
    乘法表
    Web Best Practices
    【03】const
    【02】块级作用域
    【01】let和const命令
  • 原文地址:https://www.cnblogs.com/taek/p/4118838.html
Copyright © 2011-2022 走看看