%% /* Rules */
-statement_list:
- statement_list { do_extended_info(CLS_C); } statement { ELS_FETCH(); HANDLE_INTERACTIVE(); }
+top_statement_list:
+ top_statement_list { do_extended_info(CLS_C); } top_statement { ELS_FETCH(); HANDLE_INTERACTIVE(); }
| /* empty */
;
+top_statement:
+ statement
+ | declaration_statement { do_early_binding(CLS_C); }
+;
+
+
+inner_statement_list:
+ inner_statement_list { do_extended_info(CLS_C); } inner_statement { ELS_FETCH(); HANDLE_INTERACTIVE(); }
+ | /* empty */
+;
+
+
+inner_statement:
+ statement
+ | declaration_statement
+;
+
+
statement:
- '{' statement_list '}'
+ '{' 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); } statement_list { do_if_after_statement(&$4, 1 CLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { 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); }
| T_WHILE '(' { $1.u.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' { do_while_cond(&$4, &$5 CLS_CC); } while_statement { do_while_end(&$1, &$5 CLS_CC); }
| T_DO { $1.u.opline_num = get_next_op_number(CG(active_op_array)); do_do_while_begin(CLS_C); } statement T_WHILE '(' expr ')' ';' { do_do_while_end(&$1, &$6 CLS_CC); }
| T_FOR
| T_BREAK expr ';' { do_brk_cont(ZEND_BRK, &$2 CLS_CC); }
| T_CONTINUE ';' { do_brk_cont(ZEND_CONT, NULL CLS_CC); }
| T_CONTINUE expr ';' { do_brk_cont(ZEND_CONT, &$2 CLS_CC); }
- | T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); }
- '(' parameter_list ')' '{' statement_list '}' { do_end_function_declaration(&$1 CLS_CC); }
- | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); }
- parameter_list '(' statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); }
| T_RETURN ';' { do_return(NULL CLS_CC); }
| T_RETURN expr ';' { do_return(&$2 CLS_CC); }
| T_GLOBAL global_var_list
| T_STATIC static_var_list
- | T_CLASS T_STRING { do_begin_class_declaration(&$2, NULL CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); }
- | T_CLASS T_STRING T_EXTENDS T_STRING { do_begin_class_declaration(&$2, &$4 CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); }
| T_ECHO echo_expr_list ';'
| T_INLINE_HTML { do_echo(&$1 CLS_CC); }
| expr ';' { do_free(&$1 CLS_CC); }
;
+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); }
+ | T_OLD_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); }
+ | T_CLASS T_STRING { do_begin_class_declaration(&$2, NULL CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); }
+ | T_CLASS T_STRING T_EXTENDS T_STRING { do_begin_class_declaration(&$2, &$4 CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); }
+;
+
+
foreach_optional_arg:
/* empty */ { $$.op_type = IS_UNUSED; }
| T_DOUBLE_ARROW w_cvar { $$ = $2; }
for_statement:
statement
- | ':' statement_list T_ENDFOR ';'
+ | ':' inner_statement_list T_ENDFOR ';'
;
foreach_statement:
statement
- | ':' statement_list T_ENDFOREACH ';'
+ | ':' inner_statement_list T_ENDFOREACH ';'
;
case_list:
/* empty */ { $$.u.opline_num = -1; }
- | case_list T_CASE expr case_separator { do_case_before_statement(&$1, &$2, &$3 CLS_CC); } statement_list { do_case_after_statement(&$$, &$2 CLS_CC); }
- | case_list T_DEFAULT case_separator { do_default_before_statement(&$1, &$2 CLS_CC); } statement_list { do_case_after_statement(&$$, &$2 CLS_CC); }
+ | case_list T_CASE expr case_separator { do_case_before_statement(&$1, &$2, &$3 CLS_CC); } inner_statement_list { do_case_after_statement(&$$, &$2 CLS_CC); }
+ | case_list T_DEFAULT case_separator { do_default_before_statement(&$1, &$2 CLS_CC); } inner_statement_list { do_case_after_statement(&$$, &$2 CLS_CC); }
;
while_statement:
statement
- | ':' statement_list T_ENDWHILE ';'
+ | ':' inner_statement_list T_ENDWHILE ';'
;
new_elseif_list:
/* empty */
- | new_elseif_list T_ELSEIF '(' expr ')' ':' { do_if_cond(&$4, &$5 CLS_CC); } statement_list { do_if_after_statement(&$5, 0 CLS_CC); }
+ | new_elseif_list T_ELSEIF '(' expr ')' ':' { do_if_cond(&$4, &$5 CLS_CC); } inner_statement_list { do_if_after_statement(&$5, 0 CLS_CC); }
;
new_else_single:
/* empty */
- | T_ELSE ':' statement_list
+ | T_ELSE ':' inner_statement_list
;
class_statement:
T_VAR class_variable_decleration ';'
| T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); } '('
- parameter_list ')' '{' statement_list '}' { do_end_function_declaration(&$1 CLS_CC); }
+ parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); }
| T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); }
- parameter_list '(' statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); }
+ parameter_list '(' inner_statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); }
;
}
+BEGIN_EXTERN_C()
ZEND_API void zend_bailout()
{
CLS_FETCH();
CG(unclean_shutdown) = 1;
longjmp(EG(bailout), FAILURE);
}
+END_EXTERN_C()
void zend_append_version_info(zend_extension *extension)
int zend_startup(zend_utility_functions *utility_functions, char **extensions);
void zend_shutdown();
void zend_set_utility_values(zend_utility_values *utility_values);
+BEGIN_EXTERN_C()
ZEND_API void zend_bailout();
+END_EXTERN_C()
ZEND_API char *get_zend_version();
ZEND_API int zend_print_zval(zval *expr, int indent);
if (is_method) {
zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
} else {
- zend_hash_add(CG(function_table), name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
+
+ opline->opcode = ZEND_DECLARE_FUNCTION_OR_CLASS;
+ opline->op1.op_type = IS_CONST;
+ opline->op1.u.constant.type = IS_LONG;
+ opline->op1.u.constant.value.lval = zend_hash_next_free_element(CG(function_table));
+ opline->op2.op_type = IS_CONST;
+ opline->op2.u.constant.type = IS_STRING;
+ opline->op2.u.constant.value.str.val = estrndup(name, name_len);
+ opline->op2.u.constant.value.str.len = name_len;
+ opline->extended_value = ZEND_DECLARE_FUNCTION;
+ zend_hash_next_index_insert(CG(function_table), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
}
if (CG(extended_info)) {
}
+void do_bind_function_or_class(zend_op *opline, HashTable *function_table, HashTable *class_table)
+{
+ switch (opline->extended_value) {
+ case ZEND_DECLARE_FUNCTION: {
+ zend_function *function;
+
+ zend_hash_index_find(function_table, opline->op1.u.constant.value.lval, (void **) &function);
+ (*function->op_array.refcount)++;
+ if (zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL)==FAILURE) {
+ zend_error(E_ERROR, "Cannot redeclare %s()", opline->op2.u.constant.value.str.val);
+ }
+ }
+ break;
+ case ZEND_DECLARE_CLASS: {
+ zend_class_entry *ce;
+
+ zend_hash_index_find(class_table, opline->op1.u.constant.value.lval, (void **) &ce);
+ (*ce->refcount)++;
+ if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, ce, sizeof(zend_class_entry), NULL)==FAILURE) {
+ zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ }
+ }
+ break;
+ }
+}
+
+
+void do_early_binding(CLS_D)
+{
+ zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
+
+ do_bind_function_or_class(opline, CG(function_table), CG(class_table));
+ switch (opline->extended_value) {
+ case ZEND_DECLARE_FUNCTION:
+ zend_hash_index_del(CG(function_table), opline->op1.u.constant.value.lval);
+ break;
+ case ZEND_DECLARE_CLASS:
+ zend_hash_index_del(CG(class_table), opline->op1.u.constant.value.lval);
+ break;
+ }
+ zval_dtor(&opline->op2.u.constant);
+ opline->opcode = ZEND_NOP;
+ SET_UNUSED(opline->op1);
+ SET_UNUSED(opline->op2);
+}
+
+
void do_boolean_or_begin(znode *expr1, znode *op_token CLS_DC)
{
int next_op_number = get_next_op_number(CG(active_op_array));
void do_begin_class_declaration(znode *class_name, znode *parent_class_name CLS_DC)
{
+ zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
+
if (CG(active_class_entry)) {
zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
return;
CG(class_entry).handle_property_set = NULL;
CG(class_entry).handle_property_get = NULL;
- if (zend_hash_add(CG(class_table), CG(class_entry).name, CG(class_entry).name_length+1, &CG(class_entry), sizeof(zend_class_entry), (void **) &CG(active_class_entry))==FAILURE) {
- zend_error(E_COMPILE_ERROR, "Class %s cannot be redeclared", CG(class_entry).name);
- }
+ opline->opcode = ZEND_DECLARE_FUNCTION_OR_CLASS;
+ opline->op1.op_type = IS_CONST;
+ opline->op1.u.constant.type = IS_LONG;
+ opline->op1.u.constant.value.lval = zend_hash_next_free_element(CG(function_table));
+ opline->op2.op_type = IS_CONST;
+ opline->op2.u.constant.type = IS_STRING;
+ opline->op2.u.constant.value.str.val = estrndup(CG(class_entry).name, CG(class_entry).name_length);
+ opline->op2.u.constant.value.str.len = CG(class_entry).name_length;
+ opline->extended_value = ZEND_DECLARE_CLASS;
+
+ zend_hash_next_index_insert(CG(class_table), &CG(class_entry), sizeof(zend_class_entry), (void **) &CG(active_class_entry));
}
void do_begin_class_member_function_call(znode *class_name, znode *function_name CLS_DC);
void do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method CLS_DC);
void do_return(znode *expr CLS_DC);
+void do_bind_function_or_class(zend_op *opline, HashTable *function_table, HashTable *class_table);
+void do_early_binding(CLS_D);
void do_pass_param(znode *param, int op, int offset CLS_DC);
#define ZEND_FETCH_DIM_TMP_VAR 89
#define ZEND_FETCH_CONSTANT 90
-#define ZEND_INIT_GLOBALS 91
+#define ZEND_DECLARE_FUNCTION_OR_CLASS 91
-#define ZEND_EXT_STMT 92
-#define ZEND_EXT_FCALL_BEGIN 93
-#define ZEND_EXT_FCALL_END 94
-#define ZEND_EXT_NOP 95
+#define ZEND_INIT_GLOBALS 92
+
+#define ZEND_EXT_STMT 93
+#define ZEND_EXT_FCALL_BEGIN 94
+#define ZEND_EXT_FCALL_END 95
+#define ZEND_EXT_NOP 96
/* end of block */
#define ZEND_HANDLE_FP 2
#define ZEND_HANDLE_ISTREAM 3
+#define ZEND_DECLARE_CLASS 1
+#define ZEND_DECLARE_FUNCTION 2
+
#endif /* _COMPILE_H */
active_function_table = EG(function_table);
}
if (zend_hash_find(active_function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function)==FAILURE) {
- zend_error(E_ERROR, "Call to undefined function: %s()\n", function_name->value.str.val);
+ zend_error(E_ERROR, "Call to undefined function: %s()", function_name->value.str.val);
}
zval_dtor(&tmp);
function_being_called = function;
zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_fcall_end_handler, op_array);
}
break;
+ case ZEND_DECLARE_FUNCTION_OR_CLASS:
+ do_bind_function_or_class(opline, EG(function_table), EG(class_table));
+ break;
case ZEND_INIT_GLOBALS: {
zval *globals = (zval *) emalloc(sizeof(zval));
q = p;
p = p->pListNext;
if (destruct(q->pData)) {
- if (q->arKey == NULL) {
+ if (q->nKeyLength==0) {
zend_hash_index_del(ht, q->h);
} else {
zend_hash_del(ht,q->arKey,q->nKeyLength);
q = p;
p = p->pListNext;
if (destruct(q->pData, argument)) {
- if (q->arKey == NULL) {
+ if (q->nKeyLength == 0) {
zend_hash_index_del(ht, q->h);
} else {
zend_hash_del(ht,q->arKey,q->nKeyLength);
p = source->pListHead;
while (p) {
memcpy(tmp, p->pData, size);
- if (p->arKey) {
+ if (p->nKeyLength>0) {
if (zend_hash_add(target, p->arKey, p->nKeyLength, tmp, size, &t)==SUCCESS && pCopyConstructor) {
pCopyConstructor(t);
}