From 0b5ee0647142c72ff45da22b2369739b81ae09e8 Mon Sep 17 00:00:00 2001 From: cpriest Date: Mon, 21 Jan 2013 07:20:26 -0600 Subject: [PATCH] Property Accessors Feature (smushed) --- .../abstract_accessor_body_error.phpt | 14 + .../abstract_accessor_inherit_error.phpt | 16 + .../accessors/abstract_accessor_property.phpt | 14 + .../accessors/abstract_and_final_error.phpt | 14 + .../accessors/accessor_final_inner_error.phpt | 28 + .../accessors/accessor_final_outer_error.phpt | 26 + Zend/tests/accessors/accessor_implicit.phpt | 23 + .../accessors/accessor_inherited_static.phpt | 33 + .../accessors/accessor_interface_error.phpt | 19 + ...nterface_partial_implementation_error.phpt | 20 + ...ace_property_satisfies_accessor_basic.phpt | 21 + ..._isset_calls_isset_calls_getter_basic.phpt | 27 + ...ssor_isset_unset_auto_implement_basic.phpt | 44 + ...isset_unset_default_implemented_basic.phpt | 39 + ...cessor_object_get_autoimplement_basic.phpt | 25 + .../accessor_object_get_defined_basic.phpt | 23 + .../accessor_object_get_undefined_error.phpt | 20 + ...r_object_getset_autoimplemented_basic.phpt | 22 + ...ssor_object_isset_autoimplement_basic.phpt | 31 + .../accessor_object_isset_defined_basic.phpt | 37 + ...accessor_object_isset_undefined_basic.phpt | 30 + ...cessor_object_set_autoimplement_basic.phpt | 32 + .../accessor_object_set_defined_basic.phpt | 21 + ...t_set_defined_parent_get_called_error.phpt | 32 + .../accessor_object_set_undefined_error.phpt | 16 + ...ssor_object_unset_autoimplement_basic.phpt | 32 + .../accessor_object_unset_defined_basic.phpt | 36 + ...accessor_object_unset_undefined_basic.phpt | 31 + ..._recursive_call_properly_denied_basic.phpt | 145 ++++ .../accessors/accessor_static_basic.phpt | 34 + ...cessor_static_get_autoimplement_basic.phpt | 45 ++ .../accessor_static_get_defined_basic.phpt | 31 + .../accessor_static_get_undefined_error.phpt | 25 + ...atic_get_undefined_isset_called_error.phpt | 25 + ...ssor_static_isset_autoimplement_basic.phpt | 42 + .../accessor_static_isset_defined_basic.phpt | 45 ++ ...accessor_static_isset_undefined_basic.phpt | 41 + .../accessor_static_parent_basic.phpt | 45 ++ ...cessor_static_set_autoimplement_basic.phpt | 45 ++ .../accessor_static_set_defined_basic.phpt | 31 + ...r_static_set_defined_get_called_error.phpt | 27 + ...c_set_defined_parent_get_called_error.phpt | 39 + ...tic_set_defined_self_get_called_error.phpt | 31 + .../accessor_static_set_undefined_error.phpt | 25 + ...atic_set_undefined_unset_called_error.phpt | 25 + ...ssor_static_unset_autoimplement_basic.phpt | 40 + .../accessor_static_unset_defined_basic.phpt | 44 + ...accessor_static_unset_undefined_basic.phpt | 38 + .../accessor_std_inherit_looser_basic.phpt | 29 + ...essor_std_lazy_load_with_getter_basic.phpt | 40 + .../accessor_std_numeric_operators_basic.phpt | 151 ++++ .../accessor_std_other_operations_basic.phpt | 267 ++++++ .../accessor_std_private_get_error.phpt | 20 + .../accessor_std_private_set_error.phpt | 23 + .../accessors/accessor_std_public_basic.phpt | 26 + .../accessor_std_return_reference_basic.phpt | 33 + ...sor_std_return_reference_setter_error.phpt | 35 + .../accessors/accessor_traits_basic.phpt | 27 + .../automatic_setter_with_typehint.phpt | 22 + Zend/tests/accessors/case_sensitivity.phpt | 19 + Zend/tests/accessors/debug_backtrace.phpt | 117 +++ .../duplicate_property_declared_error.phpt | 14 + Zend/tests/accessors/exception.phpt | 42 + Zend/tests/accessors/get_class_methods.phpt | 18 + Zend/tests/accessors/get_params_error.phpt | 14 + Zend/tests/accessors/isset_params_error.phpt | 14 + ...isset_unset_inherit_get_set_modifiers.phpt | 59 ++ .../tests/accessors/isset_unset_modifier.phpt | 22 + .../overwrite_with_simple_property.phpt | 39 + .../parent_accessor_through_reflection.phpt | 34 + ...property_visibility_bypassed_properly.phpt | 29 + .../std_get_with_paren_optional.phpt | 39 + .../std_isset_with_paren_optional.phpt | 26 + .../accessors/std_set_typehint_error.phpt | 24 + .../std_set_with_paren_optional.phpt | 50 ++ .../std_unset_with_paren_optional.phpt | 22 + ...ss_visibility_property_access_allowed.phpt | 69 ++ ...ass_visibility_property_access_denied.phpt | 56 ++ Zend/tests/accessors/unset_params_error.phpt | 14 + Zend/zend.c | 1 + Zend/zend.h | 3 +- Zend/zend_API.c | 1 + Zend/zend_compile.c | 664 +++++++++++---- Zend/zend_compile.h | 43 +- Zend/zend_exceptions.c | 1 + Zend/zend_execute_API.c | 29 +- Zend/zend_globals.h | 1 + Zend/zend_language_parser.y | 58 +- Zend/zend_language_scanner.c | 731 +++++++++-------- Zend/zend_language_scanner.l | 43 + Zend/zend_object_handlers.c | 759 +++++++++++------- Zend/zend_object_handlers.h | 1 + Zend/zend_opcode.c | 2 +- ext/reflection/php_reflection.c | 164 +++- .../ReflectionExtension_getClasses_basic.phpt | 26 +- .../ReflectionProperty_accessors_basic1.phpt | 278 +++++++ ...rty_accessors_getDeclaringClass_basic.phpt | 39 + ...roperty_accessors_getDocComment_basic.phpt | 58 ++ ...Property_accessors_getModifiers_basic.phpt | 30 + .../ReflectionProperty_getGetter_basic.phpt | 39 + .../ReflectionProperty_getIsset_basic.phpt | 39 + .../ReflectionProperty_getSetter_basic.phpt | 39 + .../ReflectionProperty_getUnset_basic.phpt | 39 + tests/classes/unset_properties.phpt | 4 +- 104 files changed, 5210 insertions(+), 825 deletions(-) create mode 100644 Zend/tests/accessors/abstract_accessor_body_error.phpt create mode 100644 Zend/tests/accessors/abstract_accessor_inherit_error.phpt create mode 100644 Zend/tests/accessors/abstract_accessor_property.phpt create mode 100644 Zend/tests/accessors/abstract_and_final_error.phpt create mode 100644 Zend/tests/accessors/accessor_final_inner_error.phpt create mode 100644 Zend/tests/accessors/accessor_final_outer_error.phpt create mode 100644 Zend/tests/accessors/accessor_implicit.phpt create mode 100644 Zend/tests/accessors/accessor_inherited_static.phpt create mode 100644 Zend/tests/accessors/accessor_interface_error.phpt create mode 100644 Zend/tests/accessors/accessor_interface_partial_implementation_error.phpt create mode 100644 Zend/tests/accessors/accessor_interface_property_satisfies_accessor_basic.phpt create mode 100644 Zend/tests/accessors/accessor_isset_calls_isset_calls_getter_basic.phpt create mode 100644 Zend/tests/accessors/accessor_isset_unset_auto_implement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_isset_unset_default_implemented_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_get_autoimplement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_get_defined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_get_undefined_error.phpt create mode 100644 Zend/tests/accessors/accessor_object_getset_autoimplemented_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_isset_autoimplement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_isset_defined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_isset_undefined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_set_autoimplement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_set_defined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_set_defined_parent_get_called_error.phpt create mode 100644 Zend/tests/accessors/accessor_object_set_undefined_error.phpt create mode 100644 Zend/tests/accessors/accessor_object_unset_autoimplement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_unset_defined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_object_unset_undefined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_recursive_call_properly_denied_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_get_autoimplement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_get_defined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_get_undefined_error.phpt create mode 100644 Zend/tests/accessors/accessor_static_get_undefined_isset_called_error.phpt create mode 100644 Zend/tests/accessors/accessor_static_isset_autoimplement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_isset_defined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_isset_undefined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_parent_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_set_autoimplement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_set_defined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_set_defined_get_called_error.phpt create mode 100644 Zend/tests/accessors/accessor_static_set_defined_parent_get_called_error.phpt create mode 100644 Zend/tests/accessors/accessor_static_set_defined_self_get_called_error.phpt create mode 100644 Zend/tests/accessors/accessor_static_set_undefined_error.phpt create mode 100644 Zend/tests/accessors/accessor_static_set_undefined_unset_called_error.phpt create mode 100644 Zend/tests/accessors/accessor_static_unset_autoimplement_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_unset_defined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_static_unset_undefined_basic.phpt create mode 100644 Zend/tests/accessors/accessor_std_inherit_looser_basic.phpt create mode 100644 Zend/tests/accessors/accessor_std_lazy_load_with_getter_basic.phpt create mode 100644 Zend/tests/accessors/accessor_std_numeric_operators_basic.phpt create mode 100644 Zend/tests/accessors/accessor_std_other_operations_basic.phpt create mode 100644 Zend/tests/accessors/accessor_std_private_get_error.phpt create mode 100644 Zend/tests/accessors/accessor_std_private_set_error.phpt create mode 100644 Zend/tests/accessors/accessor_std_public_basic.phpt create mode 100644 Zend/tests/accessors/accessor_std_return_reference_basic.phpt create mode 100644 Zend/tests/accessors/accessor_std_return_reference_setter_error.phpt create mode 100644 Zend/tests/accessors/accessor_traits_basic.phpt create mode 100644 Zend/tests/accessors/automatic_setter_with_typehint.phpt create mode 100644 Zend/tests/accessors/case_sensitivity.phpt create mode 100644 Zend/tests/accessors/debug_backtrace.phpt create mode 100644 Zend/tests/accessors/duplicate_property_declared_error.phpt create mode 100644 Zend/tests/accessors/exception.phpt create mode 100644 Zend/tests/accessors/get_class_methods.phpt create mode 100644 Zend/tests/accessors/get_params_error.phpt create mode 100644 Zend/tests/accessors/isset_params_error.phpt create mode 100644 Zend/tests/accessors/isset_unset_inherit_get_set_modifiers.phpt create mode 100644 Zend/tests/accessors/isset_unset_modifier.phpt create mode 100644 Zend/tests/accessors/overwrite_with_simple_property.phpt create mode 100644 Zend/tests/accessors/parent_accessor_through_reflection.phpt create mode 100644 Zend/tests/accessors/property_visibility_bypassed_properly.phpt create mode 100644 Zend/tests/accessors/std_get_with_paren_optional.phpt create mode 100644 Zend/tests/accessors/std_isset_with_paren_optional.phpt create mode 100644 Zend/tests/accessors/std_set_typehint_error.phpt create mode 100644 Zend/tests/accessors/std_set_with_paren_optional.phpt create mode 100644 Zend/tests/accessors/std_unset_with_paren_optional.phpt create mode 100644 Zend/tests/accessors/subclass_visibility_property_access_allowed.phpt create mode 100644 Zend/tests/accessors/subclass_visibility_property_access_denied.phpt create mode 100644 Zend/tests/accessors/unset_params_error.phpt create mode 100644 ext/reflection/tests/ReflectionProperty_accessors_basic1.phpt create mode 100644 ext/reflection/tests/ReflectionProperty_accessors_getDeclaringClass_basic.phpt create mode 100644 ext/reflection/tests/ReflectionProperty_accessors_getDocComment_basic.phpt create mode 100644 ext/reflection/tests/ReflectionProperty_accessors_getModifiers_basic.phpt create mode 100644 ext/reflection/tests/ReflectionProperty_getGetter_basic.phpt create mode 100644 ext/reflection/tests/ReflectionProperty_getIsset_basic.phpt create mode 100644 ext/reflection/tests/ReflectionProperty_getSetter_basic.phpt create mode 100644 ext/reflection/tests/ReflectionProperty_getUnset_basic.phpt diff --git a/Zend/tests/accessors/abstract_accessor_body_error.phpt b/Zend/tests/accessors/abstract_accessor_body_error.phpt new file mode 100644 index 0000000000000..288da93478c14 --- /dev/null +++ b/Zend/tests/accessors/abstract_accessor_body_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +Abstract accessor can't have a body +--FILE-- + +--EXPECTF-- +Fatal error: Abstract function Foo::$foo->set() cannot contain body in %s on line %d diff --git a/Zend/tests/accessors/abstract_accessor_inherit_error.phpt b/Zend/tests/accessors/abstract_accessor_inherit_error.phpt new file mode 100644 index 0000000000000..cac95d654a7d5 --- /dev/null +++ b/Zend/tests/accessors/abstract_accessor_inherit_error.phpt @@ -0,0 +1,16 @@ +--TEST-- +Classes inheriting abstract accessors have to be marked abstract +--FILE-- + +--EXPECTF-- +Fatal error: Class Foo contains 2 abstract accessors and must be declared abstract or implement the remaining accessors (Foo::$foo->set, Foo::$foo->unset) in %s on line %d diff --git a/Zend/tests/accessors/abstract_accessor_property.phpt b/Zend/tests/accessors/abstract_accessor_property.phpt new file mode 100644 index 0000000000000..299514e98cd04 --- /dev/null +++ b/Zend/tests/accessors/abstract_accessor_property.phpt @@ -0,0 +1,14 @@ +--TEST-- +Accessor properties can be declared abstract +--FILE-- + +--EXPECTF-- +Fatal error: Class Test contains 2 abstract accessors and must be declared abstract or implement the remaining accessors (Test::$foo->set, Test::$foo->unset) in %s on line %d diff --git a/Zend/tests/accessors/abstract_and_final_error.phpt b/Zend/tests/accessors/abstract_and_final_error.phpt new file mode 100644 index 0000000000000..c13f315978e53 --- /dev/null +++ b/Zend/tests/accessors/abstract_and_final_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +Abstract and final modifiers are mutually exclusive +--FILE-- + +--EXPECTF-- +Fatal error: Abstract and final modifiers are mutually exclusive in %s on line %d diff --git a/Zend/tests/accessors/accessor_final_inner_error.phpt b/Zend/tests/accessors/accessor_final_inner_error.phpt new file mode 100644 index 0000000000000..cea10bb5a7eb2 --- /dev/null +++ b/Zend/tests/accessors/accessor_final_inner_error.phpt @@ -0,0 +1,28 @@ +--TEST-- +ZE2 Tests that a asymmetrical final setter cannot be over-ridden. + Also tests that a non-final getter can be over-ridden +--FILE-- +Hours."\n"; +?> +--EXPECTF-- +Fatal error: Cannot override final accessor TimePeriod::$Hours->set() in %s on line %d diff --git a/Zend/tests/accessors/accessor_final_outer_error.phpt b/Zend/tests/accessors/accessor_final_outer_error.phpt new file mode 100644 index 0000000000000..61df813d51f88 --- /dev/null +++ b/Zend/tests/accessors/accessor_final_outer_error.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 Tests that a final getter/setter cannot be over-ridden +--FILE-- +Hours."\n"; +?> +--EXPECTF-- +Fatal error: Cannot override final accessor TimePeriod::$Hours->get() in %s on line %d diff --git a/Zend/tests/accessors/accessor_implicit.phpt b/Zend/tests/accessors/accessor_implicit.phpt new file mode 100644 index 0000000000000..192d06c27c653 --- /dev/null +++ b/Zend/tests/accessors/accessor_implicit.phpt @@ -0,0 +1,23 @@ +--TEST-- +ZE2 Tests that a getter/setter defined as private is overridable in a looser manner and that a getter is inherited +--FILE-- +Seconds."\n"; +echo "Setting Seconds to 3600\n"; +$o->Seconds = 3600; +echo "get Seconds :".$o->Seconds."\n"; +?> +--EXPECTF-- +get Seconds : +Setting Seconds to 3600 +get Seconds :3600 diff --git a/Zend/tests/accessors/accessor_inherited_static.phpt b/Zend/tests/accessors/accessor_inherited_static.phpt new file mode 100644 index 0000000000000..d32b37e2667d0 --- /dev/null +++ b/Zend/tests/accessors/accessor_inherited_static.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 Tests that an inherited static accessor works properlty +--FILE-- + +==DONE== +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d diff --git a/Zend/tests/accessors/accessor_interface_error.phpt b/Zend/tests/accessors/accessor_interface_error.phpt new file mode 100644 index 0000000000000..70b948211434b --- /dev/null +++ b/Zend/tests/accessors/accessor_interface_error.phpt @@ -0,0 +1,19 @@ +--TEST-- +ZE2 Tests that an interface which declares a getter/setter errors if an implementor does not implement them +--FILE-- + +--EXPECTF-- +Fatal error: Class TimePeriod contains 4 abstract accessors and must be declared abstract or implement the remaining accessors (Hours::$Hours->get, Hours::$Hours->set, Hours::$Hours->isset, ...) in %s on line %d diff --git a/Zend/tests/accessors/accessor_interface_partial_implementation_error.phpt b/Zend/tests/accessors/accessor_interface_partial_implementation_error.phpt new file mode 100644 index 0000000000000..152feb71b62f5 --- /dev/null +++ b/Zend/tests/accessors/accessor_interface_partial_implementation_error.phpt @@ -0,0 +1,20 @@ +--TEST-- +ZE2 Tests that an interface which declares a getter/setter errors if an implementor does not implement one of them +--FILE-- + +--EXPECTF-- +Fatal error: Class TimePeriod contains 2 abstract accessors and must be declared abstract or implement the remaining accessors (Hours::$Hours->set, Hours::$Hours->unset) in %s on line %d diff --git a/Zend/tests/accessors/accessor_interface_property_satisfies_accessor_basic.phpt b/Zend/tests/accessors/accessor_interface_property_satisfies_accessor_basic.phpt new file mode 100644 index 0000000000000..7460347b4fc37 --- /dev/null +++ b/Zend/tests/accessors/accessor_interface_property_satisfies_accessor_basic.phpt @@ -0,0 +1,21 @@ +--TEST-- +ZE2 Tests that an interface which declares a getter/setter can be legally implemented by defining a traditional property +--FILE-- +Hours = 5; +echo $o->Hours.PHP_EOL +?> +===DONE=== +--EXPECTF-- +5 +===DONE=== diff --git a/Zend/tests/accessors/accessor_isset_calls_isset_calls_getter_basic.phpt b/Zend/tests/accessors/accessor_isset_calls_isset_calls_getter_basic.phpt new file mode 100644 index 0000000000000..33291f2509f08 --- /dev/null +++ b/Zend/tests/accessors/accessor_isset_calls_isset_calls_getter_basic.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 Tests that the underlying isset() routines calls a getter if one is defined. +--FILE-- +b; } + set { echo "Setting \$b\n"; $this->b = $value; } + isset { return isset($this->b); } + } +} + +$o = new AccessorTest(); +$o->b = 3600; + +echo "\$o->b: ".$o->b."\n"; +echo "isset(\$o->b): ".((int)isset($o->b))."\n"; +?> +===DONE=== +--EXPECTF-- +Setting $b +Getting $b +$o->b: 3600 +Getting $b +isset($o->b): 1 +===DONE=== diff --git a/Zend/tests/accessors/accessor_isset_unset_auto_implement_basic.phpt b/Zend/tests/accessors/accessor_isset_unset_auto_implement_basic.phpt new file mode 100644 index 0000000000000..0076596a79157 --- /dev/null +++ b/Zend/tests/accessors/accessor_isset_unset_auto_implement_basic.phpt @@ -0,0 +1,44 @@ +--TEST-- +ZE2 Tests that isset/unset automatic implementations work as expected, also ensures that isset/unset call the getter/setter accessors +--FILE-- +b; } + set { echo "Setting \$b\n"; $this->b = $value; } + isset; + unset; + } +} + +$o = new AccessorTest(); +$o->b = 3600; + +echo "\$o->b: ".$o->b."\n"; +echo "is_null(\$o->b): ".((int)is_null($o->b))."\n"; +echo "isset(\$o->b): ".((int)isset($o->b))."\n"; +echo "Unsetting \$o->b\n"; +unset($o->b); +echo "is_null(\$o->b): ".((int)is_null($o->b))."\n"; +echo "isset(\$o->b): ".((int)isset($o->b))."\n"; +echo "empty(\$o->b): ".((int)empty($o->b))."\n"; +?> +===DONE=== +--EXPECTF-- +Setting $b +Getting $b +$o->b: 3600 +Getting $b +is_null($o->b): 0 +Getting $b +isset($o->b): 1 +Unsetting $o->b +Setting $b +Getting $b +is_null($o->b): 1 +Getting $b +isset($o->b): 0 +Getting $b +empty($o->b): 1 +===DONE=== diff --git a/Zend/tests/accessors/accessor_isset_unset_default_implemented_basic.phpt b/Zend/tests/accessors/accessor_isset_unset_default_implemented_basic.phpt new file mode 100644 index 0000000000000..5d03552772497 --- /dev/null +++ b/Zend/tests/accessors/accessor_isset_unset_default_implemented_basic.phpt @@ -0,0 +1,39 @@ +--TEST-- +ZE2 Tests that isset/unset default implementations work as expected, also ensures that isset/unset call the getter/setter accessors +--FILE-- +a; } + set { echo "Setting \$b\n"; $this->a = $value; } + } +} + +$o = new AccessorTest(); + +echo "\$o->b: ".$o->b."\n"; +echo "is_null(\$o->b): ".((int)is_null($o->b))."\n"; +echo "isset(\$o->b): ".((int)isset($o->b))."\n"; +echo "Unsetting \$o->b\n"; +unset($o->b); +echo "is_null(\$o->b): ".((int)is_null($o->b))."\n"; +echo "isset(\$o->b): ".((int)isset($o->b))."\n"; +echo "Done\n"; +?> +--EXPECTF-- +Getting $b +$o->b: 3600 +Getting $b +is_null($o->b): 0 +Getting $b +isset($o->b): 1 +Unsetting $o->b +Setting $b +Getting $b +is_null($o->b): 1 +Getting $b +isset($o->b): 0 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_object_get_autoimplement_basic.phpt b/Zend/tests/accessors/accessor_object_get_autoimplement_basic.phpt new file mode 100644 index 0000000000000..a66ecfdfa89e0 --- /dev/null +++ b/Zend/tests/accessors/accessor_object_get_autoimplement_basic.phpt @@ -0,0 +1,25 @@ +--TEST-- +ZE2 Tests that an auto-implemented getter has an auto-implemented variable defined and that it can be retrieved through the accessor +--FILE-- +b: ".$o->b."\n"; +echo "Done\n"; +?> +--EXPECTF-- +object(AccessorTest)#1 (1) { + ["b"]=> + NULL +} +$o->b: +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_object_get_defined_basic.phpt b/Zend/tests/accessors/accessor_object_get_defined_basic.phpt new file mode 100644 index 0000000000000..891422daefada --- /dev/null +++ b/Zend/tests/accessors/accessor_object_get_defined_basic.phpt @@ -0,0 +1,23 @@ +--TEST-- +ZE2 Tests that an defined getter has its code executed and return value properly returned upon access +--FILE-- +b: ".$o->b."\n"; +echo "Done\n"; +?> +--EXPECTF-- +get::$b called. +$o->b: 10 +Done diff --git a/Zend/tests/accessors/accessor_object_get_undefined_error.phpt b/Zend/tests/accessors/accessor_object_get_undefined_error.phpt new file mode 100644 index 0000000000000..c596bbcbb2361 --- /dev/null +++ b/Zend/tests/accessors/accessor_object_get_undefined_error.phpt @@ -0,0 +1,20 @@ +--TEST-- +ZE2 Tests that a non-defined getter produces an error upon access +--FILE-- +b: ".$o->b."\n"; +echo "Done\n"; +?> +--EXPECTF-- +Warning: Cannot get property AccessorTest::$b, no getter defined in %s on line %d +$o->b: +Done diff --git a/Zend/tests/accessors/accessor_object_getset_autoimplemented_basic.phpt b/Zend/tests/accessors/accessor_object_getset_autoimplemented_basic.phpt new file mode 100644 index 0000000000000..dc71899d5ff5d --- /dev/null +++ b/Zend/tests/accessors/accessor_object_getset_autoimplemented_basic.phpt @@ -0,0 +1,22 @@ +--TEST-- +ZE2 Tests that an autoimplemented getter/setter works properly +--FILE-- +b = ".$o->b.PHP_EOL; +$o->b = 1; +echo "\$o->b = ".$o->b.PHP_EOL; + +?> +--EXPECTF-- +$o->b = +$o->b = 1 diff --git a/Zend/tests/accessors/accessor_object_isset_autoimplement_basic.phpt b/Zend/tests/accessors/accessor_object_isset_autoimplement_basic.phpt new file mode 100644 index 0000000000000..92df126c9137d --- /dev/null +++ b/Zend/tests/accessors/accessor_object_isset_autoimplement_basic.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 Tests that an autoimplemented isset defaults to checking the value against a NULL/non-NULL state. +--FILE-- +b) = ".(int)isset($o->b)."\n"; +$o->b = 10; +echo "\$o->b = 10;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +$o->b = NULL; +echo "\$o->b = NULL;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +echo "Done"; +?> +--EXPECTF-- +isset($o->b) = 0 +$o->b = 10; +isset($o->b) = 1 +$o->b = NULL; +isset($o->b) = 0 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_object_isset_defined_basic.phpt b/Zend/tests/accessors/accessor_object_isset_defined_basic.phpt new file mode 100644 index 0000000000000..81e41c78992a8 --- /dev/null +++ b/Zend/tests/accessors/accessor_object_isset_defined_basic.phpt @@ -0,0 +1,37 @@ +--TEST-- +ZE2 Tests that an defined isset has its code executed and the return value passed back as the result of the isset() call. +--FILE-- +b != NULL; + } + } +} + +$o = new AccessorTest(); + +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +$o->b = 10; +echo "\$o->b = 10;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +$o->b = NULL; +echo "\$o->b = NULL;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +echo "Done"; +?> +--EXPECTF-- +$b::isset Called. +isset($o->b) = 0 +$o->b = 10; +$b::isset Called. +isset($o->b) = 1 +$o->b = NULL; +$b::isset Called. +isset($o->b) = 0 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_object_isset_undefined_basic.phpt b/Zend/tests/accessors/accessor_object_isset_undefined_basic.phpt new file mode 100644 index 0000000000000..cebe03f5f2870 --- /dev/null +++ b/Zend/tests/accessors/accessor_object_isset_undefined_basic.phpt @@ -0,0 +1,30 @@ +--TEST-- +ZE2 Tests that an unimplemented isset functions identically to an auto-implemented isset which is checking the value against a NULL/non-NULL state. +--FILE-- +b) = ".(int)isset($o->b)."\n"; +$o->b = 10; +echo "\$o->b = 10;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +$o->b = NULL; +echo "\$o->b = NULL;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +echo "Done"; +?> +--EXPECTF-- +isset($o->b) = 0 +$o->b = 10; +isset($o->b) = 1 +$o->b = NULL; +isset($o->b) = 0 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_object_set_autoimplement_basic.phpt b/Zend/tests/accessors/accessor_object_set_autoimplement_basic.phpt new file mode 100644 index 0000000000000..acb3ed17203f6 --- /dev/null +++ b/Zend/tests/accessors/accessor_object_set_autoimplement_basic.phpt @@ -0,0 +1,32 @@ +--TEST-- +ZE2 Tests that an auto-implemented setter has an auto-implemented variable defined and that it can be changed through the accessor +--FILE-- +b = 5; + } +} + +$o = new AccessorTest(); + +print_r($o); +$o->b = 10; +print_r($o); +echo "Done\n"; +?> +--EXPECTF-- +AccessorTest Object +( + [b] => 5 +) +AccessorTest Object +( + [b] => 10 +) +Done diff --git a/Zend/tests/accessors/accessor_object_set_defined_basic.phpt b/Zend/tests/accessors/accessor_object_set_defined_basic.phpt new file mode 100644 index 0000000000000..181b207639d81 --- /dev/null +++ b/Zend/tests/accessors/accessor_object_set_defined_basic.phpt @@ -0,0 +1,21 @@ +--TEST-- +ZE2 Tests that an defined setter has a protected auto-implemented variable defined and that it can be changed through the accessor +--FILE-- +b = 10; +echo "Done\n"; +?> +--EXPECTF-- +Setter called. +Done diff --git a/Zend/tests/accessors/accessor_object_set_defined_parent_get_called_error.phpt b/Zend/tests/accessors/accessor_object_set_defined_parent_get_called_error.phpt new file mode 100644 index 0000000000000..e5f6b64871acb --- /dev/null +++ b/Zend/tests/accessors/accessor_object_set_defined_parent_get_called_error.phpt @@ -0,0 +1,32 @@ +--TEST-- +ZE2 Tests that access to a undefined parent getter produces an error +--FILE-- +getValue($this); + } + set { + echo "Setter called.\n"; + } + } +} + +$o = new AccessorTest(); +echo $o->b; +?> +--EXPECTF-- +AccessorTest::$b->get() + +Warning: Cannot get property ParentAccessorTest::$b, no getter defined in %s on line %d diff --git a/Zend/tests/accessors/accessor_object_set_undefined_error.phpt b/Zend/tests/accessors/accessor_object_set_undefined_error.phpt new file mode 100644 index 0000000000000..2bdfc215e811a --- /dev/null +++ b/Zend/tests/accessors/accessor_object_set_undefined_error.phpt @@ -0,0 +1,16 @@ +--TEST-- +ZE2 Tests that an undefined setter cannot be called and produces an error +--FILE-- +b = 10; +?> +--EXPECTF-- +Warning: Cannot set property AccessorTest::$b, no setter defined in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_object_unset_autoimplement_basic.phpt b/Zend/tests/accessors/accessor_object_unset_autoimplement_basic.phpt new file mode 100644 index 0000000000000..c64eb39e871a5 --- /dev/null +++ b/Zend/tests/accessors/accessor_object_unset_autoimplement_basic.phpt @@ -0,0 +1,32 @@ +--TEST-- +ZE2 Tests that an autoimplemented unset defaults to setting the value to NULL +--FILE-- +b) = ".(int)isset($o->b)."\n"; +$o->b = 10; +echo "\$o->b = 10;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +unset($o->b); +echo "unset(\$o->b);\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +echo "Done"; +?> +--EXPECTF-- +isset($o->b) = 0 +$o->b = 10; +isset($o->b) = 1 +unset($o->b); +isset($o->b) = 0 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_object_unset_defined_basic.phpt b/Zend/tests/accessors/accessor_object_unset_defined_basic.phpt new file mode 100644 index 0000000000000..a89ae63eddd04 --- /dev/null +++ b/Zend/tests/accessors/accessor_object_unset_defined_basic.phpt @@ -0,0 +1,36 @@ +--TEST-- +ZE2 Tests that an defined unset has it's code executed +--FILE-- +b = NULL; + } + } +} + +$o = new AccessorTest(); + +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +$o->b = 10; +echo "\$o->b = 10;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +unset($o->b); +echo "unset(\$o->b);\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +echo "Done"; +?> +--EXPECTF-- +isset($o->b) = 0 +$o->b = 10; +isset($o->b) = 1 +$b::unset Called. +unset($o->b); +isset($o->b) = 0 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_object_unset_undefined_basic.phpt b/Zend/tests/accessors/accessor_object_unset_undefined_basic.phpt new file mode 100644 index 0000000000000..f87998c58845a --- /dev/null +++ b/Zend/tests/accessors/accessor_object_unset_undefined_basic.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 Tests that an undefined unset defaults to the same functionality as an autodefined unset, which is setting the value to NULL +--FILE-- +b) = ".(int)isset($o->b)."\n"; +$o->b = 10; +echo "\$o->b = 10;\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +unset($o->b); +echo "unset(\$o->b);\n"; +echo "isset(\$o->b) = ".(int)isset($o->b)."\n"; +echo "Done"; +?> +--EXPECTF-- +isset($o->b) = 0 +$o->b = 10; +isset($o->b) = 1 +unset($o->b); +isset($o->b) = 0 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_recursive_call_properly_denied_basic.phpt b/Zend/tests/accessors/accessor_recursive_call_properly_denied_basic.phpt new file mode 100644 index 0000000000000..6ac5a144fca38 --- /dev/null +++ b/Zend/tests/accessors/accessor_recursive_call_properly_denied_basic.phpt @@ -0,0 +1,145 @@ +--TEST-- +ZE2 Tests that recursive accessor calls are denied and emit warning upon detection +--FILE-- +var; + } + set { + echo '__METHOD__ = '.__METHOD__.PHP_EOL.PHP_EOL; + interloper::call_set($this, $value); + $this->var = $value; + } + isset { + echo '__METHOD__ = '.__METHOD__.PHP_EOL.PHP_EOL; + interloper::call_isset($this); + return $this->var !== NULL; + } + unset { + echo '__METHOD__ = '.__METHOD__.PHP_EOL.PHP_EOL; + interloper::call_unset($this); + $this->var = NULL; + } + } +} + +class interloper { + public static function call_set($obj, $value) { + echo "interloper::call_set('$value');".PHP_EOL; + $obj->var = $value; + } + public static function call_get($obj) { + echo "interloper::call_get();".PHP_EOL; + echo "\$obj->var = ".var_export($obj->var, true).PHP_EOL; + } + public static function call_isset($obj) { + echo "interloper::call_isset();".PHP_EOL; + isset($obj->var); + } + public static function call_unset($obj) { + echo "interloper::call_unset();".PHP_EOL; + unset($obj->var); + } +} + +function Title($s) { + echo PHP_EOL.PHP_EOL.$s.PHP_EOL; + echo str_repeat('-', strlen($s)).PHP_EOL; +} + + +$o = new base(); + +Title('Setting value'); +echo '$o->var = 5;'.PHP_EOL; +$o->var = 5; +var_dump($o); + +Title('Getting value'); +echo 'echo $o->var;'.PHP_EOL; +echo $o->var.PHP_EOL; + +Title('Checking value via isset()'); +echo 'isset($o->var);'.PHP_EOL; +var_dump(isset($o->var)); + +Title('unset()ing value'); +echo 'unset($o->var);'.PHP_EOL; +unset($o->var); + +Title('Final results of object'); +var_dump($o); + +?> +===DONE=== +--EXPECTF-- +Setting value +------------- +$o->var = 5; +__METHOD__ = base::$var->set + +interloper::call_set('5'); + +Warning: Recursive access to base::$var->set detected, call ignored. in %s on line %d +object(base)#1 (1) { + ["var"]=> + int(5) +} + + +Getting value +------------- +echo $o->var; +__METHOD__ = base::$var->get + +interloper::call_get(); + +Warning: Recursive access to base::$var->get detected, return value is NULL. in %s on line %d +$obj->var = NULL +5 + + +Checking value via isset() +-------------------------- +isset($o->var); +__METHOD__ = base::$var->isset + +interloper::call_isset(); + +Warning: Recursive access to base::$var->isset detected, call ignored. in %s on line %d +__METHOD__ = base::$var->get + +interloper::call_get(); + +Warning: Recursive access to base::$var->get detected, return value is NULL. in %s on line %d +$obj->var = NULL +bool(true) + + +unset()ing value +---------------- +unset($o->var); +__METHOD__ = base::$var->unset + +interloper::call_unset(); + +Warning: Recursive access to base::$var->unset detected, call ignored. in %s on line %d +__METHOD__ = base::$var->set + +interloper::call_set(''); + +Warning: Recursive access to base::$var->set detected, call ignored. in %s on line %d + + +Final results of object +----------------------- +object(base)#1 (1) { + ["var"]=> + NULL +} +===DONE=== \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_basic.phpt b/Zend/tests/accessors/accessor_static_basic.phpt new file mode 100644 index 0000000000000..4f5507dbcdc83 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_basic.phpt @@ -0,0 +1,34 @@ +--TEST-- +ZE2 Tests that a static getter/setter function properly +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_get_autoimplement_basic.phpt b/Zend/tests/accessors/accessor_static_get_autoimplement_basic.phpt new file mode 100644 index 0000000000000..fa74d54fa0d58 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_get_autoimplement_basic.phpt @@ -0,0 +1,45 @@ +--TEST-- +ZE2 Tests that a static auto-implemented getter has a protected auto-implemented variable defined and that it can be retrieved through the accessor +--FILE-- +getProperties(ReflectionProperty::IS_PROTECTED) as $rfp) { + if($rfp->getName() == '__b') { + if($rfp->isProtected() && $rfp->isStatic()) + echo "Protected static property: \$".$rfp->getName()." exists.\n"; + } +} + +echo "AccessorTest::\$b: ".AccessorTest::$b."\n"; +AccessorTest::setStaticValue(5); +echo "AccessorTest::setStaticValue(5);\n"; +echo "AccessorTest::\$b: ".AccessorTest::$b."\n"; +echo "Done\n"; + + +/********************************************************************************* + * Static accessors as a feature for first release was shelved, the lines below + * are what this test should output when static accessors are written: + ********************************************************************************* +Protected static property: $__b exists. +AccessorTest::$b: +AccessorTest::setStaticValue(5); +AccessorTest::$b: 5 +Done + */ + + +?> +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_get_defined_basic.phpt b/Zend/tests/accessors/accessor_static_get_defined_basic.phpt new file mode 100644 index 0000000000000..d40e9c4d6030d --- /dev/null +++ b/Zend/tests/accessors/accessor_static_get_defined_basic.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 Tests that a static defined getter has it's code called and the return value is represented as the value of the original accessor reference +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_get_undefined_error.phpt b/Zend/tests/accessors/accessor_static_get_undefined_error.phpt new file mode 100644 index 0000000000000..c4d0a719b697d --- /dev/null +++ b/Zend/tests/accessors/accessor_static_get_undefined_error.phpt @@ -0,0 +1,25 @@ +--TEST-- +ZE2 Tests that an undefined static getter produces an error indicating it's non-existence +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_get_undefined_isset_called_error.phpt b/Zend/tests/accessors/accessor_static_get_undefined_isset_called_error.phpt new file mode 100644 index 0000000000000..a3a28d10d09ec --- /dev/null +++ b/Zend/tests/accessors/accessor_static_get_undefined_isset_called_error.phpt @@ -0,0 +1,25 @@ +--TEST-- +ZE2 Tests that an undefined static getter produces an error when attempting to isset() +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_isset_autoimplement_basic.phpt b/Zend/tests/accessors/accessor_static_isset_autoimplement_basic.phpt new file mode 100644 index 0000000000000..9c34c49c3ba69 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_isset_autoimplement_basic.phpt @@ -0,0 +1,42 @@ +--TEST-- +ZE2 Tests that a static auto-implemented isset is equivalent to checking the getter for a NULL/non-NULL value +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_isset_defined_basic.phpt b/Zend/tests/accessors/accessor_static_isset_defined_basic.phpt new file mode 100644 index 0000000000000..170504d14bdc1 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_isset_defined_basic.phpt @@ -0,0 +1,45 @@ +--TEST-- +ZE2 Tests that a static auto-implemented setter has a protected auto-implemented variable defined and that it can be set through the accessor +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_isset_undefined_basic.phpt b/Zend/tests/accessors/accessor_static_isset_undefined_basic.phpt new file mode 100644 index 0000000000000..2eaad1042a55d --- /dev/null +++ b/Zend/tests/accessors/accessor_static_isset_undefined_basic.phpt @@ -0,0 +1,41 @@ +--TEST-- +ZE2 Tests that a static undefined isset is equivalent to an auto-implemented one (returns true if non-NULL) +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_parent_basic.phpt b/Zend/tests/accessors/accessor_static_parent_basic.phpt new file mode 100644 index 0000000000000..1f2635f0f079a --- /dev/null +++ b/Zend/tests/accessors/accessor_static_parent_basic.phpt @@ -0,0 +1,45 @@ +--TEST-- +ZE2 Tests that a static getter/setter function properly through parent accessors +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_set_autoimplement_basic.phpt b/Zend/tests/accessors/accessor_static_set_autoimplement_basic.phpt new file mode 100644 index 0000000000000..defa6b32c9900 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_set_autoimplement_basic.phpt @@ -0,0 +1,45 @@ +--TEST-- +ZE2 Tests that a static auto-implemented setter has a protected auto-implemented variable defined and that it can be set through the accessor +--FILE-- +getProperties(ReflectionProperty::IS_PROTECTED) as $rfp) { + if($rfp->getName() == '__b') { + if($rfp->isProtected() && $rfp->isStatic()) + echo "Protected static property: \$".$rfp->getName()." exists.\n"; + } +} + +echo "AccessorTest::\$b: ".AccessorTest::getStaticValue()."\n"; +AccessorTest::$b = 10; +echo "AccessorTest::\$b = 10;\n"; +echo "AccessorTest::\$b: ".AccessorTest::getStaticValue()."\n"; +echo "Done\n"; + + +/********************************************************************************* + * Static accessors as a feature for first release was shelved, the lines below + * are what this test should output when static accessors are written: + ********************************************************************************* +Protected static property: $__b exists. +AccessorTest::$b: +AccessorTest::$b = 10; +AccessorTest::$b: 10 +Done + */ + + +?> +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_set_defined_basic.phpt b/Zend/tests/accessors/accessor_static_set_defined_basic.phpt new file mode 100644 index 0000000000000..b5ae263cebaa1 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_set_defined_basic.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 Tests that a static defined setter has it's code called. +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_set_defined_get_called_error.phpt b/Zend/tests/accessors/accessor_static_set_defined_get_called_error.phpt new file mode 100644 index 0000000000000..ae92416cb2e1c --- /dev/null +++ b/Zend/tests/accessors/accessor_static_set_defined_get_called_error.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 Tests that a static defined setter has it's code called. +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_set_defined_parent_get_called_error.phpt b/Zend/tests/accessors/accessor_static_set_defined_parent_get_called_error.phpt new file mode 100644 index 0000000000000..6d6d1943e5eff --- /dev/null +++ b/Zend/tests/accessors/accessor_static_set_defined_parent_get_called_error.phpt @@ -0,0 +1,39 @@ +--TEST-- +ZE2 Tests that access to a static undefined parent getter produces compile error (pass_two() functionality) +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_set_defined_self_get_called_error.phpt b/Zend/tests/accessors/accessor_static_set_defined_self_get_called_error.phpt new file mode 100644 index 0000000000000..8a9cb48f9ea47 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_set_defined_self_get_called_error.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 Tests that access to a static undefined self getter produces compile error (pass_two() functionality) +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_set_undefined_error.phpt b/Zend/tests/accessors/accessor_static_set_undefined_error.phpt new file mode 100644 index 0000000000000..755ab1140be61 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_set_undefined_error.phpt @@ -0,0 +1,25 @@ +--TEST-- +ZE2 Tests that an undefined static setter emits an error +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_set_undefined_unset_called_error.phpt b/Zend/tests/accessors/accessor_static_set_undefined_unset_called_error.phpt new file mode 100644 index 0000000000000..d91ced944846c --- /dev/null +++ b/Zend/tests/accessors/accessor_static_set_undefined_unset_called_error.phpt @@ -0,0 +1,25 @@ +--TEST-- +ZE2 Tests that an undefined static setter emits an error +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_unset_autoimplement_basic.phpt b/Zend/tests/accessors/accessor_static_unset_autoimplement_basic.phpt new file mode 100644 index 0000000000000..d35391a30d017 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_unset_autoimplement_basic.phpt @@ -0,0 +1,40 @@ +--TEST-- +ZE2 Tests that a static autoimplemented unset will set the property to a NULL value +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_unset_defined_basic.phpt b/Zend/tests/accessors/accessor_static_unset_defined_basic.phpt new file mode 100644 index 0000000000000..c5bbd252959f5 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_unset_defined_basic.phpt @@ -0,0 +1,44 @@ +--TEST-- +ZE2 Tests that a static defined unset will have the unset code called +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_static_unset_undefined_basic.phpt b/Zend/tests/accessors/accessor_static_unset_undefined_basic.phpt new file mode 100644 index 0000000000000..88abcbc185098 --- /dev/null +++ b/Zend/tests/accessors/accessor_static_unset_undefined_basic.phpt @@ -0,0 +1,38 @@ +--TEST-- +ZE2 Tests that a static undefined unset is equivalent to an autoimplemented unset, which sets the property to a NULL value +--FILE-- + +--EXPECTF-- +Fatal error: Cannot define static accessor %s, not supported at this time in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_std_inherit_looser_basic.phpt b/Zend/tests/accessors/accessor_std_inherit_looser_basic.phpt new file mode 100644 index 0000000000000..2768415be0cc7 --- /dev/null +++ b/Zend/tests/accessors/accessor_std_inherit_looser_basic.phpt @@ -0,0 +1,29 @@ +--TEST-- +ZE2 Tests that a getter/setter defined as private is overridable in a looser manner and that a getter is inherited +--FILE-- +Seconds / 3600; } + private set { $this->Seconds = $value * 3600; } + } +} + +class TimePeriod2 extends TimePeriod { + public $Hours { + public set { $this->Seconds = ($value+1) * 3600; } + } +} + +$o = new TimePeriod2(); + +echo $o->Hours."\n"; +$o->Hours = 2; +echo $o->Hours."\n"; +?> +--EXPECTF-- +1 +3 diff --git a/Zend/tests/accessors/accessor_std_lazy_load_with_getter_basic.phpt b/Zend/tests/accessors/accessor_std_lazy_load_with_getter_basic.phpt new file mode 100644 index 0000000000000..c13e87413bda8 --- /dev/null +++ b/Zend/tests/accessors/accessor_std_lazy_load_with_getter_basic.phpt @@ -0,0 +1,40 @@ +--TEST-- +ZE2 Tests that a getter may define its own property for use with lazy-loading via a getter + This perpetuates a side-effect of the way __get() works, which allows you to define the gotten property + which circumvents calling __get() again. +--FILE-- +Hours ?: $this->Hours = 2; /* Calls Setter */ + } + set { + echo "Set Hours Called ({$value})\n"; + $this->Hours = $value; + } + } +} + +$o = new TimePeriod(); + +echo $o->Hours."\n"; +echo $o->Hours."\n"; +$o->Hours = 4; +echo $o->Hours."\n"; +echo "Done\n"; +?> +--EXPECTF-- +Get Hours Called +Set Hours Called (2) +2 +Get Hours Called +2 +Set Hours Called (4) +Get Hours Called +4 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_std_numeric_operators_basic.phpt b/Zend/tests/accessors/accessor_std_numeric_operators_basic.phpt new file mode 100644 index 0000000000000..e3bf0165d0298 --- /dev/null +++ b/Zend/tests/accessors/accessor_std_numeric_operators_basic.phpt @@ -0,0 +1,151 @@ +--TEST-- +ZE2 Tests that a getter/setter works properly with all operators +--FILE-- + 1, 'b' => 2); + public $_anObject = NULL; + + public function __construct() { + $this->_anObject = new SampleClass(); + } + + public $Hours { + get { return $this->Seconds / 3600; } + set { $this->Seconds = $value * 3600; } + } + public $aString { + get { return $this->_aString; } + set { $this->_aString = $value; } + } + public $anArray { + get { return $this->_anArray; } + set { $this->_anArray = $value; } + } + public $anObject { + get { return $this->_anObject; } + set { $this->_anObject = $value; } + } +} + +$o = new TimePeriod(); + +echo "\n--- Numeric Tests ---\n"; +echo "\$o->Hours = ".$o->Hours."\n"; +echo "\$o->Hours++: ".($o->Hours++)."\n"; +echo "After: {$o->Hours}\n"; +echo "\$o->Hours--: ".($o->Hours--)."\n"; +echo "After: {$o->Hours}\n"; +echo "++\$o->Hours: ".(++$o->Hours)."\n"; +echo "--\$o->Hours: ".(--$o->Hours)."\n"; +$o->Hours += 2; +echo "\$o->Hours += 2: {$o->Hours}\n"; +$o->Hours -= 2; +echo "\$o->Hours -= 2: {$o->Hours}\n"; +$o->Hours *= 3; +echo "\$o->Hours *= 3: {$o->Hours}\n"; +$o->Hours /= 3; +echo "\$o->Hours /= 3: {$o->Hours}\n"; +$o->Hours &= 2; +echo "\$o->Hours &= 2: {$o->Hours}\n"; +$o->Hours = 3; /* Reset */ +echo "\$o->Hours = ".$o->Hours."\n"; +$o->Hours |= 2; +echo "\$o->Hours |= 2: {$o->Hours}\n"; +echo "\$o->Hours % 3: ".($o->Hours % 3)."\n"; +echo "\$o->Hours << 3: ".($o->Hours << 3)."\n"; +echo "\$o->Hours >> 1: ".($o->Hours >> 1)."\n"; +echo "-\$o->Hours : ".(-$o->Hours)."\n"; +echo "\$o->Hours | 2: ".($o->Hours | 2)."\n"; +echo "\$o->Hours & 2: ".($o->Hours & 2)."\n"; +echo "\$o->Hours ^ 2: ".($o->Hours ^ 2)."\n"; +echo "~\$o->Hours: ".(~ $o->Hours)."\n"; +echo "\$o->Hours == 3: ".(int)($o->Hours == 3)."\n"; +echo "\$o->Hours === 3: ".(int)($o->Hours === 3)."\n"; +echo "\$o->Hours != 3: ".(int)($o->Hours != 3)."\n"; +echo "\$o->Hours <> 3: ".(int)($o->Hours <> 3)."\n"; +echo "\$o->Hours !== 3: ".(int)($o->Hours !== 3)."\n"; +echo "\$o->Hours < 4: ".(int)($o->Hours < 4)."\n"; +echo "\$o->Hours > 4: ".(int)($o->Hours > 4)."\n"; +echo "\$o->Hours <= 3: ".(int)($o->Hours <= 3)."\n"; +echo "\$o->Hours >= 3: ".(int)($o->Hours >= 3)."\n"; +echo "\$o->Hours && 3: ".(int)($o->Hours && 3)."\n"; +echo "\$o->Hours || 3: ".(int)($o->Hours || 3)."\n"; +echo "\$o->Hours xor 3: ".(int)($o->Hours xor 3)."\n"; +echo "\n--- String Tests ---\n"; +echo "\$o->aString = \"".($o->aString)."\"\n"; +echo "\$o->aString.\"def\": \"".($o->aString . "def")."\"\n"; +$o->aString .= 'ghi'; +echo "\$o->aString .= \"ghi\": \"".($o->aString)."\"\n"; +echo "\n--- Array Tests ---\n"; +echo "\$o->anArray = array(".implode(',', $o->anArray).")\n"; +echo "\$o->anArray + array('c' => 3, 'd' => 4) = array(".implode(',', $o->anArray + array('c' => 3,'d' => 4)).")\n"; +echo "\$o->anArray == array('a' => 1, 'b' => 2) = ".(int)($o->anArray == array('a' => 1, 'b' => 2))."\n"; +echo "\$o->anArray != array('a' => 1, 'b' => 2) = ".(int)($o->anArray != array('a' => 1, 'b' => 2))."\n"; +echo "\$o->anArray <> array('a' => 1, 'b' => 2) = ".(int)($o->anArray <> array('a' => 1, 'b' => 2))."\n"; +echo "\$o->anArray === array('a' => 1, 'b' => 2) = ".(int)($o->anArray === array('a' => 1, 'b' => 2))."\n"; +echo "\$o->anArray !== array('a' => 1, 'b' => 2) = ".(int)($o->anArray !== array('a' => 1, 'b' => 2))."\n"; +echo "\n--- Type Tests ---\n"; +echo "get_class(\$o->anObject) = ".get_class($o->anObject)."\n"; +echo "\$o->anObject instanceof SampleClass ".($o->anObject instanceof SampleClass)."\n"; +?> +--EXPECTF-- +--- Numeric Tests --- +$o->Hours = 3 +$o->Hours++: 3 +After: 4 +$o->Hours--: 4 +After: 3 +++$o->Hours: 4 +--$o->Hours: 3 +$o->Hours += 2: 5 +$o->Hours -= 2: 3 +$o->Hours *= 3: 9 +$o->Hours /= 3: 3 +$o->Hours &= 2: 2 +$o->Hours = 3 +$o->Hours |= 2: 3 +$o->Hours % 3: 0 +$o->Hours << 3: 24 +$o->Hours >> 1: 1 +-$o->Hours : -3 +$o->Hours | 2: 3 +$o->Hours & 2: 2 +$o->Hours ^ 2: 1 +~$o->Hours: -4 +$o->Hours == 3: 1 +$o->Hours === 3: 1 +$o->Hours != 3: 0 +$o->Hours <> 3: 0 +$o->Hours !== 3: 0 +$o->Hours < 4: 1 +$o->Hours > 4: 0 +$o->Hours <= 3: 1 +$o->Hours >= 3: 1 +$o->Hours && 3: 1 +$o->Hours || 3: 1 +$o->Hours xor 3: 0 + +--- String Tests --- +$o->aString = "abc" +$o->aString."def": "abcdef" +$o->aString .= "ghi": "abcghi" + +--- Array Tests --- +$o->anArray = array(1,2) +$o->anArray + array('c' => 3, 'd' => 4) = array(1,2,3,4) +$o->anArray == array('a' => 1, 'b' => 2) = 1 +$o->anArray != array('a' => 1, 'b' => 2) = 0 +$o->anArray <> array('a' => 1, 'b' => 2) = 0 +$o->anArray === array('a' => 1, 'b' => 2) = 1 +$o->anArray !== array('a' => 1, 'b' => 2) = 0 + +--- Type Tests --- +get_class($o->anObject) = SampleClass +$o->anObject instanceof SampleClass 1 diff --git a/Zend/tests/accessors/accessor_std_other_operations_basic.phpt b/Zend/tests/accessors/accessor_std_other_operations_basic.phpt new file mode 100644 index 0000000000000..8462357dce365 --- /dev/null +++ b/Zend/tests/accessors/accessor_std_other_operations_basic.phpt @@ -0,0 +1,267 @@ +--TEST-- +ZE2 Tests that a getter/setter works properly with other edge case uses +--FILE-- +tArray; } + set { $this->tArray = $value; } + } + public $tArray_ByRef { + &get { return $this->tArray_ByRef; } + set { $this->tArray_ByRef = $value; } + } + + public $objTest_ByRef { + &get { return $this->objTest_ByRef; } + set { $this->objTest_ByRef = $value; } + } + + public $str_ByRef { + &get { return $this->str_ByRef; } + set { $this->str_ByRef = $value; } + } +} + +function Title($s) { + echo PHP_EOL.PHP_EOL.$s.PHP_EOL; + echo str_repeat('-', strlen($s)).PHP_EOL; +} + +$o = new TimePeriod(); +Title("** Array Reference Tests **"); + + Title("Attempt to append to a non-by-reference array accessor:"); + $o->tArray = array(); + print_r($o->tArray); + echo "\$o->tArray[] = 1".PHP_EOL; + $o->tArray[] = 1; + print_r($o->tArray); + + + Title("Append to an array-by-ref:"); + echo '$o->tArray_ByRef = array(\'initial set\');'.PHP_EOL; + $o->tArray_ByRef = array('initial set'); + echo 'print_r($o->tArray_ByRef);'.PHP_EOL; + print_r($o->tArray_ByRef); + echo "\$o->tArray_ByRef[] = 1".PHP_EOL; + $o->tArray_ByRef[] = 1; + print_r($o->tArray_ByRef); + + + Title("Direct set to an array-by-ref:"); + echo '$o->tArray_ByRef = array(\'initial set 2\');'.PHP_EOL; + $o->tArray_ByRef = array('initial set 2'); + echo 'print_r($o->tArray_ByRef);'.PHP_EOL; + print_r($o->tArray_ByRef); + echo "\$o->tArray_ByRef[] = 1".PHP_EOL; + $o->tArray_ByRef[123] = 4; + print_r($o->tArray_ByRef); + + + Title("Copy reference to an array, modify reference copy, check original:"); + echo '$o->tArray_ByRef = array(\'initial set 3\');'.PHP_EOL; + $o->tArray_ByRef = array('initial set 3'); + echo 'print_r($o->tArray_ByRef);'.PHP_EOL; + print_r($o->tArray_ByRef); + echo '$foobar = &$o->tArray_ByRef;'.PHP_EOL; + $foobar = &$o->tArray_ByRef; + echo 'print_r($foobar);'.PHP_EOL; + print_r($foobar); + echo '$foobar[123] = 6;'.PHP_EOL; + $foobar[123] = 6; + echo 'print_r($foobar);'.PHP_EOL; + print_r($foobar); + echo 'print_r($o->tArray_ByRef);'.PHP_EOL; + print_r($o->tArray_ByRef); + +Title("** Object Tests **"); + + Title("Set property of sub-object:"); + echo '$o->objTest_ByRef = new stdClass();'.PHP_EOL; + $o->objTest_ByRef = new stdClass(); + echo 'print_r($o->objTest_ByRef);'.PHP_EOL; + print_r($o->objTest_ByRef); + echo '$o->objTest_ByRef->baz = 1;'.PHP_EOL; + $o->objTest_ByRef->baz = 1; + echo 'print_r($o->objTest_ByRef);'.PHP_EOL; + print_r($o->objTest_ByRef); + + + Title("Set property of empty property as though it were an object:"); + echo 'unset($o->objTest_ByRef);'.PHP_EOL; + unset($o->objTest_ByRef); + echo 'print_r($o->objTest_ByRef);'.PHP_EOL; + print_r($o->objTest_ByRef); + echo '$o->objTest_ByRef->baz = 1;'.PHP_EOL; + $o->objTest_ByRef->baz = 1; + echo 'print_r($o->objTest_ByRef);'.PHP_EOL; + print_r($o->objTest_ByRef); + + Title("Set property of string property as though it were an object:"); + echo '$o->objTest_ByRef = "string".PHP_EOL;'.PHP_EOL; + $o->objTest_ByRef = "string".PHP_EOL; + echo 'print_r($o->objTest_ByRef);'.PHP_EOL; + print_r($o->objTest_ByRef); + echo '$o->objTest_ByRef->baz = 1;'.PHP_EOL; + $o->objTest_ByRef->baz = 1; + echo 'print_r($o->objTest_ByRef);'.PHP_EOL; + print_r($o->objTest_ByRef); + +Title("** String Offset Tests **"); + + Title("String Offsets:"); + echo '$o->str_ByRef = "string".PHP_EOL;'.PHP_EOL; + $o->str_ByRef = "string".PHP_EOL; + echo 'print_r($o->str_ByRef);'.PHP_EOL; + print_r($o->str_ByRef); + echo '$x = 3;'.PHP_EOL; + $x = 3; + echo '$o->str_ByRef{$x} = "bar";'.PHP_EOL; + $o->str_ByRef{$x} = "bar"; + echo 'print_r($o->str_ByRef);'.PHP_EOL; + print_r($o->str_ByRef); +?> +===DONE=== +--EXPECTF-- +** Array Reference Tests ** +--------------------------- + + +Attempt to append to a non-by-reference array accessor: +------------------------------------------------------- +Array +( +) +$o->tArray[] = 1 + +Notice: Indirect modification of overloaded property TimePeriod::$tArray has no effect in %s on line %d +Array +( +) + + +Append to an array-by-ref: +-------------------------- +$o->tArray_ByRef = array('initial set'); +print_r($o->tArray_ByRef); +Array +( + [0] => initial set +) +$o->tArray_ByRef[] = 1 +Array +( + [0] => initial set + [1] => 1 +) + + +Direct set to an array-by-ref: +------------------------------ +$o->tArray_ByRef = array('initial set 2'); +print_r($o->tArray_ByRef); +Array +( + [0] => initial set 2 +) +$o->tArray_ByRef[] = 1 +Array +( + [0] => initial set 2 + [123] => 4 +) + + +Copy reference to an array, modify reference copy, check original: +------------------------------------------------------------------ +$o->tArray_ByRef = array('initial set 3'); +print_r($o->tArray_ByRef); +Array +( + [0] => initial set 3 +) +$foobar = &$o->tArray_ByRef; +print_r($foobar); +Array +( + [0] => initial set 3 +) +$foobar[123] = 6; +print_r($foobar); +Array +( + [0] => initial set 3 + [123] => 6 +) +print_r($o->tArray_ByRef); +Array +( + [0] => initial set 3 + [123] => 6 +) + + +** Object Tests ** +------------------ + + +Set property of sub-object: +--------------------------- +$o->objTest_ByRef = new stdClass(); +print_r($o->objTest_ByRef); +stdClass Object +( +) +$o->objTest_ByRef->baz = 1; +print_r($o->objTest_ByRef); +stdClass Object +( + [baz] => 1 +) + + +Set property of empty property as though it were an object: +----------------------------------------------------------- +unset($o->objTest_ByRef); +print_r($o->objTest_ByRef); +$o->objTest_ByRef->baz = 1; + +Warning: Creating default object from empty value in %s on line %d +print_r($o->objTest_ByRef); +stdClass Object +( + [baz] => 1 +) + + +Set property of string property as though it were an object: +------------------------------------------------------------ +$o->objTest_ByRef = "string".PHP_EOL; +print_r($o->objTest_ByRef); +string +$o->objTest_ByRef->baz = 1; + +Warning: Attempt to assign property of non-object in %s on line %d +print_r($o->objTest_ByRef); +string + + +** String Offset Tests ** +------------------------- + + +String Offsets: +--------------- +$o->str_ByRef = "string".PHP_EOL; +print_r($o->str_ByRef); +string +$x = 3; +$o->str_ByRef{$x} = "bar"; +print_r($o->str_ByRef); +strbng +===DONE=== \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_std_private_get_error.phpt b/Zend/tests/accessors/accessor_std_private_get_error.phpt new file mode 100644 index 0000000000000..2081fe44cc19a --- /dev/null +++ b/Zend/tests/accessors/accessor_std_private_get_error.phpt @@ -0,0 +1,20 @@ +--TEST-- +ZE2 Tests that a getter/setter defined as private is not accessible externally +--FILE-- +Seconds / 3600; } + private set { $this->Seconds = $value * 3600; } + } +} + +$o = new TimePeriod(); + +echo $o->Hours."\n"; +?> +--EXPECTF-- +Fatal error: Call to private accessor TimePeriod::$Hours->get() from context '' in %s on line %d diff --git a/Zend/tests/accessors/accessor_std_private_set_error.phpt b/Zend/tests/accessors/accessor_std_private_set_error.phpt new file mode 100644 index 0000000000000..ab432c69cc14b --- /dev/null +++ b/Zend/tests/accessors/accessor_std_private_set_error.phpt @@ -0,0 +1,23 @@ +--TEST-- +ZE2 Tests that a getter/setter defined as private is not accessible externally +--FILE-- +Seconds / 3600; } + private set { $this->Seconds = $value * 3600; } + } +} + +$o = new TimePeriod(); + +echo $o->Hours."\n"; +$o->Hours = 2; +?> +--EXPECTF-- +1 + +Fatal error: Call to private accessor TimePeriod::$Hours->set() from context '' in %s on line %d diff --git a/Zend/tests/accessors/accessor_std_public_basic.phpt b/Zend/tests/accessors/accessor_std_public_basic.phpt new file mode 100644 index 0000000000000..0712654768cdd --- /dev/null +++ b/Zend/tests/accessors/accessor_std_public_basic.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 Tests that a getter/setter defined as public applies to both getter/setter +--FILE-- +Seconds / 3600; } + set { $this->Seconds = $value * 3600; } + } +} + +$o = new TimePeriod(); + +echo $o->Hours."\n"; +$o->Hours = 2; +echo $o->Seconds."\n"; + +echo "Done\n"; +?> +--EXPECTF-- +1 +7200 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_std_return_reference_basic.phpt b/Zend/tests/accessors/accessor_std_return_reference_basic.phpt new file mode 100644 index 0000000000000..f33021c84ff14 --- /dev/null +++ b/Zend/tests/accessors/accessor_std_return_reference_basic.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 Tests that an getter which returns a reference is returning a reference +--FILE-- +_dataArray; } + } +} + +$o = new SampleClass(); +print_r($o->dataArray); +sort($o->dataArray); +print_r($o->_dataArray); +?> +--EXPECTF-- +Array +( + [0] => 1 + [1] => 2 + [2] => 5 + [3] => 3 +) +Array +( + [0] => 1 + [1] => 2 + [2] => 3 + [3] => 5 +) \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_std_return_reference_setter_error.phpt b/Zend/tests/accessors/accessor_std_return_reference_setter_error.phpt new file mode 100644 index 0000000000000..b5a4a7cb727c2 --- /dev/null +++ b/Zend/tests/accessors/accessor_std_return_reference_setter_error.phpt @@ -0,0 +1,35 @@ +--TEST-- +ZE2 Tests that an setter which returns a reference generates a warning +--FILE-- +_dataArray; } + &set { $this->_dataArray = $value; } + } +} + +$o = new SampleClass(); +print_r($o->dataArray); +sort($o->dataArray); +print_r($o->dataArray); +?> +--EXPECTF-- +Warning: Property setter SampleClass::$dataArray indicates a return reference with '&', setters do not return values, ignored. in %s on line %d +Array +( + [0] => 1 + [1] => 2 + [2] => 5 + [3] => 3 +) +Array +( + [0] => 1 + [1] => 2 + [2] => 3 + [3] => 5 +) \ No newline at end of file diff --git a/Zend/tests/accessors/accessor_traits_basic.phpt b/Zend/tests/accessors/accessor_traits_basic.phpt new file mode 100644 index 0000000000000..8adcec8f541a9 --- /dev/null +++ b/Zend/tests/accessors/accessor_traits_basic.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 Tests that a getter/setter defined in a trait is inherited appropriately +--FILE-- +Seconds / 3600; } + set { $this->Seconds = $value * 3600; } + } +} + +class TimePeriod { + use Hours; + public $Seconds = 3600; + +} + +$o = new TimePeriod(); + +echo $o->Hours."\n"; +$o->Hours = 2; +echo $o->Hours."\n"; +?> +--EXPECTF-- +1 +2 diff --git a/Zend/tests/accessors/automatic_setter_with_typehint.phpt b/Zend/tests/accessors/automatic_setter_with_typehint.phpt new file mode 100644 index 0000000000000..4915c40630b9b --- /dev/null +++ b/Zend/tests/accessors/automatic_setter_with_typehint.phpt @@ -0,0 +1,22 @@ +--TEST-- +Automatic setters can have typehints +--FILE-- +test = new stdClass; +var_dump($test->test); +$test->test = 42; + +?> +--EXPECTF-- +object(stdClass)#2 (0) { +} + +Catchable fatal error: Argument 1 passed to Test::$test->set() must be an instance of stdClass, integer given in %s on line %d diff --git a/Zend/tests/accessors/case_sensitivity.phpt b/Zend/tests/accessors/case_sensitivity.phpt new file mode 100644 index 0000000000000..171b983bf5881 --- /dev/null +++ b/Zend/tests/accessors/case_sensitivity.phpt @@ -0,0 +1,19 @@ +--TEST-- +Accessors (like all properties) are case sensitive +--FILE-- +foo = 1; +$test->Foo = 2; +var_dump($test->foo, $test->Foo); + +?> +--EXPECT-- +int(1) +int(2) diff --git a/Zend/tests/accessors/debug_backtrace.phpt b/Zend/tests/accessors/debug_backtrace.phpt new file mode 100644 index 0000000000000..23f6aaf84b570 --- /dev/null +++ b/Zend/tests/accessors/debug_backtrace.phpt @@ -0,0 +1,117 @@ +--TEST-- +debug_backtrace() from within accessor +--FILE-- +bar; +$foo->bar = 'test'; +isset($foo->bar); +unset($foo->bar); + +?> +--EXPECTF-- +array(1) { + [0]=> + array(7) { + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) + ["function"]=> + string(9) "$bar->get" + ["class"]=> + string(3) "Foo" + ["object"]=> + object(Foo)#1 (1) { + ["bar"]=> + NULL + } + ["type"]=> + string(2) "->" + ["args"]=> + array(0) { + } + } +} +array(1) { + [0]=> + array(7) { + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) + ["function"]=> + string(9) "$bar->set" + ["class"]=> + string(3) "Foo" + ["object"]=> + object(Foo)#1 (1) { + ["bar"]=> + NULL + } + ["type"]=> + string(2) "->" + ["args"]=> + array(1) { + [0]=> + &string(4) "test" + } + } +} +array(1) { + [0]=> + array(7) { + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) + ["function"]=> + string(11) "$bar->isset" + ["class"]=> + string(3) "Foo" + ["object"]=> + object(Foo)#1 (1) { + ["bar"]=> + NULL + } + ["type"]=> + string(2) "->" + ["args"]=> + array(0) { + } + } +} +array(1) { + [0]=> + array(7) { + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) + ["function"]=> + string(11) "$bar->unset" + ["class"]=> + string(3) "Foo" + ["object"]=> + object(Foo)#1 (1) { + ["bar"]=> + NULL + } + ["type"]=> + string(2) "->" + ["args"]=> + array(0) { + } + } +} diff --git a/Zend/tests/accessors/duplicate_property_declared_error.phpt b/Zend/tests/accessors/duplicate_property_declared_error.phpt new file mode 100644 index 0000000000000..a67a52d8dc168 --- /dev/null +++ b/Zend/tests/accessors/duplicate_property_declared_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 Tests that an accessor cannot be declared if a property is already declared +--FILE-- + +--EXPECTF-- +Fatal error: Cannot redeclare TimePeriod::$Seconds in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/exception.phpt b/Zend/tests/accessors/exception.phpt new file mode 100644 index 0000000000000..ebf73b97d9fb1 --- /dev/null +++ b/Zend/tests/accessors/exception.phpt @@ -0,0 +1,42 @@ +--TEST-- +Throwing an exception from an accessor +--FILE-- +bar; } catch (Exception $e) { echo $e, "\n\n"; } +try { $foo->bar = 'test'; } catch (Exception $e) { echo $e, "\n\n"; } +try { isset($foo->bar); } catch (Exception $e) { echo $e, "\n\n"; } +try { unset($foo->bar); } catch (Exception $e) { echo $e, "\n\n"; } + +?> +--EXPECTF-- +exception 'Exception' with message 'except in getter' in %s:%d +Stack trace: +#0 %s(%d): Foo->$bar->get() +#1 {main} + +exception 'Exception' with message 'except in setter' in %s:%d +Stack trace: +#0 %s(%d): Foo->$bar->set('test') +#1 {main} + +exception 'Exception' with message 'except in issetter' in %s:%d +Stack trace: +#0 %s(%d): Foo->$bar->isset() +#1 {main} + +exception 'Exception' with message 'except in unsetter' in %s:%d +Stack trace: +#0 %s(%d): Foo->$bar->unset() +#1 {main} diff --git a/Zend/tests/accessors/get_class_methods.phpt b/Zend/tests/accessors/get_class_methods.phpt new file mode 100644 index 0000000000000..f2ab5169db87a --- /dev/null +++ b/Zend/tests/accessors/get_class_methods.phpt @@ -0,0 +1,18 @@ +--TEST-- +Accessors are not class methods +--FILE-- + +--EXPECT-- +array(1) { + [0]=> + string(10) "testMethod" +} diff --git a/Zend/tests/accessors/get_params_error.phpt b/Zend/tests/accessors/get_params_error.phpt new file mode 100644 index 0000000000000..8329015bae28a --- /dev/null +++ b/Zend/tests/accessors/get_params_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 Tests that a getter defined with parameters throws an error +--FILE-- + +--EXPECTF-- +Fatal error: Getters do not accept parameters for variable TimePeriod::$Hours in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/isset_params_error.phpt b/Zend/tests/accessors/isset_params_error.phpt new file mode 100644 index 0000000000000..715e9e1a41ca2 --- /dev/null +++ b/Zend/tests/accessors/isset_params_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 Tests that an issetter defined with parameters throws an error +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected '$x' (T_VARIABLE), expecting ')' in %s on line %d \ No newline at end of file diff --git a/Zend/tests/accessors/isset_unset_inherit_get_set_modifiers.phpt b/Zend/tests/accessors/isset_unset_inherit_get_set_modifiers.phpt new file mode 100644 index 0000000000000..3f560245a8ff9 --- /dev/null +++ b/Zend/tests/accessors/isset_unset_inherit_get_set_modifiers.phpt @@ -0,0 +1,59 @@ +--TEST-- +Isset/unset inherit get/set visibility +--FILE-- + +--EXPECTF-- +Accessor [ public $foo ] { + Method [ protected method $foo->get ] { + @@ %s %d - %d + } + Method [ private method $foo->set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ protected method $foo->isset ] { + @@ %s %d - %d + } + Method [ private method $foo->unset ] { + @@ %s %d - %d + } +} + ] +Accessor [ public $bar ] { + Method [ abstract public method $bar->get ] { + @@ %s %d - %d + } + Method [ final public method $bar->set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ abstract public method $bar->isset ] { + @@ %s %d - %d + } + Method [ final public method $bar->unset ] { + @@ %s %d - %d + } +} + ] diff --git a/Zend/tests/accessors/isset_unset_modifier.phpt b/Zend/tests/accessors/isset_unset_modifier.phpt new file mode 100644 index 0000000000000..0bd4569bca3a8 --- /dev/null +++ b/Zend/tests/accessors/isset_unset_modifier.phpt @@ -0,0 +1,22 @@ +--TEST-- +Isset and unset can have modifiers +--FILE-- + +--EXPECTF-- +Fatal error: Cannot override final accessor Test::$foo->isset() in %s on line %d diff --git a/Zend/tests/accessors/overwrite_with_simple_property.phpt b/Zend/tests/accessors/overwrite_with_simple_property.phpt new file mode 100644 index 0000000000000..b38370c4322ab --- /dev/null +++ b/Zend/tests/accessors/overwrite_with_simple_property.phpt @@ -0,0 +1,39 @@ +--TEST-- +Accessors can be re-declared with a plain property +--FILE-- +foo = 'bar'; +var_dump($base->foo); + +$childO = new Child_Overriding; +$childO->foo = 'bar'; +var_dump($childO->foo); + +$childI = new Child_Inheriting; +$childI->foo = 'bar'; +var_dump($childI->foo); + +?> +--EXPECT-- +setting $foo to bar +string(4) "test" +string(3) "bar" +setting $foo to bar +string(4) "test" diff --git a/Zend/tests/accessors/parent_accessor_through_reflection.phpt b/Zend/tests/accessors/parent_accessor_through_reflection.phpt new file mode 100644 index 0000000000000..e62f0a67b0626 --- /dev/null +++ b/Zend/tests/accessors/parent_accessor_through_reflection.phpt @@ -0,0 +1,34 @@ +--TEST-- +The parent accessor can be accessed through Reflection +--FILE-- +foo; } + set { echo __METHOD__."($value)".PHP_EOL; $this->foo = $value; } + } +} + +class Test2 extends Test { + public $foo { + get { + echo __METHOD__."() -> "; + return (new ReflectionProperty(get_parent_class(), 'foo'))->getValue($this); + } + set { + echo __METHOD__."($value) -> "; + (new ReflectionProperty(get_parent_class(), 'foo'))->setValue($this, $value); + } + } +} + +$test = new Test2; +$test->foo = 'value'; +var_dump($test->foo); +?> +===DONE=== +--EXPECTF-- +Test2::$foo->set(value) -> Test::$foo->set(value) +Test2::$foo->get() -> Test::$foo->get() = string(%d) "value" +===DONE=== \ No newline at end of file diff --git a/Zend/tests/accessors/property_visibility_bypassed_properly.phpt b/Zend/tests/accessors/property_visibility_bypassed_properly.phpt new file mode 100644 index 0000000000000..e423a883388f2 --- /dev/null +++ b/Zend/tests/accessors/property_visibility_bypassed_properly.phpt @@ -0,0 +1,29 @@ +--TEST-- +ZE2 Visibility of property is ignored when involving an accessor (accessor visibility checked) +--FILE-- +bar); + +class Foo2 { + private $bar { + public get { return 'test2'; } + } +} + +$foo2 = new Foo2(); +var_dump($foo2->bar); + +?> +===DONE=== +--EXPECTF-- +string(%d) "test" +string(%d) "test2" +===DONE=== \ No newline at end of file diff --git a/Zend/tests/accessors/std_get_with_paren_optional.phpt b/Zend/tests/accessors/std_get_with_paren_optional.phpt new file mode 100644 index 0000000000000..d61809d513b42 --- /dev/null +++ b/Zend/tests/accessors/std_get_with_paren_optional.phpt @@ -0,0 +1,39 @@ +--TEST-- +ZE2 Tests that a getter can be defined with or without parenthesis +--FILE-- +Seconds / 3600; } + } + public $Hours2 { + get; + } + public $Hours3 { + get(); + } + public $Hours4 { + get() { return $this->Seconds / 3600; } + } +} + +$o = new TimePeriod(); + +echo $o->Hours."\n"; +echo $o->Hours2."\n"; +echo $o->Hours3."\n"; +echo $o->Hours4."\n"; +echo $o->Seconds."\n"; + +echo "Done\n"; +?> +--EXPECTF-- +1 + + +1 +3600 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/std_isset_with_paren_optional.phpt b/Zend/tests/accessors/std_isset_with_paren_optional.phpt new file mode 100644 index 0000000000000..62036a97d404a --- /dev/null +++ b/Zend/tests/accessors/std_isset_with_paren_optional.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 Tests that an issetter may be defined with or without parameters +--FILE-- +Test1)."\n"; +echo (int)isset($o->Test2)."\n"; +echo "Done\n"; +?> +--EXPECTF-- +1 +0 +Done \ No newline at end of file diff --git a/Zend/tests/accessors/std_set_typehint_error.phpt b/Zend/tests/accessors/std_set_typehint_error.phpt new file mode 100644 index 0000000000000..5dd63b5351f3b --- /dev/null +++ b/Zend/tests/accessors/std_set_typehint_error.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZE2 Tests that a setter defined with a typehint produces error on invalid parameter pass +--FILE-- +_Seconds = $y; } + } +} + +$o = new TimePeriod(); +$tc = new TestClass(); + +$o->Object = $tc; +?> +--EXPECTF-- +Catchable fatal error: Argument 1 passed to TimePeriod::$Object->set() must be an instance of TestClass2, instance of TestClass given in %s on line %d diff --git a/Zend/tests/accessors/std_set_with_paren_optional.phpt b/Zend/tests/accessors/std_set_with_paren_optional.phpt new file mode 100644 index 0000000000000..c59f3b5782090 --- /dev/null +++ b/Zend/tests/accessors/std_set_with_paren_optional.phpt @@ -0,0 +1,50 @@ +--TEST-- +ZE2 Tests that a setter may be defined with or without parameters +--FILE-- +_Seconds = $value; } + } + public $Seconds2 { + set; + } + public $Seconds3 { + set($x) { $this->_Seconds = $x; } + } + public $Object { + set(TestClass $y) { $this->_Seconds = $y; } + } +} + +$o = new TimePeriod(); +$tc = new TestClass(); + +echo $o->_Seconds."\n"; +$o->Seconds = 4000; +echo $o->_Seconds."\n"; +$o->Seconds2 = 45; +echo $o->_Seconds."\n"; +$o->Seconds3 = 5000; +echo $o->_Seconds."\n"; +$o->Object = $tc; +echo $o->_Seconds."\n"; + +echo "Done\n"; +?> +--EXPECTF-- +3600 +4000 +4000 +5000 +Object [TestClass] +Done \ No newline at end of file diff --git a/Zend/tests/accessors/std_unset_with_paren_optional.phpt b/Zend/tests/accessors/std_unset_with_paren_optional.phpt new file mode 100644 index 0000000000000..be778c5e09205 --- /dev/null +++ b/Zend/tests/accessors/std_unset_with_paren_optional.phpt @@ -0,0 +1,22 @@ +--TEST-- +ZE2 Tests that an unsetter may be defined with or without parameters +--FILE-- + +--EXPECTF-- +Done \ No newline at end of file diff --git a/Zend/tests/accessors/subclass_visibility_property_access_allowed.phpt b/Zend/tests/accessors/subclass_visibility_property_access_allowed.phpt new file mode 100644 index 0000000000000..63da14cd56653 --- /dev/null +++ b/Zend/tests/accessors/subclass_visibility_property_access_allowed.phpt @@ -0,0 +1,69 @@ +--TEST-- +ZE2 Visibility of the property is bypassed and visibility of accessor is allowed in subclass +--FILE-- +bar; + } + public set { + echo __METHOD__."($value)".PHP_EOL; + $this->bar = $value; + } + } + + public function __construct() { + echo __CLASS__.'::__construct()'.PHP_EOL; + $this->bar = 20; + } + + public function getbar() { + return $this->bar; + } +} + +class SubFoo extends Foo { +} + +$foo = new Foo(); +echo '$foo->bar = '; var_dump($foo->bar); +echo '$foo->getbar() = '; var_dump($foo->getbar()); + +echo PHP_EOL.'-------------------------'.PHP_EOL.PHP_EOL; + +$subfoo = new SubFoo(); +echo '$subfoo->getbar() = '; var_dump($subfoo->getbar()); +echo '$subfoo->bar = '; var_dump($subfoo->bar); +echo '$subfoo->bar = 10;'.PHP_EOL; +$subfoo->bar = 10; +echo '$subfoo->bar = '; var_dump($subfoo->bar); +echo '$subfoo->getbar() = '; var_dump($subfoo->getbar()); + +var_dump($subfoo); + +?> +==DONE== +--EXPECTF-- +Foo::__construct() +Foo::$bar->set(20) +$foo->bar = Foo::$bar->get() = int(20) +$foo->getbar() = Foo::$bar->get() = int(20) + +------------------------- + +Foo::__construct() +Foo::$bar->set(20) +$subfoo->getbar() = Foo::$bar->get() = int(20) +$subfoo->bar = Foo::$bar->get() = int(20) +$subfoo->bar = 10; +Foo::$bar->set(10) +$subfoo->bar = Foo::$bar->get() = int(10) +$subfoo->getbar() = Foo::$bar->get() = int(10) +object(SubFoo)#2 (1) { + ["bar":"Foo":private]=> + int(10) +} +==DONE== diff --git a/Zend/tests/accessors/subclass_visibility_property_access_denied.phpt b/Zend/tests/accessors/subclass_visibility_property_access_denied.phpt new file mode 100644 index 0000000000000..06d8e7dba3fde --- /dev/null +++ b/Zend/tests/accessors/subclass_visibility_property_access_denied.phpt @@ -0,0 +1,56 @@ +--TEST-- +ZE2 Visibility of the property is bypassed and visibility of accessor is denied in subclass +--FILE-- +bar; + } + private set { + echo __METHOD__."($value)".PHP_EOL; + $this->bar = $value; + } + } + + public function __construct() { + echo __CLASS__.'::__construct()'.PHP_EOL; + $this->bar = 20; + } + + public function getbar() { + return $this->bar; + } +} + +class SubFoo extends Foo { + public function getbar2() { + return $this->bar; + } +} + +$foo = new Foo(); +#echo '$foo->bar = '; var_dump($foo->bar); +echo '$foo->getbar() = '; var_dump($foo->getbar()); + +echo PHP_EOL.'-------------------------'.PHP_EOL.PHP_EOL; + +$subfoo = new SubFoo(); +echo '$subfoo->getbar() = '; var_dump($subfoo->getbar()); +echo '$subfoo->getbar2() = '; var_dump($subfoo->getbar2()); + +?> +--EXPECTF-- +Foo::__construct() +Foo::$bar->set(20) +$foo->getbar() = Foo::$bar->get() = int(20) + +------------------------- + +Foo::__construct() +Foo::$bar->set(20) +$subfoo->getbar() = Foo::$bar->get() = int(20) +$subfoo->getbar2() = +Fatal error: Call to private accessor Foo::$bar->get() from context 'SubFoo' in %s on line %d diff --git a/Zend/tests/accessors/unset_params_error.phpt b/Zend/tests/accessors/unset_params_error.phpt new file mode 100644 index 0000000000000..9ea8012faf4a7 --- /dev/null +++ b/Zend/tests/accessors/unset_params_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 Tests that an unsetter defined with parameters throws an error +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected '$x' (T_VARIABLE), expecting ')' in %s on line %d \ No newline at end of file diff --git a/Zend/zend.c b/Zend/zend.c index aad6165e408a3..c6f2bbcc3f883 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -692,6 +692,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS zend_execute_internal = NULL; #endif /* HAVE_SYS_SDT_H */ zend_compile_string = compile_string; + zend_compile_string_inline = compile_string_inline; zend_throw_exception_hook = NULL; zend_init_opcodes_handlers(); diff --git a/Zend/zend.h b/Zend/zend.h index 40515fbfdd8e2..27f296da8b280 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -314,7 +314,7 @@ typedef struct _zend_object { zend_class_entry *ce; HashTable *properties; zval **properties_table; - HashTable *guards; /* protects from __get/__set ... recursion */ + HashTable *guards; /* protects from __get/__set/accessor ... recursion */ } zend_object; #include "zend_object_handlers.h" @@ -480,6 +480,7 @@ struct _zend_class_entry { HashTable function_table; HashTable properties_info; + zval **default_properties_table; zval **default_static_members_table; zval **static_members_table; diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 95c90ea753c8d..5f85bf8dac6c4 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3430,6 +3430,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in property_info.doc_comment_len = doc_comment_len; property_info.ce = ce; + property_info.accs = NULL; zend_hash_quick_update(&ce->properties_info, name, name_length+1, h, &property_info, sizeof(zend_property_info), NULL); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 10eac2d94e1ce..273b5251fa333 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5,7 +5,7 @@ | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | + | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend license and are unable to | @@ -99,26 +99,61 @@ ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC); +ZEND_API void (*zend_compile_string_inline)(zval *source_string, char *filename TSRMLS_DC); #ifndef ZTS ZEND_API zend_compiler_globals compiler_globals; ZEND_API zend_executor_globals executor_globals; #endif +static zend_function *duplicate_accessor_function(zend_function *fn) /* {{{ */ +{ + zend_op_array *op_array = pemalloc(sizeof(zend_op_array), 1); + memcpy(op_array, &fn->op_array, sizeof(zend_op_array)); + function_add_ref((zend_function *) op_array); + return (zend_function *) op_array; +} +/* }}} */ + +static const char *zend_get_property_name(const zend_property_info *property_info) /* {{{ */ +{ + const char *class_name, *prop_name; + + if (zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name) == FAILURE) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot get property name"); + } + + return prop_name; +} +/* }}} */ + static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */ { - if (!IS_INTERNED(property_info->name)) { + zend_function **orig_accs = property_info->accs; + + if (!IS_INTERNED(property_info->name)) { property_info->name = estrndup(property_info->name, property_info->name_length); } if (property_info->doc_comment) { property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len); } + + if (orig_accs) { + int i; + + property_info->accs = ecalloc(ZEND_NUM_ACCESSORS, sizeof(zend_function *)); + for (i = 0; i < ZEND_NUM_ACCESSORS; ++i) { + if (orig_accs[i]) { + property_info->accs[i] = duplicate_accessor_function(orig_accs[i]); + } + } + } } /* }}} */ static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */ { - if (!IS_INTERNED(property_info->name)) { + if (!IS_INTERNED(property_info->name)) { property_info->name = zend_strndup(property_info->name, property_info->name_length); } } @@ -130,6 +165,21 @@ static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ if (property_info->doc_comment) { efree((char*)property_info->doc_comment); } + + if (property_info->accs) { + zend_function **accs = property_info->accs; + int i; + TSRMLS_FETCH(); + + for (i = 0; i < ZEND_NUM_ACCESSORS; ++i) { + if (accs[i]) { + destroy_op_array((zend_op_array *) accs[i] TSRMLS_CC); + pefree(accs[i], 1); + } + } + + efree(accs); + } } /* }}} */ @@ -383,7 +433,7 @@ int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC zval c; int lc_literal; - if (op_array->last_literal > 0 && + if (op_array->last_literal > 0 && &op_array->literals[op_array->last_literal - 1].constant == zv && op_array->literals[op_array->last_literal - 1].cache_slot == -1) { /* we already have function name as last literal (do nothing) */ @@ -391,7 +441,7 @@ int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC } else { ret = zend_add_literal(op_array, zv TSRMLS_CC); } - + lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0); lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC); @@ -410,7 +460,7 @@ int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS zval c; int lc_literal; - if (op_array->last_literal > 0 && + if (op_array->last_literal > 0 && &op_array->literals[op_array->last_literal - 1].constant == zv && op_array->literals[op_array->last_literal - 1].cache_slot == -1) { /* we already have function name as last literal (do nothing) */ @@ -443,7 +493,7 @@ int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_D zval c; int lc_literal; - if (op_array->last_literal > 0 && + if (op_array->last_literal > 0 && &op_array->literals[op_array->last_literal - 1].constant == zv && op_array->literals[op_array->last_literal - 1].cache_slot == -1) { /* we already have function name as last literal (do nothing) */ @@ -477,7 +527,7 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq int name_len, ns_len; zval c; - if (op_array->last_literal > 0 && + if (op_array->last_literal > 0 && &op_array->literals[op_array->last_literal - 1].constant == zv && op_array->literals[op_array->last_literal - 1].cache_slot == -1) { /* we already have function name as last literal (do nothing) */ @@ -486,7 +536,7 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq ret = zend_add_literal(op_array, zv TSRMLS_CC); } - /* skip leading '\\' */ + /* skip leading '\\' */ if (Z_STRVAL_P(zv)[0] == '\\') { name_len = Z_STRLEN_P(zv) - 1; name = Z_STRVAL_P(zv) + 1; @@ -816,7 +866,7 @@ void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS opline.result.var = opline.op1.var; zend_llist_add_element(fetch_list_ptr, &opline); } - + init_op(&opline TSRMLS_CC); opline.opcode = ZEND_FETCH_DIM_W; /* the backpatching routine assumes W */ opline.result_type = IS_VAR; @@ -830,12 +880,12 @@ void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline.op2.constant)), Z_STRLEN(CONSTANT(opline.op2.constant))+1, index, numeric = 1); if (numeric) { zval_dtor(&CONSTANT(opline.op2.constant)); - ZVAL_LONG(&CONSTANT(opline.op2.constant), index); + ZVAL_LONG(&CONSTANT(opline.op2.constant), index); } else { CALCULATE_LITERAL_HASH(opline.op2.constant); } } - + GET_NODE(result, opline.result); zend_llist_add_element(fetch_list_ptr, &opline); @@ -871,20 +921,19 @@ void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */ } /* }}} */ -void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */ +void zend_do_abstract_method(const znode *body TSRMLS_DC) /* {{{ */ { char *method_type; if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) { - Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT; method_type = "Interface"; } else { method_type = "Abstract"; } - if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) { - if(modifiers->u.constant.value.lval & ZEND_ACC_PRIVATE) { - zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val); + if (CG(active_op_array)->fn_flags & ZEND_ACC_ABSTRACT) { + if (CG(active_op_array)->fn_flags & ZEND_ACC_PRIVATE) { + zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, CG(active_op_array)->function_name); } if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -894,11 +943,11 @@ void zend_do_abstract_method(const znode *function_name, znode *modifiers, const SET_UNUSED(opline->op2); } else { /* we had code in the function body */ - zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val); + zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, CG(active_op_array)->function_name); } } else { - if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) { - zend_error(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, function_name->u.constant.value.str.val); + if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) { + zend_error(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, CG(active_op_array)->function_name); } } } @@ -940,7 +989,7 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* { opline->result.var = get_temporary_variable(CG(active_op_array)); opline->op1_type = IS_CONST; LITERAL_STRINGL(opline->op1, - CG(active_op_array)->vars[value->u.op.var].name, + CG(active_op_array)->vars[value->u.op.var].name, CG(active_op_array)->vars[value->u.op.var].name_len, 1); CALCULATE_LITERAL_HASH(opline->op1.constant); SET_UNUSED(opline->op2); @@ -963,9 +1012,7 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* { int n = 0; while (last_op_number - n > 0) { - zend_op *last_op; - - last_op = &CG(active_op_array)->opcodes[last_op_number-n-1]; + zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-n-1]; if (last_op->result_type == IS_VAR && last_op->result.var == variable->u.op.var) { @@ -1523,6 +1570,248 @@ int zend_do_verify_access_types(const znode *current_access_type, const znode *n } /* }}} */ +void zend_declare_accessor(znode *var_name TSRMLS_DC) { /* {{{ */ + zend_property_info *property_info; + char *property_name; + int property_name_len; + zend_uint orig_ce_flags = CG(active_class_entry)->ce_flags; + + if (CG(access_type) & ZEND_ACC_STATIC) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot define static accessor %s::$%s, not supported at this time", CG(active_class_entry)->name, Z_STRVAL(var_name->u.constant)); + } + + /* zend_do_declare_property free's the string, so copy it */ + property_name_len = Z_STRLEN(var_name->u.constant); + property_name = estrndup(Z_STRVAL(var_name->u.constant), property_name_len); + + /* Hide that we're working with an interface during property accessor declaration */ + CG(active_class_entry)->ce_flags &= ~ZEND_ACC_INTERFACE; + zend_do_declare_property(var_name, NULL, CG(access_type) & ~(ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT) TSRMLS_CC); + CG(active_class_entry)->ce_flags = orig_ce_flags; + + if (zend_hash_find(&CG(active_class_entry)->properties_info, property_name, property_name_len + 1, (void **) &property_info)==SUCCESS) { + /* Add back final/abstract flags that were skipped previously */ + property_info->flags |= CG(access_type); + property_info->accs = ecalloc(ZEND_NUM_ACCESSORS, sizeof(zend_function *)); + + CG(current_property_info) = property_info; + efree(property_name); + } else { + zend_error_noreturn(E_COMPILE_ERROR, "Property_info for %s::$%s is not present, should not happen in zend_declare_accessor()", CG(active_class_entry)->name, property_name); + } +} +/* }}} */ + +static inline char *create_accessor_function_name(const char *property_name, char *accessor_type) /* {{{ */ +{ + /* Format: $ property_name -> accessor_type */ + int buffer_len = strlen(property_name) + strlen(accessor_type) + 3 + 1; + char *buffer = emalloc(buffer_len); + snprintf(buffer, buffer_len, "$%s->%s", property_name, accessor_type); + return buffer; +} +/* }}} */ + +void zend_do_begin_accessor_declaration(znode *function_token, znode *modifiers, int return_reference, int has_params TSRMLS_DC) /* {{{ */ +{ + zend_property_info *property_info = CG(current_property_info); + const char *property_name = zend_get_property_name(property_info); + zend_uint property_flags; + + /* Inherit property modifiers, allowing to override PPP */ + property_flags = property_info->flags; + if ((Z_LVAL(modifiers->u.constant) & ZEND_ACC_PPP_MASK) != 0) { + property_flags &= ~ZEND_ACC_PPP_MASK; + } + Z_LVAL(modifiers->u.constant) |= property_flags | ZEND_ACC_ACCESSOR; + + if ((Z_LVAL(modifiers->u.constant) & ZEND_ACC_ABSTRACT) + && (Z_LVAL(modifiers->u.constant) & ZEND_ACC_FINAL) + ) { + zend_error_noreturn(E_COMPILE_ERROR, "Abstract and final modifiers are mutually exclusive"); + } + + if (Z_TYPE(function_token->u.constant) == IS_STRING && strcasecmp("get", Z_STRVAL(function_token->u.constant)) == 0) { + efree(Z_STRVAL(function_token->u.constant)); + ZVAL_STRING(&function_token->u.constant, create_accessor_function_name(property_name, "get"), 0); + + if (has_params) { + zend_error(E_COMPILE_ERROR, "Getters do not accept parameters for variable %s::$%s", CG(active_class_entry)->name, property_name); + } + + /* Declare Function */ + zend_do_begin_function_declaration(function_token, function_token, 1, return_reference, modifiers TSRMLS_CC); + property_info->accs[ZEND_ACCESSOR_GET] = (zend_function *) CG(active_op_array); + } else if (Z_TYPE(function_token->u.constant) == IS_STRING && strcasecmp("set", Z_STRVAL(function_token->u.constant)) == 0) { + znode unused_node, unused_node2, value_node; + + efree(Z_STRVAL(function_token->u.constant)); + ZVAL_STRING(&function_token->u.constant, create_accessor_function_name(property_name, "set"), 0); + + if (return_reference) { + zend_error(E_WARNING, "Property setter %s::$%s indicates a return reference with '&', setters do not return values, ignored.", CG(active_class_entry)->name, property_name); + } + /* Declare Function */ + zend_do_begin_function_declaration(function_token, function_token, 1, ZEND_RETURN_VAL, modifiers TSRMLS_CC); + property_info->accs[ZEND_ACCESSOR_SET] = (zend_function *) CG(active_op_array); + + if (!has_params) { + /* Add $value parameter to __setHours() */ + unused_node.op_type = unused_node2.op_type = IS_UNUSED; + unused_node.u.op.num = unused_node2.u.op.num = 1; + + ZVAL_STRINGL(&value_node.u.constant, "value", 5, 1); + + zend_do_receive_arg(ZEND_RECV, &value_node, &unused_node, NULL, &unused_node2, 0 TSRMLS_CC); + } + } else if (Z_TYPE(function_token->u.constant) == IS_LONG && Z_LVAL(function_token->u.constant) == T_ISSET) { + ZVAL_STRING(&function_token->u.constant, create_accessor_function_name(property_name, "isset"), 0); + + if (has_params) { + zend_error(E_COMPILE_ERROR, "Issetters do not accept parameters for variable %s::$%s", CG(active_class_entry)->name, property_name); + } + + /* Declare Function */ + zend_do_begin_function_declaration(function_token, function_token, 1, ZEND_RETURN_VAL, modifiers TSRMLS_CC); + property_info->accs[ZEND_ACCESSOR_ISSET] = (zend_function *) CG(active_op_array); + } else if (Z_TYPE(function_token->u.constant) == IS_LONG && Z_LVAL(function_token->u.constant) == T_UNSET) { + ZVAL_STRING(&function_token->u.constant, create_accessor_function_name(property_name, "unset"), 0); + + if (has_params) { + zend_error(E_COMPILE_ERROR, "Unsetters do not accept parameters for variable %s::$%s", CG(active_class_entry)->name, property_name); + } + + /* Declare Function */ + zend_do_begin_function_declaration(function_token, function_token, 1, ZEND_RETURN_VAL, modifiers TSRMLS_CC); + property_info->accs[ZEND_ACCESSOR_UNSET] = (zend_function *) CG(active_op_array); + } else { + zend_error(E_COMPILE_ERROR, "Unknown accessor '%s', expecting get or set for variable $%s", Z_STRVAL(function_token->u.constant), property_name); + } +} +/* }}} */ + +void zend_do_end_accessor_declaration(znode *function_token, const znode *body TSRMLS_DC) /* {{{ */ +{ + zend_property_info *property_info = CG(current_property_info); + const char *property_name = zend_get_property_name(property_info); + int property_name_len = strlen(property_name); + + if (CG(active_op_array)->fn_flags & ZEND_ACC_ABSTRACT) { + zend_do_abstract_method(body TSRMLS_CC); + } else if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) { + zval eval_php_code; + zend_uint original_compiler_options = CG(compiler_options); + + /* Find out what kind of accessor this is by checking in which + * ->fn slot it is in */ + zend_uchar acc; + for (acc = 0; acc < ZEND_NUM_ACCESSORS; ++acc) { + if (property_info->accs[acc] == (zend_function *) CG(active_op_array)) { + break; + } + } + + CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL; + + if (acc == ZEND_ACCESSOR_GET) { + /* Equivalent to: return $this->Property; */ + zend_uint bufsize = 16 + property_name_len + 1 + 1; + char *buffer = emalloc(bufsize); + + Z_STRVAL(eval_php_code) = buffer; + Z_TYPE(eval_php_code) = IS_STRING; + Z_STRLEN(eval_php_code) = snprintf(Z_STRVAL(eval_php_code), bufsize, "return $this->%s;", property_name); + zend_compile_string_inline(&eval_php_code, (char*)CG(active_op_array)->filename TSRMLS_CC); + efree(buffer); + zend_do_extended_info(TSRMLS_C); + + } else if (acc == ZEND_ACCESSOR_SET) { + /* Equivalent to: $this->Property = $value; */ + zend_arg_info *arg_info = CG(active_op_array)->arg_info; + zend_uint bufsize = property_name_len + arg_info->name_len + 12 + 1; + char *buffer = emalloc(bufsize); + + Z_STRVAL(eval_php_code) = buffer; + Z_TYPE(eval_php_code) = IS_STRING; + Z_STRLEN(eval_php_code) = snprintf(Z_STRVAL(eval_php_code), bufsize, "$this->%s = $%s;", property_name, arg_info->name); + zend_compile_string_inline(&eval_php_code, (char*)CG(active_op_array)->filename TSRMLS_CC); + efree(buffer); + zend_do_extended_info(TSRMLS_C); + + } else if (acc == ZEND_ACCESSOR_ISSET) { + /* Equivalent to: return $this->Property !== NULL; (via getter) */ + zend_uint bufsize = 14 + property_name_len + 10 + 1; + char *buffer = emalloc(bufsize); + + Z_STRVAL(eval_php_code) = buffer; + Z_TYPE(eval_php_code) = IS_STRING; + Z_STRLEN(eval_php_code) = snprintf(Z_STRVAL(eval_php_code), bufsize, "return $this->%s !== NULL;", property_name); + zend_compile_string_inline(&eval_php_code, (char*)CG(active_op_array)->filename TSRMLS_CC); + efree(buffer); + zend_do_extended_info(TSRMLS_C); + + } else if (acc == ZEND_ACCESSOR_UNSET) { + /* Equivalent to: $this->Property = NULL; (via setter) */ + zend_uint bufsize = 7 + property_name_len + 8 + 1; + char *buffer = emalloc(bufsize); + + Z_STRVAL(eval_php_code) = buffer; + Z_TYPE(eval_php_code) = IS_STRING; + Z_STRLEN(eval_php_code) = snprintf(Z_STRVAL(eval_php_code), bufsize, "$this->%s = NULL;", property_name); + zend_compile_string_inline(&eval_php_code, (char*)CG(active_op_array)->filename TSRMLS_CC); + efree(buffer); + zend_do_extended_info(TSRMLS_C); + } + CG(compiler_options) = original_compiler_options; + } + + zend_do_end_function_declaration(function_token TSRMLS_CC); +} +/* }}} */ + +void zend_finalize_accessor(TSRMLS_D) { /* {{{ */ + zend_property_info *property_info = CG(current_property_info); + + zend_uint keep_flags = 0; + if ((CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) == 0) { + keep_flags = ZEND_ACC_PPP_MASK|ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT; + } + + if (!property_info->accs[ZEND_ACCESSOR_ISSET] && property_info->accs[ZEND_ACCESSOR_GET]) { + znode zn_fntoken, zn_modifiers, zn_body; + INIT_ZNODE(zn_fntoken); + ZVAL_LONG(&zn_fntoken.u.constant, T_ISSET); + + INIT_ZNODE(zn_modifiers); + Z_LVAL(zn_modifiers.u.constant) + = property_info->accs[ZEND_ACCESSOR_GET]->common.fn_flags & keep_flags; + + INIT_ZNODE(zn_body); + Z_LVAL(zn_body.u.constant) = ZEND_ACC_ABSTRACT; + + zend_do_begin_accessor_declaration(&zn_fntoken, &zn_modifiers, 0, 0 TSRMLS_CC); + zend_do_end_accessor_declaration(&zn_fntoken, &zn_body TSRMLS_CC); + } + if (!property_info->accs[ZEND_ACCESSOR_UNSET] && property_info->accs[ZEND_ACCESSOR_SET]) { + znode zn_fntoken, zn_modifiers, zn_body; + INIT_ZNODE(zn_fntoken); + ZVAL_LONG(&zn_fntoken.u.constant, T_UNSET); + + INIT_ZNODE(zn_modifiers); + Z_LVAL(zn_modifiers.u.constant) + = property_info->accs[ZEND_ACCESSOR_SET]->common.fn_flags & keep_flags; + + INIT_ZNODE(zn_body); + Z_LVAL(zn_body.u.constant) = ZEND_ACC_ABSTRACT; + + zend_do_begin_accessor_declaration(&zn_fntoken, &zn_modifiers, 0, 0 TSRMLS_CC); + zend_do_end_accessor_declaration(&zn_fntoken, &zn_body TSRMLS_CC); + } + + CG(current_property_info) = NULL; +} +/* }}} */ + void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */ { zend_op_array op_array; @@ -1536,7 +1825,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n if (is_method) { if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) { - if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) { + if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC|ZEND_ACC_ACCESSOR))) { zend_error(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, function_name->u.constant.value.str.val); } Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */ @@ -1567,9 +1856,19 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n op_array.line_start = zend_get_compiled_lineno(TSRMLS_C); - if (is_method) { + if (IS_ACCESSOR_FN((zend_function *) &op_array)) { + CG(active_op_array) = pemalloc(sizeof(zend_op_array), 1); + memcpy(CG(active_op_array), &op_array, sizeof(zend_op_array)); + + zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context))); + zend_init_compiler_context(TSRMLS_C); + + if (fn_flags & ZEND_ACC_ABSTRACT) { + CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; + } + } else if (is_method) { int result; - + lcname = zend_new_interned_string(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC); if (IS_INTERNED(lcname)) { @@ -1624,7 +1923,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n } } else { char *class_lcname; - + class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap); zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length); /* Improve after RC: cache the lowercase class name */ @@ -1675,7 +1974,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) { if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static"); - } + } CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array); } else if (!(fn_flags & ZEND_ACC_STATIC)) { CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC; @@ -1813,7 +2112,7 @@ void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */ if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) { zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME); - } + } } CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C); @@ -1939,7 +2238,7 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace internal function with short name */ zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC); return 1; - } + } 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) || @@ -1948,10 +2247,10 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC); efree(lcname); return 1; /* Dynamic */ - } + } efree(function_name->u.constant.value.str.val); function_name->u.constant.value.str.val = lcname; - + zend_stack_push(&CG(function_call_stack), (void *) &function, sizeof(zend_function *)); if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) { CG(active_op_array)->nested_calls = CG(context).nested_calls + 1; @@ -1984,7 +2283,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */ name = CONSTANT(last_op->op2.constant); if (Z_TYPE(name) != IS_STRING) { zend_error(E_COMPILE_ERROR, "Method name must be a string"); - } + } if (!IS_INTERNED(Z_STRVAL(name))) { Z_STRVAL(name) = estrndup(Z_STRVAL(name), Z_STRLEN(name)); } @@ -2188,7 +2487,7 @@ void zend_resolve_class_name(znode *class_name, ulong fetch_type, int check_ns_n if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) { zend_error(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant)); } - } else { + } 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); @@ -2553,8 +2852,8 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{ zend_error(E_COMPILE_ERROR, "Call-time pass-by-reference has been removed"); } return; - } - + } + if (function_ptr) { if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) { if (param->op_type & (IS_VAR|IS_CV) && original_op != ZEND_SEND_VAL) { @@ -3063,7 +3362,7 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */ lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length); if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) { lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length); - if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) && + if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) && zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) { if (function->common.fn_flags & ZEND_ACC_CTOR) { /* inherit parent's constructor */ @@ -3202,8 +3501,8 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c return 0; } } - } - } + } + } if (fe->common.arg_info[i].type_hint != proto->common.arg_info[i].type_hint) { /* Incompatible type hint */ return 0; @@ -3232,7 +3531,7 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c buf = erealloc(buf, length); \ } -static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */ +static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */ { char *offset, *buf; zend_uint length = 1024; @@ -3249,7 +3548,7 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{ *(offset++) = ':'; *(offset++) = ':'; } - + { size_t name_len = strlen(fptr->common.function_name); REALLOC_BUF_IF_EXCEED(buf, offset, length, name_len); @@ -3290,7 +3589,7 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{ offset += type_name_len; *(offset++) = ' '; } - + if (arg_info->pass_by_reference) { *(offset++) = '&'; } @@ -3392,7 +3691,7 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{ *offset = '\0'; return buf; -} +} /* }}} */ static void do_inheritance_check_on_method(zend_function *child, zend_function *parent TSRMLS_DC) /* {{{ */ @@ -3404,14 +3703,14 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * && parent->common.fn_flags & ZEND_ACC_ABSTRACT && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope) && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) { - zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)", + zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)", parent->common.scope->name, child->common.function_name, child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name); } if (parent_flags & ZEND_ACC_FINAL) { - zend_error(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name); + zend_error(E_COMPILE_ERROR, "Cannot override final %s %s::%s()", IS_ACCESSOR_FN(parent) ? "accessor" : "method", ZEND_FN_SCOPE_NAME(parent), child->common.function_name); } child_flags = child->common.fn_flags; @@ -3439,12 +3738,12 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * zend_error(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK)) && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) { - child->common.fn_flags |= ZEND_ACC_CHANGED; + child->common.fn_flags |= ZEND_ACC_CHANGED; } } if (parent_flags & ZEND_ACC_PRIVATE) { - child->common.prototype = NULL; + child->common.prototype = NULL; } else if (parent_flags & ZEND_ACC_ABSTRACT) { child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT; child->common.prototype = parent; @@ -3479,13 +3778,28 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f } return 1; /* method doesn't exist in child, copy from parent */ } - + do_inheritance_check_on_method(child, parent TSRMLS_CC); - + return 0; } /* }}} */ +static void do_inherit_accessor(zend_function **child, zend_function *parent, zend_class_entry *child_ce TSRMLS_DC) /* {{{ */ +{ + if (parent) { + if (!*child) { + *child = duplicate_accessor_function(parent); + if (parent->common.fn_flags & ZEND_ACC_ABSTRACT) { + child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; + } + } else { + do_inheritance_check_on_method(*child, parent TSRMLS_CC); + } + } +} +/* }}} */ + static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, const zend_hash_key *hash_key, zend_class_entry *ce) /* {{{ */ { zend_property_info *child_info; @@ -3512,7 +3826,7 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s", (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey, (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey); - + } if(parent_info->flags & ZEND_ACC_CHANGED) { @@ -3526,9 +3840,30 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset]; ce->default_properties_table[child_info->offset] = NULL; child_info->offset = parent_info->offset; + + if (parent_info->accs && child_info->accs) { + int i; + TSRMLS_FETCH(); + + for (i = 0; i < ZEND_NUM_ACCESSORS; ++i) { + do_inherit_accessor(&child_info->accs[i], parent_info->accs[i], ce TSRMLS_CC); + } + } } return 0; /* Don't copy from parent */ } else { + /* Make sure that when we copy abstract accessors the class is marked + * abstract too */ + if (parent_info->accs) { + int i; + for (i = 0; i < ZEND_NUM_ACCESSORS; ++i) { + zend_function *fn = parent_info->accs[i]; + if (fn && (fn->common.fn_flags & ZEND_ACC_ABSTRACT)) { + ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; + } + } + } + return 1; /* Copy from parent */ } } @@ -3778,10 +4113,12 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry } } ce->interfaces[ce->num_interfaces++] = iface; - + + zend_hash_merge_ex(&ce->properties_info, &iface->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce); + zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface); zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce); - + do_implement_interface(ce, iface TSRMLS_CC); zend_do_inherit_interfaces(ce, iface TSRMLS_CC); } @@ -3821,7 +4158,7 @@ static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_ { zend_uint fn_flags = fn->common.scope->ce_flags; zend_uint other_flags = other_fn->common.scope->ce_flags; - + return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC) && zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC) && ((fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)) == @@ -3837,7 +4174,7 @@ static void zend_add_magic_methods(zend_class_entry* ce, const char* mname, uint if (ce->constructor) { zend_error(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name); } - ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR; + ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR; } else if (!strncmp(mname, ZEND_DESTRUCTOR_FUNC_NAME, mname_len)) { ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR; } else if (!strncmp(mname, ZEND_GET_FUNC_NAME, mname_len)) { @@ -3870,70 +4207,80 @@ static void zend_add_magic_methods(zend_class_entry* ce, const char* mname, uint } /* }}} */ -static void zend_add_trait_method(zend_class_entry *ce, const char *name, const char *arKey, uint nKeyLength, zend_function *fn, HashTable **overriden TSRMLS_DC) /* {{{ */ +static zend_bool zend_should_copy_trait_function(zend_function *fn, zend_function *existing_fn, zend_class_entry *ce, const char *name, const char *arKey, uint nKeyLength, ulong h, HashTable **overridden TSRMLS_DC) /* {{{ */ { - zend_function *existing_fn = NULL; - ulong h = zend_hash_func(arKey, nKeyLength); - - if (zend_hash_quick_find(&ce->function_table, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) { - if (existing_fn->common.scope == ce) { - /* members from the current class override trait methods */ - /* use temporary *overriden HashTable to detect hidden conflict */ - if (*overriden) { - if (zend_hash_quick_find(*overriden, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) { - if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) { - /* Make sure the trait method is compatible with previosly declared abstract method */ - if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) { - zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", - zend_get_function_declaration(fn TSRMLS_CC), - zend_get_function_declaration(existing_fn TSRMLS_CC)); - } - } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { - /* Make sure the abstract declaration is compatible with previous declaration */ - if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) { - zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", - zend_get_function_declaration(fn TSRMLS_CC), - zend_get_function_declaration(existing_fn TSRMLS_CC)); - } - return; + if (existing_fn->common.scope == ce) { + /* members from the current class override trait methods */ + /* use temporary *overriden HashTable to detect hidden conflict */ + if (*overridden) { + if (zend_hash_quick_find(*overridden, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) { + if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + /* Make sure the trait method is compatible with previosly declared abstract method */ + if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) { + zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", + zend_get_function_declaration(fn TSRMLS_CC), + zend_get_function_declaration(existing_fn TSRMLS_CC)); + } + } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + /* Make sure the abstract declaration is compatible with previous declaration */ + if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) { + zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", + zend_get_function_declaration(fn TSRMLS_CC), + zend_get_function_declaration(existing_fn TSRMLS_CC)); } + return 0; } - } else { - ALLOC_HASHTABLE(*overriden); - zend_hash_init_ex(*overriden, 2, NULL, NULL, 0, 0); } - zend_hash_quick_update(*overriden, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn); - return; - } else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) { - /* Make sure the trait method is compatible with previosly declared abstract method */ - if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) { - zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", - zend_get_function_declaration(fn TSRMLS_CC), - zend_get_function_declaration(existing_fn TSRMLS_CC)); - } - } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { - /* Make sure the abstract declaration is compatible with previous declaration */ - if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) { - zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", - zend_get_function_declaration(fn TSRMLS_CC), - zend_get_function_declaration(existing_fn TSRMLS_CC)); - } - return; - } else if ((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { - /* two trais can't define the same non-abstract method */ + } else { + ALLOC_HASHTABLE(*overridden); + zend_hash_init_ex(*overridden, 2, NULL, NULL, 0, 0); + } + zend_hash_quick_update(*overridden, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn); + return 0; + } else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + /* Make sure the trait method is compatible with previosly declared abstract method */ + if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) { + zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", + zend_get_function_declaration(fn TSRMLS_CC), + zend_get_function_declaration(existing_fn TSRMLS_CC)); + } + } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + /* Make sure the abstract declaration is compatible with previous declaration */ + if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) { + zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", + zend_get_function_declaration(fn TSRMLS_CC), + zend_get_function_declaration(existing_fn TSRMLS_CC)); + } + return 0; + } else if ((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { + /* two traits can't define the same non-abstract method */ #if 1 - zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s", - name, ce->name); -#else /* TODO: better errot message */ - zend_error(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s", - fn->common.scope->name, fn->common.function_name, - ce->name, name, - existing_fn->common.scope->name, existing_fn->common.function_name); + zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s", + name, ce->name); +#else /* TODO: better error message */ + zend_error(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s", + fn->common.scope->name, fn->common.function_name, + ce->name, name, + existing_fn->common.scope->name, existing_fn->common.function_name); #endif - } else { - /* inherited members are overridden by members inserted by traits */ - /* check whether the trait method fullfills the inheritance requirements */ - do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC); + } else { + /* inherited members are overridden by members inserted by traits */ + /* check whether the trait method fullfills the inheritance requirements */ + do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC); + } + + return 1; +} +/* }}} */ + +static void zend_add_trait_method(zend_class_entry *ce, const char *name, const char *arKey, uint nKeyLength, zend_function *fn, HashTable **overridden TSRMLS_DC) /* {{{ */ +{ + zend_function *existing_fn = NULL; + ulong h = zend_hash_func(arKey, nKeyLength); + + if (zend_hash_quick_find(&ce->function_table, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) { + if (!zend_should_copy_trait_function(fn, existing_fn, ce, name, arKey, nKeyLength, h, overridden TSRMLS_CC)) { + return; } } @@ -4093,7 +4440,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* cur_method_ref->ce->name, cur_method_ref->method_name); } - + /** With the other traits, we are more permissive. We do not give errors for those. This allows to be more defensive in such definitions. @@ -4114,13 +4461,13 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* exclude_from_classes, for consistency */ if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[i]) { zend_error(E_COMPILE_ERROR, - "Inconsistent insteadof definition. " + "Inconsistent insteadof definition. " "The method %s is to be used from %s, but %s is also on the exclude list", cur_method_ref->method_name, cur_precedence->trait_method->ce->name, cur_precedence->trait_method->ce->name); } - + efree(class_name); j++; } @@ -4160,7 +4507,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait) /* {{{ */ { size_t i = 0, j; - + if (!precedences) { return; } @@ -4171,7 +4518,7 @@ static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_tra if (precedences[i]->exclude_from_classes[j] == trait) { zend_uint lcname_len = precedences[i]->trait_method->mname_len; char *lcname = zend_str_tolower_dup(precedences[i]->trait_method->method_name, lcname_len); - + if (zend_hash_add(exclude_table, lcname, lcname_len, NULL, 0, NULL) == FAILURE) { efree(lcname); zend_error(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", precedences[i]->trait_method->method_name, trait->name); @@ -4234,6 +4581,20 @@ static zend_class_entry* find_first_definition(zend_class_entry *ce, size_t curr } /* }}} */ + +static void zend_do_trait_inherit_accessor(zend_function **fn, zend_function *existing_fn, zend_class_entry *ce, zend_class_entry *trait_ce, HashTable **overridden TSRMLS_DC) /* {{{ */ +{ + if (*fn) { + const char *fn_name = existing_fn->common.function_name; + int fn_name_len = strlen(fn_name) + 1; + ulong fn_name_h = zend_hash_func(fn_name, fn_name_len); + + if (!zend_should_copy_trait_function(*fn, existing_fn, ce, trait_ce->name, fn_name, fn_name_len, fn_name_h, overridden TSRMLS_CC)) return; + } + + *fn = duplicate_accessor_function(existing_fn); +} + static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { size_t i; @@ -4246,8 +4607,9 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* { const char* class_name_unused; zend_bool not_compatible; zval* prop_value; - char* doc_comment; + char* doc_comment; zend_uint flags; + HashTable *overridden = NULL; /* In the following steps the properties are inserted into the property table * for that, a very strict approach is applied: @@ -4258,7 +4620,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* { for (zend_hash_internal_pointer_reset(&ce->traits[i]->properties_info); zend_hash_get_current_data(&ce->traits[i]->properties_info, (void *) &property_info) == SUCCESS; zend_hash_move_forward(&ce->traits[i]->properties_info)) { - /* first get the unmangeld name if necessary, + /* first get the unmangled name if necessary, * then check whether the property is already there */ flags = property_info->flags; @@ -4329,6 +4691,17 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* { zend_declare_property_ex(ce, prop_name, prop_name_length, prop_value, flags, doc_comment, property_info->doc_comment_len TSRMLS_CC); + if (property_info->accs) { + zend_property_info *created_property_info; + if (zend_hash_find(&ce->properties_info, prop_name, prop_name_length+1, (void**) &created_property_info) == SUCCESS) { + int j; + created_property_info->accs = ecalloc(ZEND_NUM_ACCESSORS, sizeof(zend_function *)); + + for (j = 0; j < ZEND_NUM_ACCESSORS; ++j) { + zend_do_trait_inherit_accessor(&created_property_info->accs[j], property_info->accs[j], ce, ce->traits[i], &overridden TSRMLS_CC); + } + } + } } } } @@ -4339,7 +4712,7 @@ static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce int i = 0; zend_trait_alias* cur_alias; char* lc_method_name; - + if (ce->trait_aliases) { while (ce->trait_aliases[i]) { cur_alias = ce->trait_aliases[i]; @@ -4360,7 +4733,7 @@ static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce we check against it and abort. 2) it is just a plain old inconsitency/typo/bug as in the case where alias is set. */ - + lc_method_name = zend_str_tolower_dup(cur_alias->trait_method->method_name, cur_alias->trait_method->mname_len); if (zend_hash_exists(&ce->function_table, @@ -4397,7 +4770,7 @@ ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */ /* first care about all methods to be flattened into the class */ zend_do_traits_method_binding(ce TSRMLS_CC); - + /* Aliases which have not been applied indicate typos/bugs. */ zend_do_check_for_inconsistent_traits_aliasing(ce TSRMLS_CC); @@ -4406,7 +4779,7 @@ ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */ /* verify that all abstract methods from traits have been implemented */ zend_verify_abstract_class(ce TSRMLS_CC); - + /* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */ if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; @@ -5030,7 +5403,7 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name build_runtime_defined_function_key(&key, lcname, new_class_entry->name_length TSRMLS_CC); opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC); Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant))); - + opline->op2_type = IS_CONST; if (doing_inheritance) { @@ -5047,7 +5420,7 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name LITERAL_STRINGL(opline->op2, lcname, new_class_entry->name_length, 0); CALCULATE_LITERAL_HASH(opline->op2.constant); - + zend_hash_quick_update(CG(class_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &new_class_entry, sizeof(zend_class_entry *), NULL); CG(active_class_entry) = new_class_entry; @@ -5098,7 +5471,7 @@ void zend_do_end_class_declaration(const znode *class_token, const znode *parent } ce->info.user.line_end = zend_get_compiled_lineno(TSRMLS_C); - + /* Check for traits and proceed like with interfaces. * The only difference will be a combined handling of them in the end. * Thus, we need another opcode here. */ @@ -5325,7 +5698,7 @@ void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_D ALLOC_ZVAL(property); *property = value->u.constant; - + cname = zend_new_interned_string(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, 0 TSRMLS_CC); if (IS_INTERNED(cname)) { @@ -5338,7 +5711,7 @@ void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_D zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val); } FREE_PNODE(var_name); - + if (CG(doc_comment)) { efree(CG(doc_comment)); CG(doc_comment) = NULL; @@ -5427,17 +5800,17 @@ void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */ char *name, *cfilename; char haltoff[] = "__COMPILER_HALT_OFFSET__"; int len, clen; - + if (CG(has_bracketed_namespaces) && CG(in_namespace)) { zend_error(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope"); } - + cfilename = zend_get_compiled_filename(TSRMLS_C); clen = strlen(cfilename); zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0); zend_register_long_constant(name, len+1, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC); pefree(name, 0); - + if (CG(in_namespace)) { zend_do_end_namespace(TSRMLS_C); } @@ -5514,7 +5887,7 @@ static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal } } else if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name), Z_STRLEN_P(const_name)+1, (void **) &c) == FAILURE) { char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name), Z_STRLEN_P(const_name)); - + if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)+1, (void **) &c)==SUCCESS) { if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) { efree(lookup_name); @@ -5567,7 +5940,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con case ZEND_CT: /* this is a class constant */ type = zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant)); - + if (ZEND_FETCH_CLASS_STATIC == type) { zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants"); } else if (ZEND_FETCH_CLASS_DEFAULT == type) { @@ -5631,7 +6004,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant)); zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC); - + if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) { break; } @@ -5647,7 +6020,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con /* the name is unambiguous */ opline->extended_value = 0; opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC); - } else { + } else { opline->extended_value = IS_CONSTANT_UNQUALIFIED; if (CG(current_namespace)) { opline->extended_value |= IS_CONSTANT_IN_NAMESPACE; @@ -5721,7 +6094,7 @@ void zend_do_init_array(znode *result, const znode *expr, const znode *offset, z ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1); if (numeric) { zval_dtor(&CONSTANT(opline->op2.constant)); - ZVAL_LONG(&CONSTANT(opline->op2.constant), index); + ZVAL_LONG(&CONSTANT(opline->op2.constant), index); } else { CALCULATE_LITERAL_HASH(opline->op2.constant); } @@ -5753,7 +6126,7 @@ void zend_do_add_array_element(znode *result, const znode *expr, const znode *of ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1); if (numeric) { zval_dtor(&CONSTANT(opline->op2.constant)); - ZVAL_LONG(&CONSTANT(opline->op2.constant), index); + ZVAL_LONG(&CONSTANT(opline->op2.constant), index); } else { CALCULATE_LITERAL_HASH(opline->op2.constant); } @@ -6013,7 +6386,7 @@ void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC) Z_TYPE(value.u.constant) |= is_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR; Z_SET_REFCOUNT_P(&value.u.constant, 1); Z_UNSET_ISREF_P(&value.u.constant); - + zend_do_fetch_static_variable(varname, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC); } /* }}} */ @@ -6131,7 +6504,6 @@ void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */ last_op->opcode = ZEND_UNSET_OBJ; SET_UNUSED(last_op->result); break; - } } } @@ -6529,7 +6901,7 @@ void zend_do_jmp_set(const znode *value, znode *jmp_token, znode *colon_token TS opline->result.var = get_temporary_variable(CG(active_op_array)); SET_NODE(opline->op1, value); SET_UNUSED(opline->op2); - + GET_NODE(colon_token, opline->result); jmp_token->u.op.opline_num = op_number; @@ -6558,11 +6930,11 @@ void zend_do_jmp_set_else(znode *result, const znode *false_value, const znode * opline->extended_value = 0; SET_NODE(opline->op1, false_value); SET_UNUSED(opline->op2); - + GET_NODE(result, opline->result); CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); - + DEC_BPC(CG(active_op_array)); } /* }}} */ @@ -6775,7 +7147,7 @@ int zendlex(znode *zendlval TSRMLS_DC) /* {{{ */ CG(increment_lineno) = 1; } if (CG(has_bracketed_namespaces) && !CG(in_namespace)) { - goto again; + goto again; } retval = ';'; /* implicit ; */ break; @@ -6866,7 +7238,7 @@ 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")-1)) { - return ZEND_FETCH_CLASS_SELF; + return ZEND_FETCH_CLASS_SELF; } else if ((class_name_len == sizeof("parent")-1) && !memcmp(class_name, "parent", sizeof("parent")-1)) { return ZEND_FETCH_CLASS_PARENT; @@ -6984,7 +7356,7 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC efree(CG(current_import)); CG(current_import) = NULL; } - + if (CG(doc_comment)) { efree(CG(doc_comment)); CG(doc_comment) = NULL; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8042dd54eee81..d12218f358e79 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -34,6 +34,15 @@ #define FREE_PNODE(znode) zval_dtor(&znode->u.constant); +#define IS_ACCESSOR_FN(fn) (((fn)->common.fn_flags & ZEND_ACC_ACCESSOR) != 0) + +#define INIT_ZNODE(zn) \ + { \ + zn.op_type = IS_CONST; \ + INIT_PZVAL(&zn.u.constant); \ + zn.EA = 0; \ + } + #define SET_UNUSED(op) op ## _type = IS_UNUSED #define INC_BPC(op_array) if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { (CG(context).backpatch_count++); } @@ -213,9 +222,21 @@ typedef struct _zend_try_catch_element { #define ZEND_ACC_RETURN_REFERENCE 0x4000000 #define ZEND_ACC_DONE_PASS_TWO 0x8000000 -char *zend_visibility_string(zend_uint fn_flags); +/* fn_flag that declares that the function is an accessor zend_function.fn_flags */ +#define ZEND_ACC_ACCESSOR 0x10000000 +/* fn_flag that declares that the function is on the stack and is being guarded from recursive calls */ +#define ZEND_ACC_CALL_GUARD 0x20000000 +/* Offsets into zend_property_info->accs */ +typedef enum { + ZEND_ACCESSOR_GET, + ZEND_ACCESSOR_SET, + ZEND_ACCESSOR_ISSET, + ZEND_ACCESSOR_UNSET, +} zend_acc_index; +#define ZEND_NUM_ACCESSORS 4 + typedef struct _zend_property_info { zend_uint flags; const char *name; @@ -225,6 +246,7 @@ typedef struct _zend_property_info { const char *doc_comment; int doc_comment_len; zend_class_entry *ce; + union _zend_function **accs; } zend_property_info; @@ -261,7 +283,7 @@ typedef struct _zend_compiled_variable { struct _zend_op_array { /* Common elements */ zend_uchar type; - const char *function_name; + const char *function_name; zend_class_entry *scope; zend_uint fn_flags; union _zend_function *prototype; @@ -334,10 +356,10 @@ typedef struct _zend_internal_function { #define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : "") typedef union _zend_function { - zend_uchar type; /* MUST be the first element of this struct! */ + zend_uchar type; /* MUST be the first element of this struct! */ struct { - zend_uchar type; /* never used */ + zend_uchar type; /* never used */ const char *function_name; zend_class_entry *scope; zend_uint fn_flags; @@ -351,7 +373,6 @@ typedef union _zend_function { zend_internal_function internal_function; } zend_function; - typedef struct _zend_function_state { zend_function *function; void **arguments; @@ -426,6 +447,7 @@ void zend_init_compiler_context(TSRMLS_D); extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); extern ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC); +extern ZEND_API void (*zend_compile_string_inline)(zval *source_string, char *filename TSRMLS_DC); ZEND_API int lex_scan(zval *zendlval TSRMLS_DC); void startup_scanner(TSRMLS_D); @@ -513,6 +535,11 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC); void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_variable TSRMLS_DC); void zend_do_handle_exception(TSRMLS_D); +void zend_declare_accessor(znode *var_name TSRMLS_DC); +void zend_do_begin_accessor_declaration(znode *function_token, znode *modifiers, int return_reference, int has_params TSRMLS_DC); +void zend_do_end_accessor_declaration(znode *function_token, const znode *body TSRMLS_DC); +void zend_finalize_accessor(TSRMLS_D); + void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC); void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC); @@ -628,7 +655,7 @@ void zend_do_extended_fcall_end(TSRMLS_D); void zend_do_ticks(TSRMLS_D); -void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC); +void zend_do_abstract_method(const 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); @@ -645,6 +672,9 @@ void zend_do_goto(const znode *label TSRMLS_DC); void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC); void zend_release_labels(TSRMLS_D); +char *zend_visibility_string(zend_uint fn_flags); + + ZEND_API void function_add_ref(zend_function *function); #define INITIAL_OP_ARRAY_SIZE 64 @@ -654,6 +684,7 @@ ZEND_API void function_add_ref(zend_function *function); /* helper functions in zend_language_scanner.l */ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC); ZEND_API zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC); +ZEND_API void compile_string_inline(zval *source_string, char *filename TSRMLS_DC); ZEND_API zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC); ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...); ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC); diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index f457b2846f9e6..c110890fcc97f 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -502,6 +502,7 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg } else { TRACE_APPEND_STR("[internal function]: "); } + TRACE_APPEND_KEY("class"); TRACE_APPEND_KEY("type"); TRACE_APPEND_KEY("function"); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index f099784a42a89..8fbb423e0e17e 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1606,6 +1606,7 @@ zend_class_entry *zend_fetch_class_by_name(const char *class_name, uint class_na #define MAX_ABSTRACT_INFO_CNT 3 #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" + #define DISPLAY_ABSTRACT_FN(idx) \ ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ ai.afn[idx] ? "::" : "", \ @@ -1639,13 +1640,26 @@ static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_ } /* }}} */ +static int zend_verify_abstract_class_property(zend_property_info *prop, zend_abstract_info *ai TSRMLS_DC) /* {{{ */ +{ + if (prop->accs) { + int i; + for (i = 0; i < ZEND_NUM_ACCESSORS; ++i) { + if (prop->accs[i]) { + zend_verify_abstract_class_function(prop->accs[i], ai TSRMLS_CC); + } + } + } + return 0; +} +/* }}} */ + void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { zend_abstract_info ai; if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { memset(&ai, 0, sizeof(ai)); - zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); if (ai.cnt) { @@ -1657,6 +1671,19 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */ DISPLAY_ABSTRACT_FN(2) ); } + + memset(&ai, 0, sizeof(ai)); + zend_hash_apply_with_argument(&ce->properties_info, (apply_func_arg_t) zend_verify_abstract_class_property, &ai TSRMLS_CC); + + if (ai.cnt) { + zend_error(E_ERROR, "Class %s contains %d abstract accessor%s and must be declared abstract or implement the remaining accessors (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", + ce->name, ai.cnt, + ai.cnt > 1 ? "s" : "", + DISPLAY_ABSTRACT_FN(0), + DISPLAY_ABSTRACT_FN(1), + DISPLAY_ABSTRACT_FN(2) + ); + } } } /* }}} */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 800bdc7f66bcf..bf10e60f93d38 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -121,6 +121,7 @@ struct _zend_compiler_globals { zend_bool increment_lineno; znode implementing_class; + zend_property_info *current_property_info; zend_uint access_type; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index ccbc9b174c9d4..e3c853a338f33 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -585,12 +585,12 @@ class_statement_list: class_statement: - variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';' + variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_accessor_declarations | class_constant_declaration ';' | trait_use_statement | method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); } '(' parameter_list ')' - method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); } + method_body { zend_do_abstract_method(&$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); } ; trait_use_statement: @@ -679,6 +679,60 @@ member_modifier: | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; } ; +accessors: + /* empty */ + | accessors accessor_function +; + +accessor_modifiers: + /* empty */ { Z_LVAL($$.u.constant) = 0; } + | accessor_modifiers accessor_modifier { Z_LVAL($$.u.constant) = zend_do_verify_access_types(&$1, &$2); } +; + +accessor_modifier: + T_PUBLIC { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; } + | T_PROTECTED { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; } + | T_PRIVATE { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; } + | T_STATIC { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; } + | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; } + | T_ABSTRACT { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; } +; + +accessor_optional_parens: + /* empty */ + | '(' ')' +; + +accessor_function: + accessor_modifiers T_ISSET accessor_optional_parens + { Z_LVAL($2.u.constant) = T_ISSET; + zend_do_begin_accessor_declaration(&$2, &$1, 0, 0 TSRMLS_CC); } + method_body + { zend_do_end_accessor_declaration(&$2, &$5 TSRMLS_CC); } + | accessor_modifiers T_UNSET accessor_optional_parens + { Z_LVAL($2.u.constant) = T_UNSET; + zend_do_begin_accessor_declaration(&$2, &$1, 0, 0 TSRMLS_CC); } + method_body + { zend_do_end_accessor_declaration(&$2, &$5 TSRMLS_CC); } + | accessor_modifiers is_reference T_STRING accessor_optional_parens + { zend_do_begin_accessor_declaration(&$3, &$1, $2.op_type, 0 TSRMLS_CC); } + method_body + { zend_do_end_accessor_declaration(&$3, &$6 TSRMLS_CC); } + | accessor_modifiers is_reference T_STRING '(' + { zend_do_begin_accessor_declaration(&$3, &$1, $2.op_type, 1 TSRMLS_CC); } + non_empty_parameter_list ')' method_body + { zend_do_end_accessor_declaration(&$3, &$8 TSRMLS_CC); } +; + +class_variable_accessor_declarations: + T_VARIABLE '{' + { zend_declare_accessor(&$1 TSRMLS_CC); } + accessors + { zend_finalize_accessor(TSRMLS_C); } + '}' + | class_variable_declaration ';' +; + class_variable_declaration: class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); } | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); } diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c index f2ba6bf9d4d51..d47125a28dae8 100644 --- a/Zend/zend_language_scanner.c +++ b/Zend/zend_language_scanner.c @@ -783,6 +783,49 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC) } +void compile_string_inline(zval *source_string, char *filename TSRMLS_DC) +{ + zend_lex_state original_lex_state; + zval tmp; + int compiler_result; + zend_bool original_in_compilation = CG(in_compilation); + + if (Z_STRLEN_P(source_string) == 0) { + return; + } + + CG(in_compilation) = 1; + + tmp = *source_string; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + source_string = &tmp; + + zend_save_lexical_state(&original_lex_state TSRMLS_CC); + if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==SUCCESS) { + zend_bool orig_interactive = CG(interactive); + CG(zend_lineno) = original_lex_state.lineno; + + CG(interactive) = 0; + CG(interactive) = orig_interactive; + BEGIN(ST_IN_SCRIPTING); + compiler_result = zendparse(TSRMLS_C); + + if (SCNG(script_filtered)) { + efree(SCNG(script_filtered)); + SCNG(script_filtered) = NULL; + } + + if (compiler_result==1) { + CG(unclean_shutdown)=1; + } + } + zend_restore_lexical_state(&original_lex_state TSRMLS_CC); + zval_dtor(&tmp); + CG(in_compilation) = original_in_compilation; +} + + BEGIN_EXTERN_C() int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC) { @@ -1002,7 +1045,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yymore_restart: -#line 1006 "Zend/zend_language_scanner.c" +#line 1049 "Zend/zend_language_scanner.c" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1101,7 +1144,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy3: YYDEBUG(3, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1803 "Zend/zend_language_scanner.l" +#line 1846 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -1161,7 +1204,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) HANDLE_NEWLINES(yytext, yyleng); return T_INLINE_HTML; } -#line 1165 "Zend/zend_language_scanner.c" +#line 1208 "Zend/zend_language_scanner.c" yy4: YYDEBUG(4, *YYCURSOR); yych = *++YYCURSOR; @@ -1179,7 +1222,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy6: YYDEBUG(6, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1791 "Zend/zend_language_scanner.l" +#line 1834 "Zend/zend_language_scanner.l" { if (CG(short_tags)) { zendlval->value.str.val = yytext; /* no copying - intentional */ @@ -1191,14 +1234,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) goto inline_char_handler; } } -#line 1195 "Zend/zend_language_scanner.c" +#line 1238 "Zend/zend_language_scanner.c" yy7: YYDEBUG(7, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) == '=') goto yy43; YYDEBUG(8, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1768 "Zend/zend_language_scanner.l" +#line 1811 "Zend/zend_language_scanner.l" { if (CG(asp_tags)) { zendlval->value.str.val = yytext; /* no copying - intentional */ @@ -1210,7 +1253,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) goto inline_char_handler; } } -#line 1214 "Zend/zend_language_scanner.c" +#line 1257 "Zend/zend_language_scanner.c" yy9: YYDEBUG(9, *YYCURSOR); yych = *++YYCURSOR; @@ -1396,7 +1439,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(38, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1728 "Zend/zend_language_scanner.l" +#line 1771 "Zend/zend_language_scanner.l" { YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1)); @@ -1413,7 +1456,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) BEGIN(ST_IN_SCRIPTING); return T_OPEN_TAG; } -#line 1417 "Zend/zend_language_scanner.c" +#line 1460 "Zend/zend_language_scanner.c" yy39: YYDEBUG(39, *YYCURSOR); yych = *++YYCURSOR; @@ -1440,7 +1483,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(44, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1746 "Zend/zend_language_scanner.l" +#line 1789 "Zend/zend_language_scanner.l" { if (CG(asp_tags)) { zendlval->value.str.val = yytext; /* no copying - intentional */ @@ -1452,13 +1495,13 @@ int lex_scan(zval *zendlval TSRMLS_DC) goto inline_char_handler; } } -#line 1456 "Zend/zend_language_scanner.c" +#line 1499 "Zend/zend_language_scanner.c" yy45: YYDEBUG(45, *YYCURSOR); ++YYCURSOR; YYDEBUG(46, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1759 "Zend/zend_language_scanner.l" +#line 1802 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -1466,7 +1509,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) BEGIN(ST_IN_SCRIPTING); return T_OPEN_TAG_WITH_ECHO; } -#line 1470 "Zend/zend_language_scanner.c" +#line 1513 "Zend/zend_language_scanner.c" yy47: YYDEBUG(47, *YYCURSOR); yych = *++YYCURSOR; @@ -1493,7 +1536,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy51: YYDEBUG(51, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1781 "Zend/zend_language_scanner.l" +#line 1824 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -1502,7 +1545,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) BEGIN(ST_IN_SCRIPTING); return T_OPEN_TAG; } -#line 1506 "Zend/zend_language_scanner.c" +#line 1549 "Zend/zend_language_scanner.c" yy52: YYDEBUG(52, *YYCURSOR); ++YYCURSOR; @@ -1573,7 +1616,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy56: YYDEBUG(56, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2254 "Zend/zend_language_scanner.l" +#line 2297 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -1614,7 +1657,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 1618 "Zend/zend_language_scanner.c" +#line 1661 "Zend/zend_language_scanner.c" yy57: YYDEBUG(57, *YYCURSOR); yych = *++YYCURSOR; @@ -1625,12 +1668,12 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(59, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2198 "Zend/zend_language_scanner.l" +#line 2241 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); return '`'; } -#line 1634 "Zend/zend_language_scanner.c" +#line 1677 "Zend/zend_language_scanner.c" yy60: YYDEBUG(60, *YYCURSOR); yych = *++YYCURSOR; @@ -1640,14 +1683,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(62, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2185 "Zend/zend_language_scanner.l" +#line 2228 "Zend/zend_language_scanner.l" { zendlval->value.lval = (long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 1651 "Zend/zend_language_scanner.c" +#line 1694 "Zend/zend_language_scanner.c" yy63: YYDEBUG(63, *YYCURSOR); yyaccept = 0; @@ -1663,24 +1706,24 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy65: YYDEBUG(65, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1885 "Zend/zend_language_scanner.l" +#line 1928 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1673 "Zend/zend_language_scanner.c" +#line 1716 "Zend/zend_language_scanner.c" yy66: YYDEBUG(66, *YYCURSOR); ++YYCURSOR; YYDEBUG(67, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1461 "Zend/zend_language_scanner.l" +#line 1504 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 1684 "Zend/zend_language_scanner.c" +#line 1727 "Zend/zend_language_scanner.c" yy68: YYDEBUG(68, *YYCURSOR); yych = *++YYCURSOR; @@ -1694,7 +1737,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(71, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1877 "Zend/zend_language_scanner.l" +#line 1920 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); @@ -1702,7 +1745,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1706 "Zend/zend_language_scanner.c" +#line 1749 "Zend/zend_language_scanner.c" yy72: YYDEBUG(72, *YYCURSOR); yych = *++YYCURSOR; @@ -1720,7 +1763,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(74, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1867 "Zend/zend_language_scanner.l" +#line 1910 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); @@ -1728,7 +1771,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1732 "Zend/zend_language_scanner.c" +#line 1775 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_DOUBLE_QUOTES: @@ -1796,7 +1839,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy78: YYDEBUG(78, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2204 "Zend/zend_language_scanner.l" +#line 2247 "Zend/zend_language_scanner.l" { if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) { YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1; @@ -1845,7 +1888,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 1849 "Zend/zend_language_scanner.c" +#line 1892 "Zend/zend_language_scanner.c" yy79: YYDEBUG(79, *YYCURSOR); yych = *++YYCURSOR; @@ -1856,12 +1899,12 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(81, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2193 "Zend/zend_language_scanner.l" +#line 2236 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); return '"'; } -#line 1865 "Zend/zend_language_scanner.c" +#line 1908 "Zend/zend_language_scanner.c" yy82: YYDEBUG(82, *YYCURSOR); yych = *++YYCURSOR; @@ -1871,14 +1914,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(84, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2185 "Zend/zend_language_scanner.l" +#line 2228 "Zend/zend_language_scanner.l" { zendlval->value.lval = (long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 1882 "Zend/zend_language_scanner.c" +#line 1925 "Zend/zend_language_scanner.c" yy85: YYDEBUG(85, *YYCURSOR); yyaccept = 0; @@ -1894,24 +1937,24 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy87: YYDEBUG(87, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1885 "Zend/zend_language_scanner.l" +#line 1928 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1904 "Zend/zend_language_scanner.c" +#line 1947 "Zend/zend_language_scanner.c" yy88: YYDEBUG(88, *YYCURSOR); ++YYCURSOR; YYDEBUG(89, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1461 "Zend/zend_language_scanner.l" +#line 1504 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 1915 "Zend/zend_language_scanner.c" +#line 1958 "Zend/zend_language_scanner.c" yy90: YYDEBUG(90, *YYCURSOR); yych = *++YYCURSOR; @@ -1925,7 +1968,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(93, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1877 "Zend/zend_language_scanner.l" +#line 1920 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); @@ -1933,7 +1976,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1937 "Zend/zend_language_scanner.c" +#line 1980 "Zend/zend_language_scanner.c" yy94: YYDEBUG(94, *YYCURSOR); yych = *++YYCURSOR; @@ -1951,7 +1994,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(96, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1867 "Zend/zend_language_scanner.l" +#line 1910 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); @@ -1959,7 +2002,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1963 "Zend/zend_language_scanner.c" +#line 2006 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_END_HEREDOC: @@ -1970,7 +2013,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(100, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2171 "Zend/zend_language_scanner.l" +#line 2214 "Zend/zend_language_scanner.l" { zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack)); @@ -1983,7 +2026,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) BEGIN(ST_IN_SCRIPTING); return T_END_HEREDOC; } -#line 1987 "Zend/zend_language_scanner.c" +#line 2030 "Zend/zend_language_scanner.c" /* *********************************** */ yyc_ST_HEREDOC: { @@ -2045,7 +2088,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy104: YYDEBUG(104, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2296 "Zend/zend_language_scanner.l" +#line 2339 "Zend/zend_language_scanner.l" { int newline = 0; @@ -2118,7 +2161,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0 TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 2122 "Zend/zend_language_scanner.c" +#line 2165 "Zend/zend_language_scanner.c" yy105: YYDEBUG(105, *YYCURSOR); yych = *++YYCURSOR; @@ -2133,14 +2176,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(108, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2185 "Zend/zend_language_scanner.l" +#line 2228 "Zend/zend_language_scanner.l" { zendlval->value.lval = (long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 2144 "Zend/zend_language_scanner.c" +#line 2187 "Zend/zend_language_scanner.c" yy109: YYDEBUG(109, *YYCURSOR); yyaccept = 0; @@ -2156,24 +2199,24 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy111: YYDEBUG(111, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1885 "Zend/zend_language_scanner.l" +#line 1928 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 2166 "Zend/zend_language_scanner.c" +#line 2209 "Zend/zend_language_scanner.c" yy112: YYDEBUG(112, *YYCURSOR); ++YYCURSOR; YYDEBUG(113, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1461 "Zend/zend_language_scanner.l" +#line 1504 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 2177 "Zend/zend_language_scanner.c" +#line 2220 "Zend/zend_language_scanner.c" yy114: YYDEBUG(114, *YYCURSOR); yych = *++YYCURSOR; @@ -2187,7 +2230,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(117, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1877 "Zend/zend_language_scanner.l" +#line 1920 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); @@ -2195,7 +2238,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_VARIABLE; } -#line 2199 "Zend/zend_language_scanner.c" +#line 2242 "Zend/zend_language_scanner.c" yy118: YYDEBUG(118, *YYCURSOR); yych = *++YYCURSOR; @@ -2213,7 +2256,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(120, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1867 "Zend/zend_language_scanner.l" +#line 1910 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); @@ -2221,7 +2264,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_VARIABLE; } -#line 2225 "Zend/zend_language_scanner.c" +#line 2268 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_IN_SCRIPTING: @@ -2404,13 +2447,13 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy124: YYDEBUG(124, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1908 "Zend/zend_language_scanner.l" +#line 1951 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; return T_STRING; } -#line 2414 "Zend/zend_language_scanner.c" +#line 2457 "Zend/zend_language_scanner.c" yy125: YYDEBUG(125, *YYCURSOR); yych = *++YYCURSOR; @@ -2642,11 +2685,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy139: YYDEBUG(139, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1450 "Zend/zend_language_scanner.l" +#line 1493 "Zend/zend_language_scanner.l" { return yytext[0]; } -#line 2650 "Zend/zend_language_scanner.c" +#line 2693 "Zend/zend_language_scanner.c" yy140: YYDEBUG(140, *YYCURSOR); ++YYCURSOR; @@ -2655,7 +2698,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy141: YYDEBUG(141, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1181 "Zend/zend_language_scanner.l" +#line 1224 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -2663,7 +2706,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) HANDLE_NEWLINES(yytext, yyleng); return T_WHITESPACE; } -#line 2667 "Zend/zend_language_scanner.c" +#line 2710 "Zend/zend_language_scanner.c" yy142: YYDEBUG(142, *YYCURSOR); yych = *++YYCURSOR; @@ -2674,11 +2717,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(144, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1210 "Zend/zend_language_scanner.l" +#line 1253 "Zend/zend_language_scanner.l" { return T_NS_SEPARATOR; } -#line 2682 "Zend/zend_language_scanner.c" +#line 2725 "Zend/zend_language_scanner.c" yy145: YYDEBUG(145, *YYCURSOR); yych = *++YYCURSOR; @@ -2906,18 +2949,18 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(169, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1455 "Zend/zend_language_scanner.l" +#line 1498 "Zend/zend_language_scanner.l" { yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return '{'; } -#line 2915 "Zend/zend_language_scanner.c" +#line 2958 "Zend/zend_language_scanner.c" yy170: YYDEBUG(170, *YYCURSOR); ++YYCURSOR; YYDEBUG(171, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1467 "Zend/zend_language_scanner.l" +#line 1510 "Zend/zend_language_scanner.l" { RESET_DOC_COMMENT(); if (!zend_stack_is_empty(&SCNG(state_stack))) { @@ -2925,7 +2968,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } return '}'; } -#line 2929 "Zend/zend_language_scanner.c" +#line 2972 "Zend/zend_language_scanner.c" yy172: YYDEBUG(172, *YYCURSOR); yyaccept = 2; @@ -2953,7 +2996,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy173: YYDEBUG(173, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1518 "Zend/zend_language_scanner.l" +#line 1561 "Zend/zend_language_scanner.l" { if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */ zendlval->value.lval = strtol(yytext, NULL, 0); @@ -2974,7 +3017,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_LONG; return T_LNUMBER; } -#line 2978 "Zend/zend_language_scanner.c" +#line 3021 "Zend/zend_language_scanner.c" yy174: YYDEBUG(174, *YYCURSOR); yyaccept = 2; @@ -3002,7 +3045,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy177: YYDEBUG(177, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1915 "Zend/zend_language_scanner.l" +#line 1958 "Zend/zend_language_scanner.l" { while (YYCURSOR < YYLIMIT) { switch (*YYCURSOR++) { @@ -3036,14 +3079,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) return T_COMMENT; } -#line 3040 "Zend/zend_language_scanner.c" +#line 3083 "Zend/zend_language_scanner.c" yy178: YYDEBUG(178, *YYCURSOR); ++YYCURSOR; yy179: YYDEBUG(179, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2006 "Zend/zend_language_scanner.l" +#line 2049 "Zend/zend_language_scanner.l" { register char *s, *t; char *end; @@ -3111,14 +3154,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) } return T_CONSTANT_ENCAPSED_STRING; } -#line 3115 "Zend/zend_language_scanner.c" +#line 3158 "Zend/zend_language_scanner.c" yy180: YYDEBUG(180, *YYCURSOR); ++YYCURSOR; yy181: YYDEBUG(181, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2075 "Zend/zend_language_scanner.l" +#line 2118 "Zend/zend_language_scanner.l" { int bprefix = (yytext[0] != '"') ? 1 : 0; @@ -3159,24 +3202,24 @@ int lex_scan(zval *zendlval TSRMLS_DC) BEGIN(ST_DOUBLE_QUOTES); return '"'; } -#line 3163 "Zend/zend_language_scanner.c" +#line 3206 "Zend/zend_language_scanner.c" yy182: YYDEBUG(182, *YYCURSOR); ++YYCURSOR; YYDEBUG(183, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2165 "Zend/zend_language_scanner.l" +#line 2208 "Zend/zend_language_scanner.l" { BEGIN(ST_BACKQUOTE); return '`'; } -#line 3174 "Zend/zend_language_scanner.c" +#line 3217 "Zend/zend_language_scanner.c" yy184: YYDEBUG(184, *YYCURSOR); ++YYCURSOR; YYDEBUG(185, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2428 "Zend/zend_language_scanner.l" +#line 2471 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -3185,7 +3228,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); goto restart; } -#line 3189 "Zend/zend_language_scanner.c" +#line 3232 "Zend/zend_language_scanner.c" yy186: YYDEBUG(186, *YYCURSOR); ++YYCURSOR; @@ -3212,13 +3255,13 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy190: YYDEBUG(190, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1583 "Zend/zend_language_scanner.l" +#line 1626 "Zend/zend_language_scanner.l" { zendlval->value.dval = zend_strtod(yytext, NULL); zendlval->type = IS_DOUBLE; return T_DNUMBER; } -#line 3222 "Zend/zend_language_scanner.c" +#line 3265 "Zend/zend_language_scanner.c" yy191: YYDEBUG(191, *YYCURSOR); yyaccept = 2; @@ -3310,7 +3353,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(202, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1493 "Zend/zend_language_scanner.l" +#line 1536 "Zend/zend_language_scanner.l" { char *bin = yytext + 2; /* Skip "0b" */ int len = yyleng - 2; @@ -3335,7 +3378,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) return T_DNUMBER; } } -#line 3339 "Zend/zend_language_scanner.c" +#line 3382 "Zend/zend_language_scanner.c" yy203: YYDEBUG(203, *YYCURSOR); ++YYCURSOR; @@ -3347,7 +3390,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(205, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1539 "Zend/zend_language_scanner.l" +#line 1582 "Zend/zend_language_scanner.l" { char *hex = yytext + 2; /* Skip "0x" */ int len = yyleng - 2; @@ -3372,7 +3415,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) return T_DNUMBER; } } -#line 3376 "Zend/zend_language_scanner.c" +#line 3419 "Zend/zend_language_scanner.c" yy206: YYDEBUG(206, *YYCURSOR); ++YYCURSOR; @@ -3381,7 +3424,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy207: YYDEBUG(207, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1983 "Zend/zend_language_scanner.l" +#line 2026 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -3389,7 +3432,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) BEGIN(INITIAL); return T_CLOSE_TAG; /* implicit ';' at php-end tag */ } -#line 3393 "Zend/zend_language_scanner.c" +#line 3436 "Zend/zend_language_scanner.c" yy208: YYDEBUG(208, *YYCURSOR); yych = *++YYCURSOR; @@ -3423,13 +3466,13 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy212: YYDEBUG(212, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1885 "Zend/zend_language_scanner.l" +#line 1928 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 3433 "Zend/zend_language_scanner.c" +#line 3476 "Zend/zend_language_scanner.c" yy213: YYDEBUG(213, *YYCURSOR); yych = *++YYCURSOR; @@ -3443,11 +3486,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(215, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1438 "Zend/zend_language_scanner.l" +#line 1481 "Zend/zend_language_scanner.l" { return T_LOGICAL_XOR; } -#line 3451 "Zend/zend_language_scanner.c" +#line 3494 "Zend/zend_language_scanner.c" yy216: YYDEBUG(216, *YYCURSOR); ++YYCURSOR; @@ -3456,61 +3499,61 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(217, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1430 "Zend/zend_language_scanner.l" +#line 1473 "Zend/zend_language_scanner.l" { return T_LOGICAL_OR; } -#line 3464 "Zend/zend_language_scanner.c" +#line 3507 "Zend/zend_language_scanner.c" yy218: YYDEBUG(218, *YYCURSOR); ++YYCURSOR; YYDEBUG(219, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1418 "Zend/zend_language_scanner.l" +#line 1461 "Zend/zend_language_scanner.l" { return T_XOR_EQUAL; } -#line 3474 "Zend/zend_language_scanner.c" +#line 3517 "Zend/zend_language_scanner.c" yy220: YYDEBUG(220, *YYCURSOR); ++YYCURSOR; YYDEBUG(221, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1422 "Zend/zend_language_scanner.l" +#line 1465 "Zend/zend_language_scanner.l" { return T_BOOLEAN_OR; } -#line 3484 "Zend/zend_language_scanner.c" +#line 3527 "Zend/zend_language_scanner.c" yy222: YYDEBUG(222, *YYCURSOR); ++YYCURSOR; YYDEBUG(223, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1414 "Zend/zend_language_scanner.l" +#line 1457 "Zend/zend_language_scanner.l" { return T_OR_EQUAL; } -#line 3494 "Zend/zend_language_scanner.c" +#line 3537 "Zend/zend_language_scanner.c" yy224: YYDEBUG(224, *YYCURSOR); ++YYCURSOR; YYDEBUG(225, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1426 "Zend/zend_language_scanner.l" +#line 1469 "Zend/zend_language_scanner.l" { return T_BOOLEAN_AND; } -#line 3504 "Zend/zend_language_scanner.c" +#line 3547 "Zend/zend_language_scanner.c" yy226: YYDEBUG(226, *YYCURSOR); ++YYCURSOR; YYDEBUG(227, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1410 "Zend/zend_language_scanner.l" +#line 1453 "Zend/zend_language_scanner.l" { return T_AND_EQUAL; } -#line 3514 "Zend/zend_language_scanner.c" +#line 3557 "Zend/zend_language_scanner.c" yy228: YYDEBUG(228, *YYCURSOR); ++YYCURSOR; @@ -3519,7 +3562,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy229: YYDEBUG(229, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1992 "Zend/zend_language_scanner.l" +#line 2035 "Zend/zend_language_scanner.l" { if (CG(asp_tags)) { BEGIN(INITIAL); @@ -3532,17 +3575,17 @@ int lex_scan(zval *zendlval TSRMLS_DC) return yytext[0]; } } -#line 3536 "Zend/zend_language_scanner.c" +#line 3579 "Zend/zend_language_scanner.c" yy230: YYDEBUG(230, *YYCURSOR); ++YYCURSOR; YYDEBUG(231, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1398 "Zend/zend_language_scanner.l" +#line 1441 "Zend/zend_language_scanner.l" { return T_MOD_EQUAL; } -#line 3546 "Zend/zend_language_scanner.c" +#line 3589 "Zend/zend_language_scanner.c" yy232: YYDEBUG(232, *YYCURSOR); yych = *++YYCURSOR; @@ -3573,11 +3616,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(237, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1394 "Zend/zend_language_scanner.l" +#line 1437 "Zend/zend_language_scanner.l" { return T_CONCAT_EQUAL; } -#line 3581 "Zend/zend_language_scanner.c" +#line 3624 "Zend/zend_language_scanner.c" yy238: YYDEBUG(238, *YYCURSOR); yyaccept = 4; @@ -3586,7 +3629,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy239: YYDEBUG(239, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1949 "Zend/zend_language_scanner.l" +#line 1992 "Zend/zend_language_scanner.l" { int doc_com; @@ -3620,7 +3663,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) return T_COMMENT; } -#line 3624 "Zend/zend_language_scanner.c" +#line 3667 "Zend/zend_language_scanner.c" yy240: YYDEBUG(240, *YYCURSOR); yych = *++YYCURSOR; @@ -3630,11 +3673,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(242, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1390 "Zend/zend_language_scanner.l" +#line 1433 "Zend/zend_language_scanner.l" { return T_DIV_EQUAL; } -#line 3638 "Zend/zend_language_scanner.c" +#line 3681 "Zend/zend_language_scanner.c" yy243: YYDEBUG(243, *YYCURSOR); yych = *++YYCURSOR; @@ -3657,42 +3700,42 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(247, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1386 "Zend/zend_language_scanner.l" +#line 1429 "Zend/zend_language_scanner.l" { return T_MUL_EQUAL; } -#line 3665 "Zend/zend_language_scanner.c" +#line 3708 "Zend/zend_language_scanner.c" yy248: YYDEBUG(248, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) == '=') goto yy252; YYDEBUG(249, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1446 "Zend/zend_language_scanner.l" +#line 1489 "Zend/zend_language_scanner.l" { return T_SR; } -#line 3676 "Zend/zend_language_scanner.c" +#line 3719 "Zend/zend_language_scanner.c" yy250: YYDEBUG(250, *YYCURSOR); ++YYCURSOR; YYDEBUG(251, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1374 "Zend/zend_language_scanner.l" +#line 1417 "Zend/zend_language_scanner.l" { return T_IS_GREATER_OR_EQUAL; } -#line 3686 "Zend/zend_language_scanner.c" +#line 3729 "Zend/zend_language_scanner.c" yy252: YYDEBUG(252, *YYCURSOR); ++YYCURSOR; YYDEBUG(253, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1406 "Zend/zend_language_scanner.l" +#line 1449 "Zend/zend_language_scanner.l" { return T_SR_EQUAL; } -#line 3696 "Zend/zend_language_scanner.c" +#line 3739 "Zend/zend_language_scanner.c" yy254: YYDEBUG(254, *YYCURSOR); yyaccept = 5; @@ -3703,11 +3746,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy255: YYDEBUG(255, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1442 "Zend/zend_language_scanner.l" +#line 1485 "Zend/zend_language_scanner.l" { return T_SL; } -#line 3711 "Zend/zend_language_scanner.c" +#line 3754 "Zend/zend_language_scanner.c" yy256: YYDEBUG(256, *YYCURSOR); yych = *++YYCURSOR; @@ -3719,22 +3762,22 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(258, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1370 "Zend/zend_language_scanner.l" +#line 1413 "Zend/zend_language_scanner.l" { return T_IS_SMALLER_OR_EQUAL; } -#line 3727 "Zend/zend_language_scanner.c" +#line 3770 "Zend/zend_language_scanner.c" yy259: YYDEBUG(259, *YYCURSOR); ++YYCURSOR; yy260: YYDEBUG(260, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1366 "Zend/zend_language_scanner.l" +#line 1409 "Zend/zend_language_scanner.l" { return T_IS_NOT_EQUAL; } -#line 3738 "Zend/zend_language_scanner.c" +#line 3781 "Zend/zend_language_scanner.c" yy261: YYDEBUG(261, *YYCURSOR); yych = *++YYCURSOR; @@ -3785,11 +3828,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(269, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1402 "Zend/zend_language_scanner.l" +#line 1445 "Zend/zend_language_scanner.l" { return T_SL_EQUAL; } -#line 3793 "Zend/zend_language_scanner.c" +#line 3836 "Zend/zend_language_scanner.c" yy270: YYDEBUG(270, *YYCURSOR); ++YYCURSOR; @@ -3894,7 +3937,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy280: YYDEBUG(280, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2117 "Zend/zend_language_scanner.l" +#line 2160 "Zend/zend_language_scanner.l" { char *s; int bprefix = (yytext[0] != '<') ? 1 : 0; @@ -3941,7 +3984,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) return T_START_HEREDOC; } -#line 3945 "Zend/zend_language_scanner.c" +#line 3988 "Zend/zend_language_scanner.c" yy281: YYDEBUG(281, *YYCURSOR); yych = *++YYCURSOR; @@ -3981,31 +4024,31 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(286, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1358 "Zend/zend_language_scanner.l" +#line 1401 "Zend/zend_language_scanner.l" { return T_IS_NOT_IDENTICAL; } -#line 3989 "Zend/zend_language_scanner.c" +#line 4032 "Zend/zend_language_scanner.c" yy287: YYDEBUG(287, *YYCURSOR); ++YYCURSOR; YYDEBUG(288, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1378 "Zend/zend_language_scanner.l" +#line 1421 "Zend/zend_language_scanner.l" { return T_PLUS_EQUAL; } -#line 3999 "Zend/zend_language_scanner.c" +#line 4042 "Zend/zend_language_scanner.c" yy289: YYDEBUG(289, *YYCURSOR); ++YYCURSOR; YYDEBUG(290, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1346 "Zend/zend_language_scanner.l" +#line 1389 "Zend/zend_language_scanner.l" { return T_INC; } -#line 4009 "Zend/zend_language_scanner.c" +#line 4052 "Zend/zend_language_scanner.c" yy291: YYDEBUG(291, *YYCURSOR); yych = *++YYCURSOR; @@ -4024,42 +4067,42 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(294, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1334 "Zend/zend_language_scanner.l" +#line 1377 "Zend/zend_language_scanner.l" { return T_LIST; } -#line 4032 "Zend/zend_language_scanner.c" +#line 4075 "Zend/zend_language_scanner.c" yy295: YYDEBUG(295, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) == '=') goto yy299; YYDEBUG(296, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1362 "Zend/zend_language_scanner.l" +#line 1405 "Zend/zend_language_scanner.l" { return T_IS_EQUAL; } -#line 4043 "Zend/zend_language_scanner.c" +#line 4086 "Zend/zend_language_scanner.c" yy297: YYDEBUG(297, *YYCURSOR); ++YYCURSOR; YYDEBUG(298, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1330 "Zend/zend_language_scanner.l" +#line 1373 "Zend/zend_language_scanner.l" { return T_DOUBLE_ARROW; } -#line 4053 "Zend/zend_language_scanner.c" +#line 4096 "Zend/zend_language_scanner.c" yy299: YYDEBUG(299, *YYCURSOR); ++YYCURSOR; YYDEBUG(300, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1354 "Zend/zend_language_scanner.l" +#line 1397 "Zend/zend_language_scanner.l" { return T_IS_IDENTICAL; } -#line 4063 "Zend/zend_language_scanner.c" +#line 4106 "Zend/zend_language_scanner.c" yy301: YYDEBUG(301, *YYCURSOR); yych = *++YYCURSOR; @@ -4189,7 +4232,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(320, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1718 "Zend/zend_language_scanner.l" +#line 1761 "Zend/zend_language_scanner.l" { if (CG(current_namespace)) { *zendlval = *CG(current_namespace); @@ -4199,7 +4242,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } return T_NS_C; } -#line 4203 "Zend/zend_language_scanner.c" +#line 4246 "Zend/zend_language_scanner.c" yy321: YYDEBUG(321, *YYCURSOR); yych = *++YYCURSOR; @@ -4219,7 +4262,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(325, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1691 "Zend/zend_language_scanner.l" +#line 1734 "Zend/zend_language_scanner.l" { char *filename = zend_get_compiled_filename(TSRMLS_C); const size_t filename_len = strlen(filename); @@ -4246,7 +4289,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_DIR; } -#line 4250 "Zend/zend_language_scanner.c" +#line 4293 "Zend/zend_language_scanner.c" yy326: YYDEBUG(326, *YYCURSOR); yych = *++YYCURSOR; @@ -4271,13 +4314,13 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(331, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1673 "Zend/zend_language_scanner.l" +#line 1716 "Zend/zend_language_scanner.l" { zendlval->value.lval = CG(zend_lineno); zendlval->type = IS_LONG; return T_LINE; } -#line 4281 "Zend/zend_language_scanner.c" +#line 4324 "Zend/zend_language_scanner.c" yy332: YYDEBUG(332, *YYCURSOR); yych = *++YYCURSOR; @@ -4312,7 +4355,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(339, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1652 "Zend/zend_language_scanner.l" +#line 1695 "Zend/zend_language_scanner.l" { const char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL; const char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL; @@ -4333,7 +4376,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_METHOD_C; } -#line 4337 "Zend/zend_language_scanner.c" +#line 4380 "Zend/zend_language_scanner.c" yy340: YYDEBUG(340, *YYCURSOR); yych = *++YYCURSOR; @@ -4384,7 +4427,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(350, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1636 "Zend/zend_language_scanner.l" +#line 1679 "Zend/zend_language_scanner.l" { const char *func_name = NULL; @@ -4400,7 +4443,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_FUNC_C; } -#line 4404 "Zend/zend_language_scanner.c" +#line 4447 "Zend/zend_language_scanner.c" yy351: YYDEBUG(351, *YYCURSOR); yych = *++YYCURSOR; @@ -4420,7 +4463,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(355, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1679 "Zend/zend_language_scanner.l" +#line 1722 "Zend/zend_language_scanner.l" { char *filename = zend_get_compiled_filename(TSRMLS_C); @@ -4432,7 +4475,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zendlval->type = IS_STRING; return T_FILE; } -#line 4436 "Zend/zend_language_scanner.c" +#line 4479 "Zend/zend_language_scanner.c" yy356: YYDEBUG(356, *YYCURSOR); yych = *++YYCURSOR; @@ -4462,7 +4505,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(362, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1616 "Zend/zend_language_scanner.l" +#line 1659 "Zend/zend_language_scanner.l" { const char *trait_name = NULL; @@ -4482,7 +4525,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) return T_TRAIT_C; } -#line 4486 "Zend/zend_language_scanner.c" +#line 4529 "Zend/zend_language_scanner.c" yy363: YYDEBUG(363, *YYCURSOR); yych = *++YYCURSOR; @@ -4512,7 +4555,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(369, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1589 "Zend/zend_language_scanner.l" +#line 1632 "Zend/zend_language_scanner.l" { const char *class_name = NULL; @@ -4539,7 +4582,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } return T_CLASS_C; } -#line 4543 "Zend/zend_language_scanner.c" +#line 4586 "Zend/zend_language_scanner.c" yy370: YYDEBUG(370, *YYCURSOR); yych = *++YYCURSOR; @@ -4601,11 +4644,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(382, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1298 "Zend/zend_language_scanner.l" +#line 1341 "Zend/zend_language_scanner.l" { return T_HALT_COMPILER; } -#line 4609 "Zend/zend_language_scanner.c" +#line 4652 "Zend/zend_language_scanner.c" yy383: YYDEBUG(383, *YYCURSOR); yych = *++YYCURSOR; @@ -4625,11 +4668,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(386, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1278 "Zend/zend_language_scanner.l" +#line 1321 "Zend/zend_language_scanner.l" { return T_USE; } -#line 4633 "Zend/zend_language_scanner.c" +#line 4676 "Zend/zend_language_scanner.c" yy387: YYDEBUG(387, *YYCURSOR); yych = *++YYCURSOR; @@ -4648,11 +4691,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(390, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1326 "Zend/zend_language_scanner.l" +#line 1369 "Zend/zend_language_scanner.l" { return T_UNSET; } -#line 4656 "Zend/zend_language_scanner.c" +#line 4699 "Zend/zend_language_scanner.c" yy391: YYDEBUG(391, *YYCURSOR); ++YYCURSOR; @@ -4824,11 +4867,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(408, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1226 "Zend/zend_language_scanner.l" +#line 1269 "Zend/zend_language_scanner.l" { return T_INT_CAST; } -#line 4832 "Zend/zend_language_scanner.c" +#line 4875 "Zend/zend_language_scanner.c" yy409: YYDEBUG(409, *YYCURSOR); yych = *++YYCURSOR; @@ -4872,11 +4915,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(417, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1230 "Zend/zend_language_scanner.l" +#line 1273 "Zend/zend_language_scanner.l" { return T_DOUBLE_CAST; } -#line 4880 "Zend/zend_language_scanner.c" +#line 4923 "Zend/zend_language_scanner.c" yy418: YYDEBUG(418, *YYCURSOR); yych = *++YYCURSOR; @@ -4946,11 +4989,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(431, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1234 "Zend/zend_language_scanner.l" +#line 1277 "Zend/zend_language_scanner.l" { return T_STRING_CAST; } -#line 4954 "Zend/zend_language_scanner.c" +#line 4997 "Zend/zend_language_scanner.c" yy432: YYDEBUG(432, *YYCURSOR); yych = *++YYCURSOR; @@ -4983,11 +5026,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(438, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1238 "Zend/zend_language_scanner.l" +#line 1281 "Zend/zend_language_scanner.l" { return T_ARRAY_CAST; } -#line 4991 "Zend/zend_language_scanner.c" +#line 5034 "Zend/zend_language_scanner.c" yy439: YYDEBUG(439, *YYCURSOR); yych = *++YYCURSOR; @@ -5025,11 +5068,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(446, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1242 "Zend/zend_language_scanner.l" +#line 1285 "Zend/zend_language_scanner.l" { return T_OBJECT_CAST; } -#line 5033 "Zend/zend_language_scanner.c" +#line 5076 "Zend/zend_language_scanner.c" yy447: YYDEBUG(447, *YYCURSOR); yych = *++YYCURSOR; @@ -5070,11 +5113,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(454, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1246 "Zend/zend_language_scanner.l" +#line 1289 "Zend/zend_language_scanner.l" { return T_BOOL_CAST; } -#line 5078 "Zend/zend_language_scanner.c" +#line 5121 "Zend/zend_language_scanner.c" yy455: YYDEBUG(455, *YYCURSOR); yych = *++YYCURSOR; @@ -5134,11 +5177,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(466, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1250 "Zend/zend_language_scanner.l" +#line 1293 "Zend/zend_language_scanner.l" { return T_UNSET_CAST; } -#line 5142 "Zend/zend_language_scanner.c" +#line 5185 "Zend/zend_language_scanner.c" yy467: YYDEBUG(467, *YYCURSOR); yych = *++YYCURSOR; @@ -5152,11 +5195,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(469, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1222 "Zend/zend_language_scanner.l" +#line 1265 "Zend/zend_language_scanner.l" { return T_VAR; } -#line 5160 "Zend/zend_language_scanner.c" +#line 5203 "Zend/zend_language_scanner.c" yy470: YYDEBUG(470, *YYCURSOR); yych = *++YYCURSOR; @@ -5176,11 +5219,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(473, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1214 "Zend/zend_language_scanner.l" +#line 1257 "Zend/zend_language_scanner.l" { return T_NEW; } -#line 5184 "Zend/zend_language_scanner.c" +#line 5227 "Zend/zend_language_scanner.c" yy474: YYDEBUG(474, *YYCURSOR); yych = *++YYCURSOR; @@ -5219,21 +5262,21 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(481, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1274 "Zend/zend_language_scanner.l" +#line 1317 "Zend/zend_language_scanner.l" { return T_NAMESPACE; } -#line 5227 "Zend/zend_language_scanner.c" +#line 5270 "Zend/zend_language_scanner.c" yy482: YYDEBUG(482, *YYCURSOR); ++YYCURSOR; YYDEBUG(483, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1206 "Zend/zend_language_scanner.l" +#line 1249 "Zend/zend_language_scanner.l" { return T_PAAMAYIM_NEKUDOTAYIM; } -#line 5237 "Zend/zend_language_scanner.c" +#line 5280 "Zend/zend_language_scanner.c" yy484: YYDEBUG(484, *YYCURSOR); ++YYCURSOR; @@ -5255,32 +5298,32 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(487, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1382 "Zend/zend_language_scanner.l" +#line 1425 "Zend/zend_language_scanner.l" { return T_MINUS_EQUAL; } -#line 5263 "Zend/zend_language_scanner.c" +#line 5306 "Zend/zend_language_scanner.c" yy488: YYDEBUG(488, *YYCURSOR); ++YYCURSOR; YYDEBUG(489, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1350 "Zend/zend_language_scanner.l" +#line 1393 "Zend/zend_language_scanner.l" { return T_DEC; } -#line 5273 "Zend/zend_language_scanner.c" +#line 5316 "Zend/zend_language_scanner.c" yy490: YYDEBUG(490, *YYCURSOR); ++YYCURSOR; YYDEBUG(491, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1176 "Zend/zend_language_scanner.l" +#line 1219 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); return T_OBJECT_OPERATOR; } -#line 5284 "Zend/zend_language_scanner.c" +#line 5327 "Zend/zend_language_scanner.c" yy492: YYDEBUG(492, *YYCURSOR); yych = *++YYCURSOR; @@ -5325,11 +5368,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(498, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1322 "Zend/zend_language_scanner.l" +#line 1365 "Zend/zend_language_scanner.l" { return T_PUBLIC; } -#line 5333 "Zend/zend_language_scanner.c" +#line 5376 "Zend/zend_language_scanner.c" yy499: YYDEBUG(499, *YYCURSOR); yych = *++YYCURSOR; @@ -5384,11 +5427,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(507, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1318 "Zend/zend_language_scanner.l" +#line 1361 "Zend/zend_language_scanner.l" { return T_PROTECTED; } -#line 5392 "Zend/zend_language_scanner.c" +#line 5435 "Zend/zend_language_scanner.c" yy508: YYDEBUG(508, *YYCURSOR); yych = *++YYCURSOR; @@ -5418,11 +5461,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(513, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1314 "Zend/zend_language_scanner.l" +#line 1357 "Zend/zend_language_scanner.l" { return T_PRIVATE; } -#line 5426 "Zend/zend_language_scanner.c" +#line 5469 "Zend/zend_language_scanner.c" yy514: YYDEBUG(514, *YYCURSOR); ++YYCURSOR; @@ -5431,11 +5474,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(515, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1152 "Zend/zend_language_scanner.l" +#line 1195 "Zend/zend_language_scanner.l" { return T_PRINT; } -#line 5439 "Zend/zend_language_scanner.c" +#line 5482 "Zend/zend_language_scanner.c" yy516: YYDEBUG(516, *YYCURSOR); yych = *++YYCURSOR; @@ -5460,11 +5503,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(520, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1144 "Zend/zend_language_scanner.l" +#line 1187 "Zend/zend_language_scanner.l" { return T_GOTO; } -#line 5468 "Zend/zend_language_scanner.c" +#line 5511 "Zend/zend_language_scanner.c" yy521: YYDEBUG(521, *YYCURSOR); yych = *++YYCURSOR; @@ -5488,11 +5531,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(525, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1286 "Zend/zend_language_scanner.l" +#line 1329 "Zend/zend_language_scanner.l" { return T_GLOBAL; } -#line 5496 "Zend/zend_language_scanner.c" +#line 5539 "Zend/zend_language_scanner.c" yy526: YYDEBUG(526, *YYCURSOR); yych = *++YYCURSOR; @@ -5529,11 +5572,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(533, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1136 "Zend/zend_language_scanner.l" +#line 1179 "Zend/zend_language_scanner.l" { return T_BREAK; } -#line 5537 "Zend/zend_language_scanner.c" +#line 5580 "Zend/zend_language_scanner.c" yy534: YYDEBUG(534, *YYCURSOR); yych = *++YYCURSOR; @@ -5573,11 +5616,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(541, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1120 "Zend/zend_language_scanner.l" +#line 1163 "Zend/zend_language_scanner.l" { return T_SWITCH; } -#line 5581 "Zend/zend_language_scanner.c" +#line 5624 "Zend/zend_language_scanner.c" yy542: YYDEBUG(542, *YYCURSOR); yych = *++YYCURSOR; @@ -5601,11 +5644,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(546, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1302 "Zend/zend_language_scanner.l" +#line 1345 "Zend/zend_language_scanner.l" { return T_STATIC; } -#line 5609 "Zend/zend_language_scanner.c" +#line 5652 "Zend/zend_language_scanner.c" yy547: YYDEBUG(547, *YYCURSOR); yych = *++YYCURSOR; @@ -5632,11 +5675,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(551, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1116 "Zend/zend_language_scanner.l" +#line 1159 "Zend/zend_language_scanner.l" { return T_AS; } -#line 5640 "Zend/zend_language_scanner.c" +#line 5683 "Zend/zend_language_scanner.c" yy552: YYDEBUG(552, *YYCURSOR); yych = *++YYCURSOR; @@ -5655,11 +5698,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(555, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1338 "Zend/zend_language_scanner.l" +#line 1381 "Zend/zend_language_scanner.l" { return T_ARRAY; } -#line 5663 "Zend/zend_language_scanner.c" +#line 5706 "Zend/zend_language_scanner.c" yy556: YYDEBUG(556, *YYCURSOR); ++YYCURSOR; @@ -5668,11 +5711,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(557, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1434 "Zend/zend_language_scanner.l" +#line 1477 "Zend/zend_language_scanner.l" { return T_LOGICAL_AND; } -#line 5676 "Zend/zend_language_scanner.c" +#line 5719 "Zend/zend_language_scanner.c" yy558: YYDEBUG(558, *YYCURSOR); yych = *++YYCURSOR; @@ -5706,11 +5749,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(564, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1306 "Zend/zend_language_scanner.l" +#line 1349 "Zend/zend_language_scanner.l" { return T_ABSTRACT; } -#line 5714 "Zend/zend_language_scanner.c" +#line 5757 "Zend/zend_language_scanner.c" yy565: YYDEBUG(565, *YYCURSOR); yych = *++YYCURSOR; @@ -5734,11 +5777,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(569, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1076 "Zend/zend_language_scanner.l" +#line 1119 "Zend/zend_language_scanner.l" { return T_WHILE; } -#line 5742 "Zend/zend_language_scanner.c" +#line 5785 "Zend/zend_language_scanner.c" yy570: YYDEBUG(570, *YYCURSOR); ++YYCURSOR; @@ -5747,11 +5790,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(571, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1060 "Zend/zend_language_scanner.l" +#line 1103 "Zend/zend_language_scanner.l" { return T_IF; } -#line 5755 "Zend/zend_language_scanner.c" +#line 5798 "Zend/zend_language_scanner.c" yy572: YYDEBUG(572, *YYCURSOR); yych = *++YYCURSOR; @@ -5803,11 +5846,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(578, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1290 "Zend/zend_language_scanner.l" +#line 1333 "Zend/zend_language_scanner.l" { return T_ISSET; } -#line 5811 "Zend/zend_language_scanner.c" +#line 5854 "Zend/zend_language_scanner.c" yy579: YYDEBUG(579, *YYCURSOR); yych = *++YYCURSOR; @@ -5861,11 +5904,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy586: YYDEBUG(586, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1258 "Zend/zend_language_scanner.l" +#line 1301 "Zend/zend_language_scanner.l" { return T_INCLUDE; } -#line 5869 "Zend/zend_language_scanner.c" +#line 5912 "Zend/zend_language_scanner.c" yy587: YYDEBUG(587, *YYCURSOR); yych = *++YYCURSOR; @@ -5894,11 +5937,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(592, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1262 "Zend/zend_language_scanner.l" +#line 1305 "Zend/zend_language_scanner.l" { return T_INCLUDE_ONCE; } -#line 5902 "Zend/zend_language_scanner.c" +#line 5945 "Zend/zend_language_scanner.c" yy593: YYDEBUG(593, *YYCURSOR); yych = *++YYCURSOR; @@ -5932,11 +5975,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(599, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1160 "Zend/zend_language_scanner.l" +#line 1203 "Zend/zend_language_scanner.l" { return T_INTERFACE; } -#line 5940 "Zend/zend_language_scanner.c" +#line 5983 "Zend/zend_language_scanner.c" yy600: YYDEBUG(600, *YYCURSOR); yych = *++YYCURSOR; @@ -5986,11 +6029,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(607, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1282 "Zend/zend_language_scanner.l" +#line 1325 "Zend/zend_language_scanner.l" { return T_INSTEADOF; } -#line 5994 "Zend/zend_language_scanner.c" +#line 6037 "Zend/zend_language_scanner.c" yy608: YYDEBUG(608, *YYCURSOR); yych = *++YYCURSOR; @@ -6019,11 +6062,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(613, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1112 "Zend/zend_language_scanner.l" +#line 1155 "Zend/zend_language_scanner.l" { return T_INSTANCEOF; } -#line 6027 "Zend/zend_language_scanner.c" +#line 6070 "Zend/zend_language_scanner.c" yy614: YYDEBUG(614, *YYCURSOR); yych = *++YYCURSOR; @@ -6067,11 +6110,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(622, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1172 "Zend/zend_language_scanner.l" +#line 1215 "Zend/zend_language_scanner.l" { return T_IMPLEMENTS; } -#line 6075 "Zend/zend_language_scanner.c" +#line 6118 "Zend/zend_language_scanner.c" yy623: YYDEBUG(623, *YYCURSOR); yych = *++YYCURSOR; @@ -6099,11 +6142,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(626, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1044 "Zend/zend_language_scanner.l" +#line 1087 "Zend/zend_language_scanner.l" { return T_TRY; } -#line 6107 "Zend/zend_language_scanner.c" +#line 6150 "Zend/zend_language_scanner.c" yy627: YYDEBUG(627, *YYCURSOR); yych = *++YYCURSOR; @@ -6122,11 +6165,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(630, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1164 "Zend/zend_language_scanner.l" +#line 1207 "Zend/zend_language_scanner.l" { return T_TRAIT; } -#line 6130 "Zend/zend_language_scanner.c" +#line 6173 "Zend/zend_language_scanner.c" yy631: YYDEBUG(631, *YYCURSOR); yych = *++YYCURSOR; @@ -6145,11 +6188,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(634, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1056 "Zend/zend_language_scanner.l" +#line 1099 "Zend/zend_language_scanner.l" { return T_THROW; } -#line 6153 "Zend/zend_language_scanner.c" +#line 6196 "Zend/zend_language_scanner.c" yy635: YYDEBUG(635, *YYCURSOR); yych = *++YYCURSOR; @@ -6173,11 +6216,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(639, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1040 "Zend/zend_language_scanner.l" +#line 1083 "Zend/zend_language_scanner.l" { return T_YIELD; } -#line 6181 "Zend/zend_language_scanner.c" +#line 6224 "Zend/zend_language_scanner.c" yy640: YYDEBUG(640, *YYCURSOR); yych = *++YYCURSOR; @@ -6238,11 +6281,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy647: YYDEBUG(647, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1266 "Zend/zend_language_scanner.l" +#line 1309 "Zend/zend_language_scanner.l" { return T_REQUIRE; } -#line 6246 "Zend/zend_language_scanner.c" +#line 6289 "Zend/zend_language_scanner.c" yy648: YYDEBUG(648, *YYCURSOR); yych = *++YYCURSOR; @@ -6271,11 +6314,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(653, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1270 "Zend/zend_language_scanner.l" +#line 1313 "Zend/zend_language_scanner.l" { return T_REQUIRE_ONCE; } -#line 6279 "Zend/zend_language_scanner.c" +#line 6322 "Zend/zend_language_scanner.c" yy654: YYDEBUG(654, *YYCURSOR); yych = *++YYCURSOR; @@ -6294,11 +6337,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(657, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1036 "Zend/zend_language_scanner.l" +#line 1079 "Zend/zend_language_scanner.l" { return T_RETURN; } -#line 6302 "Zend/zend_language_scanner.c" +#line 6345 "Zend/zend_language_scanner.c" yy658: YYDEBUG(658, *YYCURSOR); yych = *++YYCURSOR; @@ -6388,11 +6431,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(668, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1140 "Zend/zend_language_scanner.l" +#line 1183 "Zend/zend_language_scanner.l" { return T_CONTINUE; } -#line 6396 "Zend/zend_language_scanner.c" +#line 6439 "Zend/zend_language_scanner.c" yy669: YYDEBUG(669, *YYCURSOR); ++YYCURSOR; @@ -6401,11 +6444,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(670, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1032 "Zend/zend_language_scanner.l" +#line 1075 "Zend/zend_language_scanner.l" { return T_CONST; } -#line 6409 "Zend/zend_language_scanner.c" +#line 6452 "Zend/zend_language_scanner.c" yy671: YYDEBUG(671, *YYCURSOR); yych = *++YYCURSOR; @@ -6430,11 +6473,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(675, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1218 "Zend/zend_language_scanner.l" +#line 1261 "Zend/zend_language_scanner.l" { return T_CLONE; } -#line 6438 "Zend/zend_language_scanner.c" +#line 6481 "Zend/zend_language_scanner.c" yy676: YYDEBUG(676, *YYCURSOR); yych = *++YYCURSOR; @@ -6448,11 +6491,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(678, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1156 "Zend/zend_language_scanner.l" +#line 1199 "Zend/zend_language_scanner.l" { return T_CLASS; } -#line 6456 "Zend/zend_language_scanner.c" +#line 6499 "Zend/zend_language_scanner.c" yy679: YYDEBUG(679, *YYCURSOR); yych = *++YYCURSOR; @@ -6498,11 +6541,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(687, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1342 "Zend/zend_language_scanner.l" +#line 1385 "Zend/zend_language_scanner.l" { return T_CALLABLE; } -#line 6506 "Zend/zend_language_scanner.c" +#line 6549 "Zend/zend_language_scanner.c" yy688: YYDEBUG(688, *YYCURSOR); ++YYCURSOR; @@ -6511,11 +6554,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(689, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1128 "Zend/zend_language_scanner.l" +#line 1171 "Zend/zend_language_scanner.l" { return T_CASE; } -#line 6519 "Zend/zend_language_scanner.c" +#line 6562 "Zend/zend_language_scanner.c" yy690: YYDEBUG(690, *YYCURSOR); yych = *++YYCURSOR; @@ -6529,11 +6572,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(692, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1048 "Zend/zend_language_scanner.l" +#line 1091 "Zend/zend_language_scanner.l" { return T_CATCH; } -#line 6537 "Zend/zend_language_scanner.c" +#line 6580 "Zend/zend_language_scanner.c" yy693: YYDEBUG(693, *YYCURSOR); yych = *++YYCURSOR; @@ -6584,11 +6627,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(702, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1028 "Zend/zend_language_scanner.l" +#line 1071 "Zend/zend_language_scanner.l" { return T_FUNCTION; } -#line 6592 "Zend/zend_language_scanner.c" +#line 6635 "Zend/zend_language_scanner.c" yy703: YYDEBUG(703, *YYCURSOR); ++YYCURSOR; @@ -6612,11 +6655,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy704: YYDEBUG(704, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1088 "Zend/zend_language_scanner.l" +#line 1131 "Zend/zend_language_scanner.l" { return T_FOR; } -#line 6620 "Zend/zend_language_scanner.c" +#line 6663 "Zend/zend_language_scanner.c" yy705: YYDEBUG(705, *YYCURSOR); yych = *++YYCURSOR; @@ -6640,11 +6683,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(709, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1096 "Zend/zend_language_scanner.l" +#line 1139 "Zend/zend_language_scanner.l" { return T_FOREACH; } -#line 6648 "Zend/zend_language_scanner.c" +#line 6691 "Zend/zend_language_scanner.c" yy710: YYDEBUG(710, *YYCURSOR); yych = *++YYCURSOR; @@ -6678,11 +6721,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy713: YYDEBUG(713, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1310 "Zend/zend_language_scanner.l" +#line 1353 "Zend/zend_language_scanner.l" { return T_FINAL; } -#line 6686 "Zend/zend_language_scanner.c" +#line 6729 "Zend/zend_language_scanner.c" yy714: YYDEBUG(714, *YYCURSOR); yych = *++YYCURSOR; @@ -6696,11 +6739,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(716, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1052 "Zend/zend_language_scanner.l" +#line 1095 "Zend/zend_language_scanner.l" { return T_FINALLY; } -#line 6704 "Zend/zend_language_scanner.c" +#line 6747 "Zend/zend_language_scanner.c" yy717: YYDEBUG(717, *YYCURSOR); yych = *++YYCURSOR; @@ -6731,11 +6774,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(720, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1084 "Zend/zend_language_scanner.l" +#line 1127 "Zend/zend_language_scanner.l" { return T_DO; } -#line 6739 "Zend/zend_language_scanner.c" +#line 6782 "Zend/zend_language_scanner.c" yy721: YYDEBUG(721, *YYCURSOR); ++YYCURSOR; @@ -6744,11 +6787,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(722, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1024 "Zend/zend_language_scanner.l" +#line 1067 "Zend/zend_language_scanner.l" { return T_EXIT; } -#line 6752 "Zend/zend_language_scanner.c" +#line 6795 "Zend/zend_language_scanner.c" yy723: YYDEBUG(723, *YYCURSOR); yych = *++YYCURSOR; @@ -6783,11 +6826,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(729, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1132 "Zend/zend_language_scanner.l" +#line 1175 "Zend/zend_language_scanner.l" { return T_DEFAULT; } -#line 6791 "Zend/zend_language_scanner.c" +#line 6834 "Zend/zend_language_scanner.c" yy730: YYDEBUG(730, *YYCURSOR); yych = *++YYCURSOR; @@ -6811,11 +6854,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(734, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1104 "Zend/zend_language_scanner.l" +#line 1147 "Zend/zend_language_scanner.l" { return T_DECLARE; } -#line 6819 "Zend/zend_language_scanner.c" +#line 6862 "Zend/zend_language_scanner.c" yy735: YYDEBUG(735, *YYCURSOR); yych = *++YYCURSOR; @@ -6895,11 +6938,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(747, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1168 "Zend/zend_language_scanner.l" +#line 1211 "Zend/zend_language_scanner.l" { return T_EXTENDS; } -#line 6903 "Zend/zend_language_scanner.c" +#line 6946 "Zend/zend_language_scanner.c" yy748: YYDEBUG(748, *YYCURSOR); ++YYCURSOR; @@ -6908,11 +6951,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(749, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1020 "Zend/zend_language_scanner.l" +#line 1063 "Zend/zend_language_scanner.l" { return T_EXIT; } -#line 6916 "Zend/zend_language_scanner.c" +#line 6959 "Zend/zend_language_scanner.c" yy750: YYDEBUG(750, *YYCURSOR); yych = *++YYCURSOR; @@ -6926,11 +6969,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(752, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1254 "Zend/zend_language_scanner.l" +#line 1297 "Zend/zend_language_scanner.l" { return T_EVAL; } -#line 6934 "Zend/zend_language_scanner.c" +#line 6977 "Zend/zend_language_scanner.c" yy753: YYDEBUG(753, *YYCURSOR); yych = *++YYCURSOR; @@ -7000,11 +7043,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(763, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1080 "Zend/zend_language_scanner.l" +#line 1123 "Zend/zend_language_scanner.l" { return T_ENDWHILE; } -#line 7008 "Zend/zend_language_scanner.c" +#line 7051 "Zend/zend_language_scanner.c" yy764: YYDEBUG(764, *YYCURSOR); yych = *++YYCURSOR; @@ -7033,11 +7076,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(769, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1124 "Zend/zend_language_scanner.l" +#line 1167 "Zend/zend_language_scanner.l" { return T_ENDSWITCH; } -#line 7041 "Zend/zend_language_scanner.c" +#line 7084 "Zend/zend_language_scanner.c" yy770: YYDEBUG(770, *YYCURSOR); ++YYCURSOR; @@ -7046,11 +7089,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(771, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1068 "Zend/zend_language_scanner.l" +#line 1111 "Zend/zend_language_scanner.l" { return T_ENDIF; } -#line 7054 "Zend/zend_language_scanner.c" +#line 7097 "Zend/zend_language_scanner.c" yy772: YYDEBUG(772, *YYCURSOR); yych = *++YYCURSOR; @@ -7079,11 +7122,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy774: YYDEBUG(774, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1092 "Zend/zend_language_scanner.l" +#line 1135 "Zend/zend_language_scanner.l" { return T_ENDFOR; } -#line 7087 "Zend/zend_language_scanner.c" +#line 7130 "Zend/zend_language_scanner.c" yy775: YYDEBUG(775, *YYCURSOR); yych = *++YYCURSOR; @@ -7107,11 +7150,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(779, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1100 "Zend/zend_language_scanner.l" +#line 1143 "Zend/zend_language_scanner.l" { return T_ENDFOREACH; } -#line 7115 "Zend/zend_language_scanner.c" +#line 7158 "Zend/zend_language_scanner.c" yy780: YYDEBUG(780, *YYCURSOR); yych = *++YYCURSOR; @@ -7145,11 +7188,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(786, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1108 "Zend/zend_language_scanner.l" +#line 1151 "Zend/zend_language_scanner.l" { return T_ENDDECLARE; } -#line 7153 "Zend/zend_language_scanner.c" +#line 7196 "Zend/zend_language_scanner.c" yy787: YYDEBUG(787, *YYCURSOR); yych = *++YYCURSOR; @@ -7168,11 +7211,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(790, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1294 "Zend/zend_language_scanner.l" +#line 1337 "Zend/zend_language_scanner.l" { return T_EMPTY; } -#line 7176 "Zend/zend_language_scanner.c" +#line 7219 "Zend/zend_language_scanner.c" yy791: YYDEBUG(791, *YYCURSOR); yych = *++YYCURSOR; @@ -7201,11 +7244,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy793: YYDEBUG(793, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1072 "Zend/zend_language_scanner.l" +#line 1115 "Zend/zend_language_scanner.l" { return T_ELSE; } -#line 7209 "Zend/zend_language_scanner.c" +#line 7252 "Zend/zend_language_scanner.c" yy794: YYDEBUG(794, *YYCURSOR); yych = *++YYCURSOR; @@ -7219,11 +7262,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(796, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1064 "Zend/zend_language_scanner.l" +#line 1107 "Zend/zend_language_scanner.l" { return T_ELSEIF; } -#line 7227 "Zend/zend_language_scanner.c" +#line 7270 "Zend/zend_language_scanner.c" yy797: YYDEBUG(797, *YYCURSOR); yych = *++YYCURSOR; @@ -7237,11 +7280,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) } YYDEBUG(799, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1148 "Zend/zend_language_scanner.l" +#line 1191 "Zend/zend_language_scanner.l" { return T_ECHO; } -#line 7245 "Zend/zend_language_scanner.c" +#line 7288 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_LOOKING_FOR_PROPERTY: @@ -7314,7 +7357,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy803: YYDEBUG(803, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1181 "Zend/zend_language_scanner.l" +#line 1224 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -7322,7 +7365,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) HANDLE_NEWLINES(yytext, yyleng); return T_WHITESPACE; } -#line 7326 "Zend/zend_language_scanner.c" +#line 7369 "Zend/zend_language_scanner.c" yy804: YYDEBUG(804, *YYCURSOR); ++YYCURSOR; @@ -7330,13 +7373,13 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy805: YYDEBUG(805, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1200 "Zend/zend_language_scanner.l" +#line 1243 "Zend/zend_language_scanner.l" { yyless(0); yy_pop_state(TSRMLS_C); goto restart; } -#line 7340 "Zend/zend_language_scanner.c" +#line 7383 "Zend/zend_language_scanner.c" yy806: YYDEBUG(806, *YYCURSOR); ++YYCURSOR; @@ -7345,14 +7388,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy807: YYDEBUG(807, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1193 "Zend/zend_language_scanner.l" +#line 1236 "Zend/zend_language_scanner.l" { yy_pop_state(TSRMLS_C); zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; return T_STRING; } -#line 7356 "Zend/zend_language_scanner.c" +#line 7399 "Zend/zend_language_scanner.c" yy808: YYDEBUG(808, *YYCURSOR); yych = *++YYCURSOR; @@ -7373,11 +7416,11 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(812, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1189 "Zend/zend_language_scanner.l" +#line 1232 "Zend/zend_language_scanner.l" { return T_OBJECT_OPERATOR; } -#line 7381 "Zend/zend_language_scanner.c" +#line 7424 "Zend/zend_language_scanner.c" yy813: YYDEBUG(813, *YYCURSOR); ++YYCURSOR; @@ -7462,14 +7505,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy818: YYDEBUG(818, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1486 "Zend/zend_language_scanner.l" +#line 1529 "Zend/zend_language_scanner.l" { yyless(0); yy_pop_state(TSRMLS_C); yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); goto restart; } -#line 7473 "Zend/zend_language_scanner.c" +#line 7516 "Zend/zend_language_scanner.c" yy819: YYDEBUG(819, *YYCURSOR); yych = *++YYCURSOR; @@ -7494,7 +7537,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(824, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1476 "Zend/zend_language_scanner.l" +#line 1519 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); zend_copy_value(zendlval, yytext, yyleng); @@ -7503,7 +7546,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return T_STRING_VARNAME; } -#line 7507 "Zend/zend_language_scanner.c" +#line 7550 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_NOWDOC: @@ -7514,7 +7557,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(828, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2370 "Zend/zend_language_scanner.l" +#line 2413 "Zend/zend_language_scanner.l" { int newline = 0; @@ -7571,7 +7614,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) HANDLE_NEWLINES(yytext, yyleng - newline); return T_ENCAPSED_AND_WHITESPACE; } -#line 7575 "Zend/zend_language_scanner.c" +#line 7618 "Zend/zend_language_scanner.c" /* *********************************** */ yyc_ST_VAR_OFFSET: { @@ -7678,7 +7721,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy832: YYDEBUG(832, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1564 "Zend/zend_language_scanner.l" +#line 1607 "Zend/zend_language_scanner.l" { /* Offset could be treated as a long */ if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) { zendlval->value.lval = strtol(yytext, NULL, 10); @@ -7690,7 +7733,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) } return T_NUM_STRING; } -#line 7694 "Zend/zend_language_scanner.c" +#line 7737 "Zend/zend_language_scanner.c" yy833: YYDEBUG(833, *YYCURSOR); yych = *++YYCURSOR; @@ -7710,23 +7753,23 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy835: YYDEBUG(835, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1896 "Zend/zend_language_scanner.l" +#line 1939 "Zend/zend_language_scanner.l" { /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */ return yytext[0]; } -#line 7719 "Zend/zend_language_scanner.c" +#line 7762 "Zend/zend_language_scanner.c" yy836: YYDEBUG(836, *YYCURSOR); ++YYCURSOR; YYDEBUG(837, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1891 "Zend/zend_language_scanner.l" +#line 1934 "Zend/zend_language_scanner.l" { yy_pop_state(TSRMLS_C); return ']'; } -#line 7730 "Zend/zend_language_scanner.c" +#line 7773 "Zend/zend_language_scanner.c" yy838: YYDEBUG(838, *YYCURSOR); yych = *++YYCURSOR; @@ -7736,14 +7779,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) ++YYCURSOR; YYDEBUG(840, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1901 "Zend/zend_language_scanner.l" +#line 1944 "Zend/zend_language_scanner.l" { /* Invalid rule to return a more explicit parse error with proper line number */ yyless(0); yy_pop_state(TSRMLS_C); return T_ENCAPSED_AND_WHITESPACE; } -#line 7747 "Zend/zend_language_scanner.c" +#line 7790 "Zend/zend_language_scanner.c" yy841: YYDEBUG(841, *YYCURSOR); ++YYCURSOR; @@ -7752,19 +7795,19 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy842: YYDEBUG(842, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1908 "Zend/zend_language_scanner.l" +#line 1951 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; return T_STRING; } -#line 7762 "Zend/zend_language_scanner.c" +#line 7805 "Zend/zend_language_scanner.c" yy843: YYDEBUG(843, *YYCURSOR); ++YYCURSOR; YYDEBUG(844, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2428 "Zend/zend_language_scanner.l" +#line 2471 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -7773,7 +7816,7 @@ int lex_scan(zval *zendlval TSRMLS_DC) zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); goto restart; } -#line 7777 "Zend/zend_language_scanner.c" +#line 7820 "Zend/zend_language_scanner.c" yy845: YYDEBUG(845, *YYCURSOR); ++YYCURSOR; @@ -7809,13 +7852,13 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy849: YYDEBUG(849, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1885 "Zend/zend_language_scanner.l" +#line 1928 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 7819 "Zend/zend_language_scanner.c" +#line 7862 "Zend/zend_language_scanner.c" yy850: YYDEBUG(850, *YYCURSOR); ++YYCURSOR; @@ -7855,14 +7898,14 @@ int lex_scan(zval *zendlval TSRMLS_DC) yy857: YYDEBUG(857, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1576 "Zend/zend_language_scanner.l" +#line 1619 "Zend/zend_language_scanner.l" { /* Offset must be treated as a string */ zendlval->value.str.val = (char *)estrndup(yytext, yyleng); zendlval->value.str.len = yyleng; zendlval->type = IS_STRING; return T_NUM_STRING; } -#line 7866 "Zend/zend_language_scanner.c" +#line 7909 "Zend/zend_language_scanner.c" yy858: YYDEBUG(858, *YYCURSOR); ++YYCURSOR; @@ -7885,6 +7928,6 @@ int lex_scan(zval *zendlval TSRMLS_DC) goto yy857; } } -#line 2437 "Zend/zend_language_scanner.l" +#line 2480 "Zend/zend_language_scanner.l" } diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index d44ba20e1bb74..5d40fd98c2cdb 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -781,6 +781,49 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC) } +void compile_string_inline(zval *source_string, char *filename TSRMLS_DC) +{ + zend_lex_state original_lex_state; + zval tmp; + int compiler_result; + zend_bool original_in_compilation = CG(in_compilation); + + if (Z_STRLEN_P(source_string) == 0) { + return; + } + + CG(in_compilation) = 1; + + tmp = *source_string; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + source_string = &tmp; + + zend_save_lexical_state(&original_lex_state TSRMLS_CC); + if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==SUCCESS) { + zend_bool orig_interactive = CG(interactive); + CG(zend_lineno) = original_lex_state.lineno; + + CG(interactive) = 0; + CG(interactive) = orig_interactive; + BEGIN(ST_IN_SCRIPTING); + compiler_result = zendparse(TSRMLS_C); + + if (SCNG(script_filtered)) { + efree(SCNG(script_filtered)); + SCNG(script_filtered) = NULL; + } + + if (compiler_result==1) { + CG(unclean_shutdown)=1; + } + } + zend_restore_lexical_state(&original_lex_state TSRMLS_CC); + zval_dtor(&tmp); + CG(in_compilation) = original_in_compilation; +} + + BEGIN_EXTERN_C() int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 176d451e053c3..59535489e9554 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -49,19 +49,20 @@ /* __X accessors explanation: - if we have __get and property that is not part of the properties array is - requested, we call __get handler. If it fails, we return uninitialized. + if we have __get/getter and property that is not part of the properties array is + requested, we call __get/getter handler. If it fails, we return uninitialized. - if we have __set and property that is not part of the properties array is - set, we call __set handler. If it fails, we do not change the array. + if we have __set/setter and property that is not part of the properties array is + set, we call __set/setter handler. If it fails, we do not change the array. - for both handlers above, when we are inside __get/__set, no further calls for - __get/__set for this property of this object will be made, to prevent endless + for both handlers above, when we are inside __get/__set/accessor, no further calls for + __get/__set/accessor for this property of this object will be made, to prevent endless recursion and enable accessors to change properties array. if we have __call and method which is not part of the class function table is called, we cal __call handler. */ +static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len, const struct _zend_literal *key TSRMLS_DC); ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */ { @@ -142,36 +143,74 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC } /* }}} */ -static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) /* {{{ */ +static zval *zend_std_call_getter(zval *object, zval *member, zend_function *getter, int bp_var_type, zend_guard *guard TSRMLS_DC) /* {{{ */ { - zval *retval = NULL; - zend_class_entry *ce = Z_OBJCE_P(object); + zval *rv = NULL; + zend_object *zobj = Z_OBJ_P(object); + + Z_ADDREF_P(object); + if (PZVAL_IS_REF(object)) { + SEPARATE_ZVAL(&object); + } /* __get handler is called with one argument: property name - it should return whether the call was successfull or not + it should return whether the call was successful or not */ SEPARATE_ARG_IF_REF(member); - zend_call_method_with_1_params(&object, ce, &ce->__get, ZEND_GET_FUNC_NAME, &retval, member); - - zval_ptr_dtor(&member); + if (getter == zobj->ce->__get) { + guard->in_get = 1; /* prevent circular getting */ + zend_call_method_with_1_params(&object, zobj->ce, &zobj->ce->__get, ZEND_GET_FUNC_NAME, &rv, member); + guard->in_get = 0; + } else { + zend_call_method_with_0_params(&object, zobj->ce, &getter, getter->common.function_name, &rv); + } - if (retval) { - Z_DELREF_P(retval); + if (rv) { + Z_DELREF_P(rv); + if (!Z_ISREF_P(rv) && + (bp_var_type == BP_VAR_W || bp_var_type == BP_VAR_RW || bp_var_type == BP_VAR_UNSET)) { + if (Z_REFCOUNT_P(rv) > 0) { + zval *tmp = rv; + + ALLOC_ZVAL(rv); + *rv = *tmp; + zval_copy_ctor(rv); + Z_UNSET_ISREF_P(rv); + Z_SET_REFCOUNT_P(rv, 0); + } + if (UNEXPECTED(Z_TYPE_P(rv) != IS_OBJECT)) { + zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", zobj->ce->name, Z_STRVAL_P(member)); + } + } + } else { + rv = EG(uninitialized_zval_ptr); + } + if (EXPECTED(rv != object)) { + zval_ptr_dtor(&object); + } else { + Z_DELREF_P(object); } - return retval; + zval_ptr_dtor(&member); + + return rv; } /* }}} */ -static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */ +static int zend_std_call_setter(zval *object, zval *member, zval *value, zend_function *setter, zend_guard *guard TSRMLS_DC) /* {{{ */ { zval *retval = NULL; - int result; - zend_class_entry *ce = Z_OBJCE_P(object); + int result = FAILURE; + zend_object *zobj = Z_OBJ_P(object); + + Z_ADDREF_P(object); + if (PZVAL_IS_REF(object)) { + SEPARATE_ZVAL(&object); + } SEPARATE_ARG_IF_REF(member); Z_ADDREF_P(value); @@ -180,26 +219,36 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D property name value to be set - it should return whether the call was successfull or not + it should return whether the call was successful or not */ - zend_call_method_with_2_params(&object, ce, &ce->__set, ZEND_SET_FUNC_NAME, &retval, member, value); + if (setter == zobj->ce->__set) { + guard->in_set = 1; /* Prevent recursion */ + zend_call_method_with_2_params(&object, zobj->ce, &zobj->ce->__set, ZEND_SET_FUNC_NAME, &retval, member, value); + guard->in_set = 0; + } else { + zend_call_method_with_1_params(&object, zobj->ce, &setter, setter->common.function_name, &retval, value); + } zval_ptr_dtor(&member); zval_ptr_dtor(&value); + zval_ptr_dtor(&object); if (retval) { result = i_zend_is_true(retval) ? SUCCESS : FAILURE; zval_ptr_dtor(&retval); - return result; - } else { - return FAILURE; } + return result; } /* }}} */ -static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{ */ +static void zend_std_call_unsetter(zval *object, zval *member, zend_function *unsetter, zend_guard *guard TSRMLS_DC) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); + zend_object *zobj = Z_OBJ_P(object); + + Z_ADDREF_P(object); + if (PZVAL_IS_REF(object)) { + SEPARATE_ZVAL(&object); + } /* __unset handler is called with one argument: property name @@ -207,16 +256,29 @@ static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{ SEPARATE_ARG_IF_REF(member); - zend_call_method_with_1_params(&object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member); + if (unsetter == zobj->ce->__unset) { + guard->in_unset = 1; /* Prevent recursion */ + zend_call_method_with_1_params(&object, zobj->ce, &zobj->ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member); + guard->in_unset = 0; /* Prevent recursion */ + } else { + zend_call_method_with_0_params(&object, zobj->ce, &unsetter, unsetter->common.function_name, NULL); + } zval_ptr_dtor(&member); + zval_ptr_dtor(&object); } /* }}} */ -static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) /* {{{ */ +static int zend_std_call_issetter(zval *object, zval *member, int has_set_exists, zend_function *issetter, const zend_literal *key, zend_guard *guard TSRMLS_DC) /* {{{ */ { - zval *retval = NULL; - zend_class_entry *ce = Z_OBJCE_P(object); + zend_object *zobj = Z_OBJ_P(object); + zval *rv; + int result = 0; + + Z_ADDREF_P(object); + if (PZVAL_IS_REF(object)) { + SEPARATE_ZVAL(&object); + } /* __isset handler is called with one argument: property name @@ -226,11 +288,33 @@ static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) /* {{{ SEPARATE_ARG_IF_REF(member); - zend_call_method_with_1_params(&object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, &retval, member); + if (issetter == zobj->ce->__isset) { + guard->in_isset = 1; /* Prevent recursion */ + zend_call_method_with_1_params(&object, zobj->ce, &zobj->ce->__isset, ZEND_ISSET_FUNC_NAME, &rv, member); + guard->in_isset = 0; + } else { + zend_call_method_with_0_params(&object, zobj->ce, &issetter, issetter->common.function_name, &rv); + } + + if (rv) { + result = zend_is_true(rv); + zval_ptr_dtor(&rv); + if (has_set_exists && result) { + rv = zend_std_read_property(object, member, BP_VAR_IS, key TSRMLS_CC); + if (rv) { + Z_ADDREF_P(rv); + result = i_zend_is_true(rv); + zval_ptr_dtor(&rv); + } else { + result = 0; + } + } + } zval_ptr_dtor(&member); + zval_ptr_dtor(&object); - return retval; + return result; } /* }}} */ @@ -267,7 +351,66 @@ static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_cla } /* }}} */ -static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent, const zend_literal *key TSRMLS_DC) /* {{{ */ +static zend_function *zend_get_accessor_from_ce(const zend_class_entry *ce, const zval *member, const zend_literal *key, zend_acc_index acc) /* {{{ */ +{ + zend_property_info *property_info; + const char *name = Z_STRVAL_P(member); + int name_len = Z_STRLEN_P(member) + 1; + zend_ulong h = key ? key->hash_value : zend_get_hash_value(name, name_len); + + if (zend_hash_quick_find(&ce->properties_info, name, name_len, h, (void **) &property_info) == FAILURE) { + return NULL; + } + + return property_info->accs ? property_info->accs[acc] : NULL; +} +/* }}} */ + +static zend_function *zend_get_accessor(const zend_property_info *property_info, zend_class_entry *ce, const zval *member, const zend_literal *key, zend_acc_index acc TSRMLS_DC) /* {{{ */ +{ + zend_function *fbc = property_info->accs[acc]; + + if (!fbc) { + return NULL; + } + + if (fbc->common.fn_flags & ZEND_ACC_PRIVATE) { + if (fbc->common.scope == ce && EG(scope) == ce) { + return fbc; + } else if (EG(scope) && is_derived_class(ce, EG(scope))) { + zend_function *real_fbc = zend_get_accessor_from_ce(EG(scope), member, key, acc); + if (real_fbc && real_fbc->common.scope == EG(scope)) { + return real_fbc; + } + } + + zend_error_noreturn(E_ERROR, "Call to %s accessor %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), fbc->common.function_name, EG(scope) ? EG(scope)->name : ""); + } + + if (EG(scope) && is_derived_class(fbc->common.scope, EG(scope))) { + zend_function *real_fbc = zend_get_accessor_from_ce(EG(scope), member, key, acc); + if (real_fbc) { + if (!(real_fbc->common.fn_flags & ZEND_ACC_PRIVATE) + || real_fbc->common.scope == EG(scope) + ) { + fbc = real_fbc; + } + } else { + return NULL; + } + } + + if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED) + && !zend_check_protected(zend_get_function_root_class(fbc), EG(scope)) + ) { + zend_error_noreturn(E_ERROR, "Call to %s accessor %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), fbc->common.function_name, EG(scope) ? EG(scope)->name : ""); + } + + return fbc; +} +/* }}} */ + +zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent, const zend_literal *key TSRMLS_DC) /* {{{ */ { zend_property_info *property_info; zend_property_info *scope_property_info; @@ -291,6 +434,10 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui property_info = NULL; h = key ? key->hash_value : zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1); if (zend_hash_quick_find(&ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) { + /* If we have accessors, even if property is private, defer access checks to accessors */ + if (property_info->accs) { + return property_info; + } if (UNEXPECTED((property_info->flags & ZEND_ACC_SHADOW) != 0)) { /* if it's a shadow - go to access it's private */ property_info = NULL; @@ -327,7 +474,7 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui } return scope_property_info; } else if (property_info) { - if (UNEXPECTED(denied_access != 0)) { + if (!property_info->accs && UNEXPECTED(denied_access != 0)) { /* Information was available, but we were denied access. Error out. */ if (!silent) { zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member)); @@ -345,6 +492,7 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui EG(std_property_info).name_length = Z_STRLEN_P(member); EG(std_property_info).h = h; EG(std_property_info).ce = ce; + EG(std_property_info).accs = NULL; EG(std_property_info).offset = -1; property_info = &EG(std_property_info); } @@ -394,10 +542,10 @@ static int zend_get_property_guard(zend_object *zobj, zend_property_info *proper info.name = Z_STRVAL_P(member); info.name_length = Z_STRLEN_P(member); info.h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1); - } else if(property_info->name[0] == '\0'){ + } else if (property_info->name[0] == '\0'){ const char *class_name = NULL, *prop_name = NULL; zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name); - if(class_name) { + if (class_name) { /* use unmangled name for protected properties */ info.name = prop_name; info.name_length = strlen(prop_name); @@ -419,11 +567,32 @@ static int zend_get_property_guard(zend_object *zobj, zend_property_info *proper } /* }}} */ +static zend_always_inline zend_bool zend_get_property_value_helper(zend_property_info *property_info, zend_object *zobj, zval ***value) /* {{{ */ +{ + if (UNEXPECTED(!property_info)) { + return 0; + } + + if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && property_info->offset >= 0) { + if (zobj->properties) { + *value = (zval **) zobj->properties_table[property_info->offset]; + } else { + *value = &zobj->properties_table[property_info->offset]; + } + + return zobj->properties_table[property_info->offset] != NULL; + } else if (UNEXPECTED(!zobj->properties) || UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) value) == FAILURE)) { + return 0; + } + return 1; +} +/* }}} */ + zval *zend_std_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ { zend_object *zobj; zval *tmp_member = NULL; - zval **retval; + zval **retval = NULL; zval *rv = NULL; zend_property_info *property_info; int silent; @@ -448,69 +617,56 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li /* make zend_get_property_info silent if we have getter - we may want to use it */ property_info = zend_get_property_info_quick(zobj->ce, member, silent || (zobj->ce->__get != NULL), key TSRMLS_CC); - if (UNEXPECTED(!property_info) || - ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) ? - (zobj->properties ? - ((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) : - (*(retval = &zobj->properties_table[property_info->offset]) == NULL)) : - (UNEXPECTED(!zobj->properties) || - UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) { - zend_guard *guard = NULL; - - if (zobj->ce->__get && - zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && - !guard->in_get) { - /* have getter - try with it! */ - Z_ADDREF_P(object); - if (PZVAL_IS_REF(object)) { - SEPARATE_ZVAL(&object); - } - guard->in_get = 1; /* prevent circular getting */ - rv = zend_std_call_getter(object, member TSRMLS_CC); - guard->in_get = 0; + /* Getter shadows property unless in guard */ + if (property_info && property_info->accs) { + zend_function *getter = zend_get_accessor( property_info, zobj->ce, member, key, ZEND_ACCESSOR_GET TSRMLS_CC ); + + if (getter) { + if (!(getter->common.fn_flags & ZEND_ACC_CALL_GUARD)) { + + getter->common.fn_flags |= ZEND_ACC_CALL_GUARD; + rv = zend_std_call_getter(object, member, getter, type, NULL TSRMLS_CC); + getter->common.fn_flags &= ~ZEND_ACC_CALL_GUARD; - if (rv) { retval = &rv; - if (!Z_ISREF_P(rv) && - (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET)) { - if (Z_REFCOUNT_P(rv) > 0) { - zval *tmp = rv; - - ALLOC_ZVAL(rv); - *rv = *tmp; - zval_copy_ctor(rv); - Z_UNSET_ISREF_P(rv); - Z_SET_REFCOUNT_P(rv, 0); - } - if (UNEXPECTED(Z_TYPE_P(rv) != IS_OBJECT)) { - zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", zobj->ce->name, Z_STRVAL_P(member)); - } - } - } else { + } else if (EG(active_op_array) != (zend_op_array*)getter) { + zend_error(E_WARNING, "Recursive access to %s::%s detected, return value is NULL.", getter->common.scope->name, getter->common.function_name); retval = &EG(uninitialized_zval_ptr); } - if (EXPECTED(*retval != object)) { - zval_ptr_dtor(&object); - } else { - Z_DELREF_P(object); - } } else { - if (zobj->ce->__get && guard && guard->in_get == 1) { - if (Z_STRVAL_P(member)[0] == '\0') { - if (Z_STRLEN_P(member) == 0) { - zend_error(E_ERROR, "Cannot access empty property"); - } else { - zend_error(E_ERROR, "Cannot access property started with '\\0'"); - } - } - } if (!silent) { - zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member)); + zend_error(E_WARNING, "Cannot get property %s::$%s, no getter defined", is_derived_class(zobj->ce, EG(scope)) ? EG(scope)->name : zobj->ce->name, Z_STRVAL_P(member)); } retval = &EG(uninitialized_zval_ptr); } } + + if (retval == NULL) { + if (!zend_get_property_value_helper(property_info, zobj, &retval)) { + zend_guard *guard = NULL; + + if ( zobj->ce->__get != NULL && zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && !guard->in_get) { + /* have magic __get - try with it! */ + rv = zend_std_call_getter(object, member, zobj->ce->__get, type, guard TSRMLS_CC); + retval = &rv; + } else { + if (zobj->ce->__get && guard && guard->in_get == 1) { + if (Z_STRVAL_P(member)[0] == '\0') { + if (Z_STRLEN_P(member) == 0) { + zend_error(E_ERROR, "Cannot access empty property"); + } else { + zend_error(E_ERROR, "Cannot access property started with '\\0'"); + } + } + } + if (!silent) { + zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member)); + } + retval = &EG(uninitialized_zval_ptr); + } + } + } + if (UNEXPECTED(tmp_member != NULL)) { Z_ADDREF_PP(retval); zval_ptr_dtor(&tmp_member); @@ -526,6 +682,7 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, c zval *tmp_member = NULL; zval **variable_ptr; zend_property_info *property_info; + zend_uint handled = 0; zobj = Z_OBJ_P(object); @@ -541,85 +698,91 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, c property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__set != NULL), key TSRMLS_CC); - if (EXPECTED(property_info != NULL) && - ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) ? - (zobj->properties ? - ((variable_ptr = (zval**)zobj->properties_table[property_info->offset]) != NULL) : - (*(variable_ptr = &zobj->properties_table[property_info->offset]) != NULL)) : - (EXPECTED(zobj->properties != NULL) && - EXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS)))) { - /* if we already have this value there, we don't actually need to do anything */ - if (EXPECTED(*variable_ptr != value)) { - /* if we are assigning reference, we shouldn't move it, but instead assign variable - to the same pointer */ - if (PZVAL_IS_REF(*variable_ptr)) { - zval garbage = **variable_ptr; /* old value should be destroyed */ - - /* To check: can't *variable_ptr be some system variable like error_zval here? */ - Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value); - (*variable_ptr)->value = value->value; - if (Z_REFCOUNT_P(value) > 0) { - zval_copy_ctor(*variable_ptr); + /* Setter shadows property unless in guard */ + if (property_info && property_info->accs) { + zend_function *setter = zend_get_accessor( property_info, zobj->ce, member, key, ZEND_ACCESSOR_SET TSRMLS_CC ); + + if (setter) { + if (!(setter->common.fn_flags & ZEND_ACC_CALL_GUARD)) { + + setter->common.fn_flags |= ZEND_ACC_CALL_GUARD; + zend_std_call_setter(object, member, value, setter, NULL TSRMLS_CC); + setter->common.fn_flags &= ~ZEND_ACC_CALL_GUARD; + + handled = 1; + } else if (EG(active_op_array) != (zend_op_array*)setter) { + zend_error(E_WARNING, "Recursive access to %s::%s detected, call ignored.", setter->common.scope->name, setter->common.function_name); + handled = 1; + } + } else { + zend_error(E_WARNING, "Cannot set property %s::$%s, no setter defined", is_derived_class(zobj->ce, EG(scope)) ? EG(scope)->name : zobj->ce->name, Z_STRVAL_P(member)); + handled = 1; + } + } + + if (handled == 0) { + if (zend_get_property_value_helper(property_info, zobj, &variable_ptr)) { + /* if we already have this value there, we don't actually need to do anything */ + if (EXPECTED(*variable_ptr != value)) { + /* if we are assigning reference, we shouldn't move it, but instead assign variable + to the same pointer */ + if (PZVAL_IS_REF(*variable_ptr)) { + zval garbage = **variable_ptr; /* old value should be destroyed */ + + /* To check: can't *variable_ptr be some system variable like error_zval here? */ + Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value); + (*variable_ptr)->value = value->value; + if (Z_REFCOUNT_P(value) > 0) { + zval_copy_ctor(*variable_ptr); + } else { + efree(value); + } + zval_dtor(&garbage); } else { - efree(value); + zval *garbage = *variable_ptr; + + /* if we assign referenced variable, we should separate it */ + Z_ADDREF_P(value); + if (PZVAL_IS_REF(value)) { + SEPARATE_ZVAL(&value); + } + *variable_ptr = value; + zval_ptr_dtor(&garbage); } - zval_dtor(&garbage); - } else { - zval *garbage = *variable_ptr; + } + } else { + zend_guard *guard = NULL; + if (zobj->ce->__set && zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && !guard->in_set) { + zend_std_call_setter(object, member, value, zobj->ce->__set, guard TSRMLS_CC); + } else if (EXPECTED(property_info != NULL)) { /* if we assign referenced variable, we should separate it */ Z_ADDREF_P(value); if (PZVAL_IS_REF(value)) { SEPARATE_ZVAL(&value); } - *variable_ptr = value; - zval_ptr_dtor(&garbage); - } - } - } else { - zend_guard *guard = NULL; - - if (zobj->ce->__set && - zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && - !guard->in_set) { - Z_ADDREF_P(object); - if (PZVAL_IS_REF(object)) { - SEPARATE_ZVAL(&object); - } - guard->in_set = 1; /* prevent circular setting */ - if (zend_std_call_setter(object, member, value TSRMLS_CC) != SUCCESS) { - /* for now, just ignore it - __set should take care of warnings, etc. */ - } - guard->in_set = 0; - zval_ptr_dtor(&object); - } else if (EXPECTED(property_info != NULL)) { - /* if we assign referenced variable, we should separate it */ - Z_ADDREF_P(value); - if (PZVAL_IS_REF(value)) { - SEPARATE_ZVAL(&value); - } - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { - if (!zobj->properties) { - zobj->properties_table[property_info->offset] = value; - } else if (zobj->properties_table[property_info->offset]) { - *(zval**)zobj->properties_table[property_info->offset] = value; + if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && + property_info->offset >= 0) { + if (!zobj->properties) { + zobj->properties_table[property_info->offset] = value; + } else if (zobj->properties_table[property_info->offset]) { + *(zval**)zobj->properties_table[property_info->offset] = value; + } else { + zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]); + } } else { - zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]); + if (!zobj->properties) { + rebuild_object_properties(zobj); } - } else { - if (!zobj->properties) { - rebuild_object_properties(zobj); + zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), NULL); } - zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), NULL); - } - } else if (zobj->ce->__set && guard && guard->in_set == 1) { - if (Z_STRVAL_P(member)[0] == '\0') { - if (Z_STRLEN_P(member) == 0) { - zend_error(E_ERROR, "Cannot access empty property"); - } else { - zend_error(E_ERROR, "Cannot access property started with '\\0'"); + } else if (zobj->ce->__set && guard && guard->in_set == 1) { + if (Z_STRVAL_P(member)[0] == '\0') { + if (Z_STRLEN_P(member) == 0) { + zend_error(E_ERROR, "Cannot access empty property"); + } else { + zend_error(E_ERROR, "Cannot access property started with '\\0'"); + } } } } @@ -637,7 +800,7 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* zval *retval; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC) != 0)) { - if(offset == NULL) { + if (offset == NULL) { /* [] construct */ ALLOC_INIT_ZVAL(offset); } else { @@ -718,7 +881,7 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const ze { zend_object *zobj; zval tmp_member; - zval **retval; + zval **retval = (zval**)-1; /* -1 indicates it has not been handled */ zend_property_info *property_info; zobj = Z_OBJ_P(object); @@ -737,46 +900,54 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const ze property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC); - if (UNEXPECTED(!property_info) || - ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) ? - (zobj->properties ? - ((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) : - (*(retval = &zobj->properties_table[property_info->offset]) == NULL)) : - (UNEXPECTED(!zobj->properties) || - UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) { - zval *new_zval; - zend_guard *guard; - - if (!zobj->ce->__get || - zend_get_property_guard(zobj, property_info, member, &guard) != SUCCESS || - (property_info && guard->in_get)) { - /* we don't have access controls - will just add it */ - new_zval = &EG(uninitialized_zval); - -/* zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */ - Z_ADDREF_P(new_zval); - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { - if (!zobj->properties) { - zobj->properties_table[property_info->offset] = new_zval; - retval = &zobj->properties_table[property_info->offset]; - } else if (zobj->properties_table[property_info->offset]) { - *(zval**)zobj->properties_table[property_info->offset] = new_zval; - retval = (zval**)zobj->properties_table[property_info->offset]; + /* Getter shadows property unless in guard */ + if (property_info && property_info->accs) { + zend_function *getter = zend_get_accessor( property_info, zobj->ce, member, key, ZEND_ACCESSOR_GET TSRMLS_CC ); + + if (getter) { + if (!(getter->common.fn_flags & ZEND_ACC_CALL_GUARD)) { + /* we do have getter - fail and let it try again with usual get/set */ + retval = NULL; + } + } else { + zend_error(E_WARNING, "Cannot get property %s::$%s, no getter defined", is_derived_class(zobj->ce, EG(scope)) ? EG(scope)->name : zobj->ce->name, Z_STRVAL_P(member)); + return &EG(uninitialized_zval_ptr); + } + } + + if (retval == (zval**)-1) { + if (!zend_get_property_value_helper(property_info, zobj, &retval)) { + zval *new_zval; + zend_guard *guard; + + if (!zobj->ce->__get || zend_get_property_guard(zobj, property_info, member, &guard) != SUCCESS || (property_info && guard->in_get)) { + /* we don't have access controls - will just add it */ + new_zval = &EG(uninitialized_zval); + + /* zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */ + Z_ADDREF_P(new_zval); + if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && + property_info->offset >= 0) { + if (!zobj->properties) { + zobj->properties_table[property_info->offset] = new_zval; + retval = &zobj->properties_table[property_info->offset]; + } else if (zobj->properties_table[property_info->offset]) { + *(zval**)zobj->properties_table[property_info->offset] = new_zval; + retval = (zval**)zobj->properties_table[property_info->offset]; + } else { + zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]); + retval = (zval**)zobj->properties_table[property_info->offset]; + } } else { - zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]); - retval = (zval**)zobj->properties_table[property_info->offset]; + if (!zobj->properties) { + rebuild_object_properties(zobj); + } + zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval); } } else { - if (!zobj->properties) { - rebuild_object_properties(zobj); - } - zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval); + /* we do have getter - fail and let it try again with usual get/set */ + retval = NULL; } - } else { - /* we do have getter - fail and let it try again with usual get/set */ - retval = NULL; } } if (UNEXPECTED(member == &tmp_member)) { @@ -788,11 +959,10 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const ze static void zend_std_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */ { - zend_object *zobj; + zend_object *zobj = Z_OBJ_P(object); zval *tmp_member = NULL; zend_property_info *property_info; - - zobj = Z_OBJ_P(object); + zend_uint handled = 0; if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { ALLOC_ZVAL(tmp_member); @@ -806,43 +976,59 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__unset != NULL), key TSRMLS_CC); - if (EXPECTED(property_info != NULL) && - EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - !zobj->properties && - property_info->offset >= 0 && - EXPECTED(zobj->properties_table[property_info->offset] != NULL)) { - zval_ptr_dtor(&zobj->properties_table[property_info->offset]); - zobj->properties_table[property_info->offset] = NULL; - } else if (UNEXPECTED(!property_info) || - !zobj->properties || - UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) { - zend_guard *guard = NULL; - - if (zobj->ce->__unset && - zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && - !guard->in_unset) { - /* have unseter - try with it! */ - Z_ADDREF_P(object); - if (PZVAL_IS_REF(object)) { - SEPARATE_ZVAL(&object); + /* Unsetter shadows property unless in guard */ + if (property_info && property_info->accs) { + zend_function *unsetter = zend_get_accessor( property_info, zobj->ce, member, key, ZEND_ACCESSOR_UNSET TSRMLS_CC ); + + if (unsetter) { + if (!(unsetter->common.fn_flags & ZEND_ACC_CALL_GUARD)) { + + unsetter->common.fn_flags |= ZEND_ACC_CALL_GUARD; + zend_std_call_unsetter(object, member, unsetter, NULL TSRMLS_CC); + unsetter->common.fn_flags &= ~ZEND_ACC_CALL_GUARD; + + handled = 1; + } else if (EG(active_op_array) != (zend_op_array*)unsetter) { + zend_error(E_WARNING, "Recursive access to %s::%s detected, call ignored.", unsetter->common.scope->name, unsetter->common.function_name); + handled = 1; } - guard->in_unset = 1; /* prevent circular unsetting */ - zend_std_call_unsetter(object, member TSRMLS_CC); - guard->in_unset = 0; - zval_ptr_dtor(&object); - } else if (zobj->ce->__unset && guard && guard->in_unset == 1) { - if (Z_STRVAL_P(member)[0] == '\0') { - if (Z_STRLEN_P(member) == 0) { - zend_error(E_ERROR, "Cannot access empty property"); - } else { - zend_error(E_ERROR, "Cannot access property started with '\\0'"); + } else { + /* Have property but no unsetter, just return and do not throw error */ + zend_error(E_WARNING, "Cannot unset guarded property %s::$%s, no unset defined.", is_derived_class(zobj->ce, EG(scope)) ? EG(scope)->name : zobj->ce->name, Z_STRVAL_P(member)); + handled = 1; + } + } + + if (handled == 0) { + if (EXPECTED(property_info != NULL) && + EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && + !zobj->properties && + property_info->offset >= 0 && + EXPECTED(zobj->properties_table[property_info->offset] != NULL)) { + zval_ptr_dtor(&zobj->properties_table[property_info->offset]); + zobj->properties_table[property_info->offset] = NULL; + } else if (UNEXPECTED(!property_info) || + !zobj->properties || + UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) { + zend_guard *guard = NULL; + + if (zobj->ce->__unset && zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && !guard->in_unset) { + /* have magic __unset - try with it! */ + zend_std_call_unsetter(object, member, zobj->ce->__unset, guard TSRMLS_CC); + } else if (zobj->ce->__unset && guard && guard->in_unset == 1) { + if (Z_STRVAL_P(member)[0] == '\0') { + if (Z_STRLEN_P(member) == 0) { + zend_error(E_ERROR, "Cannot access empty property"); + } else { + zend_error(E_ERROR, "Cannot access property started with '\\0'"); + } } } + } else if (EXPECTED(property_info != NULL) && + EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && + property_info->offset >= 0) { + zobj->properties_table[property_info->offset] = NULL; } - } else if (EXPECTED(property_info != NULL) && - EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { - zobj->properties_table[property_info->offset] = NULL; } if (UNEXPECTED(tmp_member != NULL)) { @@ -1393,14 +1579,12 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */ static int zend_std_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */ { - zend_object *zobj; - int result; + zend_object *zobj = Z_OBJ_P(object); + int result = -1; zval **value = NULL; zval *tmp_member = NULL; zend_property_info *property_info; - zobj = Z_OBJ_P(object); - if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { ALLOC_ZVAL(tmp_member); *tmp_member = *member; @@ -1411,70 +1595,63 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists, key = NULL; } + #if DEBUG_OBJECT_HANDLERS fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); #endif property_info = zend_get_property_info_quick(zobj->ce, member, 1, key TSRMLS_CC); - if (UNEXPECTED(!property_info) || - ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) ? - (zobj->properties ? - ((value = (zval**)zobj->properties_table[property_info->offset]) == NULL) : - (*(value = &zobj->properties_table[property_info->offset]) == NULL)) : - (UNEXPECTED(!zobj->properties) || - UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE)))) { - zend_guard *guard; - - result = 0; - if ((has_set_exists != 2) && - zobj->ce->__isset && - zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && - !guard->in_isset) { - zval *rv; - - /* have issetter - try with it! */ - Z_ADDREF_P(object); - if (PZVAL_IS_REF(object)) { - SEPARATE_ZVAL(&object); + /* Issetter shadows property unless in guard */ + if (property_info && property_info->accs) { + zend_function *issetter = zend_get_accessor( property_info, zobj->ce, member, key, ZEND_ACCESSOR_ISSET TSRMLS_CC ); + + if (issetter) { + if (!(issetter->common.fn_flags & ZEND_ACC_CALL_GUARD)) { + + issetter->common.fn_flags |= ZEND_ACC_CALL_GUARD; + result = zend_std_call_issetter(object, member, has_set_exists, issetter, key, NULL TSRMLS_CC); + issetter->common.fn_flags &= ~ZEND_ACC_CALL_GUARD; + + } else if (EG(active_op_array) != (zend_op_array*)issetter) { + zend_error(E_WARNING, "Recursive access to %s::%s detected, call ignored.", issetter->common.scope->name, issetter->common.function_name); + result = 0; } - guard->in_isset = 1; /* prevent circular getting */ - rv = zend_std_call_issetter(object, member TSRMLS_CC); - if (rv) { - result = zend_is_true(rv); - zval_ptr_dtor(&rv); - if (has_set_exists && result) { - if (EXPECTED(!EG(exception)) && zobj->ce->__get && !guard->in_get) { - guard->in_get = 1; - rv = zend_std_call_getter(object, member TSRMLS_CC); - guard->in_get = 0; - if (rv) { - Z_ADDREF_P(rv); - result = i_zend_is_true(rv); - zval_ptr_dtor(&rv); - } else { - result = 0; - } - } else { - result = 0; - } + } else { + /* Have property but no issetter, just return and do not throw error */ + result = has_set_exists == 2; + } + } + + if (result == -1) { + if (!zend_get_property_value_helper(property_info, zobj, &value)) { + zend_guard *guard; + + result = 0; + if ((has_set_exists != 2) && zobj->ce->__isset && zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && !guard->in_isset) { + /* have magic __isset - try with it! */ + result = zend_std_call_issetter(object, member, has_set_exists, zobj->ce->__isset, key, guard TSRMLS_CC); + } + } else { + *value = zend_std_read_property(object, member, BP_VAR_IS, key TSRMLS_CC); + + result = 0; + if (*value) { + Z_ADDREF_PP(value); + + switch (has_set_exists) { + case 0: + result = (Z_TYPE_PP(value) != IS_NULL); + break; + case 2: + result = 1; + break; + default: + result = zend_is_true(*value); + break; } + zval_ptr_dtor(value); } - guard->in_isset = 0; - zval_ptr_dtor(&object); - } - } else { - switch (has_set_exists) { - case 0: - result = (Z_TYPE_PP(value) != IS_NULL); - break; - default: - result = zend_is_true(*value); - break; - case 2: - result = 1; - break; } } diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 11635328c396a..cea348ef1044d 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -159,6 +159,7 @@ ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC); ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC); ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC); ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC); +ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, const struct _zend_literal *key TSRMLS_DC); ZEND_API void rebuild_object_properties(zend_object *zobj); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index db0a40035b6d3..95f13b049aebf 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -651,7 +651,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) { zend_op *opline, *end; - if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) { + if (op_array->type != ZEND_USER_FUNCTION && op_array->type != ZEND_EVAL_CODE) { return 0; } if (op_array->has_finally_block) { diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 5c844b8d4dd51..abb898de0e81f 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -40,6 +40,7 @@ #include "zend_interfaces.h" #include "zend_closures.h" #include "zend_extensions.h" +#include "zend_object_handlers.h" #define reflection_update_property(object, name, value) do { \ zval *member; \ @@ -349,6 +350,7 @@ static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_ static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC); static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent TSRMLS_DC); static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC); +static void _property_accessor_string(string *str, zend_property_info *prop, char *indent TSRMLS_DC); static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC); static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC); static void _zend_extension_string(string *str, zend_extension *extension, char *indent TSRMLS_DC); @@ -927,6 +929,11 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n { const char *class_name; + if (prop && prop->accs) { + _property_accessor_string(str, prop, indent TSRMLS_CC); + return; + } + string_printf(str, "%sProperty [ ", indent); if (!prop) { string_printf(str, " public $%s", prop_name); @@ -963,6 +970,51 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n } /* }}} */ + +/* {{{ _property_accessor_string */ +static void _property_accessor_string(string *str, zend_property_info *prop, char *indent TSRMLS_DC) +{ + zend_function **accs = prop->accs; + string sub_indent; + string_init(&sub_indent); + string_printf(&sub_indent, "%s ", indent); + + string_printf(str, "%sAccessor [ ", indent); + if (accs) { + int i; + + /* These are mutually exclusive */ + switch (prop->flags & ZEND_ACC_PPP_MASK) { + case ZEND_ACC_PUBLIC: + string_printf(str, "public "); + break; + case ZEND_ACC_PRIVATE: + string_printf(str, "private "); + break; + case ZEND_ACC_PROTECTED: + string_printf(str, "protected "); + break; + } + if (prop->flags & ZEND_ACC_STATIC) { + string_printf(str, "static "); + } + + string_printf(str, "$%s ] {\n", prop->name); + + for (i = 0; i < ZEND_NUM_ACCESSORS; ++i) { + if (accs[i]) { + _function_string(str, accs[i], accs[i]->common.scope, sub_indent.string TSRMLS_CC); + } + } + + string_printf(str, "%s}\n", indent); + } + + string_printf(str, " ]\n"); + string_free(&sub_indent); +} +/* }}} */ + static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { string *str = va_arg(args, string *); @@ -1322,20 +1374,24 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name); - if (!(prop->flags & ZEND_ACC_PRIVATE)) { - /* we have to search the class hierarchy for this (implicit) public or protected property */ - zend_class_entry *tmp_ce = ce, *store_ce = ce; - zend_property_info *tmp_info = NULL; - - while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, prop_name, strlen(prop_name) + 1, (void **) &tmp_info) != SUCCESS) { - ce = tmp_ce; - tmp_ce = tmp_ce->parent; - } - - if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */ - prop = tmp_info; - } else { /* not found, use initial value */ - ce = store_ce; + if (!prop->accs) { + /* Not sure what this code does, maybe dead code? Leaving it in place + * just in case it's fixing some crazy, untested bugs. */ + if (!(prop->flags & ZEND_ACC_PRIVATE)) { + /* we have to search the class hierarchy for this (implicit) public or protected property */ + zend_class_entry *tmp_ce = ce, *store_ce = ce; + zend_property_info *tmp_info = NULL; + + while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, prop_name, strlen(prop_name) + 1, (void **) &tmp_info) != SUCCESS) { + ce = tmp_ce; + tmp_ce = tmp_ce->parent; + } + + if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */ + prop = tmp_info; + } else { /* not found, use initial value */ + ce = store_ce; + } } } @@ -1344,7 +1400,10 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info ZVAL_STRING(name, prop_name, 1); ZVAL_STRINGL(classname, prop->ce->name, prop->ce->name_length, 1); - reflection_instantiate(reflection_property_ptr, object TSRMLS_CC); + reflection_instantiate( + reflection_property_ptr, + object TSRMLS_CC + ); intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); reference = (property_reference*) emalloc(sizeof(property_reference)); reference->ce = ce; @@ -3863,6 +3922,7 @@ ZEND_METHOD(reflection_class, getProperty) property_info_tmp.name_length = name_len; property_info_tmp.h = zend_get_hash_value(name, name_len+1); property_info_tmp.doc_comment = NULL; + property_info_tmp.accs = NULL; property_info_tmp.ce = ce; reflection_property_factory(ce, &property_info_tmp, return_value TSRMLS_CC); @@ -4849,6 +4909,7 @@ ZEND_METHOD(reflection_property, __construct) reference->prop.h = zend_get_hash_value(name_str, name_len+1); reference->prop.doc_comment = NULL; reference->prop.ce = ce; + reference->prop.accs = NULL; } else { reference->prop = *property_info; } @@ -4994,7 +5055,7 @@ ZEND_METHOD(reflection_property, getValue) return; } zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name); - member_p = zend_read_property(ref->ce, object, prop_name, strlen(prop_name), 1 TSRMLS_CC); + member_p = zend_read_property(ref->ce, object, prop_name, strlen(prop_name), !ref->prop.accs TSRMLS_CC); MAKE_COPY_ZVAL(&member_p, return_value); if (member_p != EG(uninitialized_zval_ptr)) { zval_add_ref(&member_p); @@ -5152,6 +5213,69 @@ ZEND_METHOD(reflection_property, setAccessible) } /* }}} */ +static void get_accessor_function_impl(INTERNAL_FUNCTION_PARAMETERS, zend_acc_index acc) /* {{{ */ +{ + reflection_object *intern; + property_reference *ref; + + METHOD_NOTSTATIC(reflection_property_ptr); + GET_REFLECTION_OBJECT_PTR(ref); + + if (ref->prop.accs[acc]) { + reflection_method_factory(ref->ce, ref->prop.accs[acc], NULL, return_value TSRMLS_CC); + return; + } + RETURN_FALSE +} +/* }}} */ + +/* {{{ proto public ReflectionMethod ReflectionProperty::getGet() + Gets the ReflectionMethod get accessor for this property, returns false if there is no get accessor */ +ZEND_METHOD(reflection_property, getGet) +{ + get_accessor_function_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACCESSOR_GET); +} +/* }}} */ + +/* {{{ proto public Method ReflectionProperty::getSet() + Gets the ReflectionMethod set accessor for this property, returns false if there is no set accessor */ +ZEND_METHOD(reflection_property, getSet) +{ + get_accessor_function_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACCESSOR_SET); +} +/* }}} */ + +/* {{{ proto public Method ReflectionProperty::getIsset() + Gets the ReflectionMethod isset accessor for this property, returns false if there is no isset accessor */ +ZEND_METHOD(reflection_property, getIsset) +{ + get_accessor_function_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACCESSOR_ISSET); +} +/* }}} */ + +/* {{{ proto public Method ReflectionProperty::getUnset() + Gets the ReflectionMethod unset accessor for this property, returns false if there is no unset accessor */ +ZEND_METHOD(reflection_property, getUnset) +{ + get_accessor_function_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACCESSOR_UNSET); +} +/* }}} */ + +/* {{{ proto public Method ReflectionProperty::hasAccessors() + Returns true if the property has accessors, false otherwise */ +ZEND_METHOD(reflection_property, hasAccessors) +{ + reflection_object *intern; + property_reference *ref; + + GET_REFLECTION_OBJECT_PTR(ref); + if (ref->prop.accs) + RETURN_TRUE; + RETURN_FALSE; +} +/* }}} */ + + /* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_extension, export) @@ -5161,7 +5285,7 @@ ZEND_METHOD(reflection_extension, export) /* }}} */ /* {{{ proto public void ReflectionExtension::__construct(string name) - Constructor. Throws an Exception in case the given extension does not exist */ + Constructor. Throws an Exception in case the given exten sion does not exist */ ZEND_METHOD(reflection_extension, __construct) { zval *name; @@ -5793,7 +5917,6 @@ static const zend_function_entry reflection_method_functions[] = { PHP_FE_END }; - ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_export, 0, 0, 1) ZEND_ARG_INFO(0, argument) ZEND_ARG_INFO(0, return) @@ -5980,6 +6103,11 @@ static const zend_function_entry reflection_property_functions[] = { ZEND_ME(reflection_property, getDeclaringClass, arginfo_reflection__void, 0) ZEND_ME(reflection_property, getDocComment, arginfo_reflection__void, 0) ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0) + ZEND_ME(reflection_property, getGet, arginfo_reflection__void, 0) + ZEND_ME(reflection_property, getSet, arginfo_reflection__void, 0) + ZEND_ME(reflection_property, getIsset, arginfo_reflection__void, 0) + ZEND_ME(reflection_property, getUnset, arginfo_reflection__void, 0) + ZEND_ME(reflection_property, hasAccessors, arginfo_reflection__void, 0) PHP_FE_END }; diff --git a/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt b/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt index 5df9e08c6954c..7ed90cffdb82c 100644 --- a/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt +++ b/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt @@ -8,65 +8,65 @@ $ext = new ReflectionExtension('reflection'); var_dump($ext->getClasses()); ?> ==DONE== ---EXPECT-- +--EXPECTF-- array(12) { ["ReflectionException"]=> - &object(ReflectionClass)#2 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(19) "ReflectionException" } ["Reflection"]=> - &object(ReflectionClass)#3 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(10) "Reflection" } ["Reflector"]=> - &object(ReflectionClass)#4 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(9) "Reflector" } ["ReflectionFunctionAbstract"]=> - &object(ReflectionClass)#5 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(26) "ReflectionFunctionAbstract" } ["ReflectionFunction"]=> - &object(ReflectionClass)#6 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(18) "ReflectionFunction" } ["ReflectionParameter"]=> - &object(ReflectionClass)#7 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(19) "ReflectionParameter" } ["ReflectionMethod"]=> - &object(ReflectionClass)#8 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(16) "ReflectionMethod" } ["ReflectionClass"]=> - &object(ReflectionClass)#9 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(15) "ReflectionClass" } ["ReflectionObject"]=> - &object(ReflectionClass)#10 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(16) "ReflectionObject" } ["ReflectionProperty"]=> - &object(ReflectionClass)#11 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(18) "ReflectionProperty" } ["ReflectionExtension"]=> - &object(ReflectionClass)#12 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(19) "ReflectionExtension" } ["ReflectionZendExtension"]=> - &object(ReflectionClass)#13 (1) { + &object(ReflectionClass)#%d (1) { ["name"]=> string(23) "ReflectionZendExtension" } diff --git a/ext/reflection/tests/ReflectionProperty_accessors_basic1.phpt b/ext/reflection/tests/ReflectionProperty_accessors_basic1.phpt new file mode 100644 index 0000000000000..3395a1ebba556 --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_accessors_basic1.phpt @@ -0,0 +1,278 @@ +--TEST-- +Test usage of ReflectionProperty methods __toString(), export(), getName(), isPublic(), isPrivate(), isProtected(), isStatic(), getValue() and setValue(). +--FILE-- +__toString()); + echo "export():\n"; + var_dump(ReflectionProperty::export($class, $property, true)); + echo "export():\n"; + var_dump(ReflectionProperty::export($class, $property, false)); + echo "getName():\n"; + var_dump($propInfo->getName()); + echo "isPublic():\n"; + var_dump($propInfo->isPublic()); + echo "isPrivate():\n"; + var_dump($propInfo->isPrivate()); + echo "isProtected():\n"; + var_dump($propInfo->isProtected()); + echo "isStatic():\n"; + var_dump($propInfo->isStatic()); + echo "isDefault():\n"; + var_dump($propInfo->isDefault()); + + $instance = new $class(); + if ($propInfo->getGet() != false && $propInfo->getGet()->isPublic()) { + echo "getValue():\n"; + var_dump($propInfo->getValue($instance)); + } + if ($propInfo->getSet() != false && $propInfo->getSet()->isPublic()) { + echo "setValue(\"NewValue\"):\n"; + $propInfo->setValue($instance, "NewValue"); + if($propInfo->getGet() != false) { + echo "getValue() after a setValue():\n"; + var_dump($propInfo->getValue($instance)); + } + } + echo "\n**********************************\n"; +} + +class TestClass { + private $_a1 = 'b1', $_a2 = 'b2', $_a3 = 'b3', $_a4 = 'b4'; + + public $a1 { + get { echo __METHOD__.'() = '; return $this->_a1; } + } + public $a2 { + set { echo __METHOD__."($value)".PHP_EOL; $this->_a2 = $value; } + } + public $a3 { + get { echo __METHOD__.'() = '; return $this->_a3; } + set { echo __METHOD__."($value)".PHP_EOL; $this->_a3 = $value; } + } +/* Commented out until static accessors are supported + public static $a4 { + protected get { return $this->_a4; } + private set { $this->a5 = $value; } + } +*/ +} +reflectProperty("TestClass", "a1"); +reflectProperty("TestClass", "a2"); +reflectProperty("TestClass", "a3"); +/* Commented out until static accessors are supported +reflectProperty("TestClass", "a4"); +*/ + +?> +--EXPECTF-- +********************************** +Reflecting on property TestClass::a1 + +__toString(): +string(%d) "Accessor [ public $a1 ] { + Method [ public method $a1->get ] { + @@ %s %d - %d + } + Method [ public method $a1->isset ] { + @@ %s %d - %d + } +} + ] +" +export(): +string(%d) "Accessor [ public $a1 ] { + Method [ public method $a1->get ] { + @@ %s %d - %d + } + Method [ public method $a1->isset ] { + @@ %s %d - %d + } +} + ] +" +export(): +Accessor [ public $a1 ] { + Method [ public method $a1->get ] { + @@ %s %d - %d + } + Method [ public method $a1->isset ] { + @@ %s %d - %d + } +} + ] + +NULL +getName(): +string(2) "a1" +isPublic(): +bool(true) +isPrivate(): +bool(false) +isProtected(): +bool(false) +isStatic(): +bool(false) +isDefault(): +bool(true) +getValue(): +TestClass::$a1->get() = string(2) "b1" + +********************************** +********************************** +Reflecting on property TestClass::a2 + +__toString(): +string(%d) "Accessor [ public $a2 ] { + Method [ public method $a2->set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ public method $a2->unset ] { + @@ %s %d - %d + } +} + ] +" +export(): +string(%d) "Accessor [ public $a2 ] { + Method [ public method $a2->set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ public method $a2->unset ] { + @@ %s %d - %d + } +} + ] +" +export(): +Accessor [ public $a2 ] { + Method [ public method $a2->set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ public method $a2->unset ] { + @@ %s %d - %d + } +} + ] + +NULL +getName(): +string(2) "a2" +isPublic(): +bool(true) +isPrivate(): +bool(false) +isProtected(): +bool(false) +isStatic(): +bool(false) +isDefault(): +bool(true) +setValue("NewValue"): +TestClass::$a2->set(NewValue) + +********************************** +********************************** +Reflecting on property TestClass::a3 + +__toString(): +string(%d) "Accessor [ public $a3 ] { + Method [ public method $a3->get ] { + @@ %s %d - %d + } + Method [ public method $a3->set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ public method $a3->isset ] { + @@ %s %d - %d + } + Method [ public method $a3->unset ] { + @@ %s %d - %d + } +} + ] +" +export(): +string(%d) "Accessor [ public $a3 ] { + Method [ public method $a3->get ] { + @@ %s %d - %d + } + Method [ public method $a3->set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ public method $a3->isset ] { + @@ %s %d - %d + } + Method [ public method $a3->unset ] { + @@ %s %d - %d + } +} + ] +" +export(): +Accessor [ public $a3 ] { + Method [ public method $a3->get ] { + @@ %s %d - %d + } + Method [ public method $a3->set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ public method $a3->isset ] { + @@ %s %d - %d + } + Method [ public method $a3->unset ] { + @@ %s %d - %d + } +} + ] + +NULL +getName(): +string(2) "a3" +isPublic(): +bool(true) +isPrivate(): +bool(false) +isProtected(): +bool(false) +isStatic(): +bool(false) +isDefault(): +bool(true) +getValue(): +TestClass::$a3->get() = string(2) "b3" +setValue("NewValue"): +TestClass::$a3->set(NewValue) +getValue() after a setValue(): +TestClass::$a3->get() = string(8) "NewValue" + +********************************** diff --git a/ext/reflection/tests/ReflectionProperty_accessors_getDeclaringClass_basic.phpt b/ext/reflection/tests/ReflectionProperty_accessors_getDeclaringClass_basic.phpt new file mode 100644 index 0000000000000..039978686150a --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_accessors_getDeclaringClass_basic.phpt @@ -0,0 +1,39 @@ +--TEST-- +ReflectionPropertyAccessor::getDeclaringClass(); +--CREDITS-- +Clint Priest +--FILE-- +getProperties() as $objProperty) { + echo $objProperty->name.' = '; + var_dump($objProperty->getDeclaringClass()); + } +?> +==DONE== +--EXPECT-- +a1 = object(ReflectionClass)#5 (1) { + ["name"]=> + string(10) "TimePeriod" +} +a2 = object(ReflectionClass)#5 (1) { + ["name"]=> + string(10) "TimePeriod" +} +a3 = object(ReflectionClass)#5 (1) { + ["name"]=> + string(10) "TimePeriod" +} +==DONE== diff --git a/ext/reflection/tests/ReflectionProperty_accessors_getDocComment_basic.phpt b/ext/reflection/tests/ReflectionProperty_accessors_getDocComment_basic.phpt new file mode 100644 index 0000000000000..740a06f7a466b --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_accessors_getDocComment_basic.phpt @@ -0,0 +1,58 @@ +--TEST-- +ReflectionPropertyAccessor::getDocComment(); +--CREDITS-- +Clint Priest +--FILE-- +getProperties() as $objProperty) { + var_dump($objProperty->getName()); + var_dump($objProperty->getDocComment()); + if($objProperty->getGet()) { + echo "getter DocComment\n"; + var_dump($objProperty->getGet()->getDocComment()); + } + if($objProperty->getSet()) { + echo "setter DocComment\n"; + var_dump($objProperty->getSet()->getDocComment()); + } + echo "******************\n"; + } +?> +==DONE== +--EXPECTF-- +string(2) "a1" +string(%d) "/** Test Comment for $a1 */" +getter DocComment +string(%d) "/** Test Getter Comment for $a1 */" +****************** +string(2) "a2" +string(%d) "/** Test Comment for $a2 */" +setter DocComment +bool(false) +****************** +string(2) "a3" +string(%d) "/** Test Comment for $a3 */" +getter DocComment +bool(false) +setter DocComment +bool(false) +****************** +==DONE== diff --git a/ext/reflection/tests/ReflectionProperty_accessors_getModifiers_basic.phpt b/ext/reflection/tests/ReflectionProperty_accessors_getModifiers_basic.phpt new file mode 100644 index 0000000000000..f096d79ded31e --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_accessors_getModifiers_basic.phpt @@ -0,0 +1,30 @@ +--TEST-- +ReflectionPropertyAccessor::getModifiers(); +--CREDITS-- +Clint Priest +--FILE-- +getProperties() as $objProperty) { + echo $objProperty->name.' = '; + var_dump($objProperty->getModifiers()); + } +?> +==DONE== +--EXPECT-- +a1 = int(256) +a2 = int(256) +a3 = int(1024) +==DONE== diff --git a/ext/reflection/tests/ReflectionProperty_getGetter_basic.phpt b/ext/reflection/tests/ReflectionProperty_getGetter_basic.phpt new file mode 100644 index 0000000000000..cf021f2d9f356 --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getGetter_basic.phpt @@ -0,0 +1,39 @@ +--TEST-- +ReflectionProperty::getGet(); +--CREDITS-- +Clint Priest +--FILE-- +getProperties() as $objProperty) { + var_dump($objProperty->getGet()); + } +?> +==DONE== +--EXPECT-- +object(ReflectionMethod)#5 (2) { + ["name"]=> + string(8) "$a1->get" + ["class"]=> + string(10) "TimePeriod" +} +bool(false) +object(ReflectionMethod)#5 (2) { + ["name"]=> + string(8) "$a3->get" + ["class"]=> + string(10) "TimePeriod" +} +==DONE== diff --git a/ext/reflection/tests/ReflectionProperty_getIsset_basic.phpt b/ext/reflection/tests/ReflectionProperty_getIsset_basic.phpt new file mode 100644 index 0000000000000..ab85c6f8f11d2 --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getIsset_basic.phpt @@ -0,0 +1,39 @@ +--TEST-- +ReflectionProperty::getIsset(); +--CREDITS-- +Clint Priest +--FILE-- +getProperties() as $objProperty) { + var_dump($objProperty->getIsset()); + } +?> +==DONE== +--EXPECTF-- +object(ReflectionMethod)#5 (2) { + ["name"]=> + string(%d) "$a1->isset" + ["class"]=> + string(10) "TimePeriod" +} +bool(false) +object(ReflectionMethod)#5 (2) { + ["name"]=> + string(%d) "$a3->isset" + ["class"]=> + string(10) "TimePeriod" +} +==DONE== diff --git a/ext/reflection/tests/ReflectionProperty_getSetter_basic.phpt b/ext/reflection/tests/ReflectionProperty_getSetter_basic.phpt new file mode 100644 index 0000000000000..f0eaf95ba543d --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getSetter_basic.phpt @@ -0,0 +1,39 @@ +--TEST-- +ReflectionProperty::getSet(); +--CREDITS-- +Clint Priest +--FILE-- +getProperties() as $objProperty) { + var_dump($objProperty->getSet()); + } +?> +==DONE== +--EXPECT-- +bool(false) +object(ReflectionMethod)#5 (2) { + ["name"]=> + string(8) "$a2->set" + ["class"]=> + string(10) "TimePeriod" +} +object(ReflectionMethod)#5 (2) { + ["name"]=> + string(8) "$a3->set" + ["class"]=> + string(10) "TimePeriod" +} +==DONE== diff --git a/ext/reflection/tests/ReflectionProperty_getUnset_basic.phpt b/ext/reflection/tests/ReflectionProperty_getUnset_basic.phpt new file mode 100644 index 0000000000000..640abfed7c833 --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getUnset_basic.phpt @@ -0,0 +1,39 @@ +--TEST-- +ReflectionProperty::getUnset(); +--CREDITS-- +Clint Priest +--FILE-- +getProperties() as $objProperty) { + var_dump($objProperty->getUnset()); + } +?> +==DONE== +--EXPECTF-- +bool(false) +object(ReflectionMethod)#5 (2) { + ["name"]=> + string(%d) "$a2->unset" + ["class"]=> + string(10) "TimePeriod" +} +object(ReflectionMethod)#5 (2) { + ["name"]=> + string(%d) "$a3->unset" + ["class"]=> + string(10) "TimePeriod" +} +==DONE== diff --git a/tests/classes/unset_properties.phpt b/tests/classes/unset_properties.phpt index 7f9b569887dcd..a4b5db1ec5511 100644 --- a/tests/classes/unset_properties.phpt +++ b/tests/classes/unset_properties.phpt @@ -140,14 +140,14 @@ true new publicProperty value via public access protectedProperty set -__isset "protectedProperty"__isset "protectedProperty"false +__isset "protectedProperty"false __get "protectedProperty" __set "protectedProperty" to "new protectedProperty value via setter" __isset "protectedProperty"true new protectedProperty value via setter privateProperty set -__isset "privateProperty"__isset "privateProperty"false +__isset "privateProperty"false __get "privateProperty" __set "privateProperty" to "new privateProperty value via setter" __isset "privateProperty"true