felipe                                   Sun, 06 Nov 2011 13:25:45 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=318823

Log:
- Added class member access on instantiation (e.g. (new foo)->bar()) support

Changed paths:
    U   php/php-src/branches/PHP_5_4/NEWS
    U   php/php-src/branches/PHP_5_4/UPGRADING
    A   php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_001.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_002.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_003.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_004.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_005.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/indirect_property_access.phpt
    U   php/php-src/branches/PHP_5_4/Zend/zend_language_parser.y
    A   php/php-src/trunk/Zend/tests/indirect_method_call_001.phpt
    A   php/php-src/trunk/Zend/tests/indirect_method_call_002.phpt
    A   php/php-src/trunk/Zend/tests/indirect_method_call_003.phpt
    A   php/php-src/trunk/Zend/tests/indirect_method_call_004.phpt
    A   php/php-src/trunk/Zend/tests/indirect_method_call_005.phpt
    A   php/php-src/trunk/Zend/tests/indirect_property_access.phpt
    U   php/php-src/trunk/Zend/zend_language_parser.y

Modified: php/php-src/branches/PHP_5_4/NEWS
===================================================================
--- php/php-src/branches/PHP_5_4/NEWS	2011-11-06 12:13:29 UTC (rev 318822)
+++ php/php-src/branches/PHP_5_4/NEWS	2011-11-06 13:25:45 UTC (rev 318823)
@@ -3,6 +3,8 @@
 ?? ??? 2011, PHP 5.4.0 RC1
 - General improvements:
   . Changed silent conversion of array to string to produce a notice. (Patrick)
+  . Added class member access on instantiation (e.g. (new foo)->bar()) support.
+    (Felipe)

 - CLI SAPI:
   . Fixed bug #60112 (If URI does not contain a file, index.php is not served).

Modified: php/php-src/branches/PHP_5_4/UPGRADING
===================================================================
--- php/php-src/branches/PHP_5_4/UPGRADING	2011-11-06 12:13:29 UTC (rev 318822)
+++ php/php-src/branches/PHP_5_4/UPGRADING	2011-11-06 13:25:45 UTC (rev 318823)
@@ -461,6 +461,10 @@
     $y = "o";
     A::{$x.$y.$y}();

+- Class member acces on instantiation:
+  (new foo)->method()
+  (new foo)->property
+  (new foo)[0]

 ===================
 13. Windows support

Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_001.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_001.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_001.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,20 @@
+--TEST--
+Testing indirect method call and exceptions
+--FILE--
+<?php
+
+class foo {
+	public function __construct() {
+		throw new Exception('foobar');
+	}
+}
+
+try {
+	$X = (new foo)->Inexistent(3);
+} catch (Exception $e) {
+	var_dump($e->getMessage()); // foobar
+}
+
+?>
+--EXPECT--
+string(6) "foobar"

Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_002.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_002.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_002.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,32 @@
+--TEST--
+Indirect method call with chaining
+--FILE--
+<?php
+
+class foo {
+	public $x = 'testing';
+
+	public function bar() {
+		return "foo";
+	}
+	public function baz() {
+		return new self;
+	}
+	static function xyz() {
+	}
+}
+
+var_dump((new foo())->bar());               // string(3) "foo"
+var_dump((new foo())->baz()->x);            // string(7) "testing"
+var_dump((new foo())->baz()->baz()->bar()); // string(3) "foo"
+var_dump((new foo())->xyz());               // NULL
+(new foo())->www();
+
+?>
+--EXPECTF--
+string(3) "foo"
+string(7) "testing"
+string(3) "foo"
+NULL
+
+Fatal error: Call to undefined method foo::www() in %s on line %d

Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_003.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_003.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_003.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,23 @@
+--TEST--
+Testing indirect method call
+--FILE--
+<?php
+
+class foo {
+	public $x = 1;
+
+	public function getX() {
+		return $this->x;
+	}
+	public function setX($val) {
+		$this->x = $val;
+		return $this;
+	}
+}
+
+$X = (new foo)->setX(10)->getX();
+var_dump($X); // int(10)
+
+?>
+--EXPECT--
+int(10)

Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_004.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_004.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_004.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,26 @@
+--TEST--
+Indirect method call and cloning
+--FILE--
+<?php
+
+
+class bar {
+	public $z;
+
+	public function __construct() {
+		$this->z = new stdclass;
+	}
+	public function getZ() {
+		return $this->z;
+	}
+}
+
+var_dump(clone (new bar)->z);
+var_dump(clone (new bar)->getZ());
+
+?>
+--EXPECTF--
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}

Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_005.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_005.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_005.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,16 @@
+--TEST--
+Testing array dereferencing from instance with ArrayObject
+--FILE--
+<?php
+
+class foo extends ArrayObject {
+	public function __construct($arr) {
+		parent::__construct($arr);
+	}
+}
+
+var_dump( (new foo( array(1, array(4, 5), 3) ))[1][0] ); // int(4)
+
+?>
+--EXPECT--
+int(4)

Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_property_access.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/indirect_property_access.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_property_access.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,26 @@
+--TEST--
+Testing indirect property access
+--FILE--
+<?php
+
+class foo {
+	public $x = 1;
+}
+
+class bar {
+	public $y = 'foo';
+}
+
+$x = 'bar';
+
+$bar = new bar;
+
+var_dump((new bar)->y);     // foo
+var_dump((new $x)->y);      // foo
+var_dump((new $bar->y)->x); // 1
+
+?>
+--EXPECT--
+string(3) "foo"
+string(3) "foo"
+int(1)

Modified: php/php-src/branches/PHP_5_4/Zend/zend_language_parser.y
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_language_parser.y	2011-11-06 12:13:29 UTC (rev 318822)
+++ php/php-src/branches/PHP_5_4/Zend/zend_language_parser.y	2011-11-06 13:25:45 UTC (rev 318823)
@@ -50,7 +50,7 @@
 %}

 %pure_parser
-%expect 2
+%expect 3

 %token END 0 "end of file"
 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
@@ -694,12 +694,37 @@
 	|	expr					{ $$ = $1; }
 ;

+chaining_method_or_property:
+		chaining_method_or_property variable_property 	{ $$.EA = $2.EA; }
+	|	variable_property 								{ $$.EA = $1.EA; }
+;
+
+chaining_dereference:
+		chaining_dereference '[' dim_offset ']'	{ fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+	|	'[' dim_offset ']'		{ zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); }
+;
+
+chaining_instance_call:
+		chaining_dereference 		{ zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; }
+	|	chaining_dereference 		{ zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; }
+	|	chaining_method_or_property { $$ = $1; }
+;
+
+instance_call:
+		/* empty */ 		{ $$ = $0; }
+	|	{ zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
+		chaining_instance_call	{ zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); }
+;
+
+new_expr:
+		T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+;
+
 expr_without_variable:
 		T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
 	|	variable '=' expr		{ zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
 	|	variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
 	|	variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");  zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
-	|	T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
 	|	T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
 	|	variable T_PLUS_EQUAL expr 	{ zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
 	|	variable T_MINUS_EQUAL expr	{ zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
@@ -746,6 +771,8 @@
 	|	expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
 	|	expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
 	|	'(' expr ')' 	{ $$ = $2; }
+	|	new_expr		{ $$ = $1; }
+	|	'(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; }
 	|	expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
 		expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
 		expr	 { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }

Added: php/php-src/trunk/Zend/tests/indirect_method_call_001.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/indirect_method_call_001.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/indirect_method_call_001.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,20 @@
+--TEST--
+Testing indirect method call and exceptions
+--FILE--
+<?php
+
+class foo {
+	public function __construct() {
+		throw new Exception('foobar');
+	}
+}
+
+try {
+	$X = (new foo)->Inexistent(3);
+} catch (Exception $e) {
+	var_dump($e->getMessage()); // foobar
+}
+
+?>
+--EXPECT--
+string(6) "foobar"

Added: php/php-src/trunk/Zend/tests/indirect_method_call_002.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/indirect_method_call_002.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/indirect_method_call_002.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,32 @@
+--TEST--
+Indirect method call with chaining
+--FILE--
+<?php
+
+class foo {
+	public $x = 'testing';
+
+	public function bar() {
+		return "foo";
+	}
+	public function baz() {
+		return new self;
+	}
+	static function xyz() {
+	}
+}
+
+var_dump((new foo())->bar());               // string(3) "foo"
+var_dump((new foo())->baz()->x);            // string(7) "testing"
+var_dump((new foo())->baz()->baz()->bar()); // string(3) "foo"
+var_dump((new foo())->xyz());               // NULL
+(new foo())->www();
+
+?>
+--EXPECTF--
+string(3) "foo"
+string(7) "testing"
+string(3) "foo"
+NULL
+
+Fatal error: Call to undefined method foo::www() in %s on line %d

Added: php/php-src/trunk/Zend/tests/indirect_method_call_003.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/indirect_method_call_003.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/indirect_method_call_003.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,23 @@
+--TEST--
+Testing indirect method call
+--FILE--
+<?php
+
+class foo {
+	public $x = 1;
+
+	public function getX() {
+		return $this->x;
+	}
+	public function setX($val) {
+		$this->x = $val;
+		return $this;
+	}
+}
+
+$X = (new foo)->setX(10)->getX();
+var_dump($X); // int(10)
+
+?>
+--EXPECT--
+int(10)

Added: php/php-src/trunk/Zend/tests/indirect_method_call_004.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/indirect_method_call_004.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/indirect_method_call_004.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,26 @@
+--TEST--
+Indirect method call and cloning
+--FILE--
+<?php
+
+
+class bar {
+	public $z;
+
+	public function __construct() {
+		$this->z = new stdclass;
+	}
+	public function getZ() {
+		return $this->z;
+	}
+}
+
+var_dump(clone (new bar)->z);
+var_dump(clone (new bar)->getZ());
+
+?>
+--EXPECTF--
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}

Added: php/php-src/trunk/Zend/tests/indirect_method_call_005.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/indirect_method_call_005.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/indirect_method_call_005.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,16 @@
+--TEST--
+Testing array dereferencing from instance with ArrayObject
+--FILE--
+<?php
+
+class foo extends ArrayObject {
+	public function __construct($arr) {
+		parent::__construct($arr);
+	}
+}
+
+var_dump( (new foo( array(1, array(4, 5), 3) ))[1][0] ); // int(4)
+
+?>
+--EXPECT--
+int(4)

Added: php/php-src/trunk/Zend/tests/indirect_property_access.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/indirect_property_access.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/indirect_property_access.phpt	2011-11-06 13:25:45 UTC (rev 318823)
@@ -0,0 +1,26 @@
+--TEST--
+Testing indirect property access
+--FILE--
+<?php
+
+class foo {
+	public $x = 1;
+}
+
+class bar {
+	public $y = 'foo';
+}
+
+$x = 'bar';
+
+$bar = new bar;
+
+var_dump((new bar)->y);     // foo
+var_dump((new $x)->y);      // foo
+var_dump((new $bar->y)->x); // 1
+
+?>
+--EXPECT--
+string(3) "foo"
+string(3) "foo"
+int(1)

Modified: php/php-src/trunk/Zend/zend_language_parser.y
===================================================================
--- php/php-src/trunk/Zend/zend_language_parser.y	2011-11-06 12:13:29 UTC (rev 318822)
+++ php/php-src/trunk/Zend/zend_language_parser.y	2011-11-06 13:25:45 UTC (rev 318823)
@@ -50,7 +50,7 @@
 %}

 %pure_parser
-%expect 2
+%expect 3

 %token END 0 "end of file"
 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
@@ -694,12 +694,37 @@
 	|	expr					{ $$ = $1; }
 ;

+chaining_method_or_property:
+		chaining_method_or_property variable_property 	{ $$.EA = $2.EA; }
+	|	variable_property 								{ $$.EA = $1.EA; }
+;
+
+chaining_dereference:
+		chaining_dereference '[' dim_offset ']'	{ fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+	|	'[' dim_offset ']'		{ zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); }
+;
+
+chaining_instance_call:
+		chaining_dereference 		{ zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; }
+	|	chaining_dereference 		{ zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; }
+	|	chaining_method_or_property { $$ = $1; }
+;
+
+instance_call:
+		/* empty */ 		{ $$ = $0; }
+	|	{ zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
+		chaining_instance_call	{ zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); }
+;
+
+new_expr:
+		T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+;
+
 expr_without_variable:
 		T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
 	|	variable '=' expr		{ zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
 	|	variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
 	|	variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");  zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
-	|	T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
 	|	T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
 	|	variable T_PLUS_EQUAL expr 	{ zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
 	|	variable T_MINUS_EQUAL expr	{ zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
@@ -746,6 +771,8 @@
 	|	expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
 	|	expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
 	|	'(' expr ')' 	{ $$ = $2; }
+	|	new_expr		{ $$ = $1; }
+	|	'(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; }
 	|	expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
 		expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
 		expr	 { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to