]> granicus.if.org Git - php/commitdiff
Namespaces
authorDmitry Stogov <dmitry@php.net>
Thu, 12 Jul 2007 09:23:48 +0000 (09:23 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 12 Jul 2007 09:23:48 +0000 (09:23 +0000)
34 files changed:
NEWS
Zend/tests/ns_001.phpt [new file with mode: 0755]
Zend/tests/ns_002.phpt [new file with mode: 0755]
Zend/tests/ns_003.phpt [new file with mode: 0755]
Zend/tests/ns_004.phpt [new file with mode: 0755]
Zend/tests/ns_005.phpt [new file with mode: 0755]
Zend/tests/ns_006.phpt [new file with mode: 0755]
Zend/tests/ns_007.phpt [new file with mode: 0755]
Zend/tests/ns_008.phpt [new file with mode: 0755]
Zend/tests/ns_009.phpt [new file with mode: 0755]
Zend/tests/ns_011.phpt [new file with mode: 0755]
Zend/tests/ns_012.phpt [new file with mode: 0755]
Zend/tests/ns_013.phpt [new file with mode: 0755]
Zend/tests/ns_014.phpt [new file with mode: 0755]
Zend/tests/ns_015.phpt [new file with mode: 0755]
Zend/tests/ns_016.phpt [new file with mode: 0755]
Zend/tests/ns_017.phpt [new file with mode: 0755]
Zend/tests/ns_018.phpt [new file with mode: 0755]
Zend/tests/ns_019.phpt [new file with mode: 0755]
Zend/tests/ns_021.phpt [new file with mode: 0755]
Zend/tests/ns_022.phpt [new file with mode: 0755]
Zend/tests/ns_023.phpt [new file with mode: 0755]
Zend/tests/ns_024.phpt [new file with mode: 0755]
Zend/tests/ns_031.phpt [new file with mode: 0755]
Zend/tests/ns_032.phpt [new file with mode: 0755]
Zend/zend_API.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute_API.c
Zend/zend_globals.h
Zend/zend_language_parser.y
Zend/zend_language_scanner.l
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 82c9faa85c9088083e5de1e2ddf87c8a07ee5ff8..6a6ee68333ada3e173eb1724aad50ddd7c1de38f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 20??, PHP 6.0
 - Unicode support. (Andrei, Dmitry, et al)
+- Namespaces. (Dmitry, Stas)
 
 - Changed dl() to be disabled by default. Enabled only when explicitly 
   registered by the SAPI layer. Enabled only with CLI, CGI and EMBED. (Dmitry)
diff --git a/Zend/tests/ns_001.phpt b/Zend/tests/ns_001.phpt
new file mode 100755 (executable)
index 0000000..6821756
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+001: Class in namespace
+--FILE--
+<?php
+namespace test::ns1;
+
+class Foo {
+
+  function __construct() {
+    echo __CLASS__,"\n";
+  }
+  
+  function bar() {
+    echo __CLASS__,"\n";
+  }
+  
+  static function baz() {
+    echo __CLASS__,"\n";
+  }
+}
+
+$x = new Foo;
+$x->bar();
+Foo::baz();
+$y = new test::ns1::Foo;
+$y->bar();
+test::ns1::Foo::baz();
+--EXPECT--
+test::ns1::Foo
+test::ns1::Foo
+test::ns1::Foo
+test::ns1::Foo
+test::ns1::Foo
+test::ns1::Foo
diff --git a/Zend/tests/ns_002.phpt b/Zend/tests/ns_002.phpt
new file mode 100755 (executable)
index 0000000..4b17012
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+002: Import in namespace
+--FILE--
+<?php
+namespace test::ns1;
+
+class Foo {
+  static function bar() {
+    echo __CLASS__,"\n";
+  }
+}
+
+import test::ns1::Foo as Bar;
+import test::ns1 as ns2;
+import test::ns1;
+
+Foo::bar();
+test::ns1::Foo::bar();
+Bar::bar();
+ns2::Foo::bar();
+ns1::Foo::bar();
+--EXPECT--
+test::ns1::Foo
+test::ns1::Foo
+test::ns1::Foo
+test::ns1::Foo
+test::ns1::Foo
diff --git a/Zend/tests/ns_003.phpt b/Zend/tests/ns_003.phpt
new file mode 100755 (executable)
index 0000000..26c21a9
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+003: Name conflict (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+class Exception {
+}
+
+echo get_class(new Exception()),"\n";
+--EXPECT--
+test::ns1::Exception
diff --git a/Zend/tests/ns_004.phpt b/Zend/tests/ns_004.phpt
new file mode 100755 (executable)
index 0000000..2aa4a80
--- /dev/null
@@ -0,0 +1,9 @@
+--TEST--
+004: Name conflict (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+echo get_class(new Exception()),"\n";
+--EXPECT--
+Exception
diff --git a/Zend/tests/ns_005.phpt b/Zend/tests/ns_005.phpt
new file mode 100755 (executable)
index 0000000..fc1d657
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+005: Name conflict (php name in case if ns name exists)
+--FILE--
+<?php
+namespace test::ns1;
+
+class Exception {
+}
+
+echo get_class(new ::Exception()),"\n";
+--EXPECT--
+Exception
diff --git a/Zend/tests/ns_006.phpt b/Zend/tests/ns_006.phpt
new file mode 100755 (executable)
index 0000000..f402740
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+006: Run-time name conflict (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+class Exception {
+}
+
+$x = "test::ns1::Exception";
+echo get_class(new $x),"\n";
+--EXPECT--
+test::ns1::Exception
diff --git a/Zend/tests/ns_007.phpt b/Zend/tests/ns_007.phpt
new file mode 100755 (executable)
index 0000000..60ccced
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+007: Run-time name conflict (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+class Exception {
+}
+
+$x = "Exception";
+echo get_class(new $x),"\n";
+--EXPECT--
+Exception
diff --git a/Zend/tests/ns_008.phpt b/Zend/tests/ns_008.phpt
new file mode 100755 (executable)
index 0000000..1c0d116
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+008: __NAMESPACE__ constant and runtime names (ns name)
+--FILE--
+<?php
+namespace test;
+
+class foo {
+}
+
+$x = __NAMESPACE__ . "::foo"; 
+echo get_class(new $x),"\n";
+--EXPECT--
+test::foo
diff --git a/Zend/tests/ns_009.phpt b/Zend/tests/ns_009.phpt
new file mode 100755 (executable)
index 0000000..3d6aa22
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+009: __NAMESPACE__ constant and runtime names (php name)
+--FILE--
+<?php
+class foo {
+}
+
+$x = __NAMESPACE__ . "::foo"; 
+echo get_class(new $x),"\n";
+--EXPECT--
+foo
diff --git a/Zend/tests/ns_011.phpt b/Zend/tests/ns_011.phpt
new file mode 100755 (executable)
index 0000000..c1d9ac3
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+011: Function in namespace
+--FILE--
+<?php
+namespace test::ns1;
+
+function foo() {
+  echo __FUNCTION__,"\n";
+}
+  
+foo();
+test::ns1::foo();
+bar();
+test::ns1::bar();
+
+function bar() {
+  echo __FUNCTION__,"\n";
+}
+
+--EXPECT--
+test::ns1::foo
+test::ns1::foo
+test::ns1::bar
+test::ns1::bar
diff --git a/Zend/tests/ns_012.phpt b/Zend/tests/ns_012.phpt
new file mode 100755 (executable)
index 0000000..aa50661
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+012: Import in namespace and functions
+--FILE--
+<?php
+namespace test::ns1;
+
+function foo() {
+  echo __FUNCTION__,"\n";
+}
+
+import test::ns1 as ns2;
+import test as ns3;
+
+foo();
+bar();
+test::ns1::foo();
+test::ns1::bar();
+ns2::foo();
+ns2::bar();
+ns3::ns1::foo();
+ns3::ns1::bar();
+
+function bar() {
+  echo __FUNCTION__,"\n";
+}
+
+--EXPECT--
+test::ns1::foo
+test::ns1::bar
+test::ns1::foo
+test::ns1::bar
+test::ns1::foo
+test::ns1::bar
+test::ns1::foo
+test::ns1::bar
diff --git a/Zend/tests/ns_013.phpt b/Zend/tests/ns_013.phpt
new file mode 100755 (executable)
index 0000000..945b6bc
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+013: Name conflict and functions (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+function strlen($x) {
+       return __FUNCTION__;
+}
+
+echo strlen("Hello"),"\n";
+--EXPECT--
+test::ns1::strlen
diff --git a/Zend/tests/ns_014.phpt b/Zend/tests/ns_014.phpt
new file mode 100755 (executable)
index 0000000..9614b48
--- /dev/null
@@ -0,0 +1,9 @@
+--TEST--
+014: Name conflict and functions (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+echo strlen("Hello"),"\n";
+--EXPECT--
+5
diff --git a/Zend/tests/ns_015.phpt b/Zend/tests/ns_015.phpt
new file mode 100755 (executable)
index 0000000..1ad05b9
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+015: Name conflict and functions (php name in case if ns name exists)
+--FILE--
+<?php
+namespace test::ns1;
+
+function strlen($x) {
+       return __FUNCTION__;
+}
+
+echo ::strlen("Hello"),"\n";
+--EXPECT--
+5
+
diff --git a/Zend/tests/ns_016.phpt b/Zend/tests/ns_016.phpt
new file mode 100755 (executable)
index 0000000..e278625
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+016: Run-time name conflict and functions (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+function strlen($x) {
+       return __FUNCTION__;
+}
+
+$x = "test::ns1::strlen";
+echo $x("Hello"),"\n";
+--EXPECT--
+test::ns1::strlen
diff --git a/Zend/tests/ns_017.phpt b/Zend/tests/ns_017.phpt
new file mode 100755 (executable)
index 0000000..15ff1ef
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+017: Run-time name conflict and functions (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+function strlen($x) {
+       return __FUNCTION__;
+}
+
+$x = "strlen";
+echo $x("Hello"),"\n";
+--EXPECT--
+5
\ No newline at end of file
diff --git a/Zend/tests/ns_018.phpt b/Zend/tests/ns_018.phpt
new file mode 100755 (executable)
index 0000000..be8b4b7
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+018: __NAMESPACE__ constant and runtime names (ns name)
+--FILE--
+<?php
+namespace test;
+
+function foo() {
+       return __FUNCTION__;
+}
+
+$x = __NAMESPACE__ . "::foo"; 
+echo $x(),"\n";
+--EXPECT--
+test::foo
diff --git a/Zend/tests/ns_019.phpt b/Zend/tests/ns_019.phpt
new file mode 100755 (executable)
index 0000000..c42e97e
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+019: __NAMESPACE__ constant and runtime names (php name)
+--FILE--
+<?php
+function foo() {
+       return __FUNCTION__;
+}
+
+$x = __NAMESPACE__ . "::foo"; 
+echo $x(),"\n";
+--EXPECT--
+foo
diff --git a/Zend/tests/ns_021.phpt b/Zend/tests/ns_021.phpt
new file mode 100755 (executable)
index 0000000..467241f
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+021: Name search priority (first look into namespace)
+--FILE--
+<?php
+namespace test;
+
+class Test {
+       static function foo() {
+               echo __CLASS__,"::",__FUNCTION__,"\n";
+       }
+}
+
+function foo() {
+       echo __FUNCTION__,"\n";
+}
+
+foo();
+test::foo();
+test::test::foo();
+--EXPECT--
+test::foo
+test::Test::foo
+test::Test::foo
diff --git a/Zend/tests/ns_022.phpt b/Zend/tests/ns_022.phpt
new file mode 100755 (executable)
index 0000000..292e08b
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+022: Name search priority (first look into import, then into current namespace and then for class)
+--FILE--
+<?php
+namespace a::b::c;
+
+import a::b::c as test;
+
+class Test {
+       static function foo() {
+               echo __CLASS__,"::",__FUNCTION__,"\n";
+       }
+}
+
+function foo() {
+       echo __FUNCTION__,"\n";
+}
+
+test::foo();
+test::test::foo();
+--EXPECT--
+a::b::c::foo
+a::b::c::Test::foo
diff --git a/Zend/tests/ns_023.phpt b/Zend/tests/ns_023.phpt
new file mode 100755 (executable)
index 0000000..4be9dc7
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+023: __NAMESPACE__ constant
+--FILE--
+<?php
+namespace test::foo;
+
+var_dump(__NAMESPACE__);
+--EXPECT--
+string(9) "test::foo"
+--UEXPECT--
+unicode(9) "test::foo"
diff --git a/Zend/tests/ns_024.phpt b/Zend/tests/ns_024.phpt
new file mode 100755 (executable)
index 0000000..6e4f8bb
--- /dev/null
@@ -0,0 +1,9 @@
+--TEST--
+024: __NAMESPACE__ constant out of namespace
+--FILE--
+<?php
+var_dump(__NAMESPACE__);
+--EXPECT--
+string(0) ""
+--UEXPECT--
+unicode(0) ""
diff --git a/Zend/tests/ns_031.phpt b/Zend/tests/ns_031.phpt
new file mode 100755 (executable)
index 0000000..3991c5a
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+031: Namespace support for user functions (ns name)
+--FILE--
+<?php
+namespace test;
+
+class Test {
+       static function foo() {
+               echo __CLASS__,"::",__FUNCTION__,"\n";
+       }
+}
+
+function foo() {
+       echo __FUNCTION__,"\n";
+}
+
+call_user_func(__NAMESPACE__."::foo");
+call_user_func(__NAMESPACE__."::test::foo");
+--EXPECT--
+test::foo
+test::Test::foo
diff --git a/Zend/tests/ns_032.phpt b/Zend/tests/ns_032.phpt
new file mode 100755 (executable)
index 0000000..86b24fc
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+032: Namespace support for user functions (php name)
+--FILE--
+<?php
+class Test {
+       static function foo() {
+               echo __CLASS__,"::",__FUNCTION__,"\n";
+       }
+}
+
+function foo() {
+       echo __FUNCTION__,"\n";
+}
+
+call_user_func(__NAMESPACE__."::foo");
+call_user_func(__NAMESPACE__."::test::foo");
+--EXPECT--
+foo
+Test::foo
index 20839caeff789aaa7412f44d6cffc1cc8eb09735..32edb49ee6eda3991a692bf9927b50756228ae89 100644 (file)
@@ -2594,14 +2594,36 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
        *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 f0b747e1fccbcd51c43eb557f7ee8b6904a4ba4f..50717a076ca6b686d35587a04435a99b1b42b30a 100644 (file)
@@ -164,6 +164,8 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
        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;
 }
 /* }}} */
 
@@ -437,13 +439,15 @@ void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {
 }
 /* }}} */
 
-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);
@@ -457,7 +461,7 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC) /*
                        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;
 
@@ -477,13 +481,13 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC) /*
                                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;
                }
        }
@@ -1238,13 +1242,24 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
        } 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));
@@ -1429,12 +1444,22 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
 }
 /* }}} */
 
-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);
@@ -1442,12 +1467,8 @@ int zend_do_begin_function_call(znode *function_name TSRMLS_DC) /* {{{ */
                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:        {
@@ -1535,12 +1556,106 @@ void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC) /* {{{
        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) /* {{{ */
 {
        long fetch_class_op_number;
@@ -1564,16 +1679,18 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
                                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;
 }
 /* }}} */
@@ -1607,11 +1724,26 @@ void zend_do_fetch_class_name(znode *result, znode *class_name_entry, znode *cla
 
 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) {
@@ -1932,11 +2064,15 @@ 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 *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) {
@@ -1944,9 +2080,13 @@ void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var,
                }
        }
 
+       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 */
@@ -2974,6 +3114,17 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
                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);
@@ -3091,11 +3242,13 @@ void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRML
 }
 /* }}} */
 
-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;
@@ -3115,7 +3268,7 @@ void zend_do_implements_interface(znode *interface_znode TSRMLS_DC) /* {{{ */
        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++;
 }
 /* }}} */
@@ -3506,13 +3659,18 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
                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);
                                }
@@ -4686,6 +4844,132 @@ 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 fa22d61867297a8008778e0934f309adb0652c93..69fd1571ea11adf9af3f39a0319b01d0437c9ab5 100644 (file)
@@ -411,7 +411,7 @@ int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier)
 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_end_vparse TSRMLS_DC);
 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 ad8c2fdc44461b39e9d1bc178e8d982103abde57..4001d8424f78a2480663a74936a6313b1faf0320 100644 (file)
@@ -1123,7 +1123,7 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
        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;
@@ -1134,15 +1134,26 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
        }
 
        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;
        }
@@ -1152,7 +1163,7 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
        */
        if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
                if (do_normalize) {
-                       efree(lc_name.v);
+                       efree(lc_free.v);
                }
                return FAILURE;
        }
@@ -1164,7 +1175,7 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
 
        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;
        }
@@ -1208,14 +1219,14 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
        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;
@@ -1229,7 +1240,7 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
 
        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;
 }
@@ -1636,6 +1647,7 @@ ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, zstr class_name,
        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;
@@ -1672,6 +1684,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 40e096c73e13cc8005bc0fd4b48a620607d9afa4..95b5ea94f8f3cce5d04ee0a4679064c75383444c 100644 (file)
@@ -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 6846384078dfd76d16b066ba807f07d2121d5677..392e6325d1225381b4a14f45f36b785b9bcef904 100644 (file)
 %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 e252411c13b4be7bb399e1286a9de2f1f8d9c0de..e3704f9fa94fef3825fd6db44a72423137454e78 100644 (file)
@@ -1699,6 +1699,14 @@ HEREDOC_CHARS       ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({
        return T_REQUIRE_ONCE;
 }
 
+<ST_IN_SCRIPTING>"namespace" {
+       return T_NAMESPACE;
+}
+
+<ST_IN_SCRIPTING>"import" {
+       return T_IMPORT;
+}
+
 <ST_IN_SCRIPTING>"use" {
        return T_USE;
 }
@@ -2072,6 +2080,16 @@ HEREDOC_CHARS       ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({
        return T_FILE;
 }
 
+<ST_IN_SCRIPTING>"__NAMESPACE__" {
+       if (CG(current_namespace)) {
+               *zendlval = *CG(current_namespace);
+               zval_copy_ctor(zendlval);
+       } else {
+               ZVAL_EMPTY_TEXT(zendlval);
+       }
+       return T_NS_C;
+}
+
 <INITIAL>(([^<]|"<"[^?%s<]){1,400})|"<s"|"<" {
        Z_STRVAL_P(zendlval) = (char *) estrndup(yytext, yyleng);
        Z_STRLEN_P(zendlval) = yyleng;
index 05b307a9f05ec0062a16554d34210122001a0710..4de0975de45d01a258ee4f59a58a1ed901037fcb 100644 (file)
@@ -1783,7 +1783,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
        ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV)
+ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUSED|CV)
 {
        zend_op *opline = EX(opline);
        zval *function_name;
@@ -1791,7 +1791,45 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV)
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
 
-       ce = EX_T(opline->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_NAME, ANY, CONST|TMP|VAR|CV)
        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|TMP|VAR|UNUSED|CV, ANY)
        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 704f2efb3a2fc7aee88d7189c85daadeb83610f0..1b7d0c55155267fda12084c9b4ac5560c1913adf 100644 (file)
@@ -667,69 +667,6 @@ static int ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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);
@@ -2688,7 +2485,108 @@ static int ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
                SELECTIVE_PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &opline->result);
 
        }
-       AI_USE_PTR(EX_T(opline->result.u.var).var);
+       AI_USE_PTR(EX_T(opline->result.u.var).var);
+       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();
 }
 
@@ -2723,53 +2621,6 @@ static int ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        }
 }
 
+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_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
        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_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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);
@@ -11191,32 +11594,133 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        zend_error_noreturn(E_ERROR, "Object does not support method calls");
                }
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
-               if (!EX(fbc)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
+               /* First, locate the function. */
+               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
+               if (!EX(fbc)) {
+                       zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
+               }
+       } else {
+               zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
+       }
+
+       if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+               EX(object) = NULL;
+       } else {
+               if (!PZVAL_IS_REF(EX(object))) {
+                       EX(object)->refcount++; /* For $this pointer */
+               } else {
+                       zval *this_ptr;
+                       ALLOC_ZVAL(this_ptr);
+                       INIT_PZVAL_COPY(this_ptr, EX(object));
+                       zval_copy_ctor(this_ptr);
+                       EX(object) = this_ptr;
+               }
+       }
+
+       zval_dtor(free_op2.var);
+       if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+
+       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 {
-               zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
+               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 (!PZVAL_IS_REF(EX(object))) {
-                       EX(object)->refcount++; /* For $this pointer */
-               } else {
-                       zval *this_ptr;
-                       ALLOC_ZVAL(this_ptr);
-                       INIT_PZVAL_COPY(this_ptr, EX(object));
-                       zval_copy_ctor(this_ptr);
-                       EX(object) = this_ptr;
+               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++;
                }
        }
 
-       zval_dtor(free_op2.var);
-       if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
-
        ZEND_VM_NEXT_OPCODE();
 }
 
@@ -12803,6 +13307,107 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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,