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)
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--TEST--
+003: Name conflict (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+class Exception {
+}
+
+echo get_class(new Exception()),"\n";
+--EXPECT--
+test::ns1::Exception
--- /dev/null
+--TEST--
+004: Name conflict (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+echo get_class(new Exception()),"\n";
+--EXPECT--
+Exception
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--TEST--
+009: __NAMESPACE__ constant and runtime names (php name)
+--FILE--
+<?php
+class foo {
+}
+
+$x = __NAMESPACE__ . "::foo";
+echo get_class(new $x),"\n";
+--EXPECT--
+foo
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--TEST--
+014: Name conflict and functions (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+echo strlen("Hello"),"\n";
+--EXPECT--
+5
--- /dev/null
+--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
+
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--TEST--
+019: __NAMESPACE__ constant and runtime names (php name)
+--FILE--
+<?php
+function foo() {
+ return __FUNCTION__;
+}
+
+$x = __NAMESPACE__ . "::foo";
+echo $x(),"\n";
+--EXPECT--
+foo
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+<?php
+class Test {
+ static function foo() {
+ echo __CLASS__,"::",__FUNCTION__,"\n";
+ }
+}
--- /dev/null
+--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
--- /dev/null
+--TEST--
+023: __NAMESPACE__ constant
+--FILE--
+<?php
+namespace test::foo;
+
+var_dump(__NAMESPACE__);
+--EXPECT--
+string(9) "test::foo"
+--UEXPECT--
+unicode(9) "test::foo"
--- /dev/null
+--TEST--
+024: __NAMESPACE__ constant out of namespace
+--FILE--
+<?php
+var_dump(__NAMESPACE__);
+--EXPECT--
+string(0) ""
+--UEXPECT--
+unicode(0) ""
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+<?php
+namespace Foo::Bar;
+
+class Foo {
+ function __construct() {
+ echo __CLASS__,"\n";
+ }
+ static function Bar() {
+ echo __CLASS__,"\n";
+ }
+}
--- /dev/null
+--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
--- /dev/null
+<?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";
+}
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
+
--- /dev/null
+--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
--- /dev/null
+--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)
--- /dev/null
+--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)
--- /dev/null
+--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
--- /dev/null
+--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
+
--- /dev/null
+--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
+)
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--TEST--
+043: Name conflict and constants (ns name)
+--FILE--
+<?php
+namespace test::ns1;
+
+const INI_ALL = 0;
+
+var_dump(INI_ALL);
+--EXPECT--
+int(0)
--- /dev/null
+--TEST--
+044: Name conflict and constants (php name)
+--FILE--
+<?php
+namespace test::ns1;
+
+var_dump(INI_ALL);
+--EXPECT--
+int(7)
--- /dev/null
+--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)
--- /dev/null
+--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)
--- /dev/null
+--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)
--- /dev/null
+--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)
--- /dev/null
+--TEST--
+049: __NAMESPACE__ constant and runtime names (php name)
+--FILE--
+<?php
+const FOO = 0;
+
+var_dump(constant(__NAMESPACE__ . "::FOO"));
+--EXPECT--
+int(0)
--- /dev/null
+--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)
--- /dev/null
+--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)
--- /dev/null
+--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)
--- /dev/null
+--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
+
#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 */
*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;
}
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;
}
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 {
/* 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);
}
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);
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);
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;
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;
}
}
} 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);
}
-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 */
}
}
-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;
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)
{
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;
}
}
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;
}
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);
}
}
-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) {
}
}
+ 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 */
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;
}
-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;
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++;
}
*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;
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;
}
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) {
}
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;
}
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;
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;
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
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);
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);
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);
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
#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) */
}
-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)) {
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);
}
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)
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);
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;
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));
}
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);
}
int call_via_handler = 0;
char *fname, *colon;
int fname_len;
+ char *lcname;
*fci->retval_ptr_ptr = NULL;
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) {
zval *retval_ptr = NULL;
int retval;
char *lc_name;
+ char *lc_free;
zval *exception;
char dummy = 1;
zend_fcall_info fcall_info;
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;
}
* (doesn't impact fuctionality of __autoload()
*/
if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
- free_alloca(lc_name);
+ free_alloca(lc_free);
return FAILURE;
}
}
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;
}
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;
}
}
retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
- free_alloca(lc_name);
+ free_alloca(lc_free);
return retval;
}
{
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:
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 {
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;
%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:
| /* 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(); }
| 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); }
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); }
;
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:
;
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);}
| 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); }
;
| 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; }
;
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; }
;
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:
;
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); }
;
%%
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;
}
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)) {
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);
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);
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();
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;
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;
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);
zend_free_op free_res;
if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m 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);
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)
}
}
+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)
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);
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);
zend_free_op free_res;
if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m 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);
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);
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);
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);
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);
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);
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);
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);
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);
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)
}
}
+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);
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();
}
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);
}
}
+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);
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();
}
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);
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);
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);
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();
}
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);
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);
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)
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,
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,
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,
#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