Commit 54098cf0 authored by Ondrej Sury's avatar Ondrej Sury

Imported Upstream version 5.5.0~alpha4

parent 8572aeb0
PHP NEWS PHP NEWS
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
10 Jan 2012, PHP 5.5.0 Alpha 3 24 Jan 2013, PHP 5.5.0 Alpha 4
- Core:
. Fixed bug #63980 (object members get trimmed by zero bytes). (Laruence)
. Implemented RFC for Class Name Resolution As Scalar Via "class" Keyword.
(Ralph Schindler, Nikita Popov, Lars)
- DateTime
. Added DateTimeImmutable - a variant of DateTime that only returns the
modified state instead of changing itself. (Derick)
- FPM:
. Fixed bug #63999 (php with fpm fails to build on Solaris 10 or 11). (Adam)
- pgsql:
. Bug #46408: Locale number format settings can cause pg_query_params to
break with numerics. (asmecher, Lars)
- dba:
. Bug #62489: dba_insert not working as expected.
(marc-bennewitz at arcor dot de, Lars)
- Reflection:
. Fixed bug #64007 (There is an ability to create instance of Generator by hand).
(Laruence)
10 Jan 2013, PHP 5.5.0 Alpha 3
- General improvements: - General improvements:
. Fixed bug #63874 (Segfault if php_strip_whitespace has heredoc). (Pierrick) . Fixed bug #63874 (Segfault if php_strip_whitespace has heredoc). (Pierrick)
...@@ -17,10 +43,10 @@ PHP NEWS ...@@ -17,10 +43,10 @@ PHP NEWS
- cURL: - cURL:
. Added new functions curl_escape, curl_multi_setopt, curl_multi_strerror . Added new functions curl_escape, curl_multi_setopt, curl_multi_strerror
curl_pause, curl_reset, curl_share_close, curl_share_init, curl_pause, curl_reset, curl_share_close, curl_share_init,
curl_share_setopt curl_strerror and curl_unescape. (Pierrick) curl_share_setopt curl_strerror and curl_unescape. (Pierrick)
. Addes new curl options CURLOPT_TELNETOPTIONS, CURLOPT_GSSAPI_DELEGATION, . Addes new curl options CURLOPT_TELNETOPTIONS, CURLOPT_GSSAPI_DELEGATION,
CURLOPT_ACCEPTTIMEOUT_MS, CURLOPT_SSL_OPTIONS, CURLOPT_TCP_KEEPALIVE, CURLOPT_ACCEPTTIMEOUT_MS, CURLOPT_SSL_OPTIONS, CURLOPT_TCP_KEEPALIVE,
CURLOPT_TCP_KEEPIDLE and CURLOPT_TCP_KEEPINTVL. (Pierrick) CURLOPT_TCP_KEEPIDLE and CURLOPT_TCP_KEEPINTVL. (Pierrick)
18 Dec 2012, PHP 5.5.0 Alpha 2 18 Dec 2012, PHP 5.5.0 Alpha 2
...@@ -232,4 +258,7 @@ PHP NEWS ...@@ -232,4 +258,7 @@ PHP NEWS
. Fixed bug #63248 (Load multiple magic files from a directory under Windows). . Fixed bug #63248 (Load multiple magic files from a directory under Windows).
(Anatoliy) (Anatoliy)
- General improvements:
. Implemented FR #46487 (Dereferencing process-handles no longer waits on those processes). (Jille Timmermans)
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
...@@ -28,6 +28,17 @@ Both functions return SUCCESS or FAILURE depending on the result. ...@@ -28,6 +28,17 @@ Both functions return SUCCESS or FAILURE depending on the result.
The auto-conversions are performed as necessary. Arrays, objects, and The auto-conversions are performed as necessary. Arrays, objects, and
resources cannot be auto-converted. resources cannot be auto-converted.
PHP 5.5 includes a new function:
int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...);
This function behaves like zend_parse_parameters_ex() except that instead of
reading the arguments from the stack, it receives a single zval to convert
(passed with double indirection). The passed zval may be changed in place as
part of the conversion process.
See also https://wiki.php.net/rfc/zpp_improv#expose_zend_parse_arg_as_zend_parse_parameter
Type specifiers Type specifiers
--------------- ---------------
...@@ -65,9 +76,13 @@ Type specifiers ...@@ -65,9 +76,13 @@ Type specifiers
will not be touched by the parsing function if they are not will not be touched by the parsing function if they are not
passed to it. passed to it.
/ - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows / - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows
! - the parameter it follows can be of specified type or NULL (applies ! - the parameter it follows can be of specified type or NULL. If NULL is
to all specifiers except for 'b', 'l', and 'd'). If NULL is passed, the passed and the output for such type is a pointer, then the output
results pointer is set to NULL as well. pointer is set to a native NULL pointer.
For 'b', 'l' and 'd', an extra argument of type zend_bool* must be
passed after the corresponding bool*, long* or double* arguments,
respectively. A non-zero value will be written to the zend_bool iif a
PHP NULL is passed.
Note on 64bit compatibility Note on 64bit compatibility
......
...@@ -105,10 +105,11 @@ PHP 5.5 UPGRADE NOTES ...@@ -105,10 +105,11 @@ PHP 5.5 UPGRADE NOTES
- pack()/unpack() had the following changes, which bring it more in line - pack()/unpack() had the following changes, which bring it more in line
with Perl's behavior: with Perl's behavior:
- Implemented format character "Z": NUL-padded string - Implemented format character "Z": NULL padded string, with trailing NULL
- "a" now does not remove trailing NUL characters on unpack() anymore bytes removed.
- "A" will now strip all trailing ASCII whitespace on unpack() (it used to - Changed format character "a": this no longer removes trailing NULL bytes.
remove only trailing spaces). - Changed format character "A": all trailing ASCII whitespace is now removed
(defined as spaces, tabs, \r, \n and NULL).
- MessageFormatter::format() and related functions now accepted named arguments - MessageFormatter::format() and related functions now accepted named arguments
and mixed numeric/named arguments in ICU 4.8+. and mixed numeric/named arguments in ICU 4.8+.
- MessageFormatter::format() and related functions now don't error out when - MessageFormatter::format() and related functions now don't error out when
......
...@@ -5,6 +5,7 @@ UPGRADE NOTES - PHP X.Y ...@@ -5,6 +5,7 @@ UPGRADE NOTES - PHP X.Y
1. Internal API changes 1. Internal API changes
a. Streams pooling API a. Streams pooling API
b. Lowercasing and locales b. Lowercasing and locales
c. zend_qsort_r
2. Build system changes 2. Build system changes
a. Unix build system changes a. Unix build system changes
...@@ -53,6 +54,16 @@ such as strcasecmp, will be using locale rules. ...@@ -53,6 +54,16 @@ such as strcasecmp, will be using locale rules.
Two new functions - zend_binary_strncasecmp_l and zend_binary_strcasecmp_l - added as Two new functions - zend_binary_strncasecmp_l and zend_binary_strcasecmp_l - added as
locale-based counterparts to zend_binary_strcasecmp and zend_binary_strncasecmp. locale-based counterparts to zend_binary_strcasecmp and zend_binary_strncasecmp.
c. zend_qsort_r
Added the function zend_qsort_r():
typedef int (*compare_r_func_t)(const void *, const void * TSRMLS_DC, void *);
void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare, void *arg TSRMLS_DC);
The extra argument it has (relatively to zend_qsort()) is passed to the
comparison function.
======================== ========================
2. Build system changes 2. Build system changes
======================== ========================
......
...@@ -15,7 +15,7 @@ $f = fopen("/tmp/blah", "r"); ...@@ -15,7 +15,7 @@ $f = fopen("/tmp/blah", "r");
?> ?>
===DONE=== ===DONE===
--EXPECTF-- --EXPECTF--
fopen(/tmp/blah): failed to open stream: No such file or directory (2) in %s:%d fopen(/tmp/blah): failed to open stream: %s (2) in %s:%d
Warning: fopen(/tmp/blah): failed to open stream: No such file or directory in %s on line %d Warning: fopen(/tmp/blah): failed to open stream: %s in %s on line %d
===DONE=== ===DONE===
...@@ -10,7 +10,7 @@ set_error_handler(function($errno, $errstr, $errfile, $errline){ ...@@ -10,7 +10,7 @@ set_error_handler(function($errno, $errstr, $errfile, $errline){
require 'notfound.php'; require 'notfound.php';
--EXPECTF-- --EXPECTF--
error(require(notfound.php): failed to open stream: No such file or directory) error(require(notfound.php): failed to open stream: %s)
Warning: Uncaught exception 'Exception' with message 'Foo' in %sbug60909_1.php:5 Warning: Uncaught exception 'Exception' with message 'Foo' in %sbug60909_1.php:5
Stack trace: Stack trace:
#0 %sbug60909_1.php(8): {closure}(2, 'require(notfoun...', '%s', 8, Array) #0 %sbug60909_1.php(8): {closure}(2, 'require(notfoun...', '%s', 8, Array)
......
--TEST--
Test script to verify that magic methods should be called only once when accessing an unset property.
--CREDITS--
Marco Pivetta <ocramius@gmail.com>
--FILE--
<?php
class Test {
public $publicProperty;
protected $protectedProperty;
private $privateProperty;
public function __construct() {
unset(
$this->publicProperty,
$this->protectedProperty,
$this->privateProperty
);
}
function __get($name) {
echo '__get ' . $name . "\n";
return $this->$name;
}
function __set($name, $value) {
echo '__set ' . $name . "\n";
$this->$name = $value;
}
function __isset($name) {
echo '__isset ' . $name . "\n";
return isset($this->$name);
}
}
$test = new Test();
$test->nonExisting;
$test->publicProperty;
$test->protectedProperty;
$test->privateProperty;
isset($test->nonExisting);
isset($test->publicProperty);
isset($test->protectedProperty);
isset($test->privateProperty);
$test->nonExisting = 'value';
$test->publicProperty = 'value';
$test->protectedProperty = 'value';
$test->privateProperty = 'value';
?>
--EXPECTF--
__get nonExisting
Notice: Undefined property: Test::$nonExisting in %s on line %d
__get publicProperty
Notice: Undefined property: Test::$publicProperty in %s on line %d
__get protectedProperty
Notice: Undefined property: Test::$protectedProperty in %s on line %d
__get privateProperty
Notice: Undefined property: Test::$privateProperty in %s on line %d
__isset nonExisting
__isset publicProperty
__isset protectedProperty
__isset privateProperty
__set nonExisting
__set publicProperty
__set protectedProperty
__set privateProperty
--TEST--
Bug #63982 (isset() inconsistently produces a fatal error on protected property)
--FILE--
<?php
class Test {
protected $protectedProperty;
}
$test = new Test();
var_dump(isset($test->protectedProperty));
var_dump(isset($test->protectedProperty->foo));
--EXPECTF--
bool(false)
bool(false)
--TEST--
class name as scalar from ::class keyword
--FILE--
<?php
namespace Foo\Bar {
class One {
// compile time constants
const A = self::class;
const B = Two::class;
}
class Two extends One {
public static function run() {
var_dump(self::class); // self compile time lookup
var_dump(static::class); // runtime lookup
var_dump(parent::class); // runtime lookup
var_dump(Baz::class); // default compile time lookup
}
}
class Three extends Two {
// compile time static lookups
public static function checkCompileTime(
$one = self::class,
$two = Baz::class,
$three = One::A,
$four = self::B
) {
var_dump($one, $two, $three, $four);
}
}
echo "In NS\n";
var_dump(Moo::CLASS); // resolve in namespace
}
namespace {
use Bee\Bop as Moo,
Foo\Bar\One;
echo "Top\n";
var_dump(One::class); // resolve from use
var_dump(Boo::class); // resolve in global namespace
var_dump(Moo::CLASS); // resolve from use as
var_dump(\Moo::Class); // resolve fully qualified
$class = One::class; // assign class as scalar to var
$x = new $class; // create new class from original scalar assignment
var_dump($x);
Foo\Bar\Two::run(); // resolve runtime lookups
echo "Parent\n";
Foo\Bar\Three::run(); // resolve runtime lookups with inheritance
echo "Compile Check\n";
Foo\Bar\Three::checkCompileTime();
}
?>
--EXPECTF--
In NS
string(11) "Foo\Bar\Moo"
Top
string(11) "Foo\Bar\One"
string(3) "Boo"
string(7) "Bee\Bop"
string(3) "Moo"
object(Foo\Bar\One)#1 (0) {
}
string(11) "Foo\Bar\Two"
string(11) "Foo\Bar\Two"
string(11) "Foo\Bar\One"
string(11) "Foo\Bar\Baz"
Parent
string(11) "Foo\Bar\Two"
string(13) "Foo\Bar\Three"
string(11) "Foo\Bar\One"
string(11) "Foo\Bar\Baz"
Compile Check
string(13) "Foo\Bar\Three"
string(11) "Foo\Bar\Baz"
string(11) "Foo\Bar\One"
string(11) "Foo\Bar\Two"
--TEST--
class name as scalar from ::class keyword error using static in class constant
--FILE--
<?php
namespace Foo\Bar {
class One {
const Baz = static::class;
}
}
?>
--EXPECTF--
Fatal error: static::class cannot be used for compile-time class name resolution in %s on line %d
--TEST--
class name as scalar from ::class keyword error using parent in class constant
--FILE--
<?php
namespace Foo\Bar {
class One {
const Baz = parent::class;
}
}
?>
--EXPECTF--
Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d
--TEST--
class name as scalar from ::class keyword error using static in method signature
--FILE--
<?php
namespace Foo\Bar {
class One {
public function baz($x = static::class) {}
}
}
?>
--EXPECTF--
Fatal error: static::class cannot be used for compile-time class name resolution in %s on line %d
--TEST--
class name as scalar from ::class keyword error using parent in method signature
--FILE--
<?php
namespace Foo\Bar {
class One {
public function baz($x = parent::class) {}
}
}
?>
--EXPECTF--
Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d
--TEST--
class name as scalar from ::class keyword error using static non class context
--FILE--
<?php
$x = static::class;
?>
--EXPECTF--
Fatal error: Cannot access static::class when no class scope is active in %s on line %d
\ No newline at end of file
--TEST--
class name as scalar from ::class keyword error using parent in non class context
--FILE--
<?php
$x = parent::class;
?>
--EXPECTF--
Fatal error: Cannot access parent::class when no class scope is active in %s on line %d
...@@ -158,9 +158,10 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent, ...@@ -158,9 +158,10 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent,
case HASH_KEY_IS_STRING: case HASH_KEY_IS_STRING:
if (is_object) { if (is_object) {
const char *prop_name, *class_name; const char *prop_name, *class_name;
int mangled = zend_unmangle_property_name(string_key, str_len - 1, &class_name, &prop_name); int prop_len;
int mangled = zend_unmangle_property_name_ex(string_key, str_len - 1, &class_name, &prop_name, &prop_len);
ZEND_PUTS_EX(prop_name); ZEND_WRITE_EX(prop_name, prop_len);
if (class_name && mangled == SUCCESS) { if (class_name && mangled == SUCCESS) {
if (class_name[0]=='*') { if (class_name[0]=='*') {
ZEND_PUTS_EX(":protected"); ZEND_PUTS_EX(":protected");
......
...@@ -306,16 +306,14 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -306,16 +306,14 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
{ {
const char *spec_walk = *spec; const char *spec_walk = *spec;
char c = *spec_walk++; char c = *spec_walk++;
int return_null = 0; int check_null = 0;
/* scan through modifiers */ /* scan through modifiers */
while (1) { while (1) {
if (*spec_walk == '/') { if (*spec_walk == '/') {
SEPARATE_ZVAL_IF_NOT_REF(arg); SEPARATE_ZVAL_IF_NOT_REF(arg);
} else if (*spec_walk == '!') { } else if (*spec_walk == '!') {
if (Z_TYPE_PP(arg) == IS_NULL) { check_null = 1;
return_null = 1;
}
} else { } else {
break; break;
} }
...@@ -327,6 +325,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -327,6 +325,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'L': case 'L':
{ {
long *p = va_arg(*va, long *); long *p = va_arg(*va, long *);
if (check_null) {
zend_bool *p = va_arg(*va, zend_bool *);
*p = (Z_TYPE_PP(arg) == IS_NULL);
}
switch (Z_TYPE_PP(arg)) { switch (Z_TYPE_PP(arg)) {
case IS_STRING: case IS_STRING:
{ {
...@@ -380,6 +384,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -380,6 +384,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'd': case 'd':
{ {
double *p = va_arg(*va, double *); double *p = va_arg(*va, double *);
if (check_null) {
zend_bool *p = va_arg(*va, zend_bool *);
*p = (Z_TYPE_PP(arg) == IS_NULL);
}
switch (Z_TYPE_PP(arg)) { switch (Z_TYPE_PP(arg)) {
case IS_STRING: case IS_STRING:
{ {
...@@ -418,7 +428,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -418,7 +428,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
int *pl = va_arg(*va, int *); int *pl = va_arg(*va, int *);
switch (Z_TYPE_PP(arg)) { switch (Z_TYPE_PP(arg)) {
case IS_NULL: case IS_NULL:
if (return_null) { if (check_null) {
*p = NULL; *p = NULL;
*pl = 0; *pl = 0;
break; break;
...@@ -462,6 +472,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -462,6 +472,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'b': case 'b':
{ {
zend_bool *p = va_arg(*va, zend_bool *); zend_bool *p = va_arg(*va, zend_bool *);
if (check_null) {
zend_bool *p = va_arg(*va, zend_bool *);
*p = (Z_TYPE_PP(arg) == IS_NULL);
}
switch (Z_TYPE_PP(arg)) { switch (Z_TYPE_PP(arg)) {
case IS_NULL: case IS_NULL:
case IS_STRING: case IS_STRING:
...@@ -484,7 +500,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -484,7 +500,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'r': case 'r':
{ {
zval **p = va_arg(*va, zval **); zval **p = va_arg(*va, zval **);
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL; *p = NULL;
break; break;
} }
...@@ -499,7 +515,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -499,7 +515,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'a': case 'a':
{ {
zval **p = va_arg(*va, zval **); zval **p = va_arg(*va, zval **);
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL; *p = NULL;
break; break;
} }
...@@ -514,7 +530,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -514,7 +530,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'h': case 'h':
{ {
HashTable **p = va_arg(*va, HashTable **); HashTable **p = va_arg(*va, HashTable **);
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL; *p = NULL;
break; break;
} }
...@@ -534,7 +550,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -534,7 +550,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'o': case 'o':
{ {
zval **p = va_arg(*va, zval **); zval **p = va_arg(*va, zval **);
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL; *p = NULL;
break; break;
} }
...@@ -551,7 +567,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -551,7 +567,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zval **p = va_arg(*va, zval **); zval **p = va_arg(*va, zval **);
zend_class_entry *ce = va_arg(*va, zend_class_entry *); zend_class_entry *ce = va_arg(*va, zend_class_entry *);
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL; *p = NULL;
break; break;
} }
...@@ -573,7 +589,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -573,7 +589,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **); zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
zend_class_entry *ce_base = *pce; zend_class_entry *ce_base = *pce;
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*pce = NULL; *pce = NULL;
break; break;
} }
...@@ -607,7 +623,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -607,7 +623,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *); zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
char *is_callable_error = NULL; char *is_callable_error = NULL;
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
fci->size = 0; fci->size = 0;
fcc->initialized = 0; fcc->initialized = 0;
break; break;
...@@ -637,7 +653,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -637,7 +653,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'z': case 'z':
{ {
zval **p = va_arg(*va, zval **); zval **p = va_arg(*va, zval **);
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL; *p = NULL;
} else { } else {
*p = *arg; *p = *arg;
...@@ -648,7 +664,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con ...@@ -648,7 +664,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'Z': case 'Z':
{ {
zval ***p = va_arg(*va, zval ***); zval ***p = va_arg(*va, zval ***);
if (return_null) { if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL; *p = NULL;
} else { } else {
*p = arg; *p = arg;
...@@ -697,6 +713,19 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, const char **spe ...@@ -697,6 +713,19 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, const char **spe
} }
/* }}} */ /* }}} */
ZEND_API int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...)
{
va_list va;
int ret;
int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
va_start(va, spec);
ret = zend_parse_arg(arg_num, arg, &va, &spec, quiet TSRMLS_CC);
va_end(va);
return ret;
}
static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
{ {
const char *spec_walk; const char *spec_walk;
......
...@@ -258,6 +258,8 @@ ZEND_API char *zend_zval_type_name(const zval *arg); ...@@ -258,6 +258,8 @@ ZEND_API char *zend_zval_type_name(const zval *arg);
ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...); ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...);
ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...); ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...);
ZEND_API int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...);
/* End of parameter parsing API -- andrei */ /* End of parameter parsing API -- andrei */
ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC); ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC);
......