好深的栈,想看下他的源码调用过程,于是打开eclipse,我的eclipse下的是php5.3 ,和5.5代码有点不同,不过没关系
op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
找到定义
Zend/zend_compile.c 35行
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
发现zend_compile_file只是个指针函数的定义,于是全局搜索下,找到了赋值
main/main.c 1823行
int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
{
…
zuf.stream_open_function = php_stream_open_for_zend;
…
}
Zend/zend.c 639行
int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC) /* {{{ */
{
…
zend_compile_file = compile_file;
…
}
Zend/zend_language_scanner.c 354行
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
{
…
if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
…
}
Zend/zend_language_scanner.c 263行
ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
{
…
if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) {
return FAILURE;
}
…
}
Zend/zend_stream.c 187行
ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len TSRMLS_DC) /* {{{ */
{
…
if (zend_stream_open(file_handle->filename, file_handle TSRMLS_CC) == FAILURE) {
return FAILURE;
}
…
}
Zend/zend_stream.c 129行
ZEND_API int zend_stream_open(const char *filename, zend_file_handle *handle TSRMLS_DC)
{
if (zend_stream_open_function) {
return zend_stream_open_function(filename, handle TSRMLS_CC);
}
handle->type = ZEND_HANDLE_FP;
handle->opened_path = NULL;
handle->handle.fp = zend_fopen(filename, &handle->opened_path TSRMLS_CC);
…
}
Zend/zend.c 54行
ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
Zend/zend.c 628行
int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC) /* {{{ */
{
…
zend_stream_open_function = utility_functions->stream_open_function;
…
}
看到了utility_functions 是传参传进来的,那就找下在哪里调用了这个函数
main/main.c 1892行
int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
{
zend_utility_functions zuf;
…
zuf.stream_open_function = php_stream_open_for_zend;
…
zend_startup(&zuf, NULL TSRMLS_CC);
}
可以看到 ,是引用php_stream_open_for_zend,继续找下去
main/main.c 1214行
static int php_stream_open_for_zend(const char *filename, zend_file_handle *handle TSRMLS_DC) /* {{{ */
{
return php_stream_open_for_zend_ex(filename, handle, ENFORCE_SAFE_MODE|USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
}
/* }}} */
PHPAPI int php_stream_open_for_zend_ex(const char *filename, zend_file_handle *handle, int mode TSRMLS_DC) /* {{{ */
{
char *p;
size_t len, mapped_len;
php_stream *stream = php_stream_open_wrapper((char *)filename, “rb”, mode, &handle->opened_path);
…
}
main/php_streams.h 546行
#define php_stream_open_wrapper(path, mode, options, opened) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), NULL STREAMS_CC TSRMLS_CC)
main/streams/streams.c 1987行
本来看到调用栈上有php_plain_files_stream_opener,但我搜索下了下没有这个函数,惊到我了。然后研究发现有的。
PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options,
char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
{
…
stream = wrapper->wops->stream_opener(wrapper,
path_to_open, mode, options ^ REPORT_ERRORS,
opened_path, context STREAMS_REL_CC TSRMLS_CC);
…
}
main/php_streams.h 132行
typedef struct _php_stream_wrapper_ops {
/* open/create a wrapped stream */
php_stream *(*stream_opener)(php_stream_wrapper *wrapper, char *filename, char *mode,
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
…
} php_stream_wrapper_ops;
是个结构体,里面定义了很多函数指针,我操。
main/streams/plain_wrapper.c 1300行
static php_stream_wrapper_ops php_plain_files_wrapper_ops = {
php_plain_files_stream_opener,
…
};
他用 php_stream_wrapper_ops结构体声明了个变量,并给stream_opener赋值为php_plain_files_stream_opener,真TMD的绕。
main/streams/plain_wrapper.c 994行
static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode,
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
{
…
return php_stream_fopen_rel(path, mode, opened_path, options);
}
main/php_streams.h 66行
#define php_stream_fopen_rel(filename, mode, opened, options) _php_stream_fopen((filename), (mode), (opened), (options) STREAMS_REL_CC TSRMLS_CC)
main/streams/plain_wrapper.c 943行
PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path, int options STREAMS_DC TSRMLS_DC)
{
…
ret = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id);
…
}
main/streams/plain_wrapper.c 47行
#define php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id) _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_REL_CC TSRMLS_CC)
main/streams/plain_wrapper.c 160行
static php_stream *_php_stream_fopen_from_fd_int(int fd, const char *mode, const char *persistent_id STREAMS_DC TSRMLS_DC)
{
…
return php_stream_alloc_rel(&php_stream_stdio_ops, self, persistent_id, mode);
…
}
main/php_streams.h 62行
#define php_stream_alloc_rel(ops, thisptr, persistent, mode) _php_stream_alloc((ops), (thisptr), (persistent), (mode) STREAMS_REL_CC TSRMLS_CC)
main/streams/streams.c 324行
PHPAPI php_stream *_php_stream_alloc(php_stream_ops *ops, void *abstract, const char *persistent_id, const char *mode STREAMS_DC TSRMLS_DC) /* {{{ */
{
…
ret->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ret, persistent_id ? le_pstream : le_stream);
…
}
zend/zend_list.h 109行
#define ZEND_REGISTER_RESOURCE(rsrc_result, rsrc_pointer, rsrc_type)
zend_register_resource(rsrc_result, rsrc_pointer, rsrc_type);
zend/zend_list.c 95行
ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type)
{
…
rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type);
…
}
zend/zend_list.c 47行
ZEND_API int zend_list_insert(void *ptr, int type)
{
…
zend_hash_index_update(&EG(regular_list), index, (void *) &le, sizeof(zend_rsrc_list_entry), NULL);
…
}
zend/zend_hash.h 120行
#define zend_hash_index_update(ht, h, pData, nDataSize, pDest)
_zend_hash_index_update_or_next_insert(ht, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
zend/zend_hash.c 350行
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
{
…
}
好了,找完了。