From: Andi Gutmans Date: Tue, 30 Nov 1999 20:15:04 +0000 (+0000) Subject: - Add use support (behaves like require, but will not use the same file twice) X-Git-Tag: PRE_RETURN_REF_PATCH~161 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5463dd5b387298a84736e590e5d213f5bafe9435;p=php - 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) --- diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index e2461a3962..b8eb3239da 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -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); } ; diff --git a/Zend/zend-scanner.l b/Zend/zend-scanner.l index 9e68ec439c..0e5ad67ecc 100644 --- a/Zend/zend-scanner.l +++ b/Zend/zend-scanner.l @@ -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; } +"import" { + return T_IMPORT; +} + "require" { return T_REQUIRE; } +"use" { + return T_USE; +} + "global" { return T_GLOBAL; } diff --git a/Zend/zend.c b/Zend/zend.c index 7a89470916..dc1b024d19 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -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"); } diff --git a/Zend/zend.h b/Zend/zend.h index 313f151be1..494c03913a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -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); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9a6dbbe4ff..d7d2aec69c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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)); } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 1d96cf9559..eb56ca2519 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index edfcc396fe..758050a39c 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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) { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 43ce0868bd..5ad78d57cb 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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)); } diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index d61542d506..947fc0044d 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -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;