mirror of
https://github.com/php/php-src.git
synced 2025-01-19 02:03:47 +08:00
- Add use support (behaves like require, but will not use the same file twice)
- Add import support (behaves like include, but requires parentheses; will not use the same file twice; Currently, it is not yet properly implemented, and only behaves like include)
This commit is contained in:
parent
08304a3c93
commit
5463dd5b38
@ -43,7 +43,7 @@
|
||||
%pure_parser
|
||||
%expect 4
|
||||
|
||||
%left T_INCLUDE T_EVAL
|
||||
%left T_INCLUDE T_EVAL T_IMPORT
|
||||
%left ','
|
||||
%left T_LOGICAL_OR
|
||||
%left T_LOGICAL_XOR
|
||||
@ -100,6 +100,7 @@
|
||||
%token T_CONST
|
||||
%token T_RETURN
|
||||
%token T_REQUIRE
|
||||
%token T_USE
|
||||
%token T_GLOBAL
|
||||
%token T_STATIC
|
||||
%token T_VAR
|
||||
@ -179,13 +180,20 @@ statement:
|
||||
| T_ECHO echo_expr_list ';'
|
||||
| T_INLINE_HTML { do_echo(&$1 CLS_CC); }
|
||||
| expr ';' { do_free(&$1 CLS_CC); }
|
||||
| T_REQUIRE expr ';' { if ($2.op_type==IS_CONST && $2.u.constant.type==IS_STRING) { require_filename($2.u.constant.value.str.val CLS_CC); zval_dtor(&$2.u.constant); } else { do_include_or_eval(ZEND_INCLUDE, &$$, &$2 CLS_CC); } }
|
||||
| T_REQUIRE expr ';' { if ($2.op_type==IS_CONST && $2.u.constant.type==IS_STRING) { require_filename($2.u.constant.value.str.val, 0 CLS_CC); zval_dtor(&$2.u.constant); } else { do_include_or_eval(ZEND_INCLUDE, &$$, &$2 CLS_CC); } }
|
||||
| T_USE use_filename ';' { require_filename($2.u.constant.value.str.val, 1 CLS_CC); zval_dtor(&$2.u.constant); }
|
||||
| T_UNSET '(' r_cvar ')' ';' { do_unset(&$3 CLS_CC); }
|
||||
| T_FOREACH '(' expr T_AS { do_foreach_begin(&$1, &$3, &$2, &$4 CLS_CC); } w_cvar foreach_optional_arg ')' { do_foreach_cont(&$6, &$7, &$4 CLS_CC); } foreach_statement { do_foreach_end(&$1, &$2 CLS_CC); }
|
||||
| ';' /* empty statement */
|
||||
;
|
||||
|
||||
|
||||
use_filename:
|
||||
T_CONSTANT_ENCAPSED_STRING { $$ = $1; }
|
||||
| '(' T_CONSTANT_ENCAPSED_STRING ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
|
||||
declaration_statement:
|
||||
T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); }
|
||||
'(' parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); }
|
||||
@ -656,8 +664,9 @@ encaps_var_offset:
|
||||
internal_functions_in_yacc:
|
||||
T_ISSET '(' cvar ')' { do_isset_or_isempty(ZEND_ISSET, &$$, &$3 CLS_CC); }
|
||||
| T_EMPTY '(' cvar ')' { do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 CLS_CC); }
|
||||
| T_INCLUDE expr { do_include_or_eval(ZEND_INCLUDE, &$$, &$2 CLS_CC); }
|
||||
| T_INCLUDE expr { do_include_or_eval(ZEND_INCLUDE, &$$, &$2 CLS_CC); }
|
||||
| T_EVAL '(' expr ')' { do_include_or_eval(ZEND_EVAL, &$$, &$3 CLS_CC); }
|
||||
| T_IMPORT '(' expr ')' { do_include_or_eval(ZEND_IMPORT, &$$, &$3 CLS_CC); }
|
||||
;
|
||||
|
||||
|
||||
|
@ -235,12 +235,14 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle CLS_DC)
|
||||
#ifndef ZTS
|
||||
switch (file_handle->type) {
|
||||
case ZEND_HANDLE_FILENAME:
|
||||
file_handle->handle.fp = zend_fopen(file_handle->filename);
|
||||
file_handle->handle.fp = zend_fopen(file_handle->filename, &file_handle->opened_path);
|
||||
break;
|
||||
case ZEND_HANDLE_FD:
|
||||
file_handle->opened_path = NULL;
|
||||
file_handle->handle.fp = fdopen(file_handle->handle.fd, "r");
|
||||
break;
|
||||
case ZEND_HANDLE_FP:
|
||||
file_handle->opened_path = NULL;
|
||||
file_handle->handle.fp = file_handle->handle.fp;
|
||||
break;
|
||||
}
|
||||
@ -258,12 +260,13 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle CLS_DC)
|
||||
#else
|
||||
switch (file_handle->type) {
|
||||
case ZEND_HANDLE_FD:
|
||||
file_handle->opened_path = NULL;
|
||||
file_handle->handle.is = new ifstream(file_handle->handle.fd);
|
||||
file_handle->type = ZEND_HANDLE_FSTREAM;
|
||||
break;
|
||||
case ZEND_HANDLE_FILENAME:
|
||||
{
|
||||
file_handle->handle.fp = zend_fopen(file_handle->filename);
|
||||
file_handle->handle.fp = zend_fopen(file_handle->filename, &file_handle->opened_path);
|
||||
if (!file_handle->handle.fp) {
|
||||
return FAILURE;
|
||||
}
|
||||
@ -272,6 +275,7 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle CLS_DC)
|
||||
break;
|
||||
}
|
||||
case ZEND_HANDLE_FP:
|
||||
file_handle->opened_path = NULL;
|
||||
if (file_handle->handle.fp==stdin) {
|
||||
file_handle->handle.is = (ifstream *) &cin;
|
||||
} else {
|
||||
@ -366,7 +370,7 @@ ZEND_API zend_op_array *v_compile_files(int mark_as_ref CLS_DC, int file_count,
|
||||
}
|
||||
|
||||
|
||||
zend_op_array *compile_filename(zval *filename CLS_DC)
|
||||
zend_op_array *compile_filename(zval *filename, zend_bool unique CLS_DC)
|
||||
{
|
||||
zend_file_handle file_handle;
|
||||
zval tmp;
|
||||
@ -381,6 +385,9 @@ zend_op_array *compile_filename(zval *filename CLS_DC)
|
||||
file_handle.filename = filename->value.str.val;
|
||||
file_handle.type = ZEND_HANDLE_FILENAME;
|
||||
retval = zend_compile_files(1 CLS_CC, 1, &file_handle);
|
||||
if (file_handle.opened_path) {
|
||||
free(file_handle.opened_path);
|
||||
}
|
||||
if (filename==&tmp) {
|
||||
zval_dtor(&tmp);
|
||||
}
|
||||
@ -459,13 +466,13 @@ zend_op_array *compile_string(zval *source_string CLS_DC)
|
||||
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
int require_filename(char *filename CLS_DC)
|
||||
int require_filename(char *filename, zend_bool unique CLS_DC)
|
||||
{
|
||||
zend_file_handle file_handle;
|
||||
|
||||
file_handle.type = ZEND_HANDLE_FILENAME;
|
||||
file_handle.filename = filename;
|
||||
if (require_file(&file_handle CLS_CC)==FAILURE) {
|
||||
if (require_file(&file_handle, unique CLS_CC)==FAILURE) {
|
||||
zend_bailout();
|
||||
return FAILURE; /* will never get here */
|
||||
}
|
||||
@ -473,7 +480,7 @@ int require_filename(char *filename CLS_DC)
|
||||
}
|
||||
|
||||
|
||||
int require_file(zend_file_handle *file_handle CLS_DC)
|
||||
int require_file(zend_file_handle *file_handle, zend_bool unique CLS_DC)
|
||||
{
|
||||
zend_lex_state original_lex_state;
|
||||
int compiler_result;
|
||||
@ -483,6 +490,18 @@ int require_file(zend_file_handle *file_handle CLS_DC)
|
||||
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
|
||||
return FAILURE;
|
||||
}
|
||||
if (file_handle->opened_path) {
|
||||
if (unique) {
|
||||
zend_bool exists=1;
|
||||
|
||||
if (zend_hash_add(&CG(used_files), file_handle->opened_path, strlen(file_handle->opened_path)+1, &exists, sizeof(zend_bool), NULL)==FAILURE) {
|
||||
zend_close_file_handle(file_handle CLS_CC);
|
||||
restore_lexical_state(&original_lex_state CLS_CC);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
free(file_handle->opened_path);
|
||||
}
|
||||
compiler_result = zendparse(CLS_C);
|
||||
zend_close_file_handle(file_handle CLS_CC);
|
||||
restore_lexical_state(&original_lex_state CLS_CC);
|
||||
@ -506,6 +525,9 @@ int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlight
|
||||
zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename);
|
||||
return FAILURE;
|
||||
}
|
||||
if (file_handle.opened_path) {
|
||||
free(file_handle.opened_path);
|
||||
}
|
||||
zend_highlight(syntax_highlighter_ini);
|
||||
zend_close_file_handle(&file_handle CLS_CC);
|
||||
restore_lexical_state(&original_lex_state CLS_CC);
|
||||
@ -808,10 +830,18 @@ ESCAPED_AND_WHITESPACE [\n\t\r #'.:;,()|^&+-/*=%!~<>?@]+
|
||||
return T_INCLUDE;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"import" {
|
||||
return T_IMPORT;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"require" {
|
||||
return T_REQUIRE;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"use" {
|
||||
return T_USE;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"global" {
|
||||
return T_GLOBAL;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ ZEND_API int (*zend_printf)(const char *format, ...);
|
||||
ZEND_API int (*zend_write)(const char *str, uint str_length);
|
||||
ZEND_API void (*zend_error)(int type, const char *format, ...);
|
||||
ZEND_API void (*zend_message_dispatcher)(long message, void *data);
|
||||
ZEND_API FILE *(*zend_fopen)(const char *filename);
|
||||
ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
|
||||
ZEND_API void (*zend_block_interruptions)();
|
||||
ZEND_API void (*zend_unblock_interruptions)();
|
||||
ZEND_API int (*zend_get_ini_entry)(char *name, uint name_length, zval *contents);
|
||||
@ -208,8 +208,11 @@ ZEND_API void zend_print_zval_r(zval *expr, int indent)
|
||||
}
|
||||
|
||||
|
||||
static FILE *zend_fopen_wrapper(const char *filename)
|
||||
static FILE *zend_fopen_wrapper(const char *filename, char **opened_path)
|
||||
{
|
||||
if (opened_path) {
|
||||
*opened_path = strdup(filename);
|
||||
}
|
||||
return fopen(filename, "r");
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ typedef struct _zend_utility_functions {
|
||||
void (*error_function)(int type, const char *format, ...);
|
||||
int (*printf_function)(const char *format, ...);
|
||||
int (*write_function)(const char *str, uint str_length);
|
||||
FILE *(*fopen_function)(const char *filename);
|
||||
FILE *(*fopen_function)(const char *filename, char **opened_path);
|
||||
void (*message_handler)(long message, void *data);
|
||||
void (*block_interruptions)();
|
||||
void (*unblock_interruptions)();
|
||||
@ -237,7 +237,7 @@ BEGIN_EXTERN_C()
|
||||
extern ZEND_API int (*zend_printf)(const char *format, ...);
|
||||
extern ZEND_API int (*zend_write)(const char *str, uint str_length);
|
||||
extern ZEND_API void (*zend_error)(int type, const char *format, ...);
|
||||
extern ZEND_API FILE *(*zend_fopen)(const char *filename);
|
||||
extern ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
|
||||
extern ZEND_API void (*zend_block_interruptions)();
|
||||
extern ZEND_API void (*zend_unblock_interruptions)();
|
||||
extern ZEND_API void (*zend_message_dispatcher)(long message, void *data);
|
||||
|
@ -95,6 +95,7 @@ void init_compiler(CLS_D ELS_DC)
|
||||
init_resource_list(ELS_C);
|
||||
CG(unclean_shutdown) = 0;
|
||||
zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) zend_open_file_dtor, 0);
|
||||
zend_hash_init(&CG(used_files), 5, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -109,6 +110,7 @@ void shutdown_compiler(CLS_D)
|
||||
zend_hash_apply(CG(function_table), (int (*)(void *)) is_not_internal_function);
|
||||
zend_hash_apply(CG(class_table), (int (*)(void *)) is_not_internal_class);
|
||||
zend_llist_destroy(&CG(open_files));
|
||||
zend_hash_destroy(&CG(used_files));
|
||||
}
|
||||
|
||||
|
||||
|
@ -169,6 +169,7 @@ typedef struct _list_llist_element {
|
||||
typedef struct _zend_file_handle {
|
||||
int type;
|
||||
char *filename;
|
||||
char *opened_path;
|
||||
union {
|
||||
int fd;
|
||||
FILE *fp;
|
||||
@ -344,12 +345,12 @@ void do_extended_fcall_end(CLS_D);
|
||||
|
||||
/* helper functions in zend-scanner.l */
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API int require_file(zend_file_handle *file_handle CLS_DC);
|
||||
ZEND_API int require_filename(char *filename CLS_DC);
|
||||
ZEND_API int require_file(zend_file_handle *file_handle, zend_bool unique CLS_DC);
|
||||
ZEND_API int require_filename(char *filename, zend_bool unique CLS_DC);
|
||||
ZEND_API zend_op_array *compile_files(int mark_as_ref CLS_DC, int file_count, ...);
|
||||
ZEND_API zend_op_array *v_compile_files(int mark_as_ref CLS_DC, int file_count, va_list files);
|
||||
ZEND_API zend_op_array *compile_string(zval *source_string CLS_DC);
|
||||
ZEND_API zend_op_array *compile_filename(zval *filename CLS_DC);
|
||||
ZEND_API zend_op_array *compile_filename(zval *filename, zend_bool unique CLS_DC);
|
||||
ZEND_API int open_file_for_scanning(zend_file_handle *file_handle CLS_DC);
|
||||
ZEND_API void init_op_array(zend_op_array *op_array, int initial_ops_size);
|
||||
ZEND_API void destroy_op_array(zend_op_array *op_array);
|
||||
@ -535,6 +536,7 @@ int zendlex(znode *zendlval CLS_DC);
|
||||
|
||||
#define ZEND_EVAL (1<<0)
|
||||
#define ZEND_INCLUDE (1<<1)
|
||||
#define ZEND_IMPORT (1<<2)
|
||||
|
||||
#define ZEND_ISSET (1<<0)
|
||||
#define ZEND_ISEMPTY (1<<1)
|
||||
|
@ -1878,11 +1878,14 @@ send_by_ref:
|
||||
|
||||
switch (opline->op2.u.constant.value.lval) {
|
||||
case ZEND_INCLUDE:
|
||||
new_op_array = compile_filename(get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R) CLS_CC);
|
||||
new_op_array = compile_filename(get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R), 0 CLS_CC);
|
||||
break;
|
||||
case ZEND_EVAL:
|
||||
new_op_array = compile_string(get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R) CLS_CC);
|
||||
break;
|
||||
case ZEND_IMPORT:
|
||||
new_op_array = compile_filename(get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R), 1 CLS_CC);
|
||||
break;
|
||||
}
|
||||
FREE_OP(&opline->op1, EG(free_op1));
|
||||
if (new_op_array) {
|
||||
|
@ -115,6 +115,8 @@ void init_executor(CLS_D ELS_DC)
|
||||
zend_llist_apply(&zend_extensions, (void (*)(void *)) zend_extension_activator);
|
||||
EG(opline_ptr) = NULL;
|
||||
EG(garbage_ptr) = 0;
|
||||
|
||||
zend_hash_init(&EG(imported_files), 5, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -148,6 +150,8 @@ void shutdown_executor(ELS_D)
|
||||
zval_dtor(EG(garbage)[EG(garbage_ptr)]);
|
||||
efree(EG(garbage)[EG(garbage_ptr)]);
|
||||
}
|
||||
|
||||
zend_hash_destroy(&EG(imported_files));
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,6 +84,8 @@ struct _zend_compiler_globals {
|
||||
HashTable *function_table; /* function symbol table */
|
||||
HashTable *class_table; /* class table */
|
||||
|
||||
HashTable used_files; /* files already included using 'use' */
|
||||
|
||||
zend_llist filenames_list;
|
||||
|
||||
zend_bool short_tags;
|
||||
@ -130,6 +132,8 @@ struct _zend_executor_globals {
|
||||
HashTable *active_symbol_table;
|
||||
HashTable symbol_table; /* main symbol table */
|
||||
|
||||
HashTable imported_files; /* files already included using 'import' */
|
||||
|
||||
jmp_buf bailout;
|
||||
|
||||
int error_reporting;
|
||||
|
Loading…
Reference in New Issue
Block a user