前言
说到PHP的include/require特性,有很多大神都解释了,include,require,include_once,require_one归根到底是一种方式,只是异常处理不一样而已。
https://www.kancloud.cn/nickbai/php7/363301这里讲的是PHP7下的,和PHP5下唯一不同是没有AST这一层
上图也说明了。
在SKL下的include
其实include语法和PHP实现的流程是一模一样的,没有根本区别。
核心代码
void execute_include_statment(include_statement_t *is, statement_list_t *statement_list) {
char *filename = is->filename;
FILE *input = fopen(filename, FILE_OPT_READ);
if (is_empty(input)) {
error_exception("File:%s can not be read!", filename);
}
global_info.include_mode = 1;
yyrestart(input);
if (yyparse()) {
error_exception("System parse file:%s failed !", filename);
}
global_info.include_mode = 0;
// 脚本hash
if (!find_hash(global_info.script_table, filename, strlen(filename))) {
insert_or_update_hash(global_info.script_table, filename, strlen(filename), filename);
}
merge_execute_statement_list(statement_list);
fclose(input);
}
/**
* 执行语句列表合并
*/
void merge_execute_statement_list(statement_list_t *statement_list) {
if (global_info.include_statement_list->tail) {
global_info.include_statement_list->tail->next = statement_list->top->next;
statement_list->top = global_info.include_statement_list->top;
} else {
statement_list->top = statement_list->top->next;
}
//reset
global_info.include_statement_list->top = global_info.include_statement_list->tail = NULL;
}
主要流程
1.读取文件流
2.设置全局包含模式为1 (解析后的语句列表放在全局包含语句变量)
3.yyrestart(input)重新解析文件流
4.重置全局包含模式为0
5.将文件地址放入hash表
6.合并全局语句列表和包含语句列表
7.关闭文件流
过程不复杂,但是在查看关于yyrestart的api文档费了点劲,还有执行语句的时候。
结束语
不会时,觉着很高深,完全了解后,也不是很难嘛,还是要有一股霸气