diff options
-rw-r--r-- | Zend/zend-parser.y | 25 | ||||
-rw-r--r-- | Zend/zend-scanner.l | 8 | ||||
-rw-r--r-- | Zend/zend.c | 2 | ||||
-rw-r--r-- | Zend/zend.h | 2 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 4 | ||||
-rw-r--r-- | Zend/zend_compile.c | 51 | ||||
-rw-r--r-- | Zend/zend_compile.h | 8 | ||||
-rw-r--r-- | Zend/zend_execute.c | 8 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 2 | ||||
-rw-r--r-- | Zend/zend_globals.h | 13 | ||||
-rw-r--r-- | Zend/zend_operators.c | 33 | ||||
-rw-r--r-- | Zend/zend_operators.h | 7 |
12 files changed, 146 insertions, 17 deletions
diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index 93938dc39c..aa20f4d5ba 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -94,6 +94,8 @@ %token T_ENDFOR %token T_FOREACH %token T_ENDFOREACH +%token T_DECLARE +%token T_ENDDECLARE %token T_AS %token T_SWITCH %token T_ENDSWITCH @@ -160,6 +162,11 @@ inner_statement: statement: + unticked_statement { do_ticks(CLS_C); } +; + + +unticked_statement: '{' inner_statement_list '}' | T_IF '(' expr ')' { do_if_cond(&$3, &$4 CLS_CC); } statement { do_if_after_statement(&$4, 1 CLS_CC); } elseif_list else_single { do_if_end(CLS_C); } | T_IF '(' expr ')' ':' { do_if_cond(&$3, &$4 CLS_CC); } inner_statement_list { do_if_after_statement(&$4, 1 CLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { do_if_end(CLS_C); } @@ -191,6 +198,7 @@ statement: | T_USE use_filename ';' { use_filename($2.u.constant.value.str.val, $2.u.constant.value.str.len 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); } + | T_DECLARE { do_declare_begin(CLS_C); } '(' declare_list ')' declare_statement { do_declare_end(CLS_C); } | ';' /* empty statement */ ; @@ -202,6 +210,11 @@ use_filename: declaration_statement: + unticked_declaration_statement { do_ticks(CLS_C); } +; + + +unticked_declaration_statement: T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 0, $3.op_type CLS_CC); } '(' parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); } | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 0, $3.op_type CLS_CC); } @@ -229,6 +242,18 @@ foreach_statement: ; +declare_statement: + statement + | ':' inner_statement_list T_ENDDECLARE ';' +; + + +declare_list: + T_STRING '=' static_scalar { do_declare_stmt(&$1, &$3 CLS_CC); } + | declare_list ',' T_STRING '=' static_scalar { do_declare_stmt(&$3, &$5 CLS_CC); } +; + + switch_case_list: '{' case_list '}' { $$ = $2; } | '{' ';' case_list '}' { $$ = $3; } diff --git a/Zend/zend-scanner.l b/Zend/zend-scanner.l index 42d9c90c85..2755dae511 100644 --- a/Zend/zend-scanner.l +++ b/Zend/zend-scanner.l @@ -780,6 +780,14 @@ ESCAPED_AND_WHITESPACE [\n\t\r #'.:;,()|^&+-/*=%!~<>?@]+ return T_ENDFOREACH; } +<ST_IN_SCRIPTING>"declare" { + return T_DECLARE; +} + +<ST_IN_SCRIPTING>"enddeclare" { + return T_ENDDECLARE; +} + <ST_IN_SCRIPTING>"as" { return T_AS; } diff --git a/Zend/zend.c b/Zend/zend.c index ba07725523..24b6525633 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -48,6 +48,7 @@ ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path); ZEND_API void (*zend_block_interruptions)(void); ZEND_API void (*zend_unblock_interruptions)(void); ZEND_API int (*zend_get_ini_entry)(char *name, uint name_length, zval *contents); +void (*zend_ticks_function)(int ticks); #ifdef ZTS ZEND_API int compiler_globals_id; @@ -318,6 +319,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) zend_block_interruptions = utility_functions->block_interruptions; zend_unblock_interruptions = utility_functions->unblock_interruptions; zend_get_ini_entry = utility_functions->get_ini_entry; + zend_ticks_function = utility_functions->ticks_function; zend_compile_files = compile_files; zend_execute = execute; diff --git a/Zend/zend.h b/Zend/zend.h index bfcf96d70a..ed306c2bbd 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -204,6 +204,7 @@ typedef struct _zend_utility_functions { void (*block_interruptions)(void); void (*unblock_interruptions)(void); int (*get_ini_entry)(char *name, uint name_length, zval *contents); + void (*ticks_function)(int ticks); } zend_utility_functions; @@ -283,6 +284,7 @@ extern ZEND_API void (*zend_block_interruptions)(void); extern ZEND_API void (*zend_unblock_interruptions)(void); extern ZEND_API void (*zend_message_dispatcher)(long message, void *data); extern ZEND_API int (*zend_get_ini_entry)(char *name, uint name_length, zval *contents); +extern void (*zend_ticks_function)(int ticks); void zenderror(char *error); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 2dbe69b914..b828a8bd7f 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -196,7 +196,7 @@ ZEND_FUNCTION(strcmp) } convert_to_string_ex(s1); convert_to_string_ex(s2); - RETURN_LONG(zend_binary_strcmp(*s1,*s2)); + RETURN_LONG(zend_binary_zval_strcmp(*s1,*s2)); } /* }}} */ @@ -211,7 +211,7 @@ ZEND_FUNCTION(strcasecmp) } convert_to_string_ex(s1); convert_to_string_ex(s2); - RETURN_LONG(zend_binary_strcasecmp(*s1, *s2)); + RETURN_LONG(zend_binary_zval_strcasecmp(*s1, *s2)); } /* }}} */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 48f5eafcde..664141093d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -85,6 +85,13 @@ static void zend_open_file_dtor_wrapper(zend_file_handle *fh) } +static void init_compiler_declarables(CLS_D ELS_DC) +{ + CG(declarables).ticks.type = IS_LONG; + CG(declarables).ticks.value.lval = 0; +} + + void init_compiler(CLS_D ELS_DC) { zend_stack_init(&CG(bp_stack)); @@ -92,6 +99,7 @@ void init_compiler(CLS_D ELS_DC) zend_stack_init(&CG(switch_cond_stack)); zend_stack_init(&CG(foreach_copy_stack)); zend_stack_init(&CG(object_stack)); + zend_stack_init(&CG(declare_stack)); CG(active_class_entry) = NULL; zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0); zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0); @@ -104,6 +112,7 @@ void init_compiler(CLS_D ELS_DC) 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, (void (*)(void *)) zend_open_file_dtor_wrapper, 0); + init_compiler_declarables(CLS_C ELS_CC); } @@ -114,6 +123,7 @@ void shutdown_compiler(CLS_D) zend_stack_destroy(&CG(switch_cond_stack)); zend_stack_destroy(&CG(foreach_copy_stack)); zend_stack_destroy(&CG(object_stack)); + zend_stack_destroy(&CG(declare_stack)); zend_llist_destroy(&CG(filenames_list)); zend_hash_apply(CG(function_table), (int (*)(void *)) is_not_internal_function); zend_hash_apply(CG(class_table), (int (*)(void *)) is_not_internal_class); @@ -2034,6 +2044,33 @@ void do_foreach_end(znode *foreach_token, znode *open_brackets_token CLS_DC) } +void do_declare_begin(CLS_D) +{ + zend_stack_push(&CG(declare_stack), &CG(declarables), sizeof(zend_declarables)); +} + + +void do_declare_stmt(znode *var, znode *val CLS_DC) +{ + convert_to_string(&var->u.constant); + + if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "ticks", sizeof("ticks")-1)) { + convert_to_long(&val->u.constant); + CG(declarables).ticks = val->u.constant; + } + zval_dtor(&var->u.constant); +} + + +void do_declare_end(CLS_D) +{ + zend_declarables *declarables; + + zend_stack_top(&CG(declare_stack), (void **) &declarables); + CG(declarables) = *declarables; +} + + void do_end_heredoc(CLS_D) { int opline_num = get_next_op_number(CG(active_op_array))-1; @@ -2144,6 +2181,7 @@ void do_qm_false(znode *result, znode *false_value, znode *qm_token, znode *colo DEC_BPC(CG(active_op_array)); } + void do_extended_info(CLS_D) { zend_op *opline; @@ -2159,6 +2197,7 @@ void do_extended_info(CLS_D) SET_UNUSED(opline->op2); } + void do_extended_fcall_begin(CLS_D) { zend_op *opline; @@ -2190,6 +2229,18 @@ void do_extended_fcall_end(CLS_D) SET_UNUSED(opline->op2); } +void do_ticks(CLS_D) +{ + if (CG(declarables).ticks.value.lval) { + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_TICKS; + opline->op1.u.constant = CG(declarables).ticks; + opline->op1.op_type = IS_CONST; + SET_UNUSED(opline->op2); + } +} + int zendlex(znode *zendlval CLS_DC) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 59ffd41009..9e331aac31 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -328,6 +328,10 @@ void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_t void do_foreach_cont(znode *value, znode *key, znode *as_token CLS_DC); void do_foreach_end(znode *foreach_token, znode *open_brackets_token CLS_DC); +void do_declare_begin(CLS_D); +void do_declare_stmt(znode *var, znode *val CLS_DC); +void do_declare_end(CLS_D); + void do_end_heredoc(CLS_D); void do_exit(znode *result, znode *message CLS_DC); @@ -343,6 +347,8 @@ void do_extended_info(CLS_D); void do_extended_fcall_begin(CLS_D); void do_extended_fcall_end(CLS_D); +void do_ticks(CLS_D); + #define INITIAL_OP_ARRAY_SIZE 64 @@ -511,6 +517,8 @@ int zendlex(znode *zendlval CLS_DC); #define ZEND_EXT_FCALL_END 99 #define ZEND_EXT_NOP 100 +#define ZEND_TICKS 101 + /* end of block */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 1bac5e2f96..0b15b0f881 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2245,6 +2245,14 @@ send_by_ref: case ZEND_DECLARE_FUNCTION_OR_CLASS: do_bind_function_or_class(opline, EG(function_table), EG(class_table), 0); break; + case ZEND_TICKS: + if (++EG(ticks_count)==opline->op1.u.constant.value.lval) { + EG(ticks_count)=0; + if (zend_ticks_function) { + zend_ticks_function(opline->op1.u.constant.value.lval); + } + } + break; case ZEND_EXT_NOP: case ZEND_NOP: break; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 8c610ef301..912310a555 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -114,6 +114,8 @@ void init_executor(CLS_D ELS_DC) EG(suspend_garbage) = 0; zend_hash_init(&EG(imported_files), 5, NULL, NULL, 0); + + EG(ticks_count) = 0; } diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index aecd3778c7..9592cb7790 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -58,12 +58,19 @@ END_EXTERN_C() /* excpt.h on Digital Unix 4.0 defines function_table */ #undef function_table - + + +typedef struct _zend_declarables { + zval ticks; +} zend_declarables; + + struct _zend_compiler_globals { zend_stack bp_stack; zend_stack switch_cond_stack; zend_stack foreach_copy_stack; zend_stack object_stack; + zend_stack declare_stack; zend_class_entry class_entry, *active_class_entry; @@ -93,6 +100,8 @@ struct _zend_compiler_globals { zend_bool asp_tags; zend_bool allow_call_time_pass_reference; + zend_declarables declarables; + /* For extensions support */ zend_bool extended_info; /* generate extension information for debugger/profiler */ zend_bool handle_op_arrays; /* run op_arrays through op_array handlers */ @@ -152,6 +161,8 @@ struct _zend_executor_globals { long precision; + int ticks_count; + /* for extended information support */ zend_bool no_extensions; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index e8c7f2c801..7bbf4ccc3f 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -1218,35 +1218,30 @@ ZEND_API void zend_str_tolower(char *str, unsigned int length) } -ZEND_API int zend_binary_strcmp(zval *s1, zval *s2) +ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2) { int retval; - retval = memcmp(s1->value.str.val, s2->value.str.val, MIN(s1->value.str.len,s2->value.str.len)); + retval = memcmp(s1, s2, MIN(len1, len2)); if (!retval) { - return (s1->value.str.len - s2->value.str.len); + return (len1 - len2); } else { return retval; } } -ZEND_API int zend_binary_strcasecmp(zval *s1, zval *s2) +ZEND_API int zend_binary_strcasecmp(char *s1, uint len1, char *s2, uint len2) { - const unsigned char *p1 = (const unsigned char *)s1->value.str.val; - const unsigned char *p2 = (const unsigned char *)s2->value.str.val; unsigned char c1 = 0, c2 = 0; - int len1, len2; - len1 = s1->value.str.len; - len2 = s2->value.str.len; if (len1 != len2 || !len1) { return len1 - len2; } while (len1--) { - c1 = tolower(*p1++); - c2 = tolower(*p2++); + c1 = tolower(*s1++); + c2 = tolower(*s2++); if (c1 != c2) { break; } @@ -1255,6 +1250,20 @@ ZEND_API int zend_binary_strcasecmp(zval *s1, zval *s2) return c1 - c2; } + +ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2) +{ + return zend_binary_strcmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len); +} + + +ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2) +{ + return zend_binary_strcasecmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len); +} + + + ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) { int ret1,ret2; @@ -1291,7 +1300,7 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) result->type = IS_LONG; } } else { - result->value.lval = zend_binary_strcmp(s1,s2); + result->value.lval = zend_binary_zval_strcmp(s1, s2); result->type = IS_LONG; } return; diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index a4378305b8..82c4f7cbd0 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -69,8 +69,11 @@ ZEND_API int zval_is_true(zval *op); ZEND_API int compare_function(zval *result, zval *op1, zval *op2); ZEND_API void zend_str_tolower(char *str, unsigned int length); -ZEND_API int zend_binary_strcmp(zval *s1, zval *s2); -ZEND_API int zend_binary_strcasecmp(zval *s1, zval *s2); +ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2); +ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2); +ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2); +ZEND_API int zend_binary_strcasecmp(char *s1, uint len1, char *s2, uint len2); + ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2); #define convert_to_long_ex(ppzv) \ |