]> granicus.if.org Git - php/commitdiff
Namespaces
authorDmitry Stogov <dmitry@php.net>
Fri, 28 Sep 2007 19:52:53 +0000 (19:52 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 28 Sep 2007 19:52:53 +0000 (19:52 +0000)
72 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_010.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_020.phpt [new file with mode: 0755]
Zend/tests/ns_021.phpt [new file with mode: 0755]
Zend/tests/ns_022.inc [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_025.phpt [new file with mode: 0755]
Zend/tests/ns_026.phpt [new file with mode: 0755]
Zend/tests/ns_027.inc [new file with mode: 0755]
Zend/tests/ns_027.phpt [new file with mode: 0755]
Zend/tests/ns_028.inc [new file with mode: 0755]
Zend/tests/ns_028.phpt [new file with mode: 0755]
Zend/tests/ns_029.phpt [new file with mode: 0755]
Zend/tests/ns_030.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/tests/ns_033.phpt [new file with mode: 0755]
Zend/tests/ns_034.phpt [new file with mode: 0755]
Zend/tests/ns_035.phpt [new file with mode: 0755]
Zend/tests/ns_036.phpt [new file with mode: 0755]
Zend/tests/ns_037.phpt [new file with mode: 0755]
Zend/tests/ns_038.phpt [new file with mode: 0755]
Zend/tests/ns_039.phpt [new file with mode: 0644]
Zend/tests/ns_040.phpt [new file with mode: 0644]
Zend/tests/ns_041.phpt [new file with mode: 0644]
Zend/tests/ns_042.phpt [new file with mode: 0644]
Zend/tests/ns_043.phpt [new file with mode: 0644]
Zend/tests/ns_044.phpt [new file with mode: 0644]
Zend/tests/ns_045.phpt [new file with mode: 0644]
Zend/tests/ns_046.phpt [new file with mode: 0644]
Zend/tests/ns_047.phpt [new file with mode: 0644]
Zend/tests/ns_048.phpt [new file with mode: 0644]
Zend/tests/ns_049.phpt [new file with mode: 0644]
Zend/tests/ns_050.phpt [new file with mode: 0644]
Zend/tests/ns_051.phpt [new file with mode: 0644]
Zend/tests/ns_052.phpt [new file with mode: 0644]
Zend/tests/ns_053.phpt [new file with mode: 0644]
Zend/zend.h
Zend/zend_API.c
Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_constants.c
Zend/zend_constants.h
Zend/zend_execute_API.c
Zend/zend_globals.h
Zend/zend_language_parser.y
Zend/zend_language_scanner.l
Zend/zend_variables.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.h

diff --git a/NEWS b/NEWS
index 311d5219bdd7312be3c7c5c538e2df5e8f66a69e..c7b084d4f1ec435162bc06f3dd516d0d91411e5e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 20??, PHP 5.3.0
+- Added support for namespaces. (Dmitry, Stas)
 - Added support for dynamic access of static members using $foo::myFunc().
   (Etienne Kneuss)
 
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_010.phpt b/Zend/tests/ns_010.phpt
new file mode 100755 (executable)
index 0000000..7be99e4
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+010: Accesing internal namespace class
+--FILE--
+<?php
+namespace X;
+import X as Y;
+class Foo {    
+       const C = "const ok\n";
+       static $var = "var ok\n";
+       function __construct() {
+               echo "class ok\n";
+       }
+       static function bar() {
+               echo "method ok\n";
+       }
+}
+new Foo();
+new X::Foo();
+new Y::Foo();
+new ::X::Foo();
+Foo::bar();
+X::Foo::bar();
+Y::Foo::bar();
+::X::Foo::bar();
+echo Foo::C;
+echo X::Foo::C;
+echo Y::Foo::C;
+echo ::X::Foo::C;
+echo Foo::$var;
+echo X::Foo::$var;
+echo Y::Foo::$var;
+echo ::X::Foo::$var;
+--EXPECT--
+class ok
+class ok
+class ok
+class ok
+method ok
+method ok
+method ok
+method ok
+const ok
+const ok
+const ok
+const ok
+var ok
+var ok
+var ok
+var ok
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_020.phpt b/Zend/tests/ns_020.phpt
new file mode 100755 (executable)
index 0000000..32325e0
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+020: Accesing internal namespace function
+--FILE--
+<?php
+namespace X;
+import X as Y;
+function foo() {
+       echo __FUNCTION__,"\n";
+}
+foo();
+X::foo();
+Y::foo();
+::X::foo();
+--EXPECT--
+X::foo
+X::foo
+X::foo
+X::foo
diff --git a/Zend/tests/ns_021.phpt b/Zend/tests/ns_021.phpt
new file mode 100755 (executable)
index 0000000..01609bb
--- /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::foo
+test::Test::foo
diff --git a/Zend/tests/ns_022.inc b/Zend/tests/ns_022.inc
new file mode 100755 (executable)
index 0000000..be571fc
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+class Test {
+       static function foo() {
+               echo __CLASS__,"::",__FUNCTION__,"\n";
+       }
+}
diff --git a/Zend/tests/ns_022.phpt b/Zend/tests/ns_022.phpt
new file mode 100755 (executable)
index 0000000..f46a856
--- /dev/null
@@ -0,0 +1,19 @@
+--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;
+
+require "ns_022.inc";
+
+function foo() {
+       echo __FUNCTION__,"\n";
+}
+
+test::foo();
+::test::foo();
+--EXPECT--
+a::b::c::foo
+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_025.phpt b/Zend/tests/ns_025.phpt
new file mode 100755 (executable)
index 0000000..e5c8ab0
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+025: Name ambiguity (class name & part of namespace name)
+--FILE--
+<?php
+namespace Foo::Bar;
+
+class Foo {
+  function __construct() {
+       echo __CLASS__,"\n";
+  }
+  static function Bar() {
+       echo __CLASS__,"\n";
+  }
+}
+
+$x = new Foo;
+Foo::Bar();
+$x = new Foo::Bar::Foo;
+Foo::Bar::Foo::Bar();
+--EXPECT--
+Foo::Bar::Foo
+Foo::Bar::Foo
+Foo::Bar::Foo
+Foo::Bar::Foo
diff --git a/Zend/tests/ns_026.phpt b/Zend/tests/ns_026.phpt
new file mode 100755 (executable)
index 0000000..ad8654d
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+026: Name ambiguity (class name & namespace name)
+--FILE--
+<?php
+namespace Foo;
+
+class Foo {
+  function __construct() {
+       echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
+  }
+  static function Bar() {
+       echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
+  }
+}
+
+function Bar() {
+  echo "Func   - ".__FUNCTION__."\n";
+}
+
+$x = new Foo;
+Foo::Bar();
+$x = new Foo::Foo;
+Foo::Foo::Bar();
+::Foo::Bar();
+--EXPECT--
+Method - Foo::Foo::__construct
+Func   - Foo::Bar
+Method - Foo::Foo::__construct
+Method - Foo::Foo::Bar
+Func   - Foo::Bar
diff --git a/Zend/tests/ns_027.inc b/Zend/tests/ns_027.inc
new file mode 100755 (executable)
index 0000000..014bc40
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+namespace Foo::Bar;
+
+class Foo {
+  function __construct() {
+       echo __CLASS__,"\n";
+  }
+  static function Bar() {
+       echo __CLASS__,"\n";
+  }
+}
diff --git a/Zend/tests/ns_027.phpt b/Zend/tests/ns_027.phpt
new file mode 100755 (executable)
index 0000000..064d052
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+027: Name ambiguity (class name & part of extertnal namespace name)
+--FILE--
+<?php
+require "ns_027.inc";
+
+class Foo {
+  function __construct() {
+       echo __CLASS__,"\n";
+  }
+  static function Bar() {
+       echo __CLASS__,"\n";
+  }
+}
+
+$x = new Foo;
+Foo::Bar();
+$x = new Foo::Bar::Foo;
+Foo::Bar::Foo::Bar();
+--EXPECT--
+Foo
+Foo
+Foo::Bar::Foo
+Foo::Bar::Foo
diff --git a/Zend/tests/ns_028.inc b/Zend/tests/ns_028.inc
new file mode 100755 (executable)
index 0000000..5bd3ae7
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+namespace Foo;
+
+class Foo {
+  function __construct() {
+       echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
+  }
+  static function Bar() {
+       echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
+  }
+}
+
+function Bar() {
+  echo "Func   - ".__FUNCTION__."\n";
+}
diff --git a/Zend/tests/ns_028.phpt b/Zend/tests/ns_028.phpt
new file mode 100755 (executable)
index 0000000..1b34a59
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+028: Name ambiguity (class name & external namespace name)
+--FILE--
+<?php
+require "ns_028.inc";
+
+class Foo {
+  function __construct() {
+       echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
+  }
+  static function Bar() {
+       echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
+  }
+}
+
+$x = new Foo;
+Foo::Bar();
+$x = new Foo::Foo;
+Foo::Foo::Bar();
+::Foo::Bar();
+--EXPECT--
+Method - Foo::__construct
+Func   - Foo::Bar
+Method - Foo::Foo::__construct
+Method - Foo::Foo::Bar
+Func   - Foo::Bar
diff --git a/Zend/tests/ns_029.phpt b/Zend/tests/ns_029.phpt
new file mode 100755 (executable)
index 0000000..a76f4fa
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+029: Name ambiguity (class name & import name)
+--FILE--
+<?php
+import A::B as Foo;
+
+class Foo {
+}
+
+new Foo();
+--EXPECTF--
+Fatal error: Class name 'Foo' conflicts with import name in %sns_029.php on line 4
diff --git a/Zend/tests/ns_030.phpt b/Zend/tests/ns_030.phpt
new file mode 100755 (executable)
index 0000000..c87b293
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+030: Name ambiguity (import name & class name)
+--FILE--
+<?php
+class Foo {
+}
+
+import A::B as Foo;
+
+new Foo();
+--EXPECTF--
+Fatal error: Import name 'Foo' conflicts with defined class in %sns_030.php on line 5
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
diff --git a/Zend/tests/ns_033.phpt b/Zend/tests/ns_033.phpt
new file mode 100755 (executable)
index 0000000..bd0bebd
--- /dev/null
@@ -0,0 +1,8 @@
+--TEST--
+033: Import statement with non-compound name
+--FILE--
+<?php
+import A;
+--EXPECTF--
+Warning: The import statement with non-compound name 'A' has no effect in %sns_033.php on line 2
+
diff --git a/Zend/tests/ns_034.phpt b/Zend/tests/ns_034.phpt
new file mode 100755 (executable)
index 0000000..a0424a9
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--
+034: Support for namespaces in compile-time constant reference
+--FILE--
+<?php
+namespace A;
+import A as B;
+class Foo {
+       const C = "ok\n";
+}
+function f1($x=Foo::C) {
+       echo $x;
+}
+function f2($x=A::Foo::C) {
+       echo $x;
+}
+function f3($x=B::Foo::C) {
+       echo $x;
+}
+function f4($x=::A::Foo::C) {
+       echo $x;
+}
+echo Foo::C;
+echo A::Foo::C;
+echo B::Foo::C;
+echo ::A::Foo::C;
+f1();
+f2();
+f3();
+f4();
+--EXPECT--
+ok
+ok
+ok
+ok
+ok
+ok
+ok
+ok
diff --git a/Zend/tests/ns_035.phpt b/Zend/tests/ns_035.phpt
new file mode 100755 (executable)
index 0000000..259d17f
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+035: Name ambiguity in compile-time constant reference (php name)
+--SKIPIF--
+<?php if (!extension_loaded("spl")) die("skip SPL is no available"); ?>
+--FILE--
+<?php
+namespace A;
+function f1($x = ArrayObject::STD_PROP_LIST) {
+       var_dump($x);
+}
+function f2($x = ::ArrayObject::STD_PROP_LIST) {
+       var_dump($x);
+}
+var_dump(ArrayObject::STD_PROP_LIST);
+var_dump(::ArrayObject::STD_PROP_LIST);
+f1();
+f2();
+
+?>
+--EXPECT--
+int(1)
+int(1)
+int(1)
+int(1)
diff --git a/Zend/tests/ns_036.phpt b/Zend/tests/ns_036.phpt
new file mode 100755 (executable)
index 0000000..9825c8f
--- /dev/null
@@ -0,0 +1,48 @@
+--TEST--
+036: Name ambiguity in compile-time constant reference (ns name)
+--SKIPIF--
+<?php if (!extension_loaded("spl")) die("skip SPL is no available"); ?>
+--FILE--
+<?php
+namespace A;
+import A as B;
+class ArrayObject {
+       const STD_PROP_LIST = 2;
+}
+function f1($x = ArrayObject::STD_PROP_LIST) {
+       var_dump($x);
+}
+function f2($x = ::ArrayObject::STD_PROP_LIST) {
+       var_dump($x);
+}
+function f3($x = A::ArrayObject::STD_PROP_LIST) {
+       var_dump($x);
+}
+function f4($x = B::ArrayObject::STD_PROP_LIST) {
+       var_dump($x);
+}
+function f5($x = ::A::ArrayObject::STD_PROP_LIST) {
+       var_dump($x);
+}
+var_dump(ArrayObject::STD_PROP_LIST);
+var_dump(::ArrayObject::STD_PROP_LIST);
+var_dump(A::ArrayObject::STD_PROP_LIST);
+var_dump(B::ArrayObject::STD_PROP_LIST);
+var_dump(::A::ArrayObject::STD_PROP_LIST);
+f1();
+f2();
+f3();
+f4();
+f5();
+?>
+--EXPECT--
+int(2)
+int(1)
+int(2)
+int(2)
+int(2)
+int(2)
+int(1)
+int(2)
+int(2)
+int(2)
diff --git a/Zend/tests/ns_037.phpt b/Zend/tests/ns_037.phpt
new file mode 100755 (executable)
index 0000000..4e6c248
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+037: Name ambiguity (namespace name or namespace's class name)
+--FILE--
+<?php
+namespace X;
+import X as Y;
+class X {
+       const C = "const ok\n";
+       static $var = "var ok\n";
+       function __construct() {
+               echo "class ok\n";
+       }
+       static function bar() {
+               echo "method ok\n";
+       }
+}
+new X();
+new X::X();
+new Y::X();
+new ::X::X();
+X::bar();
+X::X::bar();
+Y::X::bar();
+::X::X::bar();
+echo X::C;
+echo X::X::C;
+echo Y::X::C;
+echo ::X::X::C;
+echo X::$var;
+echo X::X::$var;
+echo Y::X::$var;
+echo ::X::X::$var;
+--EXPECT--
+class ok
+class ok
+class ok
+class ok
+method ok
+method ok
+method ok
+method ok
+const ok
+const ok
+const ok
+const ok
+var ok
+var ok
+var ok
+var ok
diff --git a/Zend/tests/ns_038.phpt b/Zend/tests/ns_038.phpt
new file mode 100755 (executable)
index 0000000..fcaa3c4
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+038: Name ambiguity (namespace name or internal class name)
+--FILE--
+<?php
+namespace Exception;
+function foo() {
+  echo "ok\n";
+}
+Exception::foo();
+Exception::bar();
+--EXPECTF--
+ok
+
+Fatal error: Call to undefined method Exception::bar() in %sns_038.php on line 7
+
diff --git a/Zend/tests/ns_039.phpt b/Zend/tests/ns_039.phpt
new file mode 100644 (file)
index 0000000..95fae8f
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+039: Constant declaration
+--FILE--
+<?php
+const A = "ok";
+const B = A;
+const C = array("ok");
+const D = array(B);
+echo A . "\n";
+echo B . "\n";
+print_r(C);
+print_r(D);
+--EXPECT--
+ok
+ok
+Array
+(
+    [0] => ok
+)
+Array
+(
+    [0] => ok
+)
diff --git a/Zend/tests/ns_040.phpt b/Zend/tests/ns_040.phpt
new file mode 100644 (file)
index 0000000..11799f9
--- /dev/null
@@ -0,0 +1,68 @@
+--TEST--
+040: Constant declaration and usage in namespace
+--FILE--
+<?php
+namespace X;
+import X as Y;
+const A = "ok\n";
+const B = A;
+const C = array(A);
+const D = array("aaa"=>A);
+const E = array(A=>"aaa\n");
+function f1($x=A) {
+       echo $x;
+}
+function f2($x=X::A) {
+       echo $x;
+}
+function f3($x=Y::A) {
+       echo $x;
+}
+function f4($x=::X::A) {
+       echo $x;
+}
+function f5($x=B) {
+       echo $x;
+}
+function f6($x=array(A)) {
+       echo $x[0];
+}
+function f7($x=array("aaa"=>A)) {
+       echo $x["aaa"];
+}
+function f8($x=array(A=>"aaa\n")) {
+       echo $x["ok\n"];
+}
+echo A;
+echo X::A;
+echo Y::A;
+echo ::X::A;
+f1();
+f2();
+f3();
+f4();
+echo B;
+$x = C; echo $x[0];
+$x = D; echo $x["aaa"];
+$x = E; echo $x["ok\n"];
+f5();
+f6();
+f7();
+f8();
+--EXPECT--
+ok
+ok
+ok
+ok
+ok
+ok
+ok
+ok
+ok
+ok
+ok
+aaa
+ok
+ok
+ok
+aaa
diff --git a/Zend/tests/ns_041.phpt b/Zend/tests/ns_041.phpt
new file mode 100644 (file)
index 0000000..889f3d8
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+041: Constants in namespace
+--FILE--
+<?php
+namespace test::ns1;
+
+const FOO = "ok\n";
+  
+echo(FOO);
+echo(test::ns1::FOO);
+echo(::test::ns1::FOO);
+echo(BAR);
+
+const BAR = "ok\n";
+
+--EXPECTF--
+ok
+ok
+ok
+
+Notice: Use of undefined constant BAR - assumed 'BAR' in %sns_041.php on line 9
+BAR
diff --git a/Zend/tests/ns_042.phpt b/Zend/tests/ns_042.phpt
new file mode 100644 (file)
index 0000000..bda697b
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+042: Import in namespace and constants
+--FILE--
+<?php
+namespace test::ns1;
+
+const FOO = "ok\n";
+
+import test::ns1 as ns2;
+import test as ns3;
+
+echo FOO;
+echo test::ns1::FOO;
+echo ::test::ns1::FOO;
+echo ns2::FOO;
+echo ns3::ns1::FOO;
+--EXPECT--
+ok
+ok
+ok
+ok
+ok
diff --git a/Zend/tests/ns_043.phpt b/Zend/tests/ns_043.phpt
new file mode 100644 (file)
index 0000000..63bd05e
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+043: Name conflict and constants (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+const INI_ALL = 0;
+
+var_dump(INI_ALL);
+--EXPECT--
+int(0)
diff --git a/Zend/tests/ns_044.phpt b/Zend/tests/ns_044.phpt
new file mode 100644 (file)
index 0000000..d379b97
--- /dev/null
@@ -0,0 +1,9 @@
+--TEST--
+044: Name conflict and constants (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+var_dump(INI_ALL);
+--EXPECT--
+int(7)
diff --git a/Zend/tests/ns_045.phpt b/Zend/tests/ns_045.phpt
new file mode 100644 (file)
index 0000000..d8c9429
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+045: Name conflict and constants (php name in case if ns name exists)
+--FILE--
+<?php
+namespace test::ns1;
+
+const INI_ALL = 0;
+
+var_dump(::INI_ALL);
+--EXPECT--
+int(7)
diff --git a/Zend/tests/ns_046.phpt b/Zend/tests/ns_046.phpt
new file mode 100644 (file)
index 0000000..e48f0ce
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+046: Run-time name conflict and constants (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+const INI_ALL = 0;
+
+var_dump(constant("test::ns1::INI_ALL"));
+--EXPECT--
+int(0)
diff --git a/Zend/tests/ns_047.phpt b/Zend/tests/ns_047.phpt
new file mode 100644 (file)
index 0000000..89795da
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+047: Run-time name conflict and constants (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+const INI_ALL = 0;
+
+var_dump(constant("INI_ALL"));
+--EXPECT--
+int(7)
diff --git a/Zend/tests/ns_048.phpt b/Zend/tests/ns_048.phpt
new file mode 100644 (file)
index 0000000..3837643
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+048: __NAMESPACE__ constant and runtime names (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+const FOO = 0;
+
+var_dump(constant(__NAMESPACE__ . "::FOO"));
+--EXPECT--
+int(0)
diff --git a/Zend/tests/ns_049.phpt b/Zend/tests/ns_049.phpt
new file mode 100644 (file)
index 0000000..3e5ccc6
--- /dev/null
@@ -0,0 +1,9 @@
+--TEST--
+049: __NAMESPACE__ constant and runtime names (php name)
+--FILE--
+<?php
+const FOO = 0;
+
+var_dump(constant(__NAMESPACE__ . "::FOO"));
+--EXPECT--
+int(0)
diff --git a/Zend/tests/ns_050.phpt b/Zend/tests/ns_050.phpt
new file mode 100644 (file)
index 0000000..9171f6c
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+050: Name conflict and compile-time constants (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+const INI_ALL = 0;
+
+function foo($x = INI_ALL) {
+       var_dump($x);
+}
+foo();
+--EXPECT--
+int(0)
diff --git a/Zend/tests/ns_051.phpt b/Zend/tests/ns_051.phpt
new file mode 100644 (file)
index 0000000..07985ba
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+051: Name conflict and compile-time constants (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+function foo($x = INI_ALL) {
+       var_dump($x);
+}
+foo();
+--EXPECT--
+int(7)
diff --git a/Zend/tests/ns_052.phpt b/Zend/tests/ns_052.phpt
new file mode 100644 (file)
index 0000000..1f2c4a0
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+052: Name conflict and compile-time constants (php name in case if ns name exists)
+--FILE--
+<?php
+namespace test::ns1;
+
+const INI_ALL = 0;
+
+function foo($x = ::INI_ALL) {
+       var_dump($x);
+}
+foo();
+--EXPECT--
+int(7)
diff --git a/Zend/tests/ns_053.phpt b/Zend/tests/ns_053.phpt
new file mode 100644 (file)
index 0000000..8df545f
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+053: Run-time constant definition
+--FILE--
+<?php
+namespace test::ns1;
+
+define(__NAMESPACE__ . '::NAME', basename(__FILE__));
+echo NAME."\n";
+echo test::ns1::NAME."\n";
+--EXPECT--
+ns_053.php
+ns_053.php
+
index 921eaa1ec544ead31a79569d91c3783fedaf08bc..29f3aea1039b2dd540250d64db3bb12bfa12bf43 100644 (file)
@@ -422,7 +422,9 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
 #define IS_CONSTANT_ARRAY      9
 
 /* Ugly hack to support constants as static array indices */
-#define IS_CONSTANT_INDEX      0x80
+#define IS_CONSTANT_TYPE_MASK  0x0f
+#define IS_CONSTANT_RT_NS_CHECK        0x10
+#define IS_CONSTANT_INDEX              0x80
 
 
 /* overloaded elements data types */
index 87118406b3de7a20995e60a77a412a219ac54f2a..667b88cba34205ba757433aa8cd4bda54d95c090 100644 (file)
@@ -2143,19 +2143,40 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
        *ce_ptr = NULL;
        *fptr_ptr = NULL;
 
-       if ((colon = strstr(Z_STRVAL_P(callable), "::")) != NULL) {
+
+       if (!ce_org) {
+               /* Skip leading :: */
+               if (Z_STRVAL_P(callable)[0] == ':' &&
+                   Z_STRVAL_P(callable)[1] == ':') {
+                       mlen = Z_STRLEN_P(callable) - 2;
+                       lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + 2, mlen);
+               } else {
+                       mlen = Z_STRLEN_P(callable);
+                       lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
+               }
+               /* Check if function with given name exists.
+                  This may be a compound name that includes namespace name */
+               if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fptr) == SUCCESS) {
+                       *fptr_ptr = fptr;
+                       efree(lmname);
+                       return 1;
+               }
+               efree(lmname);
+       }
+
+       /* Split name into class/namespace and method/function names */
+       if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
+            colon > Z_STRVAL_P(callable) &&
+            *(colon-1) == ':') {
+               colon--;
                clen = colon - Z_STRVAL_P(callable);
                mlen = Z_STRLEN_P(callable) - clen - 2;
-               lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), clen);
-               /* caution: lcname is not '\0' terminated */
-               if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
-                       *ce_ptr = EG(scope);
-               } else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
-                       *ce_ptr = EG(scope) ? EG(scope)->parent : NULL;
-               } else if (zend_lookup_class(Z_STRVAL_P(callable), clen, &pce TSRMLS_CC) == SUCCESS) {
-                       *ce_ptr = *pce;
-               }
-               efree(lcname);
+               lmname = colon + 2;
+       }
+       if (colon != NULL) {
+               /* This is a compound name.
+                  Try to fetch class and then find static method. */
+               *ce_ptr = zend_fetch_class(Z_STRVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
                if (!*ce_ptr) {
                        return 0;
                }
@@ -2164,15 +2185,15 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
                        return 0;
                }
                lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + clen + 2, mlen);
-       } else {
+       } else if (ce_org) {
+               /* Try to fetch find static method of given class. */
                mlen = Z_STRLEN_P(callable);
-               lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
-               if (ce_org) {
-                       ftable = &ce_org->function_table;
-                       *ce_ptr = ce_org;
-               } else {
-                       ftable = EG(function_table);
-               }
+               lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
+               ftable = &ce_org->function_table;
+               *ce_ptr = ce_org;
+       } else {
+               /* We already checked for plain function before. */
+               return 0;
        }
 
        retval = zend_hash_find(ftable, lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0;
index 7341e84ab3897ab831bae62c140c733abf5ab2b9..d4ead902ba057f28193975b962498aea3469002c 100644 (file)
@@ -543,7 +543,7 @@ ZEND_FUNCTION(defined)
        }
        
        convert_to_string_ex(var);
-       if (zend_get_constant(Z_STRVAL_PP(var), Z_STRLEN_PP(var), &c TSRMLS_CC)) {
+       if (zend_get_constant_ex(Z_STRVAL_PP(var), Z_STRLEN_PP(var), &c, NULL, 0 TSRMLS_CC)) {
                zval_dtor(&c);
                RETURN_TRUE;
        } else {
@@ -744,7 +744,7 @@ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *re
 
                        /* this is necessary to make it able to work with default array 
                        * properties, returned to user */
-                       if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || Z_TYPE_P(prop_copy) == IS_CONSTANT) {
+                       if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
                                zval_update_constant(&prop_copy, 0 TSRMLS_CC);
                        }
 
index 2cf8264dc2c2b1e77277280f9751640823de4414..6924ea3976750874682c57fbed3700367da34e4a 100644 (file)
@@ -138,6 +138,8 @@ void zend_init_compiler_data_structures(TSRMLS_D)
        CG(handle_op_arrays) = 1;
        CG(in_compilation) = 0;
        CG(start_lineno) = 0;
+       CG(current_namespace) = NULL;
+       CG(current_import) = NULL;
        init_compiler_declarables(TSRMLS_C);
        zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
 
@@ -384,13 +386,15 @@ void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC)
        fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
 }
 
-void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
+void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC)
 {
+       znode class_node;
        zend_llist *fetch_list_ptr;
        zend_llist_element *le;
        zend_op *opline_ptr;
        zend_op opline;
 
+       zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
        if (result->op_type == IS_CV) {
                init_op(&opline TSRMLS_CC);
@@ -404,7 +408,7 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
                opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
                opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
                SET_UNUSED(opline.op2);
-               opline.op2 = *class_znode;
+               opline.op2 = class_node;
                opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
                *result = opline.result;
 
@@ -424,13 +428,13 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
                        opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
                        opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
                        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;
                }
        }
@@ -1170,6 +1174,19 @@ 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)) {
+                       /* Prefix function name with current namespcae name */
+                       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_STRVAL(tmp.u.constant);
+                       efree(lcname);
+                       name_len = Z_STRLEN(tmp.u.constant);
+                       lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
+               }
+
                opline->opcode = ZEND_DECLARE_FUNCTION;
                opline->op1.op_type = IS_CONST;
                build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
@@ -1328,14 +1345,31 @@ 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;
        char *lcname;
+       int prefix_len = 0;
+
+       if (check_namespace && CG(current_namespace)) {
+               /* We assume we call function from the current namespace
+                  if it is not prefixed. */
+               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;
+
+               /* In run-time PHP will check for function with full name and
+                  internal function with short name */
+               prefix_len = Z_STRLEN_P(CG(current_namespace)) + 2;
+       }
        
        lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
        if (zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) {
-               zend_do_begin_dynamic_function_call(function_name TSRMLS_CC);
+               zend_do_begin_dynamic_function_call(function_name, prefix_len TSRMLS_CC);
                efree(lcname);
                return 1; /* Dynamic */
        }
@@ -1408,7 +1442,7 @@ void zend_do_clone(znode *result, znode *expr TSRMLS_DC)
 }
 
 
-void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC)
+void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC)
 {
        unsigned char *ptr = NULL;
        zend_op *opline;
@@ -1418,12 +1452,98 @@ void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC)
        opline->op2 = *function_name;
        opline->extended_value = 0;
 
-       SET_UNUSED(opline->op1);
+       if (prefix_len) {
+               /* In run-time PHP will check for function with full name and
+                  internal function with short name */
+               opline->op1.op_type = IS_CONST;
+               ZVAL_LONG(&opline->op1.u.constant, prefix_len);
+       } else {
+               SET_UNUSED(opline->op1);
+       }
 
        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, int check_ns_name TSRMLS_DC)
+{
+       char *compound;
+       char *lcname;
+       zval **ns;
+       znode tmp;
+       int len;
+
+       compound = memchr(Z_STRVAL(class_name->u.constant), ':', Z_STRLEN(class_name->u.constant));
+       if (compound) {
+               /* This is a compound class name that cotains namespace prefix */
+               if (Z_TYPE(class_name->u.constant) == IS_STRING &&
+                   Z_STRVAL(class_name->u.constant)[0] == ':') {
+                   /* The STRING name has "::" prefix */
+                   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)) {
+                       len = compound - Z_STRVAL(class_name->u.constant);
+                       lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), len);
+                       /* Check if first part of compound name is an import name */
+                       if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
+                               /* Substitute import name */
+                               tmp.op_type = IS_CONST;
+                               tmp.u.constant = **ns;
+                               zval_copy_ctor(&tmp.u.constant);
+                               len += 2;
+                               Z_STRLEN(class_name->u.constant) -= len;
+                               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);
+               }
+       } else if (CG(current_import) || CG(current_namespace)) {
+               /* this is a plain name (without ::) */
+               lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
+
+               if (CG(current_import) &&
+                   zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns) == SUCCESS) {
+                   /* The given name is an import name. Substitute it. */
+                       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 (check_ns_name) {
+                               char *ns_lcname = zend_str_tolower_dup(Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
+
+                               if (Z_STRLEN_P(CG(current_namespace)) == Z_STRLEN(class_name->u.constant) &&
+                                   memcmp(lcname, ns_lcname, Z_STRLEN(class_name->u.constant)) == 0) {
+                                   /* The given name is equal to name of current namespace.
+                                      PHP will need to perform additional cheks at run-time to
+                                      determine if we assume namespace or class name. */
+                                       *fetch_type |= ZEND_FETCH_CLASS_RT_NS_NAME;
+                               }
+                               efree(ns_lcname);
+                       }
+
+                       if (zend_hash_find(CG(class_table), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&pce) == SUCCESS &&
+                           (*pce)->type == ZEND_INTERNAL_CLASS) {
+                           /* There is an internal class with the same name exists.
+                              PHP will need to perform additional cheks at run-time to
+                              determine if we assume class in current namespace or
+                              internal one. */
+                               *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);
+       }
+}
 
 void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
 {
@@ -1449,6 +1569,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
                                zval_dtor(&class_name->u.constant);
                                break;
                        default:
+                               zend_resolve_class_name(class_name, &opline->extended_value, 0 TSRMLS_CC);
                                opline->op2 = *class_name;
                                break;
                }
@@ -1457,7 +1578,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
        }
        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;
 }
 
@@ -1482,26 +1603,71 @@ 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);
-
-       opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
-       opline->op1 = *class_name;
-       opline->op2 = *method_name;
+       zend_op *opline;
+       ulong fetch_type = 0;
 
-       if (opline->op2.op_type == IS_CONST) {
-               char *lcname = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
-               if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(opline->op2.u.constant) &&
+       if (method_name->op_type == IS_CONST) {
+               char *lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
+               if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
                    memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
-                       zval_dtor(&opline->op2.u.constant);
-                       SET_UNUSED(opline->op2);
+                       zval_dtor(&method_name->u.constant);
+                       SET_UNUSED(*method_name);
                        efree(lcname);
                } else {
-                       efree(opline->op2.u.constant.value.str.val);
-                       opline->op2.u.constant.value.str.val = lcname;
+                       efree(Z_STRVAL(method_name->u.constant));
+                       Z_STRVAL(method_name->u.constant) = lcname;
                }
        }
 
+       if (class_name->op_type == IS_CONST &&
+               method_name->op_type == IS_CONST &&
+           ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
+               fetch_type = ZEND_FETCH_CLASS_GLOBAL;
+               zend_resolve_class_name(class_name, &fetch_type, 1 TSRMLS_CC);
+               class_node = *class_name;
+       } else {
+               zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
+       }
+       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+       opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
+       opline->extended_value = fetch_type & ~ZEND_FETCH_CLASS_RT_NS_NAME;
+       opline->op1 = class_node;
+       opline->op2 = *method_name;
+
+       if (class_node.op_type == IS_CONST &&
+               method_name->op_type == IS_CONST) {
+               /* Prebuild ns::func name to speedup run-time check.
+                  The additional names are stored in additional OP_DATA opcode. */
+               char *nsname, *fname;
+               unsigned int nsname_len, len;
+
+               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+               opline->opcode = ZEND_OP_DATA;
+               opline->op1.op_type = IS_CONST;
+               SET_UNUSED(opline->op2);
+
+               nsname = Z_STRVAL(class_node.u.constant);
+               nsname_len = Z_STRLEN(class_node.u.constant);
+               if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                       /* Remove namespace name */
+                       nsname = (char *)memchr(nsname, ':', nsname_len) + 2;
+                       nsname_len -= (nsname - Z_STRVAL(class_node.u.constant));
+               }
+               len = nsname_len + 2 + Z_STRLEN(method_name->u.constant);
+               fname = emalloc(len + 1);
+               memcpy(fname, nsname, nsname_len);
+               fname[nsname_len] = ':';
+               fname[nsname_len + 1] = ':';
+               memcpy(fname + nsname_len + 2,
+                       Z_STRVAL(method_name->u.constant),
+                       Z_STRLEN(method_name->u.constant)+1);
+               zend_str_tolower(fname, len);
+               opline->extended_value = zend_hash_func(fname, len + 1);
+               ZVAL_STRINGL(&opline->op1.u.constant, fname, len, 0);
+       }
+
        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
        zend_do_extended_fcall_begin(TSRMLS_C);
 }
@@ -1779,11 +1945,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) {
@@ -1791,9 +1961,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 */
@@ -2798,6 +2972,24 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
                zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
        }
 
+       /* Class name must not conflict with import names */
+       if (CG(current_import) &&
+           zend_hash_exists(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1)) {
+               zend_error(E_COMPILE_ERROR, "Class name '%s' conflicts with import name", Z_STRVAL(class_name->u.constant));
+       }
+
+       if (CG(current_namespace)) {
+               /* Prefix class name with name of 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);
+               lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
+       }
+
        new_class_entry = emalloc(sizeof(zend_class_entry));
        new_class_entry->type = ZEND_USER_CLASS;
        new_class_entry->name = class_name->u.constant.value.str.val;
@@ -2910,11 +3102,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;
@@ -2934,7 +3128,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++;
 }
 
@@ -3204,7 +3398,7 @@ void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_lis
        *result = CG(active_op_array)->opcodes[new_token->u.opline_num].result;
 }
 
-static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC)
+static zend_constant* zend_get_ct_const(zval *const_name TSRMLS_DC) /* {{{ */
 {
        zend_constant *c = NULL;
 
@@ -3213,14 +3407,27 @@ static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC)
                 
                if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)+1, (void **) &c)==SUCCESS) {
                        if ((c->flags & CONST_CS) && memcmp(c->name, Z_STRVAL_P(const_name), Z_STRLEN_P(const_name))!=0) {
-                               c = NULL;
+                               efree(lookup_name);
+                               return NULL;
                        }
                } else {
-                       c = NULL;
+                       efree(lookup_name);
+                       return NULL;
                }
                efree(lookup_name);
        }
-       if (c && (c->flags & CONST_CT_SUBST)) {
+       if (c->flags & CONST_CT_SUBST) {
+               return c;
+       }
+       return NULL;
+}
+/* }}} */
+
+static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC) /* {{{ */
+{
+       zend_constant *c = zend_get_ct_const(const_name TSRMLS_CC);
+
+       if (c) {
                zval_dtor(const_name);
                result->op_type = IS_CONST;
                result->u.constant = c->value;
@@ -3230,26 +3437,62 @@ static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC)
        }
        return 0;
 }
+/* }}} */
 
-void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC)
+void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */
 {
+       ulong fetch_type = 0;
+       znode tmp;
+
        switch (mode) {
                case ZEND_CT:
                        if (constant_container) {
+                           if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
+                                       zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
+                               }
                                zend_do_fetch_class_name(NULL, constant_container, constant_name TSRMLS_CC);
                                *result = *constant_container;
-                               result->u.constant.type = IS_CONSTANT;
+                               result->u.constant.type = IS_CONSTANT | fetch_type;
                        } else if (!zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) {
+                               if (check_namespace && CG(current_namespace)) {
+                                       /* We assume we use constant from the current namespace
+                                          if it is not prefixed. */
+                                       tmp.op_type = IS_CONST;
+                                       tmp.u.constant = *CG(current_namespace);
+                                       zval_copy_ctor(&tmp.u.constant);
+                                       zend_do_build_namespace_name(&tmp, &tmp, constant_name TSRMLS_CC);
+                                       *constant_name = tmp;
+                                       fetch_type = IS_CONSTANT_RT_NS_CHECK;
+                               }
                                *result = *constant_name;
-                               result->u.constant.type = IS_CONSTANT;
+                               result->u.constant.type = IS_CONSTANT | fetch_type;
                        }
                        break;
                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;
 
+                               if (constant_container) {
+                                   if (constant_container->op_type == IS_CONST &&
+                                       ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
+                                               zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
+                                       } else {
+                                               zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
+                                               constant_container = &tmp;
+                                       }
+                               } else if (check_namespace && CG(current_namespace)) {
+                                       /* We assume we use constant from the current namespace
+                                          if it is not prefixed. */
+                                       tmp.op_type = IS_CONST;
+                                       tmp.u.constant = *CG(current_namespace);
+                                       zval_copy_ctor(&tmp.u.constant);
+                                       constant_container = &tmp;
+                                       fetch_type = IS_CONSTANT_RT_NS_CHECK;
+                               }
+                               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                                opline->opcode = ZEND_FETCH_CONSTANT;
+                               opline->extended_value = fetch_type  & ~ZEND_FETCH_CLASS_RT_NS_NAME;
                                opline->result.op_type = IS_TMP_VAR;
                                opline->result.u.var = get_temporary_variable(CG(active_op_array));
                                if (constant_container) {
@@ -3259,6 +3502,35 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
                                }
                                opline->op2 = *constant_name;
                                *result = opline->result;
+
+                               if (opline->op1.op_type == IS_CONST) {
+                                       /* Prebuild ns::func name to speedup run-time check.
+                                          The additional names are stored in additional OP_DATA opcode. */
+                                       char *nsname;
+                                       unsigned int nsname_len;
+
+                                       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+                                       opline->opcode = ZEND_OP_DATA;
+                                       opline->op1.op_type = IS_CONST;
+                                       SET_UNUSED(opline->op2);
+
+                                       nsname = Z_STRVAL(constant_container->u.constant);
+                                       nsname_len = Z_STRLEN(constant_container->u.constant);
+                                       if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                                               /* Remove namespace name */
+                                               nsname = (char *)memchr(nsname, ':', nsname_len) + 2;
+                                               nsname_len -= (nsname - Z_STRVAL(constant_container->u.constant));
+                                       }
+
+                                       Z_TYPE(opline->op1.u.constant) = IS_STRING;
+                                       Z_STRVAL(opline->op1.u.constant) = emalloc(nsname_len + 2 + Z_STRLEN(constant_name->u.constant) + 1);
+                                       zend_str_tolower_copy(Z_STRVAL(opline->op1.u.constant), nsname, nsname_len);
+                                       Z_STRVAL(opline->op1.u.constant)[nsname_len] = ':';
+                                       Z_STRVAL(opline->op1.u.constant)[nsname_len+1] = ':';
+                                       memcpy(Z_STRVAL(opline->op1.u.constant)+nsname_len+2, Z_STRVAL(constant_name->u.constant), Z_STRLEN(constant_name->u.constant) + 1);
+                                       Z_STRLEN(opline->op1.u.constant) = nsname_len + 2 + Z_STRLEN(constant_name->u.constant);
+                                       opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
+                               }
                        }
                        break;
        }
@@ -3346,7 +3618,7 @@ void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr)
        ALLOC_ZVAL(element);
        *element = expr->u.constant;
        if (offset) {
-               switch (offset->u.constant.type) {
+               switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) {
                        case IS_CONSTANT:
                                /* Ugly hack to denote that this value has a constant index */
                                Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
@@ -4222,10 +4494,10 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
 int zend_get_class_fetch_type(const char *class_name, uint class_name_len)
 {
        if ((class_name_len == sizeof("self")-1) &&
-               !memcmp(class_name, "self", sizeof("self"))) {
+               !memcmp(class_name, "self", sizeof("self")-1)) {
                return ZEND_FETCH_CLASS_SELF;           
        } else if ((class_name_len == sizeof("parent")-1) &&
-               !memcmp(class_name, "parent", sizeof("parent"))) {
+               !memcmp(class_name, "parent", sizeof("parent")-1)) {
                return ZEND_FETCH_CLASS_PARENT;
        } else {
                return ZEND_FETCH_CLASS_DEFAULT;
@@ -4240,6 +4512,159 @@ ZEND_API char* zend_get_compiled_variable_name(zend_op_array *op_array, zend_uin
        return op_array->vars[var].name;
 }
 
+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) = IS_STRING;
+               Z_STRVAL(result->u.constant) = NULL;
+               Z_STRLEN(result->u.constant) = 0;
+       }
+       len = Z_STRLEN(result->u.constant) + 2 + Z_STRLEN(name->u.constant);
+       Z_STRVAL(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_STRLEN(name->u.constant)+1);
+       Z_STRLEN(result->u.constant) = len;
+       zval_dtor(&name->u.constant);
+}
+/* }}} */
+
+void zend_do_namespace(znode *name TSRMLS_DC) /* {{{ */
+{
+       char *lcname;
+
+       if (CG(active_op_array)->last > 0) {
+               /* ignore ZEND_EXT_STMT */
+               int num = CG(active_op_array)->last;
+               while (num > 0 &&
+                      CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT) {
+                       --num;
+               }
+               if (num > 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_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
+       if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
+             !memcmp(lcname, "self", sizeof("self")-1)) ||
+           ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
+          !memcmp(lcname, "parent", sizeof("parent")-1))) {
+               zend_error(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
+       }
+       efree(lcname);
+
+       ALLOC_ZVAL(CG(current_namespace));
+       *CG(current_namespace) = name->u.constant;
+}
+/* }}} */
+
+void zend_do_import(znode *ns_name, znode *new_name TSRMLS_DC) /* {{{ */
+{
+       char *lcname;
+       zval *name, *ns, tmp;
+       zend_bool warn = 0;
+
+       if (!CG(current_import)) {
+               CG(current_import) = emalloc(sizeof(HashTable));
+               zend_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0);
+       }
+
+       ALLOC_ZVAL(ns);
+       *ns = ns_name->u.constant;
+       if (new_name) {
+               name = &new_name->u.constant;
+       } else {
+               char *p;
+
+               /* The form "import A::B" is eqivalent to "import A::B as B".
+                  So we extract the last part of compound name ti use as a new_name */
+               name = &tmp;
+               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);
+                       warn = 1;
+               }
+       }
+
+       lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+
+       if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
+          !memcmp(lcname, "self", sizeof("self")-1)) ||
+           ((Z_STRLEN_P(name) == sizeof("parent")-1) &&
+          !memcmp(lcname, "parent", sizeof("parent")-1))) {
+               zend_error(E_COMPILE_ERROR, "Cannot use '%s' as import name", Z_STRVAL_P(name));
+       }
+
+       if (zend_hash_exists(CG(class_table), lcname, Z_STRLEN_P(name)+1)) {
+               zend_error(E_COMPILE_ERROR, "Import name '%s' conflicts with defined class", Z_STRVAL_P(name));
+       }
+
+       if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
+               zend_error(E_COMPILE_ERROR, "Cannot reuse import name");
+       }
+       if (warn) {
+               zend_error(E_WARNING, "The import statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
+       }
+       efree(lcname);
+       zval_dtor(name);
+}
+/* }}} */
+
+void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
+{
+       zend_op *opline;
+
+       if (zend_get_ct_const(&name->u.constant TSRMLS_CC)) {
+               zend_error(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
+       }
+
+       if (CG(current_namespace)) {
+               /* Prefix constant name with name of current namespace */
+               znode tmp;
+
+               tmp.op_type = IS_CONST;
+               tmp.u.constant = *CG(current_namespace);
+               Z_STRVAL(tmp.u.constant) = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), Z_STRLEN(tmp.u.constant));
+               zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC);
+               *name = tmp;
+       }
+
+       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+       opline->opcode = ZEND_DECLARE_CONST;
+       SET_UNUSED(opline->result);
+       opline->op1 = *name;
+       opline->op2 = *value;
+}
+/* }}} */
+
+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 cdb7a5ff01f3ef6bafd190e4ca16ea53b78a0601..b7321a1f52621e658c49b87d6bdc19accda12e88 100644 (file)
@@ -399,10 +399,10 @@ 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);
+void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC);
 void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC);
 void zend_do_fetch_class_name(znode *result, znode *class_entry, znode *class_name TSRMLS_DC);
 void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC);
@@ -411,7 +411,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);
 
@@ -458,7 +458,7 @@ void zend_do_pop_object(znode *object TSRMLS_DC);
 void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC);
 void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC);
 
-void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC);
+void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC);
 
 void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC);
 
@@ -504,6 +504,12 @@ void zend_do_ticks(TSRMLS_D);
 
 void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC);
 
+void zend_do_declare_constant(znode *name, znode *value 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);
 
 #define INITIAL_OP_ARRAY_SIZE 64
@@ -591,6 +597,8 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_FETCH_CLASS_GLOBAL                4
 #define ZEND_FETCH_CLASS_AUTO          5
 #define ZEND_FETCH_CLASS_INTERFACE     6
+#define ZEND_FETCH_CLASS_RT_NS_CHECK 0x20
+#define ZEND_FETCH_CLASS_RT_NS_NAME  0x40
 #define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
 
 /* variable parsing type (compile-time) */
index fba024ac44d12455794679c93ea3adbe0c02b4d5..13f9ba98486f4423595b2d41179546f3331fdedf 100644 (file)
@@ -213,21 +213,82 @@ ZEND_API void zend_register_string_constant(char *name, uint name_len, char *str
 }
 
 
-ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC)
+ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
 {
        zend_constant *c;
        int retval = 1;
        char *lookup_name;
+
+       if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
+               lookup_name = zend_str_tolower_dup(name, name_len);
+
+               if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
+                       if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len) != 0) {
+                               retval=0;
+                       }
+               } else {
+                       static char haltoff[] = "__COMPILER_HALT_OFFSET__";
+
+                       if (!EG(in_execution)) {
+                               retval = 0;
+                       } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
+                                 !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
+                               char *cfilename, *haltname;
+                               int len, clen;
+
+                               cfilename = zend_get_executed_filename(TSRMLS_C);
+                               clen = strlen(cfilename);
+                               /* check for __COMPILER_HALT_OFFSET__ */
+                               zend_mangle_property_name(&haltname, &len, haltoff,
+                                       sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
+                               if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
+                                       retval = 1;
+                               } else {
+                                       retval=0;
+                               }
+                               pefree(haltname, 0);
+                       } else {
+                               retval=0;
+                       }
+               }
+               efree(lookup_name);
+       }
+
+       if (retval) {
+               *result = c->value;
+               zval_copy_ctor(result);
+               result->refcount = 1;
+               result->is_ref = 0;
+       }
+
+       return retval;
+}
+
+ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
+{
+       zend_constant *c;
+       int retval = 1;
        char *colon;
 
-       if ((colon = memchr(name, ':', name_len)) && colon[1] == ':') {
-               /* class constant */
-               zend_class_entry **ce = NULL;
-               int class_name_len = colon-name;
+       /* Skip leading :: */
+       if (name[0] == ':' && name[1] == ':') {
+               name += 2;
+               name_len -= 2;
+               flags = 0;
+       }
+
+       
+       if ((colon = zend_memrchr(name, ':', name_len)) &&
+           colon > name && 
+           *(colon-1) == ':') {
+               /* compound constant name */
+               zend_class_entry *ce = NULL;
+               int class_name_len = colon - name - 1;
                int const_name_len = name_len - class_name_len - 2;
-               char *constant_name = colon+2;
+               char *constant_name = constant_name = colon + 1;
+               char *class_name = estrndup(name, class_name_len);
+               char *lcname = zend_str_tolower_dup(class_name, class_name_len);
                zval **ret_constant;
-               char *class_name;
 
                if (!scope) {
                        if (EG(in_execution)) {
@@ -236,42 +297,81 @@ ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_
                                scope = CG(active_class_entry);
                        }
                }
-       
-               class_name = estrndup(name, class_name_len);
 
-               if (class_name_len == sizeof("self")-1 && strcmp(class_name, "self") == 0) {
+               if (class_name_len == sizeof("self")-1 &&
+                   !memcmp(lcname, "self", sizeof("self")-1)) {
                        if (scope) {
-                               ce = &scope;
+                               ce = scope;
                        } else {
                                zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
                                retval = 0;
                        }
-               } else if (class_name_len == sizeof("parent")-1 && strcmp(class_name, "parent") == 0) {
-                       if (!scope) {            
+                       efree(lcname);
+               } else if (class_name_len == sizeof("parent")-1 &&
+                          !memcmp(lcname, "parent", sizeof("parent")-1)) {
+                       if (!scope) {
                                zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
-                       } else if (!scope->parent) {     
-                               zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");    
+                       } else if (!scope->parent) {
+                               zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
                        } else {
-                               ce = &scope->parent;
+                               ce = scope->parent;
                        }
+                       efree(lcname);
                } else {
-                       if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
-                               retval = 0;
+                       /* Check for namespace constant */
+                       char *nsname;
+                       unsigned int nsname_len;
+
+                       /* Concatenate lowercase namespace name and constant name */
+                       lcname = erealloc(lcname, class_name_len + 2 + const_name_len + 1);
+                       lcname[class_name_len] = ':';
+                       lcname[class_name_len+1] = ':';
+                       memcpy(lcname + class_name_len + 2, constant_name, const_name_len + 1);
+
+                       nsname = lcname;
+                       nsname_len = class_name_len + 2 + const_name_len;
+                       if (flags & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               nsname = (char *)memchr(nsname, ':', nsname_len) + 2;
+                               nsname_len -= (nsname - lcname);
+                       }
+
+                       if (zend_hash_find(EG(zend_constants), nsname, nsname_len+1, (void **) &c) == SUCCESS) {
+                               efree(lcname);
+                               efree(class_name);
+                               *result = c->value;
+                               zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
+                               zval_copy_ctor(result);
+                               result->refcount = 1;
+                               result->is_ref = 0;
+                               return 1;
                        }
+                       efree(lcname);
+
+                       /* Check for class */
+                       ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
                }
 
                if (retval && ce) {
-                       if (zend_hash_find(&((*ce)->constants_table), constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
+                       if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
                                retval = 0;
                        }
                } else {
-                       zend_error(E_ERROR, "Class '%s' not found", class_name);
+                       if ((flags & ZEND_FETCH_CLASS_RT_NS_NAME) == 0) {
+                               if ((flags & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                                       name = constant_name;
+                                       name_len = const_name_len;
+                                       efree(class_name);
+                                       retval = 1;
+                                       return zend_get_constant(name, name_len, result TSRMLS_CC);
+                               }
+                               zend_error(E_ERROR, "Class '%s' not found", class_name);
+                       }
                        retval = 0;
                }
                efree(class_name);
 
                if (retval) {
-                       zval_update_constant_ex(ret_constant, (void*)1, *ce TSRMLS_CC);
+                       zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
                        *result = **ret_constant;
                        zval_copy_ctor(result);
                }
@@ -279,52 +379,7 @@ ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_
                return retval;
        }
 
-       if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
-               lookup_name = estrndup(name, name_len);
-               zend_str_tolower(lookup_name, name_len);
-                
-               if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
-                       if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len)!=0) {
-                               retval=0;
-                       }
-               } else {
-                       char haltoff[] = "__COMPILER_HALT_OFFSET__";
-                       if (!EG(in_execution)) {
-                               retval = 0;
-                       } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(haltoff, name, name_len) == 0) {
-                               char *cfilename, *haltname;
-                               int len, clen;
-                               cfilename = zend_get_executed_filename(TSRMLS_C);
-                               clen = strlen(cfilename);
-                               /* check for __COMPILER_HALT_OFFSET__ */
-                               zend_mangle_property_name(&haltname, &len, haltoff,
-                                       sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
-                               if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
-                                       retval = 1;
-                               } else {
-                                       retval=0;
-                               }
-                               pefree(haltname, 0);
-                       } else {
-                               retval = 0;
-                       }
-               }
-               efree(lookup_name);
-       }
-
-       if (retval) {
-               *result = c->value;
-               zval_copy_ctor(result);
-               result->refcount = 1;
-               result->is_ref = 0;
-       }
-
-       return retval;
-}
-
-ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
-{
-    return zend_get_constant_ex(name, name_len, result, NULL TSRMLS_CC);
+       return zend_get_constant(name, name_len, result TSRMLS_CC);
 }
 
 ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
index 8a983a27e5f5cf468af960a8fbc29ee0885e9c05..17ca7c0316c87df0127a8a1a02105604c40c9704 100644 (file)
@@ -56,7 +56,7 @@ int zend_shutdown_constants(TSRMLS_D);
 void zend_register_standard_constants(TSRMLS_D);
 void clean_non_persistent_constants(TSRMLS_D);
 ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC);
-ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC);
+ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC);
 ZEND_API void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC);
 ZEND_API void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC);
 ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC);
index 211036bbeab8e91cb82cb6bccd34f8d14257efc7..c16e65d511d0ddf43eac46fa94442e74964f4df8 100644 (file)
@@ -461,7 +461,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
 
        if (IS_CONSTANT_VISITED(p)) {
                zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
-       } else if (Z_TYPE_P(p) == IS_CONSTANT) {
+       } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
                int refcount;
                zend_uchar is_ref;
 
@@ -473,7 +473,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
                refcount = p->refcount;
                is_ref = p->is_ref;
 
-               if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope TSRMLS_CC)) {
+               if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_TYPE_P(p) TSRMLS_CC)) {
                        if ((colon = memchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p))) && colon[1] == ':') {
                                zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
                        }
@@ -515,7 +515,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
                                zend_hash_move_forward(Z_ARRVAL_P(p));
                                continue;
                        }
-                       if (!zend_get_constant_ex(str_index, str_index_len-1, &const_value, scope TSRMLS_CC)) {
+                       if (!zend_get_constant_ex(str_index, str_index_len-1, &const_value, scope, 0 TSRMLS_CC)) {
                                if ((colon = memchr(str_index, ':', str_index_len-1)) && colon[1] == ':') {
                                        zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
                                }
@@ -636,6 +636,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
        int call_via_handler = 0;
        char *fname, *colon;
        int fname_len;
+       char *lcname;
 
        *fci->retval_ptr_ptr = NULL;
 
@@ -766,68 +767,76 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
 
                fname = Z_STRVAL_P(fci->function_name);
                fname_len = Z_STRLEN_P(fci->function_name);
-               if ((colon = strstr(fname, "::")) != NULL) {
-                       int clen = colon - fname;
-                       int mlen = fname_len - clen - 2;
-                       zend_class_entry **pce, *ce_child = NULL;
-                       if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) {
-                               ce_child = *pce;
-                       } else {
-                               char *lcname = zend_str_tolower_dup(fname, clen);
-                               /* caution: lcname is not '\0' terminated */
-                               if (calling_scope) {
-                                       if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
-                                               ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
-                                       } else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
-                                               ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
+               if (fname[0] == ':' && fname[1] == ':') {
+                       fname += 2;
+                       fname_len -=2;
+               }
+               lcname = zend_str_tolower_dup(fname, fname_len);
+               EX(function_state).function = NULL;
+               if (!fci->object_pp &&
+                   zend_hash_find(fci->function_table, lcname, fname_len+1, (void**)&EX(function_state).function) == SUCCESS) {
+                       efree(lcname);
+               } else {
+                       efree(lcname);
+                       if ((colon = zend_memrchr(fname, ':', fname_len)) != NULL &&
+                           colon > fname &&
+                           *(colon-1) == ':') {
+                               int clen = colon - fname - 1;
+                               int mlen = fname_len - clen - 2;
+
+                               zend_class_entry **pce, *ce_child = NULL;
+                               if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) {
+                                       ce_child = *pce;
+                               } else {
+                                       char *lcname = zend_str_tolower_dup(fname, clen);
+                                       /* caution: lcname is not '\0' terminated */
+                                       if (calling_scope) {
+                                               if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
+                                                       ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
+                                               } else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
+                                                       ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
+                                               }
                                        }
+                                       efree(lcname);
                                }
-                               efree(lcname);
-                       }
-                       if (!ce_child) {
-                               zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
-                               return FAILURE;
+                               if (!ce_child) {
+                                       zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
+                                       return FAILURE;
+                               }
+                               check_scope_or_static = calling_scope;
+                               fci->function_table = &ce_child->function_table;
+                               calling_scope = ce_child;
+                               fname = fname + clen + 2;
+                               fname_len = mlen;
                        }
-                       check_scope_or_static = calling_scope;
-                       fci->function_table = &ce_child->function_table;
-                       calling_scope = ce_child;
-                       fname = fname + clen + 2;
-                       fname_len = mlen;
-               }
 
-               if (fci->object_pp) {
-                       if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) {
-                               zend_error(E_ERROR, "Object does not support method calls");
-                       }
-                       EX(function_state).function = 
-                         Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, fname, fname_len TSRMLS_CC);
-                       if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) {
-                               char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
-                               if (zend_hash_find(&calling_scope->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
+                       if (fci->object_pp) {
+                               if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) {
+                                       zend_error(E_ERROR, "Object does not support method calls");
+                               }
+                               EX(function_state).function = 
+                                 Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, fname, fname_len TSRMLS_CC);
+                               if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) {
+                                       char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
+                                       if (zend_hash_find(&calling_scope->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
+                                               efree(function_name_lc);
+                                               zend_error(E_ERROR, "Cannot call method %s::%s() or method does not exist", calling_scope->name, fname);
+                                       }
                                        efree(function_name_lc);
-                                       zend_error(E_ERROR, "Cannot call method %s::%s() or method does not exist", calling_scope->name, fname);
                                }
-                               efree(function_name_lc);
-                       }
-               } else if (calling_scope) {
-                       char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
-
-                       EX(function_state).function = 
-                               zend_std_get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC);
-                       efree(function_name_lc);
-                       if (check_scope_or_static && EX(function_state).function
-                       && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)
-                       && !instanceof_function(check_scope_or_static, calling_scope TSRMLS_CC)) {
-                               zend_error(E_ERROR, "Cannot call method %s() of class %s which is not a derived from %s", fname, calling_scope->name, check_scope_or_static->name);
-                               return FAILURE;
-                       }
-               } else {
-                       char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
+                       } else if (calling_scope) {
+                               char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
 
-                       if (zend_hash_find(fci->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
-                         EX(function_state).function = NULL;
+                               EX(function_state).function = 
+                                       zend_std_get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC);
+                               efree(function_name_lc);
+                               if (check_scope_or_static && EX(function_state).function
+                               && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)
+                               && !instanceof_function(check_scope_or_static, calling_scope TSRMLS_CC)) {
+                                       zend_error(E_ERROR, "Cannot call method %s() of class %s which is not a derived from %s", fname, calling_scope->name, check_scope_or_static->name);
+                                       return FAILURE;
+                               }
                        }
-                       efree(function_name_lc);
                }
 
                if (EX(function_state).function == NULL) {                        
@@ -1033,6 +1042,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
        zval *retval_ptr = NULL;
        int retval;
        char *lc_name;
+       char *lc_free;
        zval *exception;
        char dummy = 1;
        zend_fcall_info fcall_info;
@@ -1042,11 +1052,16 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
                return FAILURE;
        }
        
-       lc_name = do_alloca(name_length + 1);
+       lc_free = lc_name = do_alloca(name_length + 1);
        zend_str_tolower_copy(lc_name, name, name_length);
 
+       if (lc_name[0] == ':' && lc_name[1] == ':') {
+               lc_name += 2;
+               name_length -= 2;
+       }
+
        if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
-               free_alloca(lc_name);
+               free_alloca(lc_free);
                return SUCCESS;
        }
 
@@ -1054,7 +1069,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
         * (doesn't impact fuctionality of __autoload()
        */
        if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
-               free_alloca(lc_name);
+               free_alloca(lc_free);
                return FAILURE;
        }
 
@@ -1064,7 +1079,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
        }
        
        if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
-               free_alloca(lc_name);
+               free_alloca(lc_free);
                return FAILURE;
        }
 
@@ -1102,12 +1117,12 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
 
        if (retval == FAILURE) {
                EG(exception) = exception;
-               free_alloca(lc_name);
+               free_alloca(lc_free);
                return FAILURE;
        }
 
        if (EG(exception) && exception) {
-               free_alloca(lc_name);
+               free_alloca(lc_free);
                zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
                return FAILURE;
        }
@@ -1119,7 +1134,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
        }
 
        retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
-       free_alloca(lc_name);
+       free_alloca(lc_free);
        return retval;
 }
 
@@ -1475,6 +1490,7 @@ zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len,
 {
        zend_class_entry **pce;
        int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
+       int rt_ns_check  = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK)  ? 1 : 0;
 
        fetch_type = fetch_type & ~ZEND_FETCH_CLASS_NO_AUTOLOAD;
 check_fetch_type:
@@ -1501,8 +1517,30 @@ check_fetch_type:
                        break;
        }
 
-       if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC)==FAILURE) {
+       if (zend_lookup_class_ex(class_name, class_name_len, (!rt_ns_check & use_autoload), &pce TSRMLS_CC)==FAILURE) {
+               if (rt_ns_check) {
+                       /* Check if we have internal class with the same name */
+                       char *php_name;
+                       uint php_name_len;
+                       
+                       php_name = zend_memrchr(class_name, ':', class_name_len);
+                       if (php_name) {
+                               php_name++;
+                               php_name_len = class_name_len-(php_name-class_name);
+                               php_name = zend_str_tolower_dup(php_name, php_name_len);
+                               if (zend_hash_find(EG(class_table), php_name, php_name_len+1, (void **) &pce) == SUCCESS &&
+                                   (*pce)->type == ZEND_INTERNAL_CLASS) {
+                                   efree(php_name);
+                                       return *pce;
+                               }
+                           efree(php_name);
+                       }
+               }
                if (use_autoload) {
+                       if (rt_ns_check &&
+                           zend_lookup_class_ex(class_name, class_name_len, 1, &pce TSRMLS_CC)==SUCCESS) {
+                               return *pce;
+                       }
                        if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
                                zend_error(E_ERROR, "Interface '%s' not found", class_name);
                        } else {
index 93512394990ae101f1c527fc3df033af6cb401e3..832053730cdf791f59d18d3a8ddb9951c5deba64 100644 (file)
@@ -130,6 +130,9 @@ struct _zend_compiler_globals {
        char *doc_comment;
        zend_uint doc_comment_len;
 
+       zval      *current_namespace;
+       HashTable *current_import;
+
 #ifdef ZEND_MULTIBYTE
        zend_encoding **script_encoding_list;
        int script_encoding_list_size;
index 244daae9e5f9b866279d82d38e5168c04d21a4e1..3edbbb2c0ba4aae56a4c547a7c4c7a5effac010f 100644 (file)
 %token T_DOLLAR_OPEN_CURLY_BRACES
 %token T_CURLY_OPEN
 %token T_PAAMAYIM_NEKUDOTAYIM
+%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:
@@ -155,14 +158,26 @@ 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); }
+       |       constant_declaration ';'
 ;
 
+constant_declaration:
+               constant_declaration ',' T_STRING '=' static_scalar     { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); }
+       |       T_CONST T_STRING '=' static_scalar { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); }
+;
 
 inner_statement_list:
                inner_statement_list  { zend_do_extended_info(TSRMLS_C); } inner_statement { HANDLE_INTERACTIVE(); }
@@ -225,7 +240,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); }
@@ -244,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); }
 ;
 
 
@@ -307,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:
@@ -621,9 +636,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);}
@@ -636,17 +654,19 @@ function_call:
        |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); 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);}
-       |       variable_without_objects  '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); }
+       |       variable_without_objects  '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
                        function_call_parameter_list ')'
                        { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
 ;
 
 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); }
 ;
 
@@ -691,12 +711,14 @@ common_scalar:
        |       T_CLASS_C                                       { $$ = $1; }
        |       T_METHOD_C                                      { $$ = $1; }
        |       T_FUNC_C                                        { $$ = $1; }
+       |       T_NS_C                                          { $$ = $1; }
 ;
 
 
 static_scalar: /* compile-time evaluated scalars */
                common_scalar           { $$ = $1; }
-       |       T_STRING                { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT TSRMLS_CC); }
+       |       T_STRING                { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
+       |       T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
        |       '+' static_scalar       { $$ = $2; }
        |       '-' static_scalar       { zval minus_one;  Z_TYPE(minus_one) = IS_LONG; Z_LVAL(minus_one) = -1;  mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC);  $$ = $2; }
        |       T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
@@ -704,11 +726,12 @@ static_scalar: /* compile-time evaluated scalars */
 ;
 
 static_class_constant:
-               T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT TSRMLS_CC); }
+               fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
 ;
 
 scalar:
-               T_STRING                                { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT TSRMLS_CC); }
+               T_STRING                                { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); }
+       |       T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); }
        |       T_STRING_VARNAME                { $$ = $1; }
        |       class_constant  { $$ = $1; }
        |       common_scalar                   { $$ = $1; }
@@ -792,7 +815,7 @@ static_member:
 ;
 
 variable_class_name:
-               reference_variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+               reference_variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); $$=$1;; }
 ;
 
 base_variable_with_function_calls:
@@ -917,8 +940,8 @@ isset_variables:
 ;
 
 class_constant:
-               fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); }
-       |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); }
+               fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
+       |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
 ;
 
 %%
index 436e6e556697b8290549728c535a1a9d47ebe1dc..f05ab623943efe7d5ec58daf59a3d4309216d318 100644 (file)
@@ -1198,6 +1198,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;
 }
@@ -1543,6 +1551,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_STRING(zendlval);
+       }
+       return T_NS_C;
+}
+
 <INITIAL>(([^<]|"<"[^?%s<]){1,400})|"<s"|"<" {
 #ifdef ZEND_MULTIBYTE
        if (SCNG(output_filter)) {
index 7df3a7ecaac654dfc6309022c4b30ca30bd2af2b..fecaf7811c09f4d95038cbd677d28d4190ba8c23 100644 (file)
@@ -29,7 +29,7 @@
 
 ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
 {
-       switch (zvalue->type & ~IS_CONSTANT_INDEX) {
+       switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
                case IS_STRING:
                case IS_CONSTANT:
                        CHECK_ZVAL_STRING_REL(zvalue);
@@ -73,7 +73,7 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
 
 ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
 {
-       switch (zvalue->type & ~IS_CONSTANT_INDEX) {
+       switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
                case IS_STRING:
                case IS_CONSTANT:
                        CHECK_ZVAL_STRING_REL(zvalue);
@@ -103,7 +103,7 @@ ZEND_API void zval_add_ref(zval **p)
 
 ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
 {
-       switch (zvalue->type) {
+       switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
                case IS_RESOURCE: {
                                TSRMLS_FETCH();
 
index 7662d850745f09d3981452947cbfbffefd3bec54..1ceae37139d77dd85763d117eeb3bb48a32098f8 100644 (file)
@@ -1730,7 +1730,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;
@@ -1738,7 +1738,25 @@ 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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */           
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
        if(OP2_TYPE != IS_UNUSED) {
                char *function_name_strval;
                int function_name_strlen;
@@ -1818,10 +1836,29 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
                function_name_strlen = function_name->value.str.len;
        }
 
-       lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       if (OP2_TYPE != IS_CONST && 
+           function_name_strval[0] == ':' &&
+           function_name_strval[1] == ':') {
+
+           function_name_strlen -= 2;
+               lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+       } else {
+               lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       }
        if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
                efree(lcname);
-               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+               if (OP2_TYPE == IS_CONST && opline->op1.op_type == IS_CONST) {
+                       function_name_strlen -= Z_LVAL(opline->op1.u.constant);
+                       lcname = zend_str_tolower_dup(function_name_strval + Z_LVAL(opline->op1.u.constant), function_name_strlen);
+                       if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE ||
+                           function->type != ZEND_INTERNAL_FUNCTION) {
+                               efree(lcname);
+                               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+                       }
+               } else {
+                       zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+               }
        }
 
        efree(lcname);
@@ -2366,7 +2403,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
        zend_free_op free_res;
 
        if (zend_ptr_stack_get_arg(arg_num, (void **) &param TSRMLS_CC)==FAILURE) {
-               if (Z_TYPE(opline->op2.u.constant) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) {
+               if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) {
                        zval *default_value;
 
                        ALLOC_ZVAL(default_value);
@@ -2582,49 +2619,71 @@ 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|CONST|UNUSED, CONST)
 {
        zend_op *opline = EX(opline);
-       zend_class_entry *ce = NULL;
-       zval **value;
 
        if (OP1_TYPE == 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_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+               if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
                        zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
-                                               opline->op2.u.constant.value.str.val,
-                                               opline->op2.u.constant.value.str.val);
+                               Z_STRVAL(opline->op2.u.constant),
+                               Z_STRVAL(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();
-       }
+       } else {
+               zend_class_entry *ce;
+               zval **value;
+       
+               if (OP1_TYPE == IS_CONST) {
+                       zend_op *op_data = opline + 1;
+                       zend_constant *c;
+
+                       ZEND_VM_INC_OPCODE();
+
+                       /* try a constant in namespace */
+                       if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
+                               EX_T(opline->result.u.var).tmp_var = c->value;
+                               zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                               if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                                       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+                                               Z_STRVAL(opline->op2.u.constant),
+                                               Z_STRVAL(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();
+                       }
+       
+                       /* no constant found. try a constant in class */                
+                       ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);            
+                       if (!ce) {
+                               zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+                       }
+               } else {
+                       ce = EX_T(opline->op1.u.var).class_entry;
+               }
 
-       ce = EX_T(opline->op1.u.var).class_entry;
+               if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+                       if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
+                           Z_TYPE_PP(value) == IS_CONSTANT) {
+                               zend_class_entry *old_scope = EG(scope);
 
-       if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+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 '%s'", Z_STRVAL(opline->op2.u.constant));
+               }
 
-               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 '%s'", opline->op2.u.constant.value.str.val);
+               ZEND_VM_NEXT_OPCODE();
        }
-
-       ZEND_VM_NEXT_OPCODE();
 }
 
 ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV)
@@ -3846,4 +3905,39 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
        }
 }
 
+ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
+{
+       zend_op *opline = EX(opline);
+       zend_free_op free_op1, free_op2;
+       zval *name  = GET_OP1_ZVAL_PTR(BP_VAR_R);
+       zval *val   = GET_OP2_ZVAL_PTR(BP_VAR_R);
+       zend_constant c;
+
+       if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
+               zval tmp = *val;
+               zval *tmp_ptr = &tmp;
+
+               if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
+                       zval_copy_ctor(&tmp);                   
+               }
+               INIT_PZVAL(&tmp);
+               zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
+               c.value = *tmp_ptr;
+       } else {
+               c.value = *val;
+               zval_copy_ctor(&c.value);
+       }
+       c.flags = CONST_CS; /* non persistent, case sensetive */
+       c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+       c.name_len = Z_STRLEN_P(name)+1;
+       c.module_number = PHP_USER_CONSTANT;
+
+       if (zend_register_constant(&c TSRMLS_CC) == FAILURE) {
+       }
+
+       FREE_OP1();
+       FREE_OP2();
+       ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
index 2eb63d2e31a7aae4cb6a421fcb3ad0b0be845d95..2df3ee8e313e54b94b987aa9487faf39ddbf15af 100644 (file)
@@ -656,70 +656,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) {
-               char *function_name_strval;
-               int function_name_strlen;
-               zend_bool is_const = (IS_CONST == IS_CONST);
-
-
-               if (is_const) {
-                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
-                       function_name_strlen = Z_STRLEN(opline->op2.u.constant);
-               } else {
-                       function_name = &opline->op2.u.constant;
-
-                       if (Z_TYPE_P(function_name) != IS_STRING) {
-                               zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       }
-                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-                       function_name_strlen = function_name->value.str.len;
-               }
-
-               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-               if (!is_const) {
-                       efree(function_name_strval);
-
-               }
-       } 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 %s::__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 %s::%s() 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);
@@ -744,10 +680,29 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                function_name_strlen = function_name->value.str.len;
        }
 
-       lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       if (IS_CONST != IS_CONST &&
+           function_name_strval[0] == ':' &&
+           function_name_strval[1] == ':') {
+
+           function_name_strlen -= 2;
+               lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+       } else {
+               lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       }
        if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
                efree(lcname);
-               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+               if (IS_CONST == IS_CONST && opline->op1.op_type == IS_CONST) {
+                       function_name_strlen -= Z_LVAL(opline->op1.u.constant);
+                       lcname = zend_str_tolower_dup(function_name_strval + Z_LVAL(opline->op1.u.constant), function_name_strlen);
+                       if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE ||
+                           function->type != ZEND_INTERNAL_FUNCTION) {
+                               efree(lcname);
+                               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+                       }
+               } else {
+                       zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+               }
        }
 
        efree(lcname);
@@ -771,7 +726,7 @@ static int ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zend_free_op free_res;
 
        if (zend_ptr_stack_get_arg(arg_num, (void **) &param TSRMLS_CC)==FAILURE) {
-               if (Z_TYPE(opline->op2.u.constant) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) {
+               if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) {
                        zval *default_value;
 
                        ALLOC_ZVAL(default_value);
@@ -860,70 +815,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) {
-               char *function_name_strval;
-               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_STRVAL(opline->op2.u.constant);
-                       function_name_strlen = Z_STRLEN(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) {
-                               zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       }
-                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-                       function_name_strlen = function_name->value.str.len;
-               }
-
-               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-               if (!is_const) {
-                       efree(function_name_strval);
-                       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 %s::__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 %s::%s() 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);
@@ -948,10 +839,29 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                function_name_strlen = function_name->value.str.len;
        }
 
-       lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       if (IS_TMP_VAR != IS_CONST &&
+           function_name_strval[0] == ':' &&
+           function_name_strval[1] == ':') {
+
+           function_name_strlen -= 2;
+               lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+       } else {
+               lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       }
        if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
                efree(lcname);
-               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+               if (IS_TMP_VAR == IS_CONST && opline->op1.op_type == IS_CONST) {
+                       function_name_strlen -= Z_LVAL(opline->op1.u.constant);
+                       lcname = zend_str_tolower_dup(function_name_strval + Z_LVAL(opline->op1.u.constant), function_name_strlen);
+                       if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE ||
+                           function->type != ZEND_INTERNAL_FUNCTION) {
+                               efree(lcname);
+                               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+                       }
+               } else {
+                       zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+               }
        }
 
        efree(lcname);
@@ -1021,70 +931,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) {
-               char *function_name_strval;
-               int function_name_strlen;
-               zend_bool is_const = (IS_VAR == IS_CONST);
-               zend_free_op free_op2;
-
-               if (is_const) {
-                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
-                       function_name_strlen = Z_STRLEN(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) {
-                               zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       }
-                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-                       function_name_strlen = function_name->value.str.len;
-               }
-
-               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-               if (!is_const) {
-                       efree(function_name_strval);
-                       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 %s::__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 %s::%s() 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);
@@ -1109,10 +955,29 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                function_name_strlen = function_name->value.str.len;
        }
 
-       lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       if (IS_VAR != IS_CONST &&
+           function_name_strval[0] == ':' &&
+           function_name_strval[1] == ':') {
+
+           function_name_strlen -= 2;
+               lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+       } else {
+               lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       }
        if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
                efree(lcname);
-               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+               if (IS_VAR == IS_CONST && opline->op1.op_type == IS_CONST) {
+                       function_name_strlen -= Z_LVAL(opline->op1.u.constant);
+                       lcname = zend_str_tolower_dup(function_name_strval + Z_LVAL(opline->op1.u.constant), function_name_strlen);
+                       if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE ||
+                           function->type != ZEND_INTERNAL_FUNCTION) {
+                               efree(lcname);
+                               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+                       }
+               } else {
+                       zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+               }
        }
 
        efree(lcname);
@@ -1181,70 +1046,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) {
-               char *function_name_strval;
-               int function_name_strlen;
-               zend_bool is_const = (IS_UNUSED == IS_CONST);
-
-
-               if (is_const) {
-                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
-                       function_name_strlen = Z_STRLEN(opline->op2.u.constant);
-               } else {
-                       function_name = NULL;
-
-                       if (Z_TYPE_P(function_name) != IS_STRING) {
-                               zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       }
-                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-                       function_name_strlen = function_name->value.str.len;
-               }
-
-               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-               if (!is_const) {
-                       efree(function_name_strval);
-
-               }
-       } 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 %s::__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 %s::%s() 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);
@@ -1274,70 +1075,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) {
-               char *function_name_strval;
-               int function_name_strlen;
-               zend_bool is_const = (IS_CV == IS_CONST);
-
-
-               if (is_const) {
-                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
-                       function_name_strlen = Z_STRLEN(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) {
-                               zend_error_noreturn(E_ERROR, "Function name must be a string");
-                       }
-                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-                       function_name_strlen = function_name->value.str.len;
-               }
-
-               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-               if (!is_const) {
-                       efree(function_name_strval);
-
-               }
-       } 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 %s::__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 %s::%s() 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);
@@ -1362,10 +1099,29 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                function_name_strlen = function_name->value.str.len;
        }
 
-       lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       if (IS_CV != IS_CONST &&
+           function_name_strval[0] == ':' &&
+           function_name_strval[1] == ':') {
+
+           function_name_strlen -= 2;
+               lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+       } else {
+               lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+       }
        if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
                efree(lcname);
-               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+               if (IS_CV == IS_CONST && opline->op1.op_type == IS_CONST) {
+                       function_name_strlen -= Z_LVAL(opline->op1.u.constant);
+                       lcname = zend_str_tolower_dup(function_name_strval + Z_LVAL(opline->op1.u.constant), function_name_strlen);
+                       if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE ||
+                           function->type != ZEND_INTERNAL_FUNCTION) {
+                               efree(lcname);
+                               zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+                       }
+               } else {
+                       zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+               }
        }
 
        efree(lcname);
@@ -2630,6 +2386,88 @@ static int ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
        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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_CONST != IS_UNUSED) {
+               char *function_name_strval;
+               int function_name_strlen;
+               zend_bool is_const = (IS_CONST == IS_CONST);
+
+
+               if (is_const) {
+                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+               } else {
+                       function_name = &opline->op2.u.constant;
+
+                       if (Z_TYPE_P(function_name) != IS_STRING) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
+
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+
+               }
+       } 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 %s::__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 %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+               }
+               if ((EX(object) = EG(This))) {
+                       EX(object)->refcount++;
+               }
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -2664,46 +2502,68 @@ static int ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 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_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+               if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
                        zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
-                                               opline->op2.u.constant.value.str.val,
-                                               opline->op2.u.constant.value.str.val);
+                               Z_STRVAL(opline->op2.u.constant),
+                               Z_STRVAL(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();
-       }
+       } else {
+               zend_class_entry *ce;
+               zval **value;
 
-       ce = EX_T(opline->op1.u.var).class_entry;
+               if (IS_CONST == IS_CONST) {
+                       zend_op *op_data = opline + 1;
+                       zend_constant *c;
 
-       if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
-               zend_class_entry *old_scope = EG(scope);
+                       ZEND_VM_INC_OPCODE();
 
-               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 '%s'", opline->op2.u.constant.value.str.val);
-       }
+                       /* try a constant in namespace */
+                       if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
+                               EX_T(opline->result.u.var).tmp_var = c->value;
+                               zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                               if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                                       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+                                               Z_STRVAL(opline->op2.u.constant),
+                                               Z_STRVAL(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();
+                       }
 
-       ZEND_VM_NEXT_OPCODE();
+                       /* no constant found. try a constant in class */
+                       ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+                       if (!ce) {
+                               zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+                       }
+               } else {
+                       ce = EX_T(opline->op1.u.var).class_entry;
+               }
+
+               if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+                       if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
+                           Z_TYPE_PP(value) == IS_CONSTANT) {
+                               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 '%s'", Z_STRVAL(opline->op2.u.constant));
+               }
+
+               ZEND_VM_NEXT_OPCODE();
+       }
 }
 
 static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -2799,6 +2659,40 @@ static int ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        }
 }
 
+static int ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+
+       zval *name  = &opline->op1.u.constant;
+       zval *val   = &opline->op2.u.constant;
+       zend_constant c;
+
+       if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
+               zval tmp = *val;
+               zval *tmp_ptr = &tmp;
+
+               if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
+                       zval_copy_ctor(&tmp);
+               }
+               INIT_PZVAL(&tmp);
+               zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
+               c.value = *tmp_ptr;
+       } else {
+               c.value = *val;
+               zval_copy_ctor(&c.value);
+       }
+       c.flags = CONST_CS; /* non persistent, case sensetive */
+       c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+       c.name_len = Z_STRLEN_P(name)+1;
+       c.module_number = PHP_USER_CONSTANT;
+
+       if (zend_register_constant(&c TSRMLS_CC) == FAILURE) {
+       }
+
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -3007,29 +2901,111 @@ static int ZEND_BW_AND_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_BW_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-       zend_op *opline = EX(opline);
-       zend_free_op free_op2;
+static int ZEND_BW_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+       zend_free_op free_op2;
+
+       bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
+               &opline->op1.u.constant,
+               _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+
+       zval_dtor(free_op2.var);
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_BOOL_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+       zend_free_op free_op2;
+
+       boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
+               &opline->op1.u.constant,
+               _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+
+       zval_dtor(free_op2.var);
+       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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_TMP_VAR != IS_UNUSED) {
+               char *function_name_strval;
+               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_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(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) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
 
-       bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
-               &opline->op1.u.constant,
-               _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
 
-       zval_dtor(free_op2.var);
-       ZEND_VM_NEXT_OPCODE();
-}
+               if (!is_const) {
+                       efree(function_name_strval);
+                       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 %s::__construct()", ce->name);
+               }
+               EX(fbc) = ce->constructor;
+       }
 
-static int ZEND_BOOL_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-       zend_op *opline = EX(opline);
-       zend_free_op free_op2;
+       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 %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
 
-       boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
-               &opline->op1.u.constant,
-               _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+               }
+               if ((EX(object) = EG(This))) {
+                       EX(object)->refcount++;
+               }
+       }
 
-       zval_dtor(free_op2.var);
        ZEND_VM_NEXT_OPCODE();
 }
 
@@ -3392,6 +3368,88 @@ 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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_VAR != IS_UNUSED) {
+               char *function_name_strval;
+               int function_name_strlen;
+               zend_bool is_const = (IS_VAR == IS_CONST);
+               zend_free_op free_op2;
+
+               if (is_const) {
+                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(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) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
+
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+                       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 %s::__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 %s::%s() 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);
@@ -3517,6 +3575,88 @@ 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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_UNUSED != IS_UNUSED) {
+               char *function_name_strval;
+               int function_name_strlen;
+               zend_bool is_const = (IS_UNUSED == IS_CONST);
+
+
+               if (is_const) {
+                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+               } else {
+                       function_name = NULL;
+
+                       if (Z_TYPE_P(function_name) != IS_STRING) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
+
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+
+               }
+       } 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 %s::__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 %s::%s() 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);
@@ -3836,10 +3976,92 @@ static int ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zend_op *opline = EX(opline);
 
 
-       boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
-               &opline->op1.u.constant,
-               _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+       boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
+               &opline->op1.u.constant,
+               _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+
+
+       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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_CV != IS_UNUSED) {
+               char *function_name_strval;
+               int function_name_strlen;
+               zend_bool is_const = (IS_CV == IS_CONST);
+
+
+               if (is_const) {
+                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(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) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
+
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+
+               }
+       } 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 %s::__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 %s::%s() 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();
 }
@@ -9327,6 +9549,88 @@ 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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_CONST != IS_UNUSED) {
+               char *function_name_strval;
+               int function_name_strlen;
+               zend_bool is_const = (IS_CONST == IS_CONST);
+
+
+               if (is_const) {
+                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+               } else {
+                       function_name = &opline->op2.u.constant;
+
+                       if (Z_TYPE_P(function_name) != IS_STRING) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
+
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+
+               }
+       } 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 %s::__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 %s::%s() 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);
@@ -9358,6 +9662,73 @@ 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);
+
+       if (IS_VAR == IS_UNUSED) {
+               if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+                               Z_STRVAL(opline->op2.u.constant),
+                               Z_STRVAL(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();
+       } else {
+               zend_class_entry *ce;
+               zval **value;
+
+               if (IS_VAR == IS_CONST) {
+                       zend_op *op_data = opline + 1;
+                       zend_constant *c;
+
+                       ZEND_VM_INC_OPCODE();
+
+                       /* try a constant in namespace */
+                       if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
+                               EX_T(opline->result.u.var).tmp_var = c->value;
+                               zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                               if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                                       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+                                               Z_STRVAL(opline->op2.u.constant),
+                                               Z_STRVAL(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();
+                       }
+
+                       /* no constant found. try a constant in class */
+                       ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+                       if (!ce) {
+                               zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+                       }
+               } else {
+                       ce = EX_T(opline->op1.u.var).class_entry;
+               }
+
+               if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+                       if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
+                           Z_TYPE_PP(value) == IS_CONSTANT) {
+                               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 '%s'", Z_STRVAL(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);
@@ -10814,6 +11185,88 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_TMP_VAR != IS_UNUSED) {
+               char *function_name_strval;
+               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_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(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) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
+
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+                       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 %s::__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 %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+               }
+               if ((EX(object) = EG(This))) {
+                       EX(object)->refcount++;
+               }
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -12301,42 +12754,124 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                zend_error_noreturn(E_ERROR, "Method name must be a string");
        }
 
-       function_name_strval = Z_STRVAL_P(function_name);
-       function_name_strlen = Z_STRLEN_P(function_name);
-
-       EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+       function_name_strval = Z_STRVAL_P(function_name);
+       function_name_strlen = Z_STRLEN_P(function_name);
+
+       EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+
+       if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
+               if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
+                       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 %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+               }
+       } else {
+               zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", 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;
+               }
+       }
+
+       if (free_op2.var) {zval_ptr_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_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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_VAR != IS_UNUSED) {
+               char *function_name_strval;
+               int function_name_strlen;
+               zend_bool is_const = (IS_VAR == IS_CONST);
+               zend_free_op free_op2;
+
+               if (is_const) {
+                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+               } else {
+                       function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
-       if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
-               if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       if (Z_TYPE_P(function_name) != IS_STRING) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
                }
 
-               /* 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 %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+                       if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
                }
        } else {
-               zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", 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 %s::__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_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 %s::%s() 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++;
                }
        }
 
-       if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
-       if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
-
        ZEND_VM_NEXT_OPCODE();
 }
 
@@ -13069,6 +13604,88 @@ 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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_UNUSED != IS_UNUSED) {
+               char *function_name_strval;
+               int function_name_strlen;
+               zend_bool is_const = (IS_UNUSED == IS_CONST);
+
+
+               if (is_const) {
+                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+               } else {
+                       function_name = NULL;
+
+                       if (Z_TYPE_P(function_name) != IS_STRING) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
+
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+
+               }
+       } 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 %s::__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 %s::%s() 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);
@@ -14296,6 +14913,88 @@ 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 */
+               zend_op *op_data = opline+1;
+
+               ZEND_VM_INC_OPCODE();
+
+               if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
+                       EX(object) = NULL;
+                       ZEND_VM_NEXT_OPCODE();
+               }
+
+               /* no function found. try a static method in class */
+               ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               if (!ce) {
+                       zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+               }
+       } else {
+               ce = EX_T(opline->op1.u.var).class_entry;
+       }
+       if(IS_CV != IS_UNUSED) {
+               char *function_name_strval;
+               int function_name_strlen;
+               zend_bool is_const = (IS_CV == IS_CONST);
+
+
+               if (is_const) {
+                       function_name_strval = Z_STRVAL(opline->op2.u.constant);
+                       function_name_strlen = Z_STRLEN(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) {
+                               zend_error_noreturn(E_ERROR, "Function name must be a string");
+                       }
+                       function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+                       function_name_strlen = function_name->value.str.len;
+               }
+
+               EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+               if (!is_const) {
+                       efree(function_name_strval);
+
+               }
+       } 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 %s::__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 %s::%s() 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);
@@ -15456,46 +16155,68 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
 static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
-       zend_class_entry *ce = NULL;
-       zval **value;
 
        if (IS_UNUSED == 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_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+               if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
                        zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
-                                               opline->op2.u.constant.value.str.val,
-                                               opline->op2.u.constant.value.str.val);
+                               Z_STRVAL(opline->op2.u.constant),
+                               Z_STRVAL(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();
-       }
+       } else {
+               zend_class_entry *ce;
+               zval **value;
 
-       ce = EX_T(opline->op1.u.var).class_entry;
+               if (IS_UNUSED == IS_CONST) {
+                       zend_op *op_data = opline + 1;
+                       zend_constant *c;
 
-       if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
-               zend_class_entry *old_scope = EG(scope);
+                       ZEND_VM_INC_OPCODE();
 
-               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 '%s'", opline->op2.u.constant.value.str.val);
-       }
+                       /* try a constant in namespace */
+                       if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
+                               EX_T(opline->result.u.var).tmp_var = c->value;
+                               zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                               if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                                       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+                                               Z_STRVAL(opline->op2.u.constant),
+                                               Z_STRVAL(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();
+                       }
 
-       ZEND_VM_NEXT_OPCODE();
+                       /* no constant found. try a constant in class */
+                       ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+                       if (!ce) {
+                               zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+                       }
+               } else {
+                       ce = EX_T(opline->op1.u.var).class_entry;
+               }
+
+               if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+                       if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
+                           Z_TYPE_PP(value) == IS_CONSTANT) {
+                               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 '%s'", Z_STRVAL(opline->op2.u.constant));
+               }
+
+               ZEND_VM_NEXT_OPCODE();
+       }
 }
 
 static int ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -29057,7 +29778,7 @@ void zend_init_opcodes_handlers(void)
        ZEND_NULL_HANDLER,
        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,
@@ -29397,31 +30118,31 @@ void zend_init_opcodes_handlers(void)
        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,
@@ -30147,7 +30868,7 @@ void zend_init_opcodes_handlers(void)
        ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER,
        ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER,
        ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER,
-       ZEND_NULL_HANDLER,
+       ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
index 230e110973d54b493bb3d4ded562d744375a408e..82fbeda4f453abb75a046421018dcdda758cbd21 100644 (file)
 #define ZEND_DECLARE_INHERITED_CLASS 140
 #define ZEND_DECLARE_FUNCTION        141
 #define ZEND_RAISE_ABSTRACT_ERROR    142
+#define ZEND_DECLARE_CONST           143
 #define ZEND_ADD_INTERFACE           144
 #define ZEND_VERIFY_ABSTRACT_CLASS   146
 #define ZEND_ASSIGN_DIM              147