Skip to content
Browse files

- Implement declare() with declarables framework

- Implement ticks - Germany&Norway - 5 points!
  • Loading branch information...
1 parent adec569 commit fafbf6d8da6aaf71be95047b64e30efc299f1919 @zsuraski zsuraski committed
View
25 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; }
View
8 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;
}
View
2 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;
View
2 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);
View
4 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));
}
/* }}} */
View
51 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)
{
View
8 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 */
View
8 Zend/zend_execute.c
@@ -2245,6 +2245,14 @@ binary_assign_op_addr: {
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
2 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;
}
View
13 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;
View
33 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;
View
7 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) \

0 comments on commit fafbf6d

Please sign in to comment.
Something went wrong with that request. Please try again.