mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
- Implement declare() with declarables framework
- Implement ticks - Germany&Norway - 5 points!
This commit is contained in:
parent
adec56938e
commit
fafbf6d8da
@ -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; }
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user