- Implement declare() with declarables framework

- Implement ticks - Germany&Norway - 5 points!
This commit is contained in:
Zeev Suraski 2000-01-24 19:00:30 +00:00
parent adec56938e
commit fafbf6d8da
12 changed files with 146 additions and 17 deletions

View File

@ -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; }

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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));
}
/* }}} */

View File

@ -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)
{

View File

@ -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 */

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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) \