Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.434 diff -u -p -d -r1.434 zend_API.c --- Zend/zend_API.c 28 May 2007 20:26:52 -0000 1.434 +++ Zend/zend_API.c 3 Jul 2007 08:30:43 -0000 @@ -2547,14 +2547,36 @@ static int zend_is_callable_check_func(i *ce_ptr = NULL; *fptr_ptr = NULL; + if (!ce_org) { + if (Z_TYPE_P(callable) == IS_UNICODE && + Z_USTRVAL_P(callable)[0] == ':' && + Z_USTRVAL_P(callable)[1] == ':') { + lmname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(callable)+2), Z_USTRLEN_P(callable)-2, 1, &mlen); + } else if (Z_TYPE_P(callable) == IS_STRING && + Z_STRVAL_P(callable)[0] == ':' && + Z_STRVAL_P(callable)[1] == ':') { + lmname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(callable)+2), Z_STRLEN_P(callable)-2, 1, &mlen); + } else { + lmname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), Z_UNILEN_P(callable), 1, &mlen); + } + if (zend_u_hash_find(EG(function_table), Z_TYPE_P(callable), lmname, mlen+1, (void**)&fptr) == SUCCESS) { + *fptr_ptr = fptr; + efree(lmname.v); + return 1; + } + efree(lmname.v); + } if (Z_TYPE_P(callable) == IS_UNICODE) { - if ((colon.u = u_strstr(Z_USTRVAL_P(callable), u_doublecolon)) != NULL) { + if ((colon.u = u_strrstr(Z_USTRVAL_P(callable), u_doublecolon)) != NULL) { mlen = u_strlen(colon.u+2); clen = Z_USTRLEN_P(callable) - mlen - 2; mname.u = colon.u + 2; } } else { - if ((colon.s = strstr(Z_STRVAL_P(callable), "::")) != NULL) { + if ((colon.s = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL && + colon.s > Z_STRVAL_P(callable) && + *(colon.s-1) == ':') { + colon.s--; clen = colon.s - Z_STRVAL_P(callable); mlen = Z_STRLEN_P(callable) - clen - 2; mname.s = colon.s + 2; Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.752 diff -u -p -d -r1.752 zend_compile.c --- Zend/zend_compile.c 28 Jun 2007 20:27:35 -0000 1.752 +++ Zend/zend_compile.c 3 Jul 2007 08:30:46 -0000 @@ -164,6 +164,8 @@ void zend_init_compiler_data_structures( zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC); zend_stack_init(&CG(labels_stack)); CG(labels) = NULL; + CG(current_namespace) = NULL; + CG(current_import) = NULL; } @@ -432,13 +434,15 @@ void fetch_simple_variable(znode *result fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC); } -void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC) +void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) { + znode class_node; zend_llist *fetch_list_ptr; zend_llist_element *le; zend_op *opline_ptr; zend_op opline; + zend_do_fetch_class(&class_node, class_name TSRMLS_CC); zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); if (result->op_type == IS_CV) { init_op(&opline TSRMLS_CC); @@ -452,7 +456,7 @@ void zend_do_fetch_static_member(znode * CG(active_op_array)->vars[result->u.var].name, CG(active_op_array)->vars[result->u.var].name_len, 1); SET_UNUSED(opline.op2); - opline.op2 = *class_znode; + opline.op2 = class_node; opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER; *result = opline.result; @@ -472,13 +476,13 @@ void zend_do_fetch_static_member(znode * CG(active_op_array)->vars[opline_ptr->op1.u.var].name, CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len, 1); SET_UNUSED(opline.op2); - opline.op2 = *class_znode; + opline.op2 = class_node; opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER; opline_ptr->op1 = opline.result; zend_llist_prepend_element(fetch_list_ptr, &opline); } else { - opline_ptr->op2 = *class_znode; + opline_ptr->op2 = class_node; opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER; } } @@ -1224,13 +1228,24 @@ void zend_do_begin_function_declaration( } else { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + if (CG(current_namespace)) { + znode tmp; + + tmp.u.constant = *CG(current_namespace); + zval_copy_ctor(&tmp.u.constant); + zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC); + op_array.function_name = Z_UNIVAL(tmp.u.constant); + efree(lcname.v); + lcname = zend_u_str_case_fold(Z_TYPE(tmp.u.constant), Z_UNIVAL(tmp.u.constant), Z_UNILEN(tmp.u.constant), 0, &lcname_len); + } + opline->opcode = ZEND_DECLARE_FUNCTION; opline->op1.op_type = IS_CONST; build_runtime_defined_function_key(&opline->op1.u.constant, Z_TYPE(function_name->u.constant), lcname, lcname_len TSRMLS_CC); opline->op2.op_type = IS_CONST; Z_TYPE(opline->op2.u.constant) = Z_TYPE(function_name->u.constant); - Z_STRVAL(opline->op2.u.constant) = lcname.s; - Z_STRLEN(opline->op2.u.constant) = lcname_len; + Z_UNIVAL(opline->op2.u.constant) = lcname; + Z_UNILEN(opline->op2.u.constant) = lcname_len; opline->op2.u.constant.refcount = 1; opline->extended_value = ZEND_DECLARE_FUNCTION; zend_u_hash_update(CG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)); @@ -1414,12 +1429,22 @@ void zend_do_receive_arg(zend_uchar op, } -int zend_do_begin_function_call(znode *function_name TSRMLS_DC) +int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) { zend_function *function; unsigned int lcname_len; zstr lcname; + if (check_namespace && CG(current_namespace)) { + znode tmp; + + tmp.op_type = IS_CONST; + tmp.u.constant = *CG(current_namespace); + zval_copy_ctor(&tmp.u.constant); + zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC); + *function_name = tmp; + } + lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant), Z_UNILEN(function_name->u.constant), 0, &lcname_len); if (zend_u_hash_find(CG(function_table), Z_TYPE(function_name->u.constant), lcname, lcname_len+1, (void **) &function)==FAILURE) { zend_do_begin_dynamic_function_call(function_name TSRMLS_CC); @@ -1427,12 +1452,8 @@ int zend_do_begin_function_call(znode *f return 1; /* Dynamic */ } efree(Z_UNIVAL(function_name->u.constant).v); - if (Z_TYPE(function_name->u.constant) == IS_UNICODE) { - Z_USTRVAL(function_name->u.constant) = lcname.u; - Z_USTRLEN(function_name->u.constant) = lcname_len; - } else { - Z_STRVAL(function_name->u.constant) = lcname.s; - } + Z_UNIVAL(function_name->u.constant) = lcname; + Z_UNILEN(function_name->u.constant) = lcname_len; switch (function->type) { case ZEND_USER_FUNCTION: { @@ -1521,11 +1542,103 @@ void zend_do_begin_dynamic_function_call opline->extended_value = 0; SET_UNUSED(opline->op1); + if (function_name->op_type == IS_CONST) { + if (Z_TYPE(function_name->u.constant) == IS_UNICODE) { + UChar *p = u_memrchr(Z_USTRVAL(function_name->u.constant), ':', Z_USTRLEN(function_name->u.constant)); + if (p) { + opline->op1.op_type = IS_CONST; + ZVAL_LONG(&opline->op1.u.constant, p + 1 - Z_USTRVAL(function_name->u.constant)); + } + } else { + char *p = zend_memrchr(Z_STRVAL(function_name->u.constant), ':', Z_STRLEN(function_name->u.constant)); + if (p) { + opline->op1.op_type = IS_CONST; + ZVAL_LONG(&opline->op1.u.constant, p + 1 - Z_STRVAL(function_name->u.constant)); + } + } + } zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); zend_do_extended_fcall_begin(TSRMLS_C); } +void zend_resolve_class_name(znode *class_name, ulong *fetch_type TSRMLS_DC) +{ + zstr compound; + unsigned int lcname_len; + zstr lcname; + zval **ns; + znode tmp; + int len; + + if (Z_TYPE(class_name->u.constant) == IS_UNICODE) { + compound.u = u_memchr(Z_USTRVAL(class_name->u.constant), ':', Z_USTRLEN(class_name->u.constant)); + } else { + compound.s = memchr(Z_STRVAL(class_name->u.constant), ':', Z_STRLEN(class_name->u.constant)); + } + if (compound.v) { + if (Z_TYPE(class_name->u.constant) == IS_UNICODE && + Z_USTRVAL(class_name->u.constant)[0] == ':') { + Z_USTRLEN(class_name->u.constant) -= 2; + memmove(Z_USTRVAL(class_name->u.constant), Z_USTRVAL(class_name->u.constant)+2, UBYTES(Z_USTRLEN(class_name->u.constant)+1)); + Z_USTRVAL(class_name->u.constant) = eurealloc( + Z_USTRVAL(class_name->u.constant), + Z_USTRLEN(class_name->u.constant) + 1); + } else if (Z_TYPE(class_name->u.constant) == IS_STRING && + Z_STRVAL(class_name->u.constant)[0] == ':') { + Z_STRLEN(class_name->u.constant) -= 2; + memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+2, Z_STRLEN(class_name->u.constant)+1); + Z_STRVAL(class_name->u.constant) = erealloc( + Z_STRVAL(class_name->u.constant), + Z_STRLEN(class_name->u.constant) + 1); + } else if (CG(current_import)) { + if (Z_TYPE(class_name->u.constant) == IS_UNICODE) { + len = compound.u - Z_USTRVAL(class_name->u.constant); + lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), len, 0, &lcname_len); + } else { + len = compound.s - Z_STRVAL(class_name->u.constant); + lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), len , 0, &lcname_len); + } + if (zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) { + tmp.op_type = IS_CONST; + tmp.u.constant = **ns; + zval_copy_ctor(&tmp.u.constant); + len += 2; + Z_UNILEN(class_name->u.constant) -= len; + if (Z_TYPE(class_name->u.constant) == IS_UNICODE) { + memmove(Z_USTRVAL(class_name->u.constant), Z_USTRVAL(class_name->u.constant)+len, UBYTES(Z_USTRLEN(class_name->u.constant)+1)); + } else { + memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1); + } + zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC); + *class_name = tmp; + } + efree(lcname.v); + } + } else if (CG(current_import) || CG(current_namespace)) { + lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len); + + if (CG(current_import) && + zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) { + zval_dtor(&class_name->u.constant); + class_name->u.constant = **ns; + zval_copy_ctor(&class_name->u.constant); + } else if (CG(current_namespace)) { + zend_class_entry **pce; + + if (zend_u_hash_find(CG(class_table), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&pce) == SUCCESS && + (*pce)->type == ZEND_INTERNAL_CLASS) { + *fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK; + } + tmp.op_type = IS_CONST; + tmp.u.constant = *CG(current_namespace); + zval_copy_ctor(&tmp.u.constant); + zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC); + *class_name = tmp; + } + efree(lcname.v); + } +} void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) { @@ -1550,16 +1663,18 @@ void zend_do_fetch_class(znode *result, opline->extended_value = fetch_type; zval_dtor(&class_name->u.constant); break; - default: + default: { + zend_resolve_class_name(class_name, &opline->extended_value TSRMLS_CC); opline->op2 = *class_name; break; + } } } else { opline->op2 = *class_name; } opline->result.u.var = get_temporary_variable(CG(active_op_array)); opline->result.u.EA.type = opline->extended_value; - opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */ + opline->result.op_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */ *result = opline->result; } @@ -1592,11 +1707,26 @@ void zend_do_fetch_class_name(znode *res void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) { + znode class_node; unsigned char *ptr = NULL; - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - + zend_op *opline; + ulong fetch_type; + + if (class_name->op_type == IS_CONST && + method_name->op_type == IS_CONST && + ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant))) { + fetch_type = ZEND_FETCH_CLASS_GLOBAL; + zend_resolve_class_name(class_name, &fetch_type TSRMLS_CC); + class_node = *class_name; + fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK; + } else { + zend_do_fetch_class(&class_node, class_name TSRMLS_CC); + fetch_type = 0; + } + opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_INIT_STATIC_METHOD_CALL; - opline->op1 = *class_name; + opline->extended_value = fetch_type; + opline->op1 = class_node; opline->op2 = *method_name; if (opline->op2.op_type == IS_CONST) { @@ -1914,11 +2044,15 @@ void zend_do_try(znode *try_token TSRMLS } -void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC) +void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) { - long catch_op_number = get_next_op_number(CG(active_op_array)); + long catch_op_number; zend_op *opline; + znode catch_class; + zend_do_fetch_class(&catch_class, class_name TSRMLS_CC); + + catch_op_number = get_next_op_number(CG(active_op_array)); if (catch_op_number > 0) { opline = &CG(active_op_array)->opcodes[catch_op_number-1]; if (opline->opcode == ZEND_FETCH_CLASS) { @@ -1926,9 +2060,13 @@ void zend_do_begin_catch(znode *try_toke } } + if (first_catch) { + first_catch->u.opline_num = catch_op_number; + } + opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_CATCH; - opline->op1 = *catch_class; + opline->op1 = catch_class; /* SET_UNUSED(opline->op1); */ /* FIXME: Define IS_CLASS or something like that */ opline->op2 = *catch_var; opline->op1.u.EA.type = 0; /* 1 means it's the last catch in the block */ @@ -2955,6 +3093,17 @@ void zend_do_begin_class_declaration(zno zend_error(E_COMPILE_ERROR, "Cannot use '%R' as class name as it is reserved", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant)); } + if (CG(current_namespace)) { + znode tmp; + + tmp.u.constant = *CG(current_namespace); + zval_copy_ctor(&tmp.u.constant); + zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC); + class_name = &tmp; + efree(lcname.v); + lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len); + } + new_class_entry = emalloc(sizeof(zend_class_entry)); new_class_entry->type = ZEND_USER_CLASS; new_class_entry->name = Z_UNIVAL(class_name->u.constant); @@ -3072,11 +3221,13 @@ void zend_do_end_class_declaration(znode } -void zend_do_implements_interface(znode *interface_znode TSRMLS_DC) +void zend_do_implements_interface(znode *interface_name TSRMLS_DC) { + znode interface_node; zend_op *opline; - switch (interface_znode->u.EA.type) { + zend_do_fetch_class(&interface_node, interface_name TSRMLS_CC); + switch (interface_node.u.EA.type) { case ZEND_FETCH_CLASS_SELF: zend_error(E_COMPILE_ERROR, "Cannot use 'self' as interface name as it is reserved"); break; @@ -3096,7 +3247,7 @@ void zend_do_implements_interface(znode opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_ADD_INTERFACE; opline->op1 = CG(implementing_class); - opline->op2 = *interface_znode; + opline->op2 = interface_node; opline->extended_value = CG(active_class_entry)->num_interfaces++; } @@ -3480,13 +3631,18 @@ void zend_do_fetch_constant(znode *resul case ZEND_RT: if (constant_container || !zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_op *opline; + znode class_node; + if (constant_container) { + zend_do_fetch_class(&class_node, constant_container TSRMLS_CC); + } + opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_FETCH_CONSTANT; opline->result.op_type = IS_TMP_VAR; opline->result.u.var = get_temporary_variable(CG(active_op_array)); if (constant_container) { - opline->op1 = *constant_container; + opline->op1 = class_node; } else { SET_UNUSED(opline->op1); } @@ -4647,6 +4803,128 @@ void zend_release_labels(TSRMLS_D) } } +void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC) +{ + int len; + + if (prefix) { + *result = *prefix; + } else { + result->op_type = IS_CONST; + Z_TYPE(result->u.constant) = ZEND_STR_TYPE; + Z_UNIVAL(result->u.constant) = NULL_ZSTR; + Z_UNILEN(result->u.constant) = 0; + } + len = Z_UNILEN(result->u.constant) + 2 + Z_UNILEN(name->u.constant); + if (UG(unicode)) { + Z_USTRVAL(result->u.constant) = eurealloc(Z_USTRVAL(result->u.constant), len + 1); + Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)] = ':'; + Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)+1] = ':'; + memcpy(Z_USTRVAL(result->u.constant)+Z_USTRLEN(result->u.constant)+2, + Z_USTRVAL(name->u.constant), + UBYTES(Z_USTRLEN(name->u.constant)+1)); + } else { + Z_USTRVAL(result->u.constant) = erealloc(Z_STRVAL(result->u.constant), len + 1); + Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)] = ':'; + Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)+1] = ':'; + memcpy(Z_STRVAL(result->u.constant)+Z_STRLEN(result->u.constant)+2, + Z_STRVAL(name->u.constant), + Z_USTRLEN(name->u.constant)+1); + } + Z_UNILEN(result->u.constant) = len; + zval_dtor(&name->u.constant); +} + +void zend_do_namespace(znode *name TSRMLS_DC) +{ + unsigned int lcname_len; + zstr lcname; + + if (CG(active_op_array)->last > 0) { + zend_error(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script"); + } + if (CG(current_namespace)) { + zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice"); + } + lcname = zend_u_str_case_fold(Z_TYPE(name->u.constant), Z_UNIVAL(name->u.constant), Z_UNILEN(name->u.constant), 0, &lcname_len); + if (((lcname_len == sizeof("self")-1) && + ZEND_U_EQUAL(Z_TYPE(name->u.constant), lcname, lcname_len, "self", sizeof("self")-1)) || + ((lcname_len == sizeof("parent")-1) && + ZEND_U_EQUAL(Z_TYPE(name->u.constant), lcname, lcname_len, "parent", sizeof("parent")-1))) { + zend_error(E_COMPILE_ERROR, "Cannot use '%R' as namespace name", Z_TYPE(name->u.constant), Z_UNIVAL(name->u.constant)); + } + efree(lcname.v); + + ALLOC_ZVAL(CG(current_namespace)); + *CG(current_namespace) = name->u.constant; +} + +void zend_do_import(znode *ns_name, znode *new_name TSRMLS_DC) +{ + unsigned int lcname_len; + zstr lcname; + zval *name, *ns, tmp; + + if (!CG(current_import)) { + CG(current_import) = emalloc(sizeof(HashTable)); + zend_u_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode)); + } + + ALLOC_ZVAL(ns); + *ns = ns_name->u.constant; + if (new_name) { + name = &new_name->u.constant; + } else { + name = &tmp; + if (UG(unicode)) { + UChar *p = u_memrchr(Z_USTRVAL_P(ns), ':', Z_USTRLEN_P(ns)); + if (p) { + ZVAL_UNICODE(name, p+1, 1); + } else { + *name = *ns; + zval_copy_ctor(name); + } + } else { + char *p = zend_memrchr(Z_STRVAL_P(ns), ':', Z_STRLEN_P(ns)); + if (p) { + ZVAL_STRING(name, p+1, 1); + } else { + *name = *ns; + zval_copy_ctor(name); + } + } + } + + lcname = zend_u_str_case_fold(Z_TYPE_P(name), Z_UNIVAL_P(name), Z_UNILEN_P(name), 0, &lcname_len); + + if (((lcname_len == sizeof("self")-1) && + ZEND_U_EQUAL(Z_TYPE_P(name), lcname, lcname_len, "self", sizeof("self")-1)) || + ((lcname_len == sizeof("parent")-1) && + ZEND_U_EQUAL(Z_TYPE_P(name), lcname, lcname_len, "parent", sizeof("parent")-1))) { + zend_error(E_COMPILE_ERROR, "Cannot use '%R' as import name", Z_TYPE_P(name), Z_UNIVAL_P(name)); + } + + if (zend_u_hash_add(CG(current_import), Z_TYPE_P(name), lcname, lcname_len+1, &ns, sizeof(zval*), NULL) != SUCCESS) { + zend_error(E_COMPILE_ERROR, "Cannot reuse import name"); + } + efree(lcname.v); + zval_dtor(name); +} + +void zend_do_end_compilation(TSRMLS_D) +{ + if (CG(current_namespace)) { + zval_dtor(CG(current_namespace)); + efree(CG(current_namespace)); + CG(current_namespace) = NULL; + } + if (CG(current_import)) { + zend_hash_destroy(CG(current_import)); + efree(CG(current_import)); + CG(current_import) = NULL; + } +} + /* * Local variables: * tab-width: 4 Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.359 diff -u -p -d -r1.359 zend_compile.h --- Zend/zend_compile.h 28 Jun 2007 20:19:58 -0000 1.359 +++ Zend/zend_compile.h 3 Jul 2007 08:30:46 -0000 @@ -411,7 +411,7 @@ int zend_do_verify_access_types(znode *c void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC); void zend_do_end_function_declaration(znode *function_token TSRMLS_DC); void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, znode *varname, zend_bool pass_by_reference TSRMLS_DC); -int zend_do_begin_function_call(znode *function_name TSRMLS_DC); +int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC); void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC); void zend_do_clone(znode *result, znode *expr TSRMLS_DC); void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC); @@ -423,7 +423,7 @@ void zend_do_return(znode *expr, int do_ void zend_do_handle_exception(TSRMLS_D); void zend_do_try(znode *try_token TSRMLS_DC); -void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC); +void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, znode *first_catch TSRMLS_DC); void zend_do_end_catch(znode *try_token TSRMLS_DC); void zend_do_throw(znode *expr TSRMLS_DC); @@ -519,6 +519,11 @@ void zend_do_ticks(TSRMLS_D); void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC); +void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC); +void zend_do_namespace(znode *name TSRMLS_DC); +void zend_do_import(znode *name, znode *new_name TSRMLS_DC); +void zend_do_end_compilation(TSRMLS_D); + ZEND_API void function_add_ref(zend_function *function TSRMLS_DC); void zend_do_normalization(znode *result, znode *str TSRMLS_DC); @@ -628,6 +633,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_CLASS_INTERFACE 6 #define ZEND_FETCH_CLASS_FLAGS 0xF0 #define ZEND_FETCH_CLASS_NO_NORMALIZE 0x10 +#define ZEND_FETCH_CLASS_RT_NS_CHECK 0x20 #define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80 /* variable parsing type (compile-time) */ Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.405 diff -u -p -d -r1.405 zend_execute_API.c --- Zend/zend_execute_API.c 27 Jun 2007 11:16:21 -0000 1.405 +++ Zend/zend_execute_API.c 3 Jul 2007 08:30:47 -0000 @@ -1116,7 +1116,7 @@ ZEND_API int zend_u_lookup_class_ex(zend zval *retval_ptr = NULL; int retval; unsigned int lc_name_len; - zstr lc_name; + zstr lc_name, lc_free; zval *exception; char dummy = 1; zend_fcall_info fcall_info; @@ -1127,15 +1127,26 @@ ZEND_API int zend_u_lookup_class_ex(zend } if (do_normalize) { - lc_name = zend_u_str_case_fold(type, name, name_length, 1, &lc_name_len); + lc_free = lc_name = zend_u_str_case_fold(type, name, name_length, 1, &lc_name_len); } else { lc_name = name; lc_name_len = name_length; } + if (type == IS_UNICODE && + lc_name.u[0] == ':' && + lc_name.u[1] == ':') { + lc_name.u += 2; + lc_name_len -= 2; + } else if (type == IS_STRING && + lc_name.s[0] == ':' && + lc_name.s[1] == ':') { + lc_name.s += 2; + lc_name_len -= 2; + } if (zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len+1, (void **) ce) == SUCCESS) { if (do_normalize) { - efree(lc_name.v); + efree(lc_free.v); } return SUCCESS; } @@ -1145,7 +1156,7 @@ ZEND_API int zend_u_lookup_class_ex(zend */ if (!use_autoload || zend_is_compiling(TSRMLS_C)) { if (do_normalize) { - efree(lc_name.v); + efree(lc_free.v); } return FAILURE; } @@ -1157,7 +1168,7 @@ ZEND_API int zend_u_lookup_class_ex(zend if (zend_u_hash_add(EG(in_autoload), type, lc_name, lc_name_len+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) { if (do_normalize) { - efree(lc_name.v); + efree(lc_free.v); } return FAILURE; } @@ -1201,14 +1212,14 @@ ZEND_API int zend_u_lookup_class_ex(zend if (retval == FAILURE) { EG(exception) = exception; if (do_normalize) { - efree(lc_name.v); + efree(lc_free.v); } return FAILURE; } if (EG(exception) && exception) { if (do_normalize) { - efree(lc_name.v); + efree(lc_free.v); } zend_error(E_ERROR, "Function %s(%R) threw an exception of type '%v'", ZEND_AUTOLOAD_FUNC_NAME, type, name, Z_OBJCE_P(EG(exception))->name); return FAILURE; @@ -1222,7 +1233,7 @@ ZEND_API int zend_u_lookup_class_ex(zend retval = zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len + 1, (void **) ce); if (do_normalize) { - efree(lc_name.v); + efree(lc_free.v); } return retval; } @@ -1621,6 +1632,7 @@ ZEND_API zend_class_entry *zend_u_fetch_ zend_class_entry **pce; int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) ? 0 : 1; int do_normalize = (fetch_type & ZEND_FETCH_CLASS_NO_NORMALIZE) ? 0 : 1; + int rt_ns_check = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK) ? 1 : 0; zstr lcname = class_name; fetch_type = fetch_type & ~ZEND_FETCH_CLASS_FLAGS; @@ -1657,6 +1669,36 @@ check_fetch_type: } if (zend_u_lookup_class_ex(type, lcname, class_name_len, use_autoload, do_normalize, &pce TSRMLS_CC)==FAILURE) { + if (rt_ns_check) { + /* Check if we have internal class with the same name */ + zstr php_name; + + if (type == IS_UNICODE) { + php_name.u = u_memrchr(lcname.u, ':', class_name_len); + if (php_name.u) { + php_name.u++; + if (zend_u_lookup_class_ex(type, php_name, class_name_len-(php_name.u-lcname.u), 0, do_normalize, &pce TSRMLS_CC)==SUCCESS && + (*pce)->type == ZEND_INTERNAL_CLASS) { + if (lcname.v != class_name.v) { + efree(lcname.v); + } + return *pce; + } + } + } else { + php_name.s = zend_memrchr(lcname.s, ':', class_name_len); + if (php_name.s) { + php_name.s++; + if (zend_u_lookup_class_ex(type, php_name, class_name_len-(php_name.s-lcname.s), 0, do_normalize, &pce TSRMLS_CC)==SUCCESS && + (*pce)->type == ZEND_INTERNAL_CLASS) { + if (lcname.v != class_name.v) { + efree(lcname.v); + } + return *pce; + } + } + } + } if (use_autoload) { if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { zend_error(E_ERROR, "Interface '%R' not found", type, class_name); Index: Zend/zend_globals.h =================================================================== RCS file: /repository/ZendEngine2/zend_globals.h,v retrieving revision 1.167 diff -u -p -d -r1.167 zend_globals.h --- Zend/zend_globals.h 16 Feb 2007 19:36:45 -0000 1.167 +++ Zend/zend_globals.h 3 Jul 2007 08:30:47 -0000 @@ -138,6 +138,9 @@ struct _zend_compiler_globals { HashTable *labels; zend_stack labels_stack; + zval *current_namespace; + HashTable *current_import; + #ifdef ZTS HashTable **static_members; int last_static_member; Index: Zend/zend_language_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_language_parser.y,v retrieving revision 1.184 diff -u -p -d -r1.184 zend_language_parser.y --- Zend/zend_language_parser.y 28 Jun 2007 00:01:57 -0000 1.184 +++ Zend/zend_language_parser.y 3 Jul 2007 08:30:48 -0000 @@ -146,11 +146,14 @@ %token T_PAAMAYIM_NEKUDOTAYIM %token T_BINARY_DOUBLE %token T_BINARY_HEREDOC +%token T_NAMESPACE +%token T_IMPORT +%token T_NS_C %% /* Rules */ start: - top_statement_list + top_statement_list { zend_do_end_compilation(TSRMLS_C); } ; top_statement_list: @@ -158,12 +161,19 @@ top_statement_list: | /* empty */ ; +namespace_name: + T_STRING { $$ = $1; } + | namespace_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); } +; top_statement: statement | function_declaration_statement { zend_do_early_binding(TSRMLS_C); } | class_declaration_statement { zend_do_early_binding(TSRMLS_C); } - | T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; } + | T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; } + | T_NAMESPACE namespace_name ';' { zend_do_namespace(&$2 TSRMLS_CC); } + | T_IMPORT namespace_name ';' { zend_do_import(&$2, NULL TSRMLS_CC); } + | T_IMPORT namespace_name T_AS T_STRING ';' { zend_do_import(&$2, &$4 TSRMLS_CC); } ; @@ -229,7 +239,7 @@ unticked_statement: | T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}' T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); } fully_qualified_class_name { zend_do_first_catch(&$7 TSRMLS_CC); } - T_VARIABLE ')' { zend_do_begin_catch(&$1, &$9, &$11, 1 TSRMLS_CC); } + T_VARIABLE ')' { zend_do_begin_catch(&$1, &$9, &$11, &$7 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } additional_catches { zend_do_mark_last_catch(&$7, &$18 TSRMLS_CC); } | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); } @@ -249,7 +259,7 @@ non_empty_additional_catches: additional_catch: - T_CATCH '(' fully_qualified_class_name { $$.u.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } + T_CATCH '(' fully_qualified_class_name { $$.u.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } ; @@ -312,7 +322,7 @@ class_entry_type: extends_from: /* empty */ { $$.op_type = IS_UNUSED; } - | T_EXTENDS fully_qualified_class_name { $$ = $2; } + | T_EXTENDS fully_qualified_class_name { zend_do_fetch_class(&$$, &$2 TSRMLS_CC); } ; interface_entry: @@ -630,9 +640,12 @@ expr_without_variable: ; function_call: - T_STRING '(' { $2.u.opline_num = zend_do_begin_function_call(&$1 TSRMLS_CC); } + T_STRING '(' { $2.u.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } + | T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $3.u.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); } + function_call_parameter_list + ')' { zend_do_end_function_call(&$2, &$$, &$5, 0, $3.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} @@ -645,11 +658,14 @@ function_call: ; fully_qualified_class_name: - T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } + T_STRING { $$ = $1; } + | T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, NULL, &$2 TSRMLS_CC); } + | fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); } ; + class_name_reference: - T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } + fully_qualified_class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } | dynamic_class_name_reference { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } ; @@ -694,6 +710,7 @@ common_scalar: | T_CLASS_C { $$ = $1; } | T_METHOD_C { $$ = $1; } | T_FUNC_C { $$ = $1; } + | T_NS_C { $$ = $1; } ; Index: Zend/zend_language_scanner.l =================================================================== RCS file: /repository/ZendEngine2/zend_language_scanner.l,v retrieving revision 1.166 diff -u -p -d -r1.166 zend_language_scanner.l --- Zend/zend_language_scanner.l 24 May 2007 08:56:50 -0000 1.166 +++ Zend/zend_language_scanner.l 3 Jul 2007 08:30:50 -0000 @@ -1699,6 +1699,14 @@ HEREDOC_CHARS ("{"*([^$\n\r\\{]|(" return T_REQUIRE_ONCE; } +"namespace" { + return T_NAMESPACE; +} + +"import" { + return T_IMPORT; +} + "use" { return T_USE; } @@ -2072,6 +2080,16 @@ HEREDOC_CHARS ("{"*([^$\n\r\\{]|(" return T_FILE; } +"__NAMESPACE__" { + if (CG(current_namespace)) { + *zendlval = *CG(current_namespace); + zval_copy_ctor(zendlval); + } else { + ZVAL_EMPTY_TEXT(zendlval); + } + return T_NS_C; +} + (([^<]|"<"[^?%s<]){1,400})|"op1.u.var).class_entry; + if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } if(OP2_TYPE != IS_UNUSED) { zstr function_name_strval; unsigned int function_name_strlen; @@ -1869,10 +1907,38 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_N function_name_strval = Z_UNIVAL_P(function_name); function_name_strlen = Z_UNILEN_P(function_name); - lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + if (OP2_TYPE != IS_CONST && + ((Z_TYPE_P(function_name) == IS_UNICODE && + Z_USTRVAL_P(function_name)[0] == ':' && + Z_USTRVAL_P(function_name)[1] == ':') || + (Z_TYPE_P(function_name) == IS_STRING && + Z_STRVAL_P(function_name)[0] == ':' && + Z_STRVAL_P(function_name)[1] == ':'))) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } + } else { + lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + } if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) { efree(lcname.v); - zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + + if (OP2_TYPE == IS_CONST && opline->op1.op_type == IS_CONST) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } + if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE || + function->type != ZEND_INTERNAL_FUNCTION) { + efree(lcname.v); + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } + } else { + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } } efree(lcname.v); @@ -2638,7 +2704,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|T ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, CONST|UNUSED, CONST) +ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED, CONST) { zend_op *opline = EX(opline); zend_class_entry *ce = NULL; Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.173 diff -u -p -d -r1.173 zend_vm_execute.h --- Zend/zend_vm_execute.h 18 Jun 2007 11:20:01 -0000 1.173 +++ Zend/zend_vm_execute.h 3 Jul 2007 08:31:04 -0000 @@ -667,69 +667,6 @@ static int ZEND_FETCH_CLASS_SPEC_CONST_H ZEND_VM_NEXT_OPCODE(); } -static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_op *opline = EX(opline); - zval *function_name; - zend_class_entry *ce; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); - - ce = EX_T(opline->op1.u.var).class_entry; - if(IS_CONST != IS_UNUSED) { - zstr function_name_strval; - unsigned int function_name_strlen; - zend_bool is_const = (IS_CONST == IS_CONST); - - - if (is_const) { - function_name_strval = Z_UNIVAL(opline->op2.u.constant); - function_name_strlen = Z_UNILEN(opline->op2.u.constant); - } else { - function_name = &opline->op2.u.constant; - - if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); - } - - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); - - if (!is_const) { - efree(function_name_strval.v); - - } - } else { - if(!ce->constructor) { - zend_error_noreturn(E_ERROR, "Can not call constructor"); - } - if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); - } - EX(fbc) = ce->constructor; - } - - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; - } else { - if (IS_CONST != IS_UNUSED && - EG(This) && - Z_OBJ_HT_P(EG(This))->get_class_entry && - !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); - - } - if ((EX(object) = EG(This))) { - EX(object)->refcount++; - } - } - - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -753,10 +690,38 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_ function_name_strval = Z_UNIVAL_P(function_name); function_name_strlen = Z_UNILEN_P(function_name); - lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + if (IS_CONST != IS_CONST && + ((Z_TYPE_P(function_name) == IS_UNICODE && + Z_USTRVAL_P(function_name)[0] == ':' && + Z_USTRVAL_P(function_name)[1] == ':') || + (Z_TYPE_P(function_name) == IS_STRING && + Z_STRVAL_P(function_name)[0] == ':' && + Z_STRVAL_P(function_name)[1] == ':'))) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } + } else { + lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + } if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) { efree(lcname.v); - zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + + if (IS_CONST == IS_CONST && opline->op1.op_type == IS_CONST) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } + if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE || + function->type != ZEND_INTERNAL_FUNCTION) { + efree(lcname.v); + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } + } else { + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } } efree(lcname.v); @@ -888,69 +853,6 @@ static int ZEND_FETCH_CLASS_SPEC_TMP_HAN ZEND_VM_NEXT_OPCODE(); } -static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_op *opline = EX(opline); - zval *function_name; - zend_class_entry *ce; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); - - ce = EX_T(opline->op1.u.var).class_entry; - if(IS_TMP_VAR != IS_UNUSED) { - zstr function_name_strval; - unsigned int function_name_strlen; - zend_bool is_const = (IS_TMP_VAR == IS_CONST); - zend_free_op free_op2; - - if (is_const) { - function_name_strval = Z_UNIVAL(opline->op2.u.constant); - function_name_strlen = Z_UNILEN(opline->op2.u.constant); - } else { - function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - - if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); - } - - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); - - if (!is_const) { - efree(function_name_strval.v); - zval_dtor(free_op2.var); - } - } else { - if(!ce->constructor) { - zend_error_noreturn(E_ERROR, "Can not call constructor"); - } - if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); - } - EX(fbc) = ce->constructor; - } - - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; - } else { - if (IS_TMP_VAR != IS_UNUSED && - EG(This) && - Z_OBJ_HT_P(EG(This))->get_class_entry && - !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); - - } - if ((EX(object) = EG(This))) { - EX(object)->refcount++; - } - } - - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -974,10 +876,38 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_ function_name_strval = Z_UNIVAL_P(function_name); function_name_strlen = Z_UNILEN_P(function_name); - lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + if (IS_TMP_VAR != IS_CONST && + ((Z_TYPE_P(function_name) == IS_UNICODE && + Z_USTRVAL_P(function_name)[0] == ':' && + Z_USTRVAL_P(function_name)[1] == ':') || + (Z_TYPE_P(function_name) == IS_STRING && + Z_STRVAL_P(function_name)[0] == ':' && + Z_STRVAL_P(function_name)[1] == ':'))) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } + } else { + lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + } if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) { efree(lcname.v); - zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + + if (IS_TMP_VAR == IS_CONST && opline->op1.op_type == IS_CONST) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } + if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE || + function->type != ZEND_INTERNAL_FUNCTION) { + efree(lcname.v); + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } + } else { + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } } efree(lcname.v); @@ -1024,69 +954,6 @@ static int ZEND_FETCH_CLASS_SPEC_VAR_HAN ZEND_VM_NEXT_OPCODE(); } -static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_op *opline = EX(opline); - zval *function_name; - zend_class_entry *ce; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); - - ce = EX_T(opline->op1.u.var).class_entry; - if(IS_VAR != IS_UNUSED) { - zstr function_name_strval; - unsigned int function_name_strlen; - zend_bool is_const = (IS_VAR == IS_CONST); - zend_free_op free_op2; - - if (is_const) { - function_name_strval = Z_UNIVAL(opline->op2.u.constant); - function_name_strlen = Z_UNILEN(opline->op2.u.constant); - } else { - function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - - if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); - } - - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); - - if (!is_const) { - efree(function_name_strval.v); - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - } - } else { - if(!ce->constructor) { - zend_error_noreturn(E_ERROR, "Can not call constructor"); - } - if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); - } - EX(fbc) = ce->constructor; - } - - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; - } else { - if (IS_VAR != IS_UNUSED && - EG(This) && - Z_OBJ_HT_P(EG(This))->get_class_entry && - !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); - - } - if ((EX(object) = EG(This))) { - EX(object)->refcount++; - } - } - - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -1110,10 +977,38 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_ function_name_strval = Z_UNIVAL_P(function_name); function_name_strlen = Z_UNILEN_P(function_name); - lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + if (IS_VAR != IS_CONST && + ((Z_TYPE_P(function_name) == IS_UNICODE && + Z_USTRVAL_P(function_name)[0] == ':' && + Z_USTRVAL_P(function_name)[1] == ':') || + (Z_TYPE_P(function_name) == IS_STRING && + Z_STRVAL_P(function_name)[0] == ':' && + Z_STRVAL_P(function_name)[1] == ':'))) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } + } else { + lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + } if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) { efree(lcname.v); - zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + + if (IS_VAR == IS_CONST && opline->op1.op_type == IS_CONST) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } + if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE || + function->type != ZEND_INTERNAL_FUNCTION) { + efree(lcname.v); + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } + } else { + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } } efree(lcname.v); @@ -1159,69 +1054,6 @@ static int ZEND_FETCH_CLASS_SPEC_UNUSED_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_op *opline = EX(opline); - zval *function_name; - zend_class_entry *ce; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); - - ce = EX_T(opline->op1.u.var).class_entry; - if(IS_UNUSED != IS_UNUSED) { - zstr function_name_strval; - unsigned int function_name_strlen; - zend_bool is_const = (IS_UNUSED == IS_CONST); - - - if (is_const) { - function_name_strval = Z_UNIVAL(opline->op2.u.constant); - function_name_strlen = Z_UNILEN(opline->op2.u.constant); - } else { - function_name = NULL; - - if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); - } - - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); - - if (!is_const) { - efree(function_name_strval.v); - - } - } else { - if(!ce->constructor) { - zend_error_noreturn(E_ERROR, "Can not call constructor"); - } - if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); - } - EX(fbc) = ce->constructor; - } - - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; - } else { - if (IS_UNUSED != IS_UNUSED && - EG(This) && - Z_OBJ_HT_P(EG(This))->get_class_entry && - !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); - - } - if ((EX(object) = EG(This))) { - EX(object)->refcount++; - } - } - - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -1252,69 +1084,6 @@ static int ZEND_FETCH_CLASS_SPEC_CV_HAND ZEND_VM_NEXT_OPCODE(); } -static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_op *opline = EX(opline); - zval *function_name; - zend_class_entry *ce; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); - - ce = EX_T(opline->op1.u.var).class_entry; - if(IS_CV != IS_UNUSED) { - zstr function_name_strval; - unsigned int function_name_strlen; - zend_bool is_const = (IS_CV == IS_CONST); - - - if (is_const) { - function_name_strval = Z_UNIVAL(opline->op2.u.constant); - function_name_strlen = Z_UNILEN(opline->op2.u.constant); - } else { - function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - - if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { - zend_error_noreturn(E_ERROR, "Function name must be a string"); - } - function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); - } - - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); - - if (!is_const) { - efree(function_name_strval.v); - - } - } else { - if(!ce->constructor) { - zend_error_noreturn(E_ERROR, "Can not call constructor"); - } - if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); - } - EX(fbc) = ce->constructor; - } - - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; - } else { - if (IS_CV != IS_UNUSED && - EG(This) && - Z_OBJ_HT_P(EG(This))->get_class_entry && - !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); - - } - if ((EX(object) = EG(This))) { - EX(object)->refcount++; - } - } - - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -1338,10 +1107,38 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_ function_name_strval = Z_UNIVAL_P(function_name); function_name_strlen = Z_UNILEN_P(function_name); - lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + if (IS_CV != IS_CONST && + ((Z_TYPE_P(function_name) == IS_UNICODE && + Z_USTRVAL_P(function_name)[0] == ':' && + Z_USTRVAL_P(function_name)[1] == ':') || + (Z_TYPE_P(function_name) == IS_STRING && + Z_STRVAL_P(function_name)[0] == ':' && + Z_STRVAL_P(function_name)[1] == ':'))) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+2), function_name_strlen-2, 1, &lcname_len); + } + } else { + lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), function_name_strlen, 1, &lcname_len); + } if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) { efree(lcname.v); - zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + + if (IS_CV == IS_CONST && opline->op1.op_type == IS_CONST) { + if (Z_TYPE_P(function_name) == IS_UNICODE) { + lcname = zend_u_str_case_fold(IS_UNICODE, (zstr)(Z_USTRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } else { + lcname = zend_u_str_case_fold(IS_STRING, (zstr)(Z_STRVAL_P(function_name)+Z_LVAL(opline->op1.u.constant)), function_name_strlen-Z_LVAL(opline->op1.u.constant), 1, &lcname_len); + } + if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE || + function->type != ZEND_INTERNAL_FUNCTION) { + efree(lcname.v); + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } + } else { + zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval); + } } efree(lcname.v); @@ -2692,6 +2489,107 @@ static int ZEND_FETCH_DIM_TMP_VAR_SPEC_C ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_CONST != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_CONST == IS_CONST); + + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = &opline->op2.u.constant; + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_CONST != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -2723,53 +2621,6 @@ static int ZEND_CASE_SPEC_CONST_CONST_HA ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_op *opline = EX(opline); - zend_class_entry *ce = NULL; - zval **value; - - if (IS_CONST == IS_UNUSED) { -/* This seems to be a reminant of namespaces - if (EG(scope)) { - ce = EG(scope); - if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } - } -*/ - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL TSRMLS_CC)) { - zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), - Z_UNIVAL(opline->op2.u.constant)); - EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - } - ZEND_VM_NEXT_OPCODE(); - } - - ce = EX_T(opline->op1.u.var).class_entry; - - if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zend_class_entry *old_scope = EG(scope); - - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); - } - - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -3098,6 +2949,107 @@ static int ZEND_BOOL_XOR_SPEC_CONST_TMP_ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_CONST == IS_CONST && IS_TMP_VAR == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_TMP_VAR != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_TMP_VAR == IS_CONST); + zend_free_op free_op2; + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + zval_dtor(free_op2.var); + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_TMP_VAR != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_CASE_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -3458,6 +3410,107 @@ static int ZEND_BOOL_XOR_SPEC_CONST_VAR_ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_CONST == IS_CONST && IS_VAR == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_VAR != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_VAR == IS_CONST); + zend_free_op free_op2; + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_VAR != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_CASE_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -3584,6 +3637,107 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_VA } } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_CONST == IS_CONST && IS_UNUSED == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_UNUSED != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_UNUSED == IS_CONST); + + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = NULL; + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_UNUSED != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -3912,6 +4066,107 @@ static int ZEND_BOOL_XOR_SPEC_CONST_CV_H ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_CONST == IS_CONST && IS_CV == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_CV != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_CV == IS_CONST); + + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_CV != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -9676,6 +9931,107 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_VAR == IS_CONST && IS_CONST == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_CONST != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_CONST == IS_CONST); + + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = &opline->op2.u.constant; + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_CONST != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -9707,6 +10063,53 @@ static int ZEND_CASE_SPEC_VAR_CONST_HAND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_class_entry *ce = NULL; + zval **value; + + if (IS_VAR == IS_UNUSED) { +/* This seems to be a reminant of namespaces + if (EG(scope)) { + ce = EG(scope); + if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EX_T(opline->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } + } +*/ + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), + Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), + Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); + } + + ce = EX_T(opline->op1.u.var).class_entry; + + if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + EX_T(opline->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } else { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -11220,6 +11623,107 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_VAR == IS_CONST && IS_TMP_VAR == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_TMP_VAR != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_TMP_VAR == IS_CONST); + zend_free_op free_op2; + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + zval_dtor(free_op2.var); + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_TMP_VAR != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_CASE_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -12803,6 +13307,107 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_VAR == IS_CONST && IS_VAR == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_VAR != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_VAR == IS_CONST); + zend_free_op free_op2; + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_VAR != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_CASE_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -13584,6 +14189,107 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_UNUS ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_VAR == IS_CONST && IS_UNUSED == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_UNUSED != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_UNUSED == IS_CONST); + + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = NULL; + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_UNUSED != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -14817,6 +15523,107 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zval *function_name; + zend_class_entry *ce; + + zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + + if (IS_VAR == IS_CONST && IS_CV == IS_CONST) { + /* try a function in namespace */ + zstr fname, lcname; + unsigned int len, lcname_len; + + len = Z_UNILEN(opline->op1.u.constant) + 2 + Z_UNILEN(opline->op2.u.constant); + if (UG(unicode)) { + fname.u = eumalloc(len + 1); + memcpy(fname.u, Z_USTRVAL(opline->op1.u.constant), UBYTES(Z_USTRLEN(opline->op1.u.constant))); + fname.u[Z_USTRLEN(opline->op1.u.constant)] = ':'; + fname.u[Z_USTRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.u+Z_USTRLEN(opline->op1.u.constant)+2, + Z_USTRVAL(opline->op2.u.constant), + UBYTES(Z_USTRLEN(opline->op2.u.constant)+1)); + lcname = zend_u_str_case_fold(IS_UNICODE, fname, len, 1, &lcname_len); + } else { + fname.s = emalloc(len + 1); + memcpy(fname.s, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)); + fname.s[Z_STRLEN(opline->op1.u.constant)] = ':'; + fname.s[Z_STRLEN(opline->op1.u.constant)+1] = ':'; + memcpy(fname.s+Z_STRLEN(opline->op1.u.constant)+2, + Z_STRVAL(opline->op2.u.constant), + Z_STRLEN(opline->op2.u.constant)+1); + lcname = zend_u_str_case_fold(IS_STRING, fname, len, 1, &lcname_len); + } + efree(fname.v); + + if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, lcname, lcname_len+1, (void **) &EX(fbc))==SUCCESS) { + efree(lcname.v); + EX(object) = NULL; + ZEND_VM_NEXT_OPCODE(); + } + efree(lcname.v); + + /* no function found. try a static method in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + } else { + ce = EX_T(opline->op1.u.var).class_entry; + } + if(IS_CV != IS_UNUSED) { + zstr function_name_strval; + unsigned int function_name_strlen; + zend_bool is_const = (IS_CV == IS_CONST); + + + if (is_const) { + function_name_strval = Z_UNIVAL(opline->op2.u.constant); + function_name_strlen = Z_UNILEN(opline->op2.u.constant); + } else { + function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + + if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) { + zend_error_noreturn(E_ERROR, "Function name must be a string"); + } + function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen); + } + + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + + if (!is_const) { + efree(function_name_strval.v); + + } + } else { + if(!ce->constructor) { + zend_error_noreturn(E_ERROR, "Can not call constructor"); + } + if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_error(E_COMPILE_ERROR, "Cannot call private %v::__construct()", ce->name); + } + EX(fbc) = ce->constructor; + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (IS_CV != IS_UNUSED && + EG(This) && + Z_OBJ_HT_P(EG(This))->get_class_entry && + !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + zend_error(E_STRICT, "Non-static method %v::%v() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + + } + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_CASE_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -30195,7 +31002,6 @@ void zend_init_opcodes_handlers() ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -30206,6 +31012,7 @@ void zend_init_opcodes_handlers() ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -30545,31 +31352,31 @@ void zend_init_opcodes_handlers() ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER, ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER, ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,